Beginnings of ambient occlusion. Looks like an architectural drawing.

This commit is contained in:
Andrzej Kapolka 2013-08-15 17:52:31 -07:00
parent cceeb1c6ff
commit 3ddab484e0
9 changed files with 160 additions and 19 deletions

View file

@ -30,6 +30,13 @@ vec3 texCoordToViewSpace(vec2 texCoord) {
}
void main(void) {
float depth = texture2D(depthTexture, gl_TexCoord[0].st).r;
gl_FragColor = vec4(depth, depth, depth, 1.0);
float ds = dFdx(gl_TexCoord[0].s);
float dt = dFdy(gl_TexCoord[0].t);
vec3 center = texCoordToViewSpace(gl_TexCoord[0].st);
vec3 left = texCoordToViewSpace(gl_TexCoord[0].st - vec2(-ds, 0.0)) - center;
vec3 right = texCoordToViewSpace(gl_TexCoord[0].st - vec2(ds, 0.0)) - center;
vec3 up = texCoordToViewSpace(gl_TexCoord[0].st - vec2(0.0, dt)) - center;
vec3 down = texCoordToViewSpace(gl_TexCoord[0].st - vec2(0.0, -dt)) - center;
float occlusion = 0.5 - (left.z / length(left) + right.z / length(right) + up.z / length(up) + down.z / length(down)) / 8.0;
gl_FragColor = vec4(occlusion, occlusion, occlusion, 0.0);
}

View file

