Basic glow effect.

This commit is contained in:
Andrzej Kapolka 2013-08-08 16:55:45 -07:00
parent 5bca763c14
commit 1828a105d4
8 changed files with 240 additions and 2 deletions

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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) {

View file

@ -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; }

View file

@ -5,7 +5,101 @@
// Created by Andrzej Kapolka on 8/7/13.
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
#include <QOpenGLFramebufferObject>
#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);
}

View file

@ -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__) */

View file

@ -5,17 +5,28 @@
// Created by Andrzej Kapolka on 8/6/13.
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
#include <QGLWidget>
#include <QOpenGLFramebufferObject>
#include <glm/gtc/random.hpp>
#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<QResizeEvent*>(event)->size();
if (_primaryFramebufferObject != NULL && _primaryFramebufferObject->size() != size) {
delete _primaryFramebufferObject;
_primaryFramebufferObject = NULL;
}
if (_secondaryFramebufferObject != NULL && _secondaryFramebufferObject->size() != size) {
delete _secondaryFramebufferObject;
_secondaryFramebufferObject = NULL;
}
}
return false;
}

View file

@ -9,9 +9,13 @@
#ifndef __interface__TextureCache__
#define __interface__TextureCache__
#include <QObject>
#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__) */