Browse Source

Copy oversampled FramebufferWidgets to actual-size framebuffers after rendering.

tags/v1.0.0
Andrew Belt 7 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 { struct FramebufferWidget : Widget {
/** Set this to true to re-render the children to the framebuffer the next time it is drawn */ /** Set this to true to re-render the children to the framebuffer the next time it is drawn */
bool dirty = true; bool dirty = true;
float oversample;
bool bypass = false;
float oversample = 1.0;
NVGLUframebuffer *fb = NULL; NVGLUframebuffer *fb = NULL;
/** Scale relative to the world */ /** Scale relative to the world */
math::Vec scale; math::Vec scale;


+ 8
- 0
src/dep.cpp View File

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


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

#include <nanovg.h> #include <nanovg.h>

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

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

#define BLENDISH_IMPLEMENTATION #define BLENDISH_IMPLEMENTATION
#include <blendish.h> #include <blendish.h>

#define NANOSVG_IMPLEMENTATION #define NANOSVG_IMPLEMENTATION
#define NANOSVG_ALL_COLOR_KEYWORDS #define NANOSVG_ALL_COLOR_KEYWORDS
#include <nanosvg.h> #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() { FramebufferWidget::FramebufferWidget() {
oversample = 1.0;
} }


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


fbScale = scale; fbScale = scale;
// Get subpixel offset in range [0, 1) // Get subpixel offset in range [0, 1)
@@ -48,7 +48,7 @@ void FramebufferWidget::step() {
fbBox = math::Rect::fromMinMax(min, max); fbBox = math::Rect::fromMinMax(min, max);
// DEBUG("%g %g %g %g", RECT_ARGS(fbBox)); // 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 // Create framebuffer if a new size is needed
if (!fb || !newFbSize.isEqual(fbSize)) { if (!fb || !newFbSize.isEqual(fbSize)) {
@@ -56,9 +56,9 @@ void FramebufferWidget::step() {
// Delete old framebuffer // Delete old framebuffer
if (fb) if (fb)
nvgluDeleteFramebuffer(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()) 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) if (!fb)
@@ -67,12 +67,44 @@ void FramebufferWidget::step() {
nvgluBindFramebuffer(fb); nvgluBindFramebuffer(fb);
drawFramebuffer(); drawFramebuffer();
nvgluBindFramebuffer(NULL); 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) { void FramebufferWidget::draw(const DrawArgs &args) {
// Draw directly if already drawing in a framebuffer // Draw directly if already drawing in a framebuffer
if (args.fb) {
if (bypass || args.fb) {
Widget::draw(args); Widget::draw(args);
return; return;
} }
@@ -126,7 +158,7 @@ void FramebufferWidget::draw(const DrawArgs &args) {
void FramebufferWidget::drawFramebuffer() { void FramebufferWidget::drawFramebuffer() {
NVGcontext *vg = APP->window->vg; 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); nvgBeginFrame(vg, fbBox.size.x, fbBox.size.y, pixelRatio);


// Use local scaling // Use local scaling
@@ -140,7 +172,7 @@ void FramebufferWidget::drawFramebuffer() {
args.fb = fb; args.fb = fb;
Widget::draw(args); 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, 0.0, 0.0, 0.0);
// glClearColor(0.0, 1.0, 1.0, 0.5); // glClearColor(0.0, 1.0, 1.0, 0.5);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);


Loading…
Cancel
Save