History

Merge pull request #865 from ey6es/ssao

Basic screen space ambient occlusion effect. Defaults to off, because at the moment it slows things down substantially.

Stephen Birarda committed 13 years ago

Commit d0ab8312 parents 7ab0f18 dec4a4c14 files · +382 −17Browse files

Unified · Split

14 files
  1. interface/resources/shaders/ambient_occlusion.frag +66 −0
  2. interface/resources/shaders/ambient_occlusion.vert +14 −0
  3. interface/resources/shaders/occlusion_blur.frag +25 −0
  4. interface/src/Application.cpp +6 −0
  5. interface/src/Application.h +3 −1
  6. interface/src/Menu.cpp +1 −0
  7. interface/src/Menu.h +1 −0
  8. interface/src/renderer/AmbientOcclusionEffect.cpp +145 −0
  9. interface/src/renderer/AmbientOcclusionEffect.h +39 −0
  10. interface/src/renderer/GlowEffect.cpp +4 −14
  11. interface/src/renderer/RenderUtil.cpp +22 −0
  12. interface/src/renderer/RenderUtil.h +15 −0
  13. interface/src/renderer/TextureCache.cpp +25 −2
  14. interface/src/renderer/TextureCache.h +16 −0
interface/resources/shaders/ambient_occlusion.frag+66−0
@@ -0,0 +1,66 @@
1#version 120
2
3//
4// ambient_occlusion.frag
5// fragment shader
6//
7// Created by Andrzej Kapolka on 7/5/13.
8// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
9//
10
11// the depth texture
12uniform sampler2D depthTexture;
13
14// the random rotation texture
15uniform sampler2D rotationTexture;
16
17// the sample kernel containing the unit offset vectors
18const int SAMPLE_KERNEL_SIZE = 16;
19uniform vec3 sampleKernel[SAMPLE_KERNEL_SIZE];
20
21// the distance to the near clip plane
22uniform float near;
23
24// the distance to the far clip plane
25uniform float far;
26
27// the left and bottom edges of the view window
28uniform vec2 leftBottom;
29
30// the right and top edges of the view window
31uniform vec2 rightTop;
32
33// the radius of the effect
34uniform float radius;
35
36// the scale for the noise texture
37uniform vec2 noiseScale;
38
39// given a texture coordinate, returns the 3D view space z coordinate
40float texCoordToViewSpaceZ(vec2 texCoord) {
41 return (far * near) / (texture2D(depthTexture, texCoord).r * (far - near) - far);
42}
43
44// given a texture coordinate, returns the 3D view space coordinate
45vec3 texCoordToViewSpace(vec2 texCoord) {
46 float z = texCoordToViewSpaceZ(texCoord);
47 return vec3(((texCoord * 2.0 - vec2(1.0, 1.0)) * (rightTop - leftBottom) + rightTop + leftBottom) * z / (-2.0 * near), z);
48}
49
50void main(void) {
51 vec3 rotationX = texture2D(rotationTexture, gl_TexCoord[0].st * noiseScale).rgb;
52 vec3 rotationY = normalize(cross(rotationX, vec3(0.0, 0.0, 1.0)));
53 mat3 rotation = mat3(rotationX, rotationY, cross(rotationX, rotationY));
54
55 vec3 center = texCoordToViewSpace(gl_TexCoord[0].st);
56
57 float occlusion = 4.0;
58 for (int i = 0; i < SAMPLE_KERNEL_SIZE; i++) {
59 vec3 offset = center + rotation * (radius * sampleKernel[i]);
60 vec4 projected = gl_ProjectionMatrix * vec4(offset, 1.0);
61 float depth = texCoordToViewSpaceZ(projected.xy * 0.5 / projected.w + vec2(0.5, 0.5));
62 occlusion += 1.0 - step(offset.z, depth); // * step(abs(center.z - depth), radius);
63 }
64
65 gl_FragColor = vec4(occlusion, occlusion, occlusion, 0.0) / 16.0;
66}
interface/resources/shaders/ambient_occlusion.vert+14−0
@@ -0,0 +1,14 @@
1#version 120
2
3//
4// ambient_occlusion.vert
5// vertex shader
6//
7// Created by Andrzej Kapolka on 8/16/13.
8// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
9//
10
11void main(void) {
12 gl_TexCoord[0] = gl_MultiTexCoord0;
13 gl_Position = gl_Vertex;
14}
interface/resources/shaders/occlusion_blur.frag+25−0
@@ -0,0 +1,25 @@
1#version 120
2
3//
4// occlusion_blur.frag
5// fragment shader
6//
7// Created by Andrzej Kapolka on 8/16/13.
8// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
9//
10
11// the original texture
12uniform sampler2D originalTexture;
13
14void main(void) {
15 float ds = dFdx(gl_TexCoord[0].s);
16 float dt = dFdy(gl_TexCoord[0].t);
17 vec4 sum = vec4(0.0, 0.0, 0.0, 0.0);
18 for (int i = 0; i < 4; i++) {
19 for (int j = 0; j < 4; j++) {
20 sum += texture2D(originalTexture, gl_TexCoord[0].st +
21 vec2(ds, dt) * vec2(-2.0 + float(i), -2.0 + float(j)));
22 }
23 }
24 gl_FragColor = sum / 16.0;
25}
interface/src/Application.cpp+6−0
@@ -1449,6 +1449,7 @@ void Application::init() { · 1448 unmodified lines
1449 _environment.init();1449 _environment.init();
1450 1450
1451 _glowEffect.init();1451 _glowEffect.init();
1452 _ambientOcclusionEffect.init();
1452 1453
1453 _handControl.setScreenDimensions(_glWidget->width(), _glWidget->height());1454 _handControl.setScreenDimensions(_glWidget->width(), _glWidget->height());
1454 1455
@@ -2375,6 +2376,11 @@ void Application::displaySide(Camera& whichCamera) { · 920 unmodified lines
2375 renderWorldBox();2376 renderWorldBox();
2376 }2377 }
2377 2378
2379 // render the ambient occlusion effect if enabled
2380 if (Menu::getInstance()->isOptionChecked(MenuOption::AmbientOcclusion)) {
2381 _ambientOcclusionEffect.render();
2382 }
2383
2378 // brad's frustum for debugging2384 // brad's frustum for debugging
2379 if (Menu::getInstance()->isOptionChecked(MenuOption::DisplayFrustum)) {2385 if (Menu::getInstance()->isOptionChecked(MenuOption::DisplayFrustum)) {
2380 renderViewFrustum(_viewFrustum);2386 renderViewFrustum(_viewFrustum);
interface/src/Application.h+3−1
@@ -32,6 +32,7 @@ · 31 unmodified lines
32#include "Environment.h"32#include "Environment.h"
33#include "GLCanvas.h"33#include "GLCanvas.h"
34#include "PacketHeaders.h"34#include "PacketHeaders.h"
35#include "PieMenu.h"
35#include "SerialInterface.h"36#include "SerialInterface.h"
36#include "Stars.h"37#include "Stars.h"
37#include "Swatch.h"38#include "Swatch.h"
@@ -42,9 +43,9 @@ · 4 unmodified lines
42#include "VoxelPacketProcessor.h"43#include "VoxelPacketProcessor.h"
43#include "VoxelSystem.h"44#include "VoxelSystem.h"
44#include "Webcam.h"45#include "Webcam.h"
45#include "PieMenu.h"
46#include "avatar/Avatar.h"46#include "avatar/Avatar.h"
47#include "avatar/HandControl.h"47#include "avatar/HandControl.h"
48#include "renderer/AmbientOcclusionEffect.h"
48#include "renderer/GeometryCache.h"49#include "renderer/GeometryCache.h"
49#include "renderer/GlowEffect.h"50#include "renderer/GlowEffect.h"
50#include "renderer/TextureCache.h"51#include "renderer/TextureCache.h"
@@ -314,6 +315,7 @@ private: · 263 unmodified lines
314 TextureCache _textureCache;315 TextureCache _textureCache;
315 316
316 GlowEffect _glowEffect;317 GlowEffect _glowEffect;
318 AmbientOcclusionEffect _ambientOcclusionEffect;
317 319
318 #ifndef _WIN32320 #ifndef _WIN32
319 Audio _audio;321 Audio _audio;
interface/src/Menu.cpp+1−0
@@ -163,6 +163,7 @@ Menu::Menu() : · 162 unmodified lines
163 appInstance->getGlowEffect(),163 appInstance->getGlowEffect(),
164 SLOT(cycleRenderMode()));164 SLOT(cycleRenderMode()));
165 165
166 addCheckableActionToQMenuAndActionHash(renderMenu, MenuOption::AmbientOcclusion);
166 addCheckableActionToQMenuAndActionHash(renderMenu, MenuOption::FrameTimer);167 addCheckableActionToQMenuAndActionHash(renderMenu, MenuOption::FrameTimer);
167 addCheckableActionToQMenuAndActionHash(renderMenu, MenuOption::LookAtVectors);168 addCheckableActionToQMenuAndActionHash(renderMenu, MenuOption::LookAtVectors);
168 addCheckableActionToQMenuAndActionHash(renderMenu, MenuOption::LookAtIndicator, 0, true);169 addCheckableActionToQMenuAndActionHash(renderMenu, MenuOption::LookAtIndicator, 0, true);
interface/src/Menu.h+1−0
@@ -108,6 +108,7 @@ private: · 107 unmodified lines
108 108
109namespace MenuOption {109namespace MenuOption {
110 110
111 const QString AmbientOcclusion = "Ambient Occlusion";
111 const QString Avatars = "Avatars";112 const QString Avatars = "Avatars";
112 const QString AvatarAsBalls = "Avatar as Balls";113 const QString AvatarAsBalls = "Avatar as Balls";
113 const QString Atmosphere = "Atmosphere";114 const QString Atmosphere = "Atmosphere";
interface/src/renderer/AmbientOcclusionEffect.cpp+145−0
@@ -0,0 +1,145 @@
1//
2// AmbientOcclusionEffect.cpp
3// interface
4//
5// Created by Andrzej Kapolka on 7/14/13.
6// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
7//
8
9// include this before QOpenGLFramebufferObject, which includes an earlier version of OpenGL
10#include "InterfaceConfig.h"
11
12#include <QOpenGLFramebufferObject>
13
14#include <glm/gtc/random.hpp>
15
16#include <SharedUtil.h>
17
18#include "AmbientOcclusionEffect.h"
19#include "Application.h"
20#include "InterfaceConfig.h"
21#include "ProgramObject.h"
22#include "RenderUtil.h"
23
24const int ROTATION_WIDTH = 4;
25const int ROTATION_HEIGHT = 4;
26
27void AmbientOcclusionEffect::init() {
28 switchToResourcesParentIfRequired();
29
30 _occlusionProgram = new ProgramObject();
31 _occlusionProgram->addShaderFromSourceFile(QGLShader::Vertex, "resources/shaders/ambient_occlusion.vert");
32 _occlusionProgram->addShaderFromSourceFile(QGLShader::Fragment, "resources/shaders/ambient_occlusion.frag");
33 _occlusionProgram->link();
34
35 _blurProgram = new ProgramObject();
36 _blurProgram->addShaderFromSourceFile(QGLShader::Vertex, "resources/shaders/ambient_occlusion.vert");
37 _blurProgram->addShaderFromSourceFile(QGLShader::Fragment, "resources/shaders/occlusion_blur.frag");
38 _blurProgram->link();
39
40 _blurProgram->bind();
41 _blurProgram->setUniformValue("originalTexture", 0);
42 _blurProgram->release();
43
44 // create the sample kernel: an array of spherically distributed offset vectors
45 const int SAMPLE_KERNEL_SIZE = 16;
46 QVector3D sampleKernel[SAMPLE_KERNEL_SIZE];
47 for (int i = 0; i < SAMPLE_KERNEL_SIZE; i++) {
48 // square the length in order to increase density towards the center
49 glm::vec3 vector = glm::sphericalRand(1.0f);
50 float scale = randFloat();
51 const float MIN_VECTOR_LENGTH = 0.01f;
52 const float MAX_VECTOR_LENGTH = 1.0f;
53 vector *= glm::mix(MIN_VECTOR_LENGTH, MAX_VECTOR_LENGTH, scale * scale);
54 sampleKernel[i] = QVector3D(vector.x, vector.y, vector.z);
55 }
56
57 _occlusionProgram->bind();
58 _occlusionProgram->setUniformValue("depthTexture", 0);
59 _occlusionProgram->setUniformValue("rotationTexture", 1);
60 _occlusionProgram->setUniformValueArray("sampleKernel", sampleKernel, SAMPLE_KERNEL_SIZE);
61 _occlusionProgram->setUniformValue("radius", 0.1f);
62 _occlusionProgram->release();
63
64 _nearLocation = _occlusionProgram->uniformLocation("near");
65 _farLocation = _occlusionProgram->uniformLocation("far");
66 _leftBottomLocation = _occlusionProgram->uniformLocation("leftBottom");
67 _rightTopLocation = _occlusionProgram->uniformLocation("rightTop");
68 _noiseScaleLocation = _occlusionProgram->uniformLocation("noiseScale");
69
70 // generate the random rotation texture
71 glGenTextures(1, &_rotationTextureID);
72 glBindTexture(GL_TEXTURE_2D, _rotationTextureID);
73 const int ELEMENTS_PER_PIXEL = 3;
74 unsigned char rotationData[ROTATION_WIDTH * ROTATION_HEIGHT * ELEMENTS_PER_PIXEL];
75 unsigned char* rotation = rotationData;
76 for (int i = 0; i < ROTATION_WIDTH * ROTATION_HEIGHT; i++) {
77 glm::vec3 randvec = glm::sphericalRand(1.0f);
78 *rotation++ = ((randvec.x + 1.0f) / 2.0f) * 255.0f;
79 *rotation++ = ((randvec.y + 1.0f) / 2.0f) * 255.0f;
80 *rotation++ = ((randvec.z + 1.0f) / 2.0f) * 255.0f;
81 }
82 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, ROTATION_WIDTH, ROTATION_HEIGHT, 0, GL_RGB, GL_UNSIGNED_BYTE, rotationData);
83 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
84 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
85 glBindTexture(GL_TEXTURE_2D, 0);
86}
87
88void AmbientOcclusionEffect::render() {
89 glDisable(GL_BLEND);
90 glDisable(GL_DEPTH_TEST);
91 glDepthMask(GL_FALSE);
92
93 glBindTexture(GL_TEXTURE_2D, Application::getInstance()->getTextureCache()->getPrimaryDepthTextureID());
94
95 glActiveTexture(GL_TEXTURE1);
96 glBindTexture(GL_TEXTURE_2D, _rotationTextureID);
97
98 // render with the occlusion shader to the secondary buffer
99 QOpenGLFramebufferObject* secondaryFBO = Application::getInstance()->getTextureCache()->getSecondaryFramebufferObject();
100 secondaryFBO->bind();
101
102 float left, right, bottom, top, nearVal, farVal;
103 glm::vec4 nearClipPlane, farClipPlane;
104 Application::getInstance()->getViewFrustum()->computeOffAxisFrustum(
105 left, right, bottom, top, nearVal, farVal, nearClipPlane, farClipPlane);
106
107 _occlusionProgram->bind();
108 _occlusionProgram->setUniformValue(_nearLocation, nearVal);
109 _occlusionProgram->setUniformValue(_farLocation, farVal);
110 _occlusionProgram->setUniformValue(_leftBottomLocation, left, bottom);
111 _occlusionProgram->setUniformValue(_rightTopLocation, right, top);
112 QSize size = Application::getInstance()->getGLWidget()->size();
113 _occlusionProgram->setUniformValue(_noiseScaleLocation, size.width() / (float)ROTATION_WIDTH,
114 size.height() / (float)ROTATION_HEIGHT);
115
116 renderFullscreenQuad();
117
118 _occlusionProgram->release();
119
120 secondaryFBO->release();
121
122 glBindTexture(GL_TEXTURE_2D, 0);
123 glActiveTexture(GL_TEXTURE0);
124
125 // now render secondary to primary with 4x4 blur
126 Application::getInstance()->getTextureCache()->getPrimaryFramebufferObject()->bind();
127
128 glEnable(GL_BLEND);
129 glBlendFuncSeparate(GL_ZERO, GL_SRC_COLOR, GL_ZERO, GL_ONE);
130
131 glBindTexture(GL_TEXTURE_2D, secondaryFBO->texture());
132
133 _blurProgram->bind();
134
135 renderFullscreenQuad();
136
137 _blurProgram->release();
138
139 glBindTexture(GL_TEXTURE_2D, 0);
140
141 //glEnable(GL_BLEND);
142 glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_CONSTANT_ALPHA, GL_ONE);
143 glEnable(GL_DEPTH_TEST);
144 glDepthMask(GL_TRUE);
145}
interface/src/renderer/AmbientOcclusionEffect.h+39−0
@@ -0,0 +1,39 @@
1//
2// AmbientOcclusionEffect.h
3// interface
4//
5// Created by Andrzej Kapolka on 7/14/13.
6// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
7//
8
9#ifndef __interface__AmbientOcclusionEffect__
10#define __interface__AmbientOcclusionEffect__
11
12#include "InterfaceConfig.h"
13
14class ProgramObject;
15
16/// A screen space ambient occlusion effect. See John Chapman's tutorial at
17/// http://john-chapman-graphics.blogspot.co.uk/2013/01/ssao-tutorial.html for reference.
18class AmbientOcclusionEffect {
19public:
20
21 void init();
22
23 void render();
24
25private:
26
27 ProgramObject* _occlusionProgram;
28 int _nearLocation;
29 int _farLocation;
30 int _leftBottomLocation;
31 int _rightTopLocation;
32 int _noiseScaleLocation;
33
34 ProgramObject* _blurProgram;
35
36 GLuint _rotationTextureID;
37};
38
39#endif /* defined(__interface__AmbientOcclusionEffect__) */
interface/src/renderer/GlowEffect.cpp+4−14
@@ -5,7 +5,7 @@ · 4 unmodified lines
5// Created by Andrzej Kapolka on 8/7/13.5// Created by Andrzej Kapolka on 8/7/13.
6// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.6// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
7 7
8// include this before QGLWidget, which includes an earlier version of OpenGL8// include this before QOpenGLFramebufferObject, which includes an earlier version of OpenGL
9#include "InterfaceConfig.h"9#include "InterfaceConfig.h"
10 10
11#include <QOpenGLFramebufferObject>11#include <QOpenGLFramebufferObject>
@@ -13,6 +13,7 @@ · 1 unmodified line
13#include "Application.h"13#include "Application.h"
14#include "GlowEffect.h"14#include "GlowEffect.h"
15#include "ProgramObject.h"15#include "ProgramObject.h"
16#include "RenderUtil.h"
16 17
17GlowEffect::GlowEffect() : _renderMode(BLUR_ADD_MODE) {18GlowEffect::GlowEffect() : _renderMode(BLUR_ADD_MODE) {
18}19}
@@ -68,19 +69,6 @@ void GlowEffect::end() { · 49 unmodified lines
68 glBlendColor(0.0f, 0.0f, 0.0f, 0.0f);69 glBlendColor(0.0f, 0.0f, 0.0f, 0.0f);
69}70}
70 71
71static void renderFullscreenQuad() {
72 glBegin(GL_QUADS);
73 glTexCoord2f(0.0f, 0.0f);
74 glVertex2f(-1.0f, -1.0f);
75 glTexCoord2f(1.0f, 0.0f);
76 glVertex2f(1.0f, -1.0f);
77 glTexCoord2f(1.0f, 1.0f);
78 glVertex2f(1.0f, 1.0f);
79 glTexCoord2f(0.0f, 1.0f);
80 glVertex2f(-1.0f, 1.0f);
81 glEnd();
82}
83
84void GlowEffect::render() {72void GlowEffect::render() {
85 QOpenGLFramebufferObject* primaryFBO = Application::getInstance()->getTextureCache()->getPrimaryFramebufferObject();73 QOpenGLFramebufferObject* primaryFBO = Application::getInstance()->getTextureCache()->getPrimaryFramebufferObject();
86 primaryFBO->release();74 primaryFBO->release();
@@ -95,6 +83,7 @@ void GlowEffect::render() { · 8 unmodified lines
95 83
96 glDisable(GL_BLEND);84 glDisable(GL_BLEND);
97 glDisable(GL_DEPTH_TEST);85 glDisable(GL_DEPTH_TEST);
86 glDepthMask(GL_FALSE);
98 87
99 if (_isEmpty) {88 if (_isEmpty) {
100 // copy the primary to the screen89 // copy the primary to the screen
@@ -210,6 +199,7 @@ void GlowEffect::render() { · 109 unmodified lines
210 199
211 glEnable(GL_BLEND);200 glEnable(GL_BLEND);
212 glEnable(GL_DEPTH_TEST);201 glEnable(GL_DEPTH_TEST);
202 glDepthMask(GL_TRUE);
213 glBindTexture(GL_TEXTURE_2D, 0);203 glBindTexture(GL_TEXTURE_2D, 0);
214}204}
215 205
interface/src/renderer/RenderUtil.cpp+22−0
@@ -0,0 +1,22 @@
1//
2// RenderUtil.cpp
3// interface
4//
5// Created by Andrzej Kapolka on 8/15/13.
6// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
7
8#include "InterfaceConfig.h"
9#include "RenderUtil.h"
10
11void renderFullscreenQuad() {
12 glBegin(GL_QUADS);
13 glTexCoord2f(0.0f, 0.0f);
14 glVertex2f(-1.0f, -1.0f);
15 glTexCoord2f(1.0f, 0.0f);
16 glVertex2f(1.0f, -1.0f);
17 glTexCoord2f(1.0f, 1.0f);
18 glVertex2f(1.0f, 1.0f);
19 glTexCoord2f(0.0f, 1.0f);
20 glVertex2f(-1.0f, 1.0f);
21 glEnd();
22}
interface/src/renderer/RenderUtil.h+15−0
@@ -0,0 +1,15 @@
1//
2// RenderUtil.h
3// interface
4//
5// Created by Andrzej Kapolka on 8/15/13.
6// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
7//
8
9#ifndef __interface__RenderUtil__
10#define __interface__RenderUtil__
11
12/// Renders a quad from (-1, -1, 0) to (1, 1, 0) with texture coordinates from (0, 0) to (1, 1).
13void renderFullscreenQuad();
14
15#endif /* defined(__interface__RenderUtil__) */
interface/src/renderer/TextureCache.cpp+25−2
@@ -5,6 +5,9 @@ · 4 unmodified lines
5// Created by Andrzej Kapolka on 8/6/13.5// Created by Andrzej Kapolka on 8/6/13.
6// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.6// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
7 7
8// include this before QGLWidget, which includes an earlier version of OpenGL
9#include "InterfaceConfig.h"
10
8#include <QGLWidget>11#include <QGLWidget>
9#include <QOpenGLFramebufferObject>12#include <QOpenGLFramebufferObject>
10 13
@@ -23,6 +26,7 @@ TextureCache::~TextureCache() { · 12 unmodified lines
23 }26 }
24 if (_primaryFramebufferObject != NULL) {27 if (_primaryFramebufferObject != NULL) {
25 delete _primaryFramebufferObject;28 delete _primaryFramebufferObject;
29 glDeleteTextures(1, &_primaryDepthTextureID);
26 }30 }
27 if (_secondaryFramebufferObject != NULL) {31 if (_secondaryFramebufferObject != NULL) {
28 delete _secondaryFramebufferObject;32 delete _secondaryFramebufferObject;
@@ -60,13 +64,31 @@ GLuint TextureCache::getPermutationNormalTextureID() { · 31 unmodified lines
60 64
61QOpenGLFramebufferObject* TextureCache::getPrimaryFramebufferObject() {65QOpenGLFramebufferObject* TextureCache::getPrimaryFramebufferObject() {
62 if (_primaryFramebufferObject == NULL) {66 if (_primaryFramebufferObject == NULL) {
63 _primaryFramebufferObject = new QOpenGLFramebufferObject(Application::getInstance()->getGLWidget()->size(),67 QSize size = Application::getInstance()->getGLWidget()->size();
64 QOpenGLFramebufferObject::Depth);68 _primaryFramebufferObject = new QOpenGLFramebufferObject(size);
65 Application::getInstance()->getGLWidget()->installEventFilter(this);69 Application::getInstance()->getGLWidget()->installEventFilter(this);
70
71 glGenTextures(1, &_primaryDepthTextureID);
72 glBindTexture(GL_TEXTURE_2D, _primaryDepthTextureID);
73 glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, size.width(), size.height(),
74 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, 0);
75 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
76 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
77 glBindTexture(GL_TEXTURE_2D, 0);
78
79 _primaryFramebufferObject->bind();
80 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, _primaryDepthTextureID, 0);
81 _primaryFramebufferObject->release();
66 }82 }
67 return _primaryFramebufferObject;83 return _primaryFramebufferObject;
68}84}
69 85
86GLuint TextureCache::getPrimaryDepthTextureID() {
87 // ensure that the primary framebuffer object is initialized before returning the depth texture id
88 getPrimaryFramebufferObject();
89 return _primaryDepthTextureID;
90}
91
70QOpenGLFramebufferObject* TextureCache::getSecondaryFramebufferObject() {92QOpenGLFramebufferObject* TextureCache::getSecondaryFramebufferObject() {
71 if (_secondaryFramebufferObject == NULL) {93 if (_secondaryFramebufferObject == NULL) {
72 _secondaryFramebufferObject = new QOpenGLFramebufferObject(Application::getInstance()->getGLWidget()->size());94 _secondaryFramebufferObject = new QOpenGLFramebufferObject(Application::getInstance()->getGLWidget()->size());
@@ -89,6 +111,7 @@ bool TextureCache::eventFilter(QObject* watched, QEvent* event) { · 16 unmodified lines
89 if (_primaryFramebufferObject != NULL && _primaryFramebufferObject->size() != size) {111 if (_primaryFramebufferObject != NULL && _primaryFramebufferObject->size() != size) {
90 delete _primaryFramebufferObject;112 delete _primaryFramebufferObject;
91 _primaryFramebufferObject = NULL;113 _primaryFramebufferObject = NULL;
114 glDeleteTextures(1, &_primaryDepthTextureID);
92 }115 }
93 if (_secondaryFramebufferObject != NULL && _secondaryFramebufferObject->size() != size) {116 if (_secondaryFramebufferObject != NULL && _secondaryFramebufferObject->size() != size) {
94 delete _secondaryFramebufferObject;117 delete _secondaryFramebufferObject;
interface/src/renderer/TextureCache.h+16−0
@@ -15,16 +15,31 @@ · 14 unmodified lines
15 15
16class QOpenGLFramebufferObject;16class QOpenGLFramebufferObject;
17 17
18/// Stored cached textures, including render-to-texture targets.
18class TextureCache : public QObject {19class TextureCache : public QObject {
19public:20public:
20 21
21 TextureCache();22 TextureCache();
22 ~TextureCache();23 ~TextureCache();
23 24
25 /// Returns the ID of the permutation/normal texture used for Perlin noise shader programs. This texture
26 /// has two lines: the first, a set of random numbers in [0, 255] to be used as permutation offsets, and
27 /// the second, a set of random unit vectors to be used as noise gradients.
24 GLuint getPermutationNormalTextureID();28 GLuint getPermutationNormalTextureID();
25 29
30 /// Returns a pointer to the primary framebuffer object. This render target includes a depth component, and is
31 /// used for scene rendering.
26 QOpenGLFramebufferObject* getPrimaryFramebufferObject();32 QOpenGLFramebufferObject* getPrimaryFramebufferObject();
33
34 /// Returns the ID of the primary framebuffer object's depth texture. This contains the Z buffer used in rendering.
35 GLuint getPrimaryDepthTextureID();
36
37 /// Returns a pointer to the secondary framebuffer object, used as an additional render target when performing full
38 /// screen effects.
27 QOpenGLFramebufferObject* getSecondaryFramebufferObject();39 QOpenGLFramebufferObject* getSecondaryFramebufferObject();
40
41 /// Returns a pointer to the tertiary framebuffer object, used as an additional render target when performing full
42 /// screen effects.
28 QOpenGLFramebufferObject* getTertiaryFramebufferObject();43 QOpenGLFramebufferObject* getTertiaryFramebufferObject();
29 44
30 virtual bool eventFilter(QObject* watched, QEvent* event);45 virtual bool eventFilter(QObject* watched, QEvent* event);
@@ -34,6 +49,7 @@ private: · 3 unmodified lines
34 GLuint _permutationNormalTextureID;49 GLuint _permutationNormalTextureID;
35 50
36 QOpenGLFramebufferObject* _primaryFramebufferObject;51 QOpenGLFramebufferObject* _primaryFramebufferObject;
52 GLuint _primaryDepthTextureID;
37 QOpenGLFramebufferObject* _secondaryFramebufferObject;53 QOpenGLFramebufferObject* _secondaryFramebufferObject;
38 QOpenGLFramebufferObject* _tertiaryFramebufferObject;54 QOpenGLFramebufferObject* _tertiaryFramebufferObject;
39};55};