Render to texture first, rather than copying from the frame buffer. Copying

from the frame buffer requires it to have an alpha channel, which actually
does something on OS X (meaning we have to set it to 1.0).  We're going to
want to render to texture anyway for SSAO (or other effects).
This commit is contained in:
Andrzej Kapolka 2013-08-13 12:27:52 -07:00
parent c1f6794295
commit b05b43f027
5 changed files with 93 additions and 69 deletions

View file

@ -8,25 +8,25 @@
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved. // Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
// //
// the texture containing the color to blur // the texture containing the original color
uniform sampler2D colorTexture; uniform sampler2D originalTexture;
void main(void) { void main(void) {
float ds = dFdx(gl_TexCoord[0].s); float ds = dFdx(gl_TexCoord[0].s);
gl_FragColor = (texture2D(colorTexture, gl_TexCoord[0].st + vec2(ds * -15.5, 0.0)) + gl_FragColor = (texture2D(originalTexture, gl_TexCoord[0].st + vec2(ds * -15.5, 0.0)) +
texture2D(colorTexture, gl_TexCoord[0].st + vec2(ds * -13.5, 0.0)) + texture2D(originalTexture, gl_TexCoord[0].st + vec2(ds * -13.5, 0.0)) +
texture2D(colorTexture, gl_TexCoord[0].st + vec2(ds * -11.5, 0.0)) + texture2D(originalTexture, gl_TexCoord[0].st + vec2(ds * -11.5, 0.0)) +
texture2D(colorTexture, gl_TexCoord[0].st + vec2(ds * -9.5, 0.0)) + texture2D(originalTexture, gl_TexCoord[0].st + vec2(ds * -9.5, 0.0)) +
texture2D(colorTexture, gl_TexCoord[0].st + vec2(ds * -7.5, 0.0)) + texture2D(originalTexture, gl_TexCoord[0].st + vec2(ds * -7.5, 0.0)) +
texture2D(colorTexture, gl_TexCoord[0].st + vec2(ds * -5.5, 0.0)) + texture2D(originalTexture, gl_TexCoord[0].st + vec2(ds * -5.5, 0.0)) +
texture2D(colorTexture, gl_TexCoord[0].st + vec2(ds * -3.5, 0.0)) + texture2D(originalTexture, gl_TexCoord[0].st + vec2(ds * -3.5, 0.0)) +
texture2D(colorTexture, gl_TexCoord[0].st + vec2(ds * -1.5, 0.0)) + texture2D(originalTexture, gl_TexCoord[0].st + vec2(ds * -1.5, 0.0)) +
texture2D(colorTexture, gl_TexCoord[0].st + vec2(ds * 1.5, 0.0)) + texture2D(originalTexture, gl_TexCoord[0].st + vec2(ds * 1.5, 0.0)) +
texture2D(colorTexture, gl_TexCoord[0].st + vec2(ds * 3.5, 0.0)) + texture2D(originalTexture, gl_TexCoord[0].st + vec2(ds * 3.5, 0.0)) +
texture2D(colorTexture, gl_TexCoord[0].st + vec2(ds * 5.5, 0.0)) + texture2D(originalTexture, gl_TexCoord[0].st + vec2(ds * 5.5, 0.0)) +
texture2D(colorTexture, gl_TexCoord[0].st + vec2(ds * 7.5, 0.0)) + texture2D(originalTexture, gl_TexCoord[0].st + vec2(ds * 7.5, 0.0)) +
texture2D(colorTexture, gl_TexCoord[0].st + vec2(ds * 9.5, 0.0)) + texture2D(originalTexture, gl_TexCoord[0].st + vec2(ds * 9.5, 0.0)) +
texture2D(colorTexture, gl_TexCoord[0].st + vec2(ds * 11.5, 0.0)) + texture2D(originalTexture, gl_TexCoord[0].st + vec2(ds * 11.5, 0.0)) +
texture2D(colorTexture, gl_TexCoord[0].st + vec2(ds * 13.5, 0.0)) + texture2D(originalTexture, gl_TexCoord[0].st + vec2(ds * 13.5, 0.0)) +
texture2D(colorTexture, gl_TexCoord[0].st + vec2(ds * 15.5, 0.0))) / 16.0; texture2D(originalTexture, gl_TexCoord[0].st + vec2(ds * 15.5, 0.0))) / 16.0;
} }

View file

