From 1828a105d46f542a00bf89f011912b4117e4ca1b Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Thu, 8 Aug 2013 16:55:45 -0700 Subject: [PATCH] Basic glow effect. --- .../resources/shaders/horizontal_blur.frag | 32 +++++++ .../resources/shaders/vertical_blur.frag | 32 +++++++ interface/src/Application.cpp | 12 +++ interface/src/Application.h | 1 + interface/src/renderer/GlowEffect.cpp | 94 +++++++++++++++++++ interface/src/renderer/GlowEffect.h | 13 +++ interface/src/renderer/TextureCache.cpp | 44 ++++++++- interface/src/renderer/TextureCache.h | 14 ++- 8 files changed, 240 insertions(+), 2 deletions(-) create mode 100644 interface/resources/shaders/horizontal_blur.frag create mode 100644 interface/resources/shaders/vertical_blur.frag diff --git a/interface/resources/shaders/horizontal_blur.frag b/interface/resources/shaders/horizontal_blur.frag new file mode 100644 index 0000000000..b1b40c2187 --- /dev/null +++ b/interface/resources/shaders/horizontal_blur.frag @@ -0,0 +1,32 @@ +#version 120 + +// +// horizontal_blur.frag +// fragment shader +// +// Created by Andrzej Kapolka on 8/8/13. +// Copyright (c) 2013 High Fidelity, Inc. All rights reserved. +// + +// the texture containing the color to blur +uniform sampler2D colorTexture; + +void main(void) { + float ds = dFdx(gl_TexCoord[0].s); + gl_FragColor = (texture2D(colorTexture, gl_TexCoord[0].st + vec2(ds * -15.5, 0.0)) + + texture2D(colorTexture, gl_TexCoord[0].st + vec2(ds * -13.5, 0.0)) + + texture2D(colorTexture, gl_TexCoord[0].st + vec2(ds * -11.5, 0.0)) + + texture2D(colorTexture, gl_TexCoord[0].st + vec2(ds * -9.5, 0.0)) + + texture2D(colorTexture, gl_TexCoord[0].st + vec2(ds * -7.5, 0.0)) + + texture2D(colorTexture, gl_TexCoord[0].st + vec2(ds * -5.5, 0.0)) + + texture2D(colorTexture, gl_TexCoord[0].st + vec2(ds * -3.5, 0.0)) + + texture2D(colorTexture, gl_TexCoord[0].st + vec2(ds * -1.5, 0.0)) + + texture2D(colorTexture, gl_TexCoord[0].st + vec2(ds * 1.5, 0.0)) + + texture2D(colorTexture, gl_TexCoord[0].st + vec2(ds * 3.5, 0.0)) + + texture2D(colorTexture, gl_TexCoord[0].st + vec2(ds * 5.5, 0.0)) + + texture2D(colorTexture, gl_TexCoord[0].st + vec2(ds * 7.5, 0.0)) + + texture2D(colorTexture, gl_TexCoord[0].st + vec2(ds * 9.5, 0.0)) + + texture2D(colorTexture, gl_TexCoord[0].st + vec2(ds * 11.5, 0.0)) + + texture2D(colorTexture, gl_TexCoord[0].st + vec2(ds * 13.5, 0.0)) + + texture2D(colorTexture, gl_TexCoord[0].st + vec2(ds * 15.5, 0.0))) / 16.0; +} diff --git a/interface/resources/shaders/vertical_blur.frag b/interface/resources/shaders/vertical_blur.frag new file mode 100644 index 0000000000..0641c773e7 --- /dev/null +++ b/interface/resources/shaders/vertical_blur.frag @@ -0,0 +1,32 @@ +#version 120 + +// +// vertical_blur.frag +// fragment shader +// +// Created by Andrzej Kapolka on 8/8/13. +// Copyright (c) 2013 High Fidelity, Inc. All rights reserved. +// + +// the texture containing the color to blur +uniform sampler2D colorTexture; + +void main(void) { + float dt = dFdy(gl_TexCoord[0].t); + gl_FragColor = (texture2D(colorTexture, gl_TexCoord[0].st + vec2(0.0, dt * -15.5)) + + texture2D(colorTexture, gl_TexCoord[0].st + vec2(0.0, dt * -13.5)) + + texture2D(colorTexture, gl_TexCoord[0].st + vec2(0.0, dt * -11.5)) + + texture2D(colorTexture, gl_TexCoord[0].st + vec2(0.0, dt * -9.5)) + + texture2D(colorTexture, gl_TexCoord[0].st + vec2(0.0, dt * -7.5)) + + texture2D(colorTexture, gl_TexCoord[0].st + vec2(0.0, dt * -4.5)) + + texture2D(colorTexture, gl_TexCoord[0].st + vec2(0.0, dt * -3.5)) + + texture2D(colorTexture, gl_TexCoord[0].st + vec2(0.0, dt * -1.5)) + + texture2D(colorTexture, gl_TexCoord[0].st + vec2(0.0, dt * 1.5)) + + texture2D(colorTexture, gl_TexCoord[0].st + vec2(0.0, dt * 3.5)) + + texture2D(colorTexture, gl_TexCoord[0].st + vec2(0.0, dt * 5.5)) + + texture2D(colorTexture, gl_TexCoord[0].st + vec2(0.0, dt * 7.5)) + + texture2D(colorTexture, gl_TexCoord[0].st + vec2(0.0, dt * 9.5)) + + texture2D(colorTexture, gl_TexCoord[0].st + vec2(0.0, dt * 11.5)) + + texture2D(colorTexture, gl_TexCoord[0].st + vec2(0.0, dt * 13.5)) + + texture2D(colorTexture, gl_TexCoord[0].st + vec2(0.0, dt * 15.5))) / 16.0; +} diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 5239750447..55c4a249dc 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2202,6 +2202,8 @@ void Application::init() { _environment.init(); + _glowEffect.init(); + _handControl.setScreenDimensions(_glWidget->width(), _glWidget->height()); _headMouseX = _mouseX = _glWidget->width() / 2; @@ -3022,6 +3024,9 @@ void Application::displaySide(Camera& whichCamera) { glEnable(GL_LIGHTING); glEnable(GL_DEPTH_TEST); + // prepare the glow effect + _glowEffect.prepare(); + // Enable to show line from me to the voxel I am touching //renderLineToTouchedVoxel(); //renderThrustAtVoxel(_voxelThrust); @@ -3118,6 +3123,13 @@ void Application::displaySide(Camera& whichCamera) { _myAvatar.getHead().setLookAtPosition(_myCamera.getPosition()); } _myAvatar.render(_lookingInMirror->isChecked(), _renderAvatarBalls->isChecked()); + + _glowEffect.bind(); + _myAvatar.render(_lookingInMirror->isChecked(), _renderAvatarBalls->isChecked()); + _glowEffect.release(); + + _myAvatar.render(_lookingInMirror->isChecked(), _renderAvatarBalls->isChecked()); + _myAvatar.setDisplayingLookatVectors(_renderLookatOn->isChecked()); if (_renderLookatIndicatorOn->isChecked() && _isLookingAtOtherAvatar) { diff --git a/interface/src/Application.h b/interface/src/Application.h index 662604a3dd..f2c9c38e15 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -101,6 +101,7 @@ public: void updateParticleSystem(float deltaTime); + QGLWidget* getGLWidget() { return _glWidget; } Avatar* getAvatar() { return &_myAvatar; } Audio* getAudio() { return &_audio; } Camera* getCamera() { return &_myCamera; } diff --git a/interface/src/renderer/GlowEffect.cpp b/interface/src/renderer/GlowEffect.cpp index 56b3cb5233..82a9c43820 100644 --- a/interface/src/renderer/GlowEffect.cpp +++ b/interface/src/renderer/GlowEffect.cpp @@ -5,7 +5,101 @@ // Created by Andrzej Kapolka on 8/7/13. // Copyright (c) 2013 High Fidelity, Inc. All rights reserved. +#include + +#include "Application.h" #include "GlowEffect.h" +#include "InterfaceConfig.h" +#include "ProgramObject.h" + +static ProgramObject* createBlurProgram(const QString& direction) { + ProgramObject* program = new ProgramObject(); + program->addShaderFromSourceFile(QGLShader::Fragment, "resources/shaders/" + direction + "_blur.frag"); + program->link(); + + program->bind(); + program->setUniformValue("colorTexture", 0); + program->release(); + + return program; +} + +void GlowEffect::init() { + switchToResourcesParentIfRequired(); + _horizontalBlurProgram = createBlurProgram("horizontal"); + _verticalBlurProgram = createBlurProgram("vertical"); +} + +void GlowEffect::prepare() { + bind(); + glClear(GL_COLOR_BUFFER_BIT); + release(); +} + +void GlowEffect::bind() { + Application::getInstance()->getTextureCache()->getPrimaryFramebufferObject()->bind(); +} + +void GlowEffect::release() { + Application::getInstance()->getTextureCache()->getPrimaryFramebufferObject()->release(); +} + +static void renderFullscreenQuad() { + glBegin(GL_QUADS); + glTexCoord2f(0.0f, 0.0f); + glVertex2f(-1.0f, -1.0f); + glTexCoord2f(1.0f, 0.0f); + glVertex2f(1.0f, -1.0f); + glTexCoord2f(1.0f, 1.0f); + glVertex2f(1.0f, 1.0f); + glTexCoord2f(0.0f, 1.0f); + glVertex2f(-1.0f, 1.0f); + glEnd(); +} void GlowEffect::render() { + glEnable(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D, Application::getInstance()->getTextureCache()->getPrimaryFramebufferObject()->texture()); + glDisable(GL_LIGHTING); + + glPushMatrix(); + glLoadIdentity(); + + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadIdentity(); + + glDisable(GL_BLEND); + + // render the primary to the secondary with the horizontal blur + QOpenGLFramebufferObject* secondaryFBO = Application::getInstance()->getTextureCache()->getSecondaryFramebufferObject(); + secondaryFBO->bind(); + + _horizontalBlurProgram->bind(); + renderFullscreenQuad(); + _horizontalBlurProgram->release(); + + secondaryFBO->release(); + + // render the secondary to the screen with the vertical blur + glBindTexture(GL_TEXTURE_2D, secondaryFBO->texture()); + + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE); + + _verticalBlurProgram->bind(); + renderFullscreenQuad(); + _verticalBlurProgram->release(); + + glPopMatrix(); + + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); + + glBindTexture(GL_TEXTURE_2D, 0); + + glDisable(GL_TEXTURE_2D); + glEnable(GL_LIGHTING); + + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); } diff --git a/interface/src/renderer/GlowEffect.h b/interface/src/renderer/GlowEffect.h index 25dd1062be..ab07556fee 100644 --- a/interface/src/renderer/GlowEffect.h +++ b/interface/src/renderer/GlowEffect.h @@ -9,11 +9,24 @@ #ifndef __interface__GlowEffect__ #define __interface__GlowEffect__ +class ProgramObject; + class GlowEffect { public: + void init(); + void prepare(); + + void bind(); + void release(); + void render(); + +private: + + ProgramObject* _horizontalBlurProgram; + ProgramObject* _verticalBlurProgram; }; #endif /* defined(__interface__GlowEffect__) */ diff --git a/interface/src/renderer/TextureCache.cpp b/interface/src/renderer/TextureCache.cpp index 1c832a648e..98cfebcee0 100644 --- a/interface/src/renderer/TextureCache.cpp +++ b/interface/src/renderer/TextureCache.cpp @@ -5,17 +5,28 @@ // Created by Andrzej Kapolka on 8/6/13. // Copyright (c) 2013 High Fidelity, Inc. All rights reserved. +#include +#include + #include +#include "Application.h" #include "TextureCache.h" -TextureCache::TextureCache() : _permutationNormalTextureID(0) { +TextureCache::TextureCache() : _permutationNormalTextureID(0), + _primaryFramebufferObject(NULL), _secondaryFramebufferObject(NULL) { } TextureCache::~TextureCache() { if (_permutationNormalTextureID != 0) { glDeleteTextures(1, &_permutationNormalTextureID); } + if (_primaryFramebufferObject != NULL) { + delete _primaryFramebufferObject; + } + if (_secondaryFramebufferObject != NULL) { + delete _secondaryFramebufferObject; + } } GLuint TextureCache::getPermutationNormalTextureID() { @@ -43,3 +54,34 @@ GLuint TextureCache::getPermutationNormalTextureID() { } return _permutationNormalTextureID; } + +QOpenGLFramebufferObject* TextureCache::getPrimaryFramebufferObject() { + if (_primaryFramebufferObject == NULL) { + _primaryFramebufferObject = new QOpenGLFramebufferObject(Application::getInstance()->getGLWidget()->size()); + Application::getInstance()->getGLWidget()->installEventFilter(this); + } + return _primaryFramebufferObject; +} + +QOpenGLFramebufferObject* TextureCache::getSecondaryFramebufferObject() { + if (_secondaryFramebufferObject == NULL) { + _secondaryFramebufferObject = new QOpenGLFramebufferObject(Application::getInstance()->getGLWidget()->size()); + Application::getInstance()->getGLWidget()->installEventFilter(this); + } + return _secondaryFramebufferObject; +} + +bool TextureCache::eventFilter(QObject* watched, QEvent* event) { + if (event->type() == QEvent::Resize) { + QSize size = static_cast(event)->size(); + if (_primaryFramebufferObject != NULL && _primaryFramebufferObject->size() != size) { + delete _primaryFramebufferObject; + _primaryFramebufferObject = NULL; + } + if (_secondaryFramebufferObject != NULL && _secondaryFramebufferObject->size() != size) { + delete _secondaryFramebufferObject; + _secondaryFramebufferObject = NULL; + } + } + return false; +} diff --git a/interface/src/renderer/TextureCache.h b/interface/src/renderer/TextureCache.h index 9804f038ba..29920e1f1f 100644 --- a/interface/src/renderer/TextureCache.h +++ b/interface/src/renderer/TextureCache.h @@ -9,9 +9,13 @@ #ifndef __interface__TextureCache__ #define __interface__TextureCache__ +#include + #include "InterfaceConfig.h" -class TextureCache { +class QOpenGLFramebufferObject; + +class TextureCache : public QObject { public: TextureCache(); @@ -19,9 +23,17 @@ public: GLuint getPermutationNormalTextureID(); + QOpenGLFramebufferObject* getPrimaryFramebufferObject(); + QOpenGLFramebufferObject* getSecondaryFramebufferObject(); + + virtual bool eventFilter(QObject* watched, QEvent* event); + private: GLuint _permutationNormalTextureID; + + QOpenGLFramebufferObject* _primaryFramebufferObject; + QOpenGLFramebufferObject* _secondaryFramebufferObject; }; #endif /* defined(__interface__TextureCache__) */