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
12+uniform sampler2D depthTexture;
13+
14+// the random rotation texture
15+uniform sampler2D rotationTexture;
16+
17+// the sample kernel containing the unit offset vectors
18+const int SAMPLE_KERNEL_SIZE = 16;
19+uniform vec3 sampleKernel[SAMPLE_KERNEL_SIZE];
20+
21+// the distance to the near clip plane
22+uniform float near;
23+
24+// the distance to the far clip plane
25+uniform float far;
26+
27+// the left and bottom edges of the view window
28+uniform vec2 leftBottom;
29+
30+// the right and top edges of the view window
31+uniform vec2 rightTop;
32+
33+// the radius of the effect
34+uniform float radius;
35+
36+// the scale for the noise texture
37+uniform vec2 noiseScale;
38+
39+// given a texture coordinate, returns the 3D view space z coordinate
40+float 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
45+vec3 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+
50+void 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+
11+void 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
12+uniform sampler2D originalTexture;
13+
14+void 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
14491449 _environment.init();
14501450
14511451 _glowEffect.init();
1452+ _ambientOcclusionEffect.init();
14521453
14531454 _handControl.setScreenDimensions(_glWidget->width(), _glWidget->height());
14541455
@@ -2375,6 +2376,11 @@ void Application::displaySide(Camera& whichCamera) { · 920 unmodified lines
23752376 renderWorldBox();
23762377 }
23772378
2379+ // render the ambient occlusion effect if enabled
2380+ if (Menu::getInstance()->isOptionChecked(MenuOption::AmbientOcclusion)) {
2381+ _ambientOcclusionEffect.render();
2382+ }
2383+
23782384 // brad's frustum for debugging
23792385 if (Menu::getInstance()->isOptionChecked(MenuOption::DisplayFrustum)) {
23802386 renderViewFrustum(_viewFrustum);
interface/src/Application.h+3−1
@@ -32,6 +32,7 @@ · 31 unmodified lines
3232 #include "Environment.h"
3333 #include "GLCanvas.h"
3434 #include "PacketHeaders.h"
35+#include "PieMenu.h"
3536 #include "SerialInterface.h"
3637 #include "Stars.h"
3738 #include "Swatch.h"
@@ -42,9 +43,9 @@ · 4 unmodified lines
4243 #include "VoxelPacketProcessor.h"
4344 #include "VoxelSystem.h"
4445 #include "Webcam.h"
45−#include "PieMenu.h"
4646 #include "avatar/Avatar.h"
4747 #include "avatar/HandControl.h"
48+#include "renderer/AmbientOcclusionEffect.h"
4849 #include "renderer/GeometryCache.h"
4950 #include "renderer/GlowEffect.h"
5051 #include "renderer/TextureCache.h"
@@ -314,6 +315,7 @@ private: · 263 unmodified lines
314315 TextureCache _textureCache;
315316
316317 GlowEffect _glowEffect;
318+ AmbientOcclusionEffect _ambientOcclusionEffect;
317319
318320 #ifndef _WIN32
319321 Audio _audio;
interface/src/Menu.cpp+1−0
@@ -163,6 +163,7 @@ Menu::Menu() : · 162 unmodified lines
163163 appInstance->getGlowEffect(),
164164 SLOT(cycleRenderMode()));
165165
166+ addCheckableActionToQMenuAndActionHash(renderMenu, MenuOption::AmbientOcclusion);
166167 addCheckableActionToQMenuAndActionHash(renderMenu, MenuOption::FrameTimer);
167168 addCheckableActionToQMenuAndActionHash(renderMenu, MenuOption::LookAtVectors);
168169 addCheckableActionToQMenuAndActionHash(renderMenu, MenuOption::LookAtIndicator, 0, true);
interface/src/Menu.h+1−0
@@ -108,6 +108,7 @@ private: · 107 unmodified lines
108108
109109 namespace MenuOption {
110110
111+ const QString AmbientOcclusion = "Ambient Occlusion";
111112 const QString Avatars = "Avatars";
112113 const QString AvatarAsBalls = "Avatar as Balls";
113114 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+
24+const int ROTATION_WIDTH = 4;
25+const int ROTATION_HEIGHT = 4;
26+
27+void 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+
88+void 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+
14+class 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.
18+class AmbientOcclusionEffect {
19+public:
20+
21+ void init();
22+
23+ void render();
24+
25+private:
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
55 // Created by Andrzej Kapolka on 8/7/13.
66 // Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
77
8−// include this before QGLWidget, which includes an earlier version of OpenGL
8+// include this before QOpenGLFramebufferObject, which includes an earlier version of OpenGL
99 #include "InterfaceConfig.h"
1010
1111 #include <QOpenGLFramebufferObject>
@@ -13,6 +13,7 @@ · 1 unmodified line
1313 #include "Application.h"
1414 #include "GlowEffect.h"
1515 #include "ProgramObject.h"
16+#include "RenderUtil.h"
1617
1718 GlowEffect::GlowEffect() : _renderMode(BLUR_ADD_MODE) {
1819 }
@@ -68,19 +69,6 @@ void GlowEffect::end() { · 49 unmodified lines
6869 glBlendColor(0.0f, 0.0f, 0.0f, 0.0f);
6970 }
7071
71−static 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−
8472 void GlowEffect::render() {
8573 QOpenGLFramebufferObject* primaryFBO = Application::getInstance()->getTextureCache()->getPrimaryFramebufferObject();
8674 primaryFBO->release();
@@ -95,6 +83,7 @@ void GlowEffect::render() { · 8 unmodified lines
9583
9684 glDisable(GL_BLEND);
9785 glDisable(GL_DEPTH_TEST);
86+ glDepthMask(GL_FALSE);
9887
9988 if (_isEmpty) {
10089 // copy the primary to the screen
@@ -210,6 +199,7 @@ void GlowEffect::render() { · 109 unmodified lines
210199
211200 glEnable(GL_BLEND);
212201 glEnable(GL_DEPTH_TEST);
202+ glDepthMask(GL_TRUE);
213203 glBindTexture(GL_TEXTURE_2D, 0);
214204 }
215205
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+
11+void 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).
13+void renderFullscreenQuad();
14+
15+#endif /* defined(__interface__RenderUtil__) */
interface/src/renderer/TextureCache.cpp+25−2
@@ -5,6 +5,9 @@ · 4 unmodified lines
55 // Created by Andrzej Kapolka on 8/6/13.
66 // Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
77
8+// include this before QGLWidget, which includes an earlier version of OpenGL
9+#include "InterfaceConfig.h"
10+
811 #include <QGLWidget>
912 #include <QOpenGLFramebufferObject>
1013
@@ -23,6 +26,7 @@ TextureCache::~TextureCache() { · 12 unmodified lines
2326 }
2427 if (_primaryFramebufferObject != NULL) {
2528 delete _primaryFramebufferObject;
29+ glDeleteTextures(1, &_primaryDepthTextureID);
2630 }
2731 if (_secondaryFramebufferObject != NULL) {
2832 delete _secondaryFramebufferObject;
@@ -60,13 +64,31 @@ GLuint TextureCache::getPermutationNormalTextureID() { · 31 unmodified lines
6064
6165 QOpenGLFramebufferObject* TextureCache::getPrimaryFramebufferObject() {
6266 if (_primaryFramebufferObject == NULL) {
63− _primaryFramebufferObject = new QOpenGLFramebufferObject(Application::getInstance()->getGLWidget()->size(),
64− QOpenGLFramebufferObject::Depth);
67+ QSize size = Application::getInstance()->getGLWidget()->size();
68+ _primaryFramebufferObject = new QOpenGLFramebufferObject(size);
6569 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();
6682 }
6783 return _primaryFramebufferObject;
6884 }
6985
86+GLuint TextureCache::getPrimaryDepthTextureID() {
87+ // ensure that the primary framebuffer object is initialized before returning the depth texture id
88+ getPrimaryFramebufferObject();
89+ return _primaryDepthTextureID;
90+}
91+
7092 QOpenGLFramebufferObject* TextureCache::getSecondaryFramebufferObject() {
7193 if (_secondaryFramebufferObject == NULL) {
7294 _secondaryFramebufferObject = new QOpenGLFramebufferObject(Application::getInstance()->getGLWidget()->size());
@@ -89,6 +111,7 @@ bool TextureCache::eventFilter(QObject* watched, QEvent* event) { · 16 unmodified lines
89111 if (_primaryFramebufferObject != NULL && _primaryFramebufferObject->size() != size) {
90112 delete _primaryFramebufferObject;
91113 _primaryFramebufferObject = NULL;
114+ glDeleteTextures(1, &_primaryDepthTextureID);
92115 }
93116 if (_secondaryFramebufferObject != NULL && _secondaryFramebufferObject->size() != size) {
94117 delete _secondaryFramebufferObject;
interface/src/renderer/TextureCache.h+16−0
@@ -15,16 +15,31 @@ · 14 unmodified lines
1515
1616 class QOpenGLFramebufferObject;
1717
18+/// Stored cached textures, including render-to-texture targets.
1819 class TextureCache : public QObject {
1920 public:
2021
2122 TextureCache();
2223 ~TextureCache();
2324
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.
2428 GLuint getPermutationNormalTextureID();
2529
30+ /// Returns a pointer to the primary framebuffer object. This render target includes a depth component, and is
31+ /// used for scene rendering.
2632 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.
2739 QOpenGLFramebufferObject* getSecondaryFramebufferObject();
40+
41+ /// Returns a pointer to the tertiary framebuffer object, used as an additional render target when performing full
42+ /// screen effects.
2843 QOpenGLFramebufferObject* getTertiaryFramebufferObject();
2944
3045 virtual bool eventFilter(QObject* watched, QEvent* event);
@@ -34,6 +49,7 @@ private: · 3 unmodified lines
3449 GLuint _permutationNormalTextureID;
3550
3651 QOpenGLFramebufferObject* _primaryFramebufferObject;
52+ GLuint _primaryDepthTextureID;
3753 QOpenGLFramebufferObject* _secondaryFramebufferObject;
3854 QOpenGLFramebufferObject* _tertiaryFramebufferObject;
3955 };