@ -8,25 +8,29 @@
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved. // Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
// //
// the texture containing the color to blur // the texture containing the original color
uniform sampler2D colorTexture; uniform sampler2D originalTexture;
// the texture containing the horizontally blurred color
uniform sampler2D horizontallyBlurredTexture;
void main(void) { void main(void) {
float dt = dFdy(gl_TexCoord[0].t); float dt = dFdy(gl_TexCoord[0].t);
gl_FragColor = (texture2D(colorTexture, gl_TexCoord[0].st + vec2(0.0, dt * -15.5)) + vec4 blurred = (texture2D(horizontallyBlurredTexture, gl_TexCoord[0].st + vec2(0.0, dt * -15.5)) +
texture2D(colorTexture, gl_TexCoord[0].st + vec2(0.0, dt * -13.5)) + texture2D(horizontallyBlurredTexture, gl_TexCoord[0].st + vec2(0.0, dt * -13.5)) +
texture2D(colorTexture, gl_TexCoord[0].st + vec2(0.0, dt * -11.5)) + texture2D(horizontallyBlurredTexture, gl_TexCoord[0].st + vec2(0.0, dt * -11.5)) +
texture2D(colorTexture, gl_TexCoord[0].st + vec2(0.0, dt * -9.5)) + texture2D(horizontallyBlurredTexture, gl_TexCoord[0].st + vec2(0.0, dt * -9.5)) +
texture2D(colorTexture, gl_TexCoord[0].st + vec2(0.0, dt * -7.5)) + texture2D(horizontallyBlurredTexture, gl_TexCoord[0].st + vec2(0.0, dt * -7.5)) +
texture2D(colorTexture, gl_TexCoord[0].st + vec2(0.0, dt * -4.5)) + texture2D(horizontallyBlurredTexture, gl_TexCoord[0].st + vec2(0.0, dt * -4.5)) +
texture2D(colorTexture, gl_TexCoord[0].st + vec2(0.0, dt * -3.5)) + texture2D(horizontallyBlurredTexture, gl_TexCoord[0].st + vec2(0.0, dt * -3.5)) +
texture2D(colorTexture, gl_TexCoord[0].st + vec2(0.0, dt * -1.5)) + texture2D(horizontallyBlurredTexture, gl_TexCoord[0].st + vec2(0.0, dt * -1.5)) +
texture2D(colorTexture, gl_TexCoord[0].st + vec2(0.0, dt * 1.5)) + texture2D(horizontallyBlurredTexture, gl_TexCoord[0].st + vec2(0.0, dt * 1.5)) +
texture2D(colorTexture, gl_TexCoord[0].st + vec2(0.0, dt * 3.5)) + texture2D(horizontallyBlurredTexture, gl_TexCoord[0].st + vec2(0.0, dt * 3.5)) +
texture2D(colorTexture, gl_TexCoord[0].st + vec2(0.0, dt * 5.5)) + texture2D(horizontallyBlurredTexture, gl_TexCoord[0].st + vec2(0.0, dt * 5.5)) +
texture2D(colorTexture, gl_TexCoord[0].st + vec2(0.0, dt * 7.5)) + texture2D(horizontallyBlurredTexture, gl_TexCoord[0].st + vec2(0.0, dt * 7.5)) +
texture2D(colorTexture, gl_TexCoord[0].st + vec2(0.0, dt * 9.5)) + texture2D(horizontallyBlurredTexture, gl_TexCoord[0].st + vec2(0.0, dt * 9.5)) +
texture2D(colorTexture, gl_TexCoord[0].st + vec2(0.0, dt * 11.5)) + texture2D(horizontallyBlurredTexture, gl_TexCoord[0].st + vec2(0.0, dt * 11.5)) +
texture2D(colorTexture, gl_TexCoord[0].st + vec2(0.0, dt * 13.5)) + texture2D(horizontallyBlurredTexture, gl_TexCoord[0].st + vec2(0.0, dt * 13.5)) +
texture2D(colorTexture, gl_TexCoord[0].st + vec2(0.0, dt * 15.5))) / 16.0; texture2D(horizontallyBlurredTexture, gl_TexCoord[0].st + vec2(0.0, dt * 15.5))) / 16.0;
gl_FragColor = blurred * blurred.a + texture2D(originalTexture, gl_TexCoord[0].st);
} }

View file

