Browse Source

Copy oversampled FramebufferWidgets to actual-size framebuffers after rendering.

tags/v1.0.0
Andrew Belt 5 years ago
parent
commit
7b0c04aa9f
4 changed files with 50 additions and 9 deletions
  1. +1
    -1
      dep/nanovg
  2. +2
    -1
      include/widget/FramebufferWidget.hpp
  3. +8
    -0
      src/dep.cpp
  4. +39
    -7
      src/widget/FramebufferWidget.cpp

+ 1
- 1
dep/nanovg

@@ -1 +1 @@
Subproject commit e5f559523f03ca93739c3067d7ac1fa5d82d2a0d
Subproject commit 8e697cf0e157f42740582f54d0ac76b55d7e3ac1

+ 2
- 1
include/widget/FramebufferWidget.hpp View File

@@ -13,7 +13,8 @@ Events are not passed to the underlying scene.
struct FramebufferWidget : Widget {
/** Set this to true to re-render the children to the framebuffer the next time it is drawn */
bool dirty = true;
float oversample;
bool bypass = false;
float oversample = 1.0;
NVGLUframebuffer *fb = NULL;
/** Scale relative to the world */
math::Vec scale;


+ 8
- 0
src/dep.cpp View File

@@ -2,17 +2,25 @@

#define GLEW_STATIC
#include <GL/glew.h>

#include <nanovg.h>

#define NANOVG_GL2_IMPLEMENTATION
// #define NANOVG_GL3_IMPLEMENTATION
// #define NANOVG_GLES2_IMPLEMENTATION
// #define NANOVG_GLES3_IMPLEMENTATION
#include <nanovg_gl.h>

// Hack to get framebuffer objects working on OpenGL 2 (we blindly assume the extension is supported)
#define NANOVG_FBO_VALID
#include <nanovg_gl_utils.h>

#define BLENDISH_IMPLEMENTATION
#include <blendish.h>

#define NANOSVG_IMPLEMENTATION
#define NANOSVG_ALL_COLOR_KEYWORDS
#include <nanosvg.h>

#define STB_IMAGE_WRITE_IMPLEMENTATION
#include <stb_image_write.h>

+ 39
- 7
src/widget/FramebufferWidget.cpp View File

@@ -8,7 +8,6 @@ namespace widget {


FramebufferWidget::FramebufferWidget() {
oversample = 1.0;
}

FramebufferWidget::~FramebufferWidget() {
@@ -27,6 +26,7 @@ void FramebufferWidget::step() {
if (dirty && !scale.isZero()) {
// In case we fail drawing the framebuffer, don't try again the next frame, so reset `dirty` here.
dirty = false;
NVGcontext *vg = APP->window->vg;

fbScale = scale;
// Get subpixel offset in range [0, 1)
@@ -48,7 +48,7 @@ void FramebufferWidget::step() {
fbBox = math::Rect::fromMinMax(min, max);
// DEBUG("%g %g %g %g", RECT_ARGS(fbBox));

math::Vec newFbSize = fbBox.size.mult(APP->window->pixelRatio * oversample);
math::Vec newFbSize = fbBox.size.mult(APP->window->pixelRatio).ceil();

// Create framebuffer if a new size is needed
if (!fb || !newFbSize.isEqual(fbSize)) {
@@ -56,9 +56,9 @@ void FramebufferWidget::step() {
// Delete old framebuffer
if (fb)
nvgluDeleteFramebuffer(fb);
// Create a framebuffer from the main nanovg context. We will draw to this in the secondary nanovg context.
// Create a framebuffer at the oversampled size
if (fbSize.isFinite() && !fbSize.isZero())
fb = nvgluCreateFramebuffer(APP->window->vg, fbSize.x, fbSize.y, 0);
fb = nvgluCreateFramebuffer(vg, fbSize.x * oversample, fbSize.y * oversample, 0);
}

if (!fb)
@@ -67,12 +67,44 @@ void FramebufferWidget::step() {
nvgluBindFramebuffer(fb);
drawFramebuffer();
nvgluBindFramebuffer(NULL);

// If oversampling, create another framebuffer and copy it to actual size.
if (oversample != 1.0) {
NVGLUframebuffer *newFb = nvgluCreateFramebuffer(vg, fbSize.x, fbSize.y, 0);
if (!newFb)
return;

// Use NanoVG for resizing framebuffers
nvgluBindFramebuffer(newFb);

nvgBeginFrame(vg, fbBox.size.x, fbBox.size.y, 1.0);

// Draw oversampled framebuffer
nvgBeginPath(vg);
nvgRect(vg, 0.0, 0.0, fbSize.x, fbSize.y);
NVGpaint paint = nvgImagePattern(vg, 0.0, 0.0, fbSize.x, fbSize.y,
0.0, fb->image, 1.0);
nvgFillPaint(vg, paint);
nvgFill(vg);

glViewport(0.0, 0.0, fbSize.x, fbSize.y);
glClearColor(0.0, 0.0, 0.0, 0.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
nvgEndFrame(vg);
nvgReset(vg);

nvgluBindFramebuffer(NULL);

// Swap the framebuffers
nvgluDeleteFramebuffer(fb);
fb = newFb;
}
}
}

void FramebufferWidget::draw(const DrawArgs &args) {
// Draw directly if already drawing in a framebuffer
if (args.fb) {
if (bypass || args.fb) {
Widget::draw(args);
return;
}
@@ -126,7 +158,7 @@ void FramebufferWidget::draw(const DrawArgs &args) {
void FramebufferWidget::drawFramebuffer() {
NVGcontext *vg = APP->window->vg;

float pixelRatio = fbSize.x / fbBox.size.x;
float pixelRatio = fbSize.x * oversample / fbBox.size.x;
nvgBeginFrame(vg, fbBox.size.x, fbBox.size.y, pixelRatio);

// Use local scaling
@@ -140,7 +172,7 @@ void FramebufferWidget::drawFramebuffer() {
args.fb = fb;
Widget::draw(args);

glViewport(0.0, 0.0, fbSize.x, fbSize.y);
glViewport(0.0, 0.0, fbSize.x * oversample, fbSize.y * oversample);
glClearColor(0.0, 0.0, 0.0, 0.0);
// glClearColor(0.0, 1.0, 1.0, 0.5);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);


Loading…
Cancel
Save