@ -2121,6 +2121,7 @@ void Application::init() {
_environment.init();
_glowEffect.init();
_ambientOcclusionEffect.init();
_handControl.setScreenDimensions(_glWidget->width(), _glWidget->height());

View file

@ -9,8 +9,66 @@
#include <SharedUtil.h>
#include "AmbientOcclusionEffect.h"
#include "Application.h"
#include "InterfaceConfig.h"
#include "ProgramObject.h"
#include "RenderUtil.h"
void AmbientOcclusionEffect::init() {
switchToResourcesParentIfRequired();
_program = new ProgramObject();
_program->addShaderFromSourceFile(QGLShader::Fragment, "resources/shaders/ambient_occlusion.frag");
_program->link();
_nearLocation = _program->uniformLocation("near");
_farLocation = _program->uniformLocation("far");
_leftBottomLocation = _program->uniformLocation("leftBottom");
_rightTopLocation = _program->uniformLocation("rightTop");
_program->bind();
_program->setUniformValue("depthTexture", 0);
_program->release();
}
void AmbientOcclusionEffect::render() {
glPushMatrix();
glLoadIdentity();
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
glDisable(GL_BLEND);
//glBlendFuncSeparate(GL_ZERO, GL_SRC_COLOR, GL_ZERO, GL_ONE);
glDisable(GL_DEPTH_TEST);
glDepthMask(GL_FALSE);
glBindTexture(GL_TEXTURE_2D, Application::getInstance()->getTextureCache()->getPrimaryDepthTextureID());
float left, right, bottom, top, nearVal, farVal;
glm::vec4 nearClipPlane, farClipPlane;
Application::getInstance()->getViewFrustum()->computeOffAxisFrustum(
left, right, bottom, top, nearVal, farVal, nearClipPlane, farClipPlane);
_program->bind();
_program->setUniformValue(_nearLocation, nearVal);
_program->setUniformValue(_farLocation, farVal);
_program->setUniformValue(_leftBottomLocation, left, bottom);
_program->setUniformValue(_rightTopLocation, right, top);
renderFullscreenQuad();
_program->release();
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
glEnable(GL_BLEND);
//glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_CONSTANT_ALPHA, GL_ONE);
glEnable(GL_DEPTH_TEST);
glDepthMask(GL_TRUE);
glBindTexture(GL_TEXTURE_2D, 0);
}

View file

@ -9,14 +9,23 @@
#ifndef __interface__AmbientOcclusionEffect__
#define __interface__AmbientOcclusionEffect__
#include "InterfaceConfig.h"
class ProgramObject;
/// A screen space ambient occlusion effect.
class AmbientOcclusionEffect {
public:
void init();
void render();
private:
ProgramObject* _program;
int _nearLocation;
int _farLocation;
int _leftBottomLocation;
int _rightTopLocation;
};
#endif /* defined(__interface__AmbientOcclusionEffect__) */

View file

@ -13,6 +13,7 @@
#include "Application.h"
#include "GlowEffect.h"
#include "ProgramObject.h"
#include "RenderUtil.h"
GlowEffect::GlowEffect() : _renderMode(BLUR_ADD_MODE) {
}
@ -68,19 +69,6 @@ void GlowEffect::end() {
glBlendColor(0.0f, 0.0f, 0.0f, 0.0f);
}
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() {
QOpenGLFramebufferObject* primaryFBO = Application::getInstance()->getTextureCache()->getPrimaryFramebufferObject();
primaryFBO->release();
@ -95,6 +83,7 @@ void GlowEffect::render() {
glDisable(GL_BLEND);
glDisable(GL_DEPTH_TEST);
glDepthMask(GL_FALSE);
if (_isEmpty) {
// copy the primary to the screen
@ -210,6 +199,7 @@ void GlowEffect::render() {
glEnable(GL_BLEND);
glEnable(GL_DEPTH_TEST);
glDepthMask(GL_TRUE);
glBindTexture(GL_TEXTURE_2D, 0);
}

View file

@ -0,0 +1,22 @@
//
// RenderUtil.cpp
// interface
//
// Created by Andrzej Kapolka on 8/15/13.
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
#include "InterfaceConfig.h"
#include "RenderUtil.h"
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();
}

View file

@ -0,0 +1,15 @@
//
// RenderUtil.h
// interface
//
// Created by Andrzej Kapolka on 8/15/13.
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
//
#ifndef __interface__RenderUtil__
#define __interface__RenderUtil__
/// Renders a quad from (-1, -1, 0) to (1, 1, 0) with texture coordinates from (0, 0) to (1, 1).
void renderFullscreenQuad();
#endif /* defined(__interface__RenderUtil__) */

View file

@ -5,6 +5,9 @@
// Created by Andrzej Kapolka on 8/6/13.
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
// include this before QGLWidget, which includes an earlier version of OpenGL
#include "InterfaceConfig.h"
#include <QGLWidget>
#include <QOpenGLFramebufferObject>
@ -23,6 +26,7 @@ TextureCache::~TextureCache() {
}
if (_primaryFramebufferObject != NULL) {
delete _primaryFramebufferObject;
glDeleteTextures(1, &_primaryDepthTextureID);
}
if (_secondaryFramebufferObject != NULL) {
delete _secondaryFramebufferObject;
@ -60,13 +64,31 @@ GLuint TextureCache::getPermutationNormalTextureID() {
QOpenGLFramebufferObject* TextureCache::getPrimaryFramebufferObject() {
if (_primaryFramebufferObject == NULL) {
_primaryFramebufferObject = new QOpenGLFramebufferObject(Application::getInstance()->getGLWidget()->size(),
QOpenGLFramebufferObject::Depth);
QSize size = Application::getInstance()->getGLWidget()->size();
_primaryFramebufferObject = new QOpenGLFramebufferObject(size);
Application::getInstance()->getGLWidget()->installEventFilter(this);
glGenTextures(1, &_primaryDepthTextureID);
glBindTexture(GL_TEXTURE_2D, _primaryDepthTextureID);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, size.width(), size.height(),
0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glBindTexture(GL_TEXTURE_2D, 0);
_primaryFramebufferObject->bind();
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, _primaryDepthTextureID, 0);
_primaryFramebufferObject->release();
}
return _primaryFramebufferObject;
}
GLuint TextureCache::getPrimaryDepthTextureID() {
// ensure that the primary framebuffer object is initialized before returning the depth texture id
getPrimaryFramebufferObject();
return _primaryDepthTextureID;
}
QOpenGLFramebufferObject* TextureCache::getSecondaryFramebufferObject() {
if (_secondaryFramebufferObject == NULL) {
_secondaryFramebufferObject = new QOpenGLFramebufferObject(Application::getInstance()->getGLWidget()->size());
@ -89,6 +111,7 @@ bool TextureCache::eventFilter(QObject* watched, QEvent* event) {
if (_primaryFramebufferObject != NULL && _primaryFramebufferObject->size() != size) {
delete _primaryFramebufferObject;
_primaryFramebufferObject = NULL;
glDeleteTextures(1, &_primaryDepthTextureID);
}
if (_secondaryFramebufferObject != NULL && _secondaryFramebufferObject->size() != size) {
delete _secondaryFramebufferObject;

View file

@ -15,16 +15,31 @@
class QOpenGLFramebufferObject;
/// Stored cached textures, including render-to-texture targets.
class TextureCache : public QObject {
public:
TextureCache();
~TextureCache();
/// Returns the ID of the permutation/normal texture used for Perlin noise shader programs. This texture
/// has two lines: the first, a set of random numbers in [0, 255] to be used as permutation offsets, and
/// the second, a set of random unit vectors to be used as noise gradients.
GLuint getPermutationNormalTextureID();
/// Returns a pointer to the primary framebuffer object. This render target includes a depth component, and is
/// used for scene rendering.
QOpenGLFramebufferObject* getPrimaryFramebufferObject();
/// Returns the ID of the primary framebuffer object's depth texture. This contains the Z buffer used in rendering.
GLuint getPrimaryDepthTextureID();
/// Returns a pointer to the secondary framebuffer object, used as an additional render target when performing full
/// screen effects.
QOpenGLFramebufferObject* getSecondaryFramebufferObject();
/// Returns a pointer to the tertiary framebuffer object, used as an additional render target when performing full
/// screen effects.
QOpenGLFramebufferObject* getTertiaryFramebufferObject();
virtual bool eventFilter(QObject* watched, QEvent* event);
@ -34,6 +49,7 @@ private:
GLuint _permutationNormalTextureID;
QOpenGLFramebufferObject* _primaryFramebufferObject;
GLuint _primaryDepthTextureID;
QOpenGLFramebufferObject* _secondaryFramebufferObject;
QOpenGLFramebufferObject* _tertiaryFramebufferObject;
};