@ -116,7 +116,7 @@ protected:
virtual void wheelEvent(QWheelEvent* event); virtual void wheelEvent(QWheelEvent* event);
}; };
GLCanvas::GLCanvas() : QGLWidget(QGLFormat(QGL::AlphaChannel)) { GLCanvas::GLCanvas() : QGLWidget(QGLFormat(QGL::NoDepthBuffer, QGL::NoStencilBuffer)) {
} }
void GLCanvas::initializeGL() { void GLCanvas::initializeGL() {
@ -418,8 +418,7 @@ void Application::paintGL() {
PerfStat("display"); PerfStat("display");
glEnable(GL_LINE_SMOOTH); glEnable(GL_LINE_SMOOTH);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
if (_myCamera.getMode() == CAMERA_MODE_MIRROR) { if (_myCamera.getMode() == CAMERA_MODE_MIRROR) {
_myCamera.setTightness (100.0f); _myCamera.setTightness (100.0f);
_myCamera.setTargetPosition(_myAvatar.getUprightHeadPosition()); _myCamera.setTargetPosition(_myAvatar.getUprightHeadPosition());

View file

@ -20,7 +20,7 @@ static ProgramObject* createBlurProgram(const QString& direction) {
program->link(); program->link();
program->bind(); program->bind();
program->setUniformValue("colorTexture", 0); program->setUniformValue("originalTexture", 0);
program->release(); program->release();
return program; return program;
@ -30,9 +30,16 @@ void GlowEffect::init() {
switchToResourcesParentIfRequired(); switchToResourcesParentIfRequired();
_horizontalBlurProgram = createBlurProgram("horizontal"); _horizontalBlurProgram = createBlurProgram("horizontal");
_verticalBlurProgram = createBlurProgram("vertical"); _verticalBlurProgram = createBlurProgram("vertical");
_verticalBlurProgram->bind();
_verticalBlurProgram->setUniformValue("horizontallyBlurredTexture", 1);
_verticalBlurProgram->release();
} }
void GlowEffect::prepare() { void GlowEffect::prepare() {
Application::getInstance()->getTextureCache()->getPrimaryFramebufferObject()->bind();
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
_isEmpty = true; _isEmpty = true;
} }
@ -59,15 +66,10 @@ static void renderFullscreenQuad() {
} }
void GlowEffect::render() { void GlowEffect::render() {
if (_isEmpty) {
return; // nothing glowing
}
QOpenGLFramebufferObject* primaryFBO = Application::getInstance()->getTextureCache()->getPrimaryFramebufferObject(); QOpenGLFramebufferObject* primaryFBO = Application::getInstance()->getTextureCache()->getPrimaryFramebufferObject();
primaryFBO->release();
glBindTexture(GL_TEXTURE_2D, primaryFBO->texture()); glBindTexture(GL_TEXTURE_2D, primaryFBO->texture());
QSize size = primaryFBO->size();
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, size.width(), size.height());
glPushMatrix(); glPushMatrix();
glLoadIdentity(); glLoadIdentity();
@ -76,33 +78,51 @@ void GlowEffect::render() {
glLoadIdentity(); glLoadIdentity();
glDisable(GL_BLEND); glDisable(GL_BLEND);
glDisable(GL_DEPTH_TEST);
// render the primary to the secondary with the horizontal blur if (_isEmpty) {
QOpenGLFramebufferObject* secondaryFBO = Application::getInstance()->getTextureCache()->getSecondaryFramebufferObject(); // copy the primary to the screen
secondaryFBO->bind(); if (QOpenGLFramebufferObject::hasOpenGLFramebufferBlit()) {
QOpenGLFramebufferObject::blitFramebuffer(NULL, primaryFBO);
_horizontalBlurProgram->bind();
renderFullscreenQuad(); } else {
_horizontalBlurProgram->release(); glEnable(GL_TEXTURE_2D);
glDisable(GL_LIGHTING);
secondaryFBO->release(); glColor3f(1.0f, 1.0f, 1.0f);
renderFullscreenQuad();
// render the secondary to the screen with the vertical blur glDisable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, secondaryFBO->texture()); glEnable(GL_LIGHTING);
}
glEnable(GL_BLEND); } else {
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE, GL_CONSTANT_ALPHA, GL_ONE); // render the primary to the secondary with the horizontal blur
QOpenGLFramebufferObject* secondaryFBO =
_verticalBlurProgram->bind(); Application::getInstance()->getTextureCache()->getSecondaryFramebufferObject();
renderFullscreenQuad(); secondaryFBO->bind();
_verticalBlurProgram->release();
_horizontalBlurProgram->bind();
renderFullscreenQuad();
_horizontalBlurProgram->release();
secondaryFBO->release();
// render the secondary to the screen with the vertical blur
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, secondaryFBO->texture());
_verticalBlurProgram->bind();
renderFullscreenQuad();
_verticalBlurProgram->release();
glBindTexture(GL_TEXTURE_2D, 0);
glActiveTexture(GL_TEXTURE0);
}
glPopMatrix(); glPopMatrix();
glMatrixMode(GL_MODELVIEW); glMatrixMode(GL_MODELVIEW);
glPopMatrix(); glPopMatrix();
glEnable(GL_BLEND);
glEnable(GL_DEPTH_TEST);
glBindTexture(GL_TEXTURE_2D, 0); glBindTexture(GL_TEXTURE_2D, 0);
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_CONSTANT_ALPHA, GL_ONE);
} }

View file

@ -57,7 +57,8 @@ GLuint TextureCache::getPermutationNormalTextureID() {
QOpenGLFramebufferObject* TextureCache::getPrimaryFramebufferObject() { QOpenGLFramebufferObject* TextureCache::getPrimaryFramebufferObject() {
if (_primaryFramebufferObject == NULL) { if (_primaryFramebufferObject == NULL) {
_primaryFramebufferObject = new QOpenGLFramebufferObject(Application::getInstance()->getGLWidget()->size()); _primaryFramebufferObject = new QOpenGLFramebufferObject(Application::getInstance()->getGLWidget()->size(),
QOpenGLFramebufferObject::Depth);
Application::getInstance()->getGLWidget()->installEventFilter(this); Application::getInstance()->getGLWidget()->installEventFilter(this);
} }
return _primaryFramebufferObject; return _primaryFramebufferObject;