From c3f6cab19913921dc2668cf1a40dedff5d177bb9 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Wed, 28 May 2014 15:20:09 -0700 Subject: [PATCH 1/9] Working on cascading shadow maps. --- interface/resources/shaders/shadow_map.frag | 12 +- interface/resources/shaders/shadow_map.vert | 10 +- interface/src/Application.cpp | 150 +++++++++++--------- interface/src/Application.h | 6 +- interface/src/renderer/Model.cpp | 9 +- interface/src/voxels/VoxelSystem.cpp | 10 +- 6 files changed, 108 insertions(+), 89 deletions(-) diff --git a/interface/resources/shaders/shadow_map.frag b/interface/resources/shaders/shadow_map.frag index fb3474d9ef..f53c66b095 100644 --- a/interface/resources/shaders/shadow_map.frag +++ b/interface/resources/shaders/shadow_map.frag @@ -13,15 +13,11 @@ uniform sampler2DShadow shadowMap; -// the inverse of the size of the shadow map -const float shadowScale = 1.0 / 2048.0; - varying vec4 shadowColor; void main(void) { - gl_FragColor = mix(shadowColor, gl_Color, 0.25 * - (shadow2D(shadowMap, gl_TexCoord[0].stp + vec3(-shadowScale, -shadowScale, 0.0)).r + - shadow2D(shadowMap, gl_TexCoord[0].stp + vec3(-shadowScale, shadowScale, 0.0)).r + - shadow2D(shadowMap, gl_TexCoord[0].stp + vec3(shadowScale, -shadowScale, 0.0)).r + - shadow2D(shadowMap, gl_TexCoord[0].stp + vec3(shadowScale, shadowScale, 0.0)).r)); + gl_FragColor = mix(shadowColor, gl_Color, shadow2D(shadowMap, gl_TexCoord[0].stp).r * + shadow2D(shadowMap, gl_TexCoord[1].stp).r * + shadow2D(shadowMap, gl_TexCoord[2].stp).r * + shadow2D(shadowMap, gl_TexCoord[3].stp).r); } diff --git a/interface/resources/shaders/shadow_map.vert b/interface/resources/shaders/shadow_map.vert index abe5f99b44..e7efcd7c0f 100644 --- a/interface/resources/shaders/shadow_map.vert +++ b/interface/resources/shaders/shadow_map.vert @@ -21,10 +21,16 @@ void main(void) { vec4 normal = normalize(gl_ModelViewMatrix * vec4(gl_Normal, 0.0)); gl_FrontColor = shadowColor + gl_Color * (gl_LightSource[0].diffuse * max(0.0, dot(normal, gl_LightSource[0].position))); - // generate the shadow texture coordinate using the eye position + // generate the shadow texture coordinates using the eye position vec4 eyePosition = gl_ModelViewMatrix * gl_Vertex; gl_TexCoord[0] = vec4(dot(gl_EyePlaneS[0], eyePosition), dot(gl_EyePlaneT[0], eyePosition), - dot(gl_EyePlaneR[0], eyePosition), 1.0); + dot(gl_EyePlaneR[0], eyePosition), 1.0); + gl_TexCoord[1] = vec4(dot(gl_EyePlaneS[1], eyePosition), dot(gl_EyePlaneT[1], eyePosition), + dot(gl_EyePlaneR[1], eyePosition), 1.0); + gl_TexCoord[2] = vec4(dot(gl_EyePlaneS[2], eyePosition), dot(gl_EyePlaneT[2], eyePosition), + dot(gl_EyePlaneR[2], eyePosition), 1.0); + gl_TexCoord[3] = vec4(dot(gl_EyePlaneS[3], eyePosition), dot(gl_EyePlaneT[3], eyePosition), + dot(gl_EyePlaneR[3], eyePosition), 1.0); // use the fixed function transform gl_Position = ftransform(); diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index fac0ef154f..a1c2507822 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2256,94 +2256,104 @@ void Application::updateShadowMap() { glEnable(GL_DEPTH_TEST); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - glViewport(0, 0, fbo->width(), fbo->height()); - glm::vec3 lightDirection = -getSunDirection(); glm::quat rotation = rotationBetween(IDENTITY_FRONT, lightDirection); glm::quat inverseRotation = glm::inverse(rotation); - float nearScale = 0.0f; - const float MAX_SHADOW_DISTANCE = 2.0f; - float farScale = (MAX_SHADOW_DISTANCE - _viewFrustum.getNearClip()) / - (_viewFrustum.getFarClip() - _viewFrustum.getNearClip()); - loadViewFrustum(_myCamera, _viewFrustum); - glm::vec3 points[] = { - glm::mix(_viewFrustum.getNearTopLeft(), _viewFrustum.getFarTopLeft(), nearScale), - glm::mix(_viewFrustum.getNearTopRight(), _viewFrustum.getFarTopRight(), nearScale), - glm::mix(_viewFrustum.getNearBottomLeft(), _viewFrustum.getFarBottomLeft(), nearScale), - glm::mix(_viewFrustum.getNearBottomRight(), _viewFrustum.getFarBottomRight(), nearScale), - glm::mix(_viewFrustum.getNearTopLeft(), _viewFrustum.getFarTopLeft(), farScale), - glm::mix(_viewFrustum.getNearTopRight(), _viewFrustum.getFarTopRight(), farScale), - glm::mix(_viewFrustum.getNearBottomLeft(), _viewFrustum.getFarBottomLeft(), farScale), - glm::mix(_viewFrustum.getNearBottomRight(), _viewFrustum.getFarBottomRight(), farScale) }; - glm::vec3 center; - for (size_t i = 0; i < sizeof(points) / sizeof(points[0]); i++) { - center += points[i]; - } - center /= (float)(sizeof(points) / sizeof(points[0])); - float radius = 0.0f; - for (size_t i = 0; i < sizeof(points) / sizeof(points[0]); i++) { - radius = qMax(radius, glm::distance(points[i], center)); - } - center = inverseRotation * center; - // to reduce texture "shimmer," move in texel increments - float texelSize = (2.0f * radius) / fbo->width(); - center = glm::vec3(roundf(center.x / texelSize) * texelSize, roundf(center.y / texelSize) * texelSize, - roundf(center.z / texelSize) * texelSize); + const float MAP_DISTANCES[] = { 0.0f, 2.0f, 6.0f, 14.0f, 30.0f }; + const glm::vec2 MAP_COORDS[] = { glm::vec2(0.0f, 0.0f), glm::vec2(0.5f, 0.0f), + glm::vec2(0.0f, 0.5f), glm::vec2(0.5f, 0.5f) }; - glm::vec3 minima(center.x - radius, center.y - radius, center.z - radius); - glm::vec3 maxima(center.x + radius, center.y + radius, center.z + radius); + int halfSize = fbo->width() / 2; + float frustumScale = 1.0f / (_viewFrustum.getFarClip() - _viewFrustum.getNearClip()); + + for (int i = 0; i < SHADOW_MATRIX_COUNT; i++) { + const glm::vec2& coord = MAP_COORDS[i]; + glViewport(coord.s * halfSize, coord.t * halfSize, halfSize, halfSize); - // stretch out our extents in z so that we get all of the avatars - minima.z -= _viewFrustum.getFarClip() * 0.5f; - maxima.z += _viewFrustum.getFarClip() * 0.5f; + float nearScale = MAP_DISTANCES[i] * frustumScale; + float farScale = MAP_DISTANCES[i + 1] * frustumScale; + loadViewFrustum(_myCamera, _viewFrustum); + glm::vec3 points[] = { + glm::mix(_viewFrustum.getNearTopLeft(), _viewFrustum.getFarTopLeft(), nearScale), + glm::mix(_viewFrustum.getNearTopRight(), _viewFrustum.getFarTopRight(), nearScale), + glm::mix(_viewFrustum.getNearBottomLeft(), _viewFrustum.getFarBottomLeft(), nearScale), + glm::mix(_viewFrustum.getNearBottomRight(), _viewFrustum.getFarBottomRight(), nearScale), + glm::mix(_viewFrustum.getNearTopLeft(), _viewFrustum.getFarTopLeft(), farScale), + glm::mix(_viewFrustum.getNearTopRight(), _viewFrustum.getFarTopRight(), farScale), + glm::mix(_viewFrustum.getNearBottomLeft(), _viewFrustum.getFarBottomLeft(), farScale), + glm::mix(_viewFrustum.getNearBottomRight(), _viewFrustum.getFarBottomRight(), farScale) }; + glm::vec3 center; + for (size_t j = 0; j < sizeof(points) / sizeof(points[0]); j++) { + center += points[j]; + } + center /= (float)(sizeof(points) / sizeof(points[0])); + float radius = 0.0f; + for (size_t j = 0; j < sizeof(points) / sizeof(points[0]); j++) { + radius = qMax(radius, glm::distance(points[j], center)); + } + center = inverseRotation * center; + + // to reduce texture "shimmer," move in texel increments + float texelSize = (2.0f * radius) / halfSize; + center = glm::vec3(roundf(center.x / texelSize) * texelSize, roundf(center.y / texelSize) * texelSize, + roundf(center.z / texelSize) * texelSize); + + glm::vec3 minima(center.x - radius, center.y - radius, center.z - radius); + glm::vec3 maxima(center.x + radius, center.y + radius, center.z + radius); - // save the combined matrix for rendering - _shadowMatrix = glm::transpose(glm::translate(glm::vec3(0.5f, 0.5f, 0.5f)) * glm::scale(glm::vec3(0.5f, 0.5f, 0.5f)) * - glm::ortho(minima.x, maxima.x, minima.y, maxima.y, -maxima.z, -minima.z) * glm::mat4_cast(inverseRotation)); + // stretch out our extents in z so that we get all of the avatars + minima.z -= _viewFrustum.getFarClip() * 0.5f; + maxima.z += _viewFrustum.getFarClip() * 0.5f; - // update the shadow view frustum - _shadowViewFrustum.setPosition(rotation * ((minima + maxima) * 0.5f)); - _shadowViewFrustum.setOrientation(rotation); - _shadowViewFrustum.setOrthographic(true); - _shadowViewFrustum.setWidth(maxima.x - minima.x); - _shadowViewFrustum.setHeight(maxima.y - minima.y); - _shadowViewFrustum.setNearClip(minima.z); - _shadowViewFrustum.setFarClip(maxima.z); - _shadowViewFrustum.setEyeOffsetPosition(glm::vec3()); - _shadowViewFrustum.setEyeOffsetOrientation(glm::quat()); - _shadowViewFrustum.calculate(); + // save the combined matrix for rendering + _shadowMatrices[i] = glm::transpose(glm::translate(glm::vec3(coord, 0.0f)) * glm::scale(glm::vec3(0.5f, 0.5f, 1.0f)) * + glm::translate(glm::vec3(0.5f, 0.5f, 0.5f)) * glm::scale(glm::vec3(0.5f, 0.5f, 0.5f)) * + glm::ortho(minima.x, maxima.x, minima.y, maxima.y, -maxima.z, -minima.z) * glm::mat4_cast(inverseRotation)); - glMatrixMode(GL_PROJECTION); - glPushMatrix(); - glLoadIdentity(); - glOrtho(minima.x, maxima.x, minima.y, maxima.y, -maxima.z, -minima.z); + // update the shadow view frustum + _shadowViewFrustum.setPosition(rotation * ((minima + maxima) * 0.5f)); + _shadowViewFrustum.setOrientation(rotation); + _shadowViewFrustum.setOrthographic(true); + _shadowViewFrustum.setWidth(maxima.x - minima.x); + _shadowViewFrustum.setHeight(maxima.y - minima.y); + _shadowViewFrustum.setNearClip(minima.z); + _shadowViewFrustum.setFarClip(maxima.z); + _shadowViewFrustum.setEyeOffsetPosition(glm::vec3()); + _shadowViewFrustum.setEyeOffsetOrientation(glm::quat()); + _shadowViewFrustum.calculate(); - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); - glLoadIdentity(); - glm::vec3 axis = glm::axis(inverseRotation); - glRotatef(glm::degrees(glm::angle(inverseRotation)), axis.x, axis.y, axis.z); + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadIdentity(); + glOrtho(minima.x, maxima.x, minima.y, maxima.y, -maxima.z, -minima.z); - // store view matrix without translation, which we'll use for precision-sensitive objects - updateUntranslatedViewMatrix(); + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + glLoadIdentity(); + glm::vec3 axis = glm::axis(inverseRotation); + glRotatef(glm::degrees(glm::angle(inverseRotation)), axis.x, axis.y, axis.z); - glEnable(GL_POLYGON_OFFSET_FILL); - glPolygonOffset(1.1f, 4.0f); // magic numbers courtesy http://www.eecs.berkeley.edu/~ravir/6160/papers/shadowmaps.ppt + // store view matrix without translation, which we'll use for precision-sensitive objects + updateUntranslatedViewMatrix(); - _avatarManager.renderAvatars(Avatar::SHADOW_RENDER_MODE); - _particles.render(OctreeRenderer::SHADOW_RENDER_MODE); - _models.render(OctreeRenderer::SHADOW_RENDER_MODE); + glEnable(GL_POLYGON_OFFSET_FILL); + glPolygonOffset(1.1f, 4.0f); // magic numbers courtesy http://www.eecs.berkeley.edu/~ravir/6160/papers/shadowmaps.ppt - glDisable(GL_POLYGON_OFFSET_FILL); + _avatarManager.renderAvatars(Avatar::SHADOW_RENDER_MODE); + _particles.render(OctreeRenderer::SHADOW_RENDER_MODE); + _models.render(OctreeRenderer::SHADOW_RENDER_MODE); - glPopMatrix(); + glDisable(GL_POLYGON_OFFSET_FILL); - glMatrixMode(GL_PROJECTION); - glPopMatrix(); + glPopMatrix(); - glMatrixMode(GL_MODELVIEW); + glMatrixMode(GL_PROJECTION); + glPopMatrix(); + glMatrixMode(GL_MODELVIEW); + } + fbo->release(); glViewport(0, 0, _glWidget->width(), _glWidget->height()); diff --git a/interface/src/Application.h b/interface/src/Application.h index 0065944611..5d29a9057a 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -126,6 +126,8 @@ static const float MIRROR_REARVIEW_DISTANCE = 0.65f; static const float MIRROR_REARVIEW_BODY_DISTANCE = 2.3f; static const float MIRROR_FIELD_OF_VIEW = 30.0f; +static const int SHADOW_MATRIX_COUNT = 4; + class Application : public QApplication { Q_OBJECT @@ -261,7 +263,7 @@ public: /// result from matrix multiplication at high translation magnitudes. void loadTranslatedViewMatrix(const glm::vec3& translation); - const glm::mat4& getShadowMatrix() const { return _shadowMatrix; } + const glm::mat4* getShadowMatrices() const { return _shadowMatrices; } void getModelViewMatrix(glm::dmat4* modelViewMatrix); void getProjectionMatrix(glm::dmat4* projectionMatrix); @@ -491,7 +493,7 @@ private: float _rotateMirror; float _raiseMirror; - glm::mat4 _shadowMatrix; + glm::mat4 _shadowMatrices[SHADOW_MATRIX_COUNT]; Environment _environment; diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index 678a4b09c0..7c9ba50346 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -1509,9 +1509,12 @@ void Model::renderMeshes(float alpha, RenderMode mode, bool translucent, bool re const QVector& networkMeshes = _geometry->getMeshes(); if (receiveShadows) { - glTexGenfv(GL_S, GL_EYE_PLANE, (const GLfloat*)&Application::getInstance()->getShadowMatrix()[0]); - glTexGenfv(GL_T, GL_EYE_PLANE, (const GLfloat*)&Application::getInstance()->getShadowMatrix()[1]); - glTexGenfv(GL_R, GL_EYE_PLANE, (const GLfloat*)&Application::getInstance()->getShadowMatrix()[2]); + for (int i = SHADOW_MATRIX_COUNT - 1; i >= 0; i--) { + glActiveTexture(GL_TEXTURE0 + i); + glTexGenfv(GL_S, GL_EYE_PLANE, (const GLfloat*)&Application::getInstance()->getShadowMatrices()[i][0]); + glTexGenfv(GL_T, GL_EYE_PLANE, (const GLfloat*)&Application::getInstance()->getShadowMatrices()[i][1]); + glTexGenfv(GL_R, GL_EYE_PLANE, (const GLfloat*)&Application::getInstance()->getShadowMatrices()[i][2]); + } } for (int i = 0; i < networkMeshes.size(); i++) { // exit early if the translucency doesn't match what we're drawing diff --git a/interface/src/voxels/VoxelSystem.cpp b/interface/src/voxels/VoxelSystem.cpp index 8937cef7dd..4f1b322455 100644 --- a/interface/src/voxels/VoxelSystem.cpp +++ b/interface/src/voxels/VoxelSystem.cpp @@ -1490,10 +1490,12 @@ void VoxelSystem::applyScaleAndBindProgram(bool texture) { _shadowMapProgram.bind(); glBindTexture(GL_TEXTURE_2D, Application::getInstance()->getTextureCache()->getShadowDepthTextureID()); - glTexGenfv(GL_S, GL_EYE_PLANE, (const GLfloat*)&Application::getInstance()->getShadowMatrix()[0]); - glTexGenfv(GL_T, GL_EYE_PLANE, (const GLfloat*)&Application::getInstance()->getShadowMatrix()[1]); - glTexGenfv(GL_R, GL_EYE_PLANE, (const GLfloat*)&Application::getInstance()->getShadowMatrix()[2]); - + for (int i = SHADOW_MATRIX_COUNT - 1; i >= 0; i--) { + glActiveTexture(GL_TEXTURE0 + i); + glTexGenfv(GL_S, GL_EYE_PLANE, (const GLfloat*)&Application::getInstance()->getShadowMatrices()[i][0]); + glTexGenfv(GL_T, GL_EYE_PLANE, (const GLfloat*)&Application::getInstance()->getShadowMatrices()[i][1]); + glTexGenfv(GL_R, GL_EYE_PLANE, (const GLfloat*)&Application::getInstance()->getShadowMatrices()[i][2]); + } } else if (texture) { _perlinModulateProgram.bind(); glBindTexture(GL_TEXTURE_2D, Application::getInstance()->getTextureCache()->getPermutationNormalTextureID()); From 698ecbf9c5ab7f4c7719ee812159a1a7f9b0e613 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Wed, 28 May 2014 15:58:45 -0700 Subject: [PATCH 2/9] Fix for shadow map rendering. --- interface/src/Application.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index a1c2507822..0cae0f3e75 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2266,14 +2266,14 @@ void Application::updateShadowMap() { int halfSize = fbo->width() / 2; float frustumScale = 1.0f / (_viewFrustum.getFarClip() - _viewFrustum.getNearClip()); + loadViewFrustum(_myCamera, _viewFrustum); for (int i = 0; i < SHADOW_MATRIX_COUNT; i++) { const glm::vec2& coord = MAP_COORDS[i]; - glViewport(coord.s * halfSize, coord.t * halfSize, halfSize, halfSize); + glViewport(coord.s * fbo->width(), coord.t * fbo->height(), halfSize, halfSize); float nearScale = MAP_DISTANCES[i] * frustumScale; float farScale = MAP_DISTANCES[i + 1] * frustumScale; - loadViewFrustum(_myCamera, _viewFrustum); glm::vec3 points[] = { glm::mix(_viewFrustum.getNearTopLeft(), _viewFrustum.getFarTopLeft(), nearScale), glm::mix(_viewFrustum.getNearTopRight(), _viewFrustum.getFarTopRight(), nearScale), From ff77644caa90fd668c4f9093e2ab7be726edc651 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Wed, 28 May 2014 18:35:30 -0700 Subject: [PATCH 3/9] Progress on selecting cascades. --- interface/resources/shaders/shadow_map.frag | 14 ++++++++++---- interface/resources/shaders/shadow_map.vert | 14 +++++--------- interface/src/Application.cpp | 5 ++--- interface/src/Application.h | 1 + interface/src/voxels/VoxelSystem.cpp | 2 ++ 5 files changed, 20 insertions(+), 16 deletions(-) diff --git a/interface/resources/shaders/shadow_map.frag b/interface/resources/shaders/shadow_map.frag index f53c66b095..f2246fff55 100644 --- a/interface/resources/shaders/shadow_map.frag +++ b/interface/resources/shaders/shadow_map.frag @@ -13,11 +13,17 @@ uniform sampler2DShadow shadowMap; +uniform vec3 shadowDistances; + +// the color in shadow varying vec4 shadowColor; +// the interpolated position +varying vec4 position; + void main(void) { - gl_FragColor = mix(shadowColor, gl_Color, shadow2D(shadowMap, gl_TexCoord[0].stp).r * - shadow2D(shadowMap, gl_TexCoord[1].stp).r * - shadow2D(shadowMap, gl_TexCoord[2].stp).r * - shadow2D(shadowMap, gl_TexCoord[3].stp).r); + int shadowIndex = int(dot(step(vec3(position.z), shadowDistances), vec3(1.0, 1.0, 1.0))); + vec3 texCoord = vec3(dot(gl_EyePlaneS[shadowIndex], position), dot(gl_EyePlaneT[shadowIndex], position), + dot(gl_EyePlaneR[shadowIndex], position)); + gl_FragColor = mix(shadowColor, gl_Color, shadow2D(shadowMap, texCoord).r); } diff --git a/interface/resources/shaders/shadow_map.vert b/interface/resources/shaders/shadow_map.vert index e7efcd7c0f..dcc5324927 100644 --- a/interface/resources/shaders/shadow_map.vert +++ b/interface/resources/shaders/shadow_map.vert @@ -11,8 +11,12 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +// the color in shadow varying vec4 shadowColor; +// the interpolated position +varying vec4 position; + void main(void) { // the shadow color includes only the ambient terms shadowColor = gl_Color * (gl_LightModel.ambient + gl_LightSource[0].ambient); @@ -22,15 +26,7 @@ void main(void) { gl_FrontColor = shadowColor + gl_Color * (gl_LightSource[0].diffuse * max(0.0, dot(normal, gl_LightSource[0].position))); // generate the shadow texture coordinates using the eye position - vec4 eyePosition = gl_ModelViewMatrix * gl_Vertex; - gl_TexCoord[0] = vec4(dot(gl_EyePlaneS[0], eyePosition), dot(gl_EyePlaneT[0], eyePosition), - dot(gl_EyePlaneR[0], eyePosition), 1.0); - gl_TexCoord[1] = vec4(dot(gl_EyePlaneS[1], eyePosition), dot(gl_EyePlaneT[1], eyePosition), - dot(gl_EyePlaneR[1], eyePosition), 1.0); - gl_TexCoord[2] = vec4(dot(gl_EyePlaneS[2], eyePosition), dot(gl_EyePlaneT[2], eyePosition), - dot(gl_EyePlaneR[2], eyePosition), 1.0); - gl_TexCoord[3] = vec4(dot(gl_EyePlaneS[3], eyePosition), dot(gl_EyePlaneT[3], eyePosition), - dot(gl_EyePlaneR[3], eyePosition), 1.0); + position = gl_ModelViewMatrix * gl_Vertex; // use the fixed function transform gl_Position = ftransform(); diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 0cae0f3e75..a2892eb003 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2260,7 +2260,6 @@ void Application::updateShadowMap() { glm::quat rotation = rotationBetween(IDENTITY_FRONT, lightDirection); glm::quat inverseRotation = glm::inverse(rotation); - const float MAP_DISTANCES[] = { 0.0f, 2.0f, 6.0f, 14.0f, 30.0f }; const glm::vec2 MAP_COORDS[] = { glm::vec2(0.0f, 0.0f), glm::vec2(0.5f, 0.0f), glm::vec2(0.0f, 0.5f), glm::vec2(0.5f, 0.5f) }; @@ -2272,8 +2271,8 @@ void Application::updateShadowMap() { const glm::vec2& coord = MAP_COORDS[i]; glViewport(coord.s * fbo->width(), coord.t * fbo->height(), halfSize, halfSize); - float nearScale = MAP_DISTANCES[i] * frustumScale; - float farScale = MAP_DISTANCES[i + 1] * frustumScale; + float nearScale = SHADOW_MATRIX_DISTANCES[i] * frustumScale; + float farScale = SHADOW_MATRIX_DISTANCES[i + 1] * frustumScale; glm::vec3 points[] = { glm::mix(_viewFrustum.getNearTopLeft(), _viewFrustum.getFarTopLeft(), nearScale), glm::mix(_viewFrustum.getNearTopRight(), _viewFrustum.getFarTopRight(), nearScale), diff --git a/interface/src/Application.h b/interface/src/Application.h index 5d29a9057a..59f9ad4e15 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -127,6 +127,7 @@ static const float MIRROR_REARVIEW_BODY_DISTANCE = 2.3f; static const float MIRROR_FIELD_OF_VIEW = 30.0f; static const int SHADOW_MATRIX_COUNT = 4; +static const float SHADOW_MATRIX_DISTANCES[] = { 0.0f, 2.0f, 6.0f, 14.0f, 30.0f }; class Application : public QApplication { Q_OBJECT diff --git a/interface/src/voxels/VoxelSystem.cpp b/interface/src/voxels/VoxelSystem.cpp index 4f1b322455..11bd47b7e4 100644 --- a/interface/src/voxels/VoxelSystem.cpp +++ b/interface/src/voxels/VoxelSystem.cpp @@ -518,6 +518,8 @@ void VoxelSystem::initVoxelMemory() { _shadowMapProgram.bind(); _shadowMapProgram.setUniformValue("shadowMap", 0); + _shadowMapProgram.setUniformValue("shadowDistances", -SHADOW_MATRIX_DISTANCES[1], + -SHADOW_MATRIX_DISTANCES[2], -SHADOW_MATRIX_DISTANCES[3]); _shadowMapProgram.release(); } } From 09231f01f3e96a293ffe6280e200c46b8030a7b8 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Thu, 29 May 2014 12:48:41 -0700 Subject: [PATCH 4/9] Retain "simple" shadows, supply cascaded as option. --- .../shaders/cascaded_shadow_map.frag | 29 ++++++++++++++ .../shaders/cascaded_shadow_map.vert | 33 ++++++++++++++++ interface/resources/shaders/shadow_map.frag | 15 ++++---- interface/resources/shaders/shadow_map.vert | 7 ++-- interface/src/Application.cpp | 34 ++++++++++++++--- interface/src/Application.h | 6 +-- interface/src/Menu.cpp | 15 ++++++-- interface/src/Menu.h | 7 +++- interface/src/renderer/Model.cpp | 10 +---- interface/src/voxels/VoxelSystem.cpp | 38 ++++++++++++------- interface/src/voxels/VoxelSystem.h | 1 + 11 files changed, 146 insertions(+), 49 deletions(-) create mode 100644 interface/resources/shaders/cascaded_shadow_map.frag create mode 100644 interface/resources/shaders/cascaded_shadow_map.vert diff --git a/interface/resources/shaders/cascaded_shadow_map.frag b/interface/resources/shaders/cascaded_shadow_map.frag new file mode 100644 index 0000000000..9b3e8f7cc7 --- /dev/null +++ b/interface/resources/shaders/cascaded_shadow_map.frag @@ -0,0 +1,29 @@ +#version 120 + +// +// cascaded_shadow_map.frag +// fragment shader +// +// Created by Andrzej Kapolka on 5/29/14. +// Copyright 2014 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +uniform sampler2DShadow shadowMap; + +uniform vec3 shadowDistances; + +// the color in shadow +varying vec4 shadowColor; + +// the interpolated position +varying vec4 position; + +void main(void) { + int shadowIndex = int(dot(step(vec3(position.z), shadowDistances), vec3(1.0, 1.0, 1.0))); + vec3 texCoord = vec3(dot(gl_EyePlaneS[shadowIndex], position), dot(gl_EyePlaneT[shadowIndex], position), + dot(gl_EyePlaneR[shadowIndex], position)); + gl_FragColor = mix(shadowColor, gl_Color, shadow2D(shadowMap, texCoord).r); +} diff --git a/interface/resources/shaders/cascaded_shadow_map.vert b/interface/resources/shaders/cascaded_shadow_map.vert new file mode 100644 index 0000000000..68ff95b28a --- /dev/null +++ b/interface/resources/shaders/cascaded_shadow_map.vert @@ -0,0 +1,33 @@ +#version 120 + +// +// cascaded_shadow_map.vert +// vertex shader +// +// Created by Andrzej Kapolka on 5/29/14. +// Copyright 2014 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +// the color in shadow +varying vec4 shadowColor; + +// the interpolated position +varying vec4 position; + +void main(void) { + // the shadow color includes only the ambient terms + shadowColor = gl_Color * (gl_LightModel.ambient + gl_LightSource[0].ambient); + + // the normal color includes diffuse + vec4 normal = normalize(gl_ModelViewMatrix * vec4(gl_Normal, 0.0)); + gl_FrontColor = shadowColor + gl_Color * (gl_LightSource[0].diffuse * max(0.0, dot(normal, gl_LightSource[0].position))); + + // generate the shadow texture coordinates using the eye position + position = gl_ModelViewMatrix * gl_Vertex; + + // use the fixed function transform + gl_Position = ftransform(); +} diff --git a/interface/resources/shaders/shadow_map.frag b/interface/resources/shaders/shadow_map.frag index f2246fff55..fa79040ce3 100644 --- a/interface/resources/shaders/shadow_map.frag +++ b/interface/resources/shaders/shadow_map.frag @@ -13,17 +13,16 @@ uniform sampler2DShadow shadowMap; -uniform vec3 shadowDistances; +// the inverse of the size of the shadow map +const float shadowScale = 1.0 / 2048.0; // the color in shadow varying vec4 shadowColor; -// the interpolated position -varying vec4 position; - void main(void) { - int shadowIndex = int(dot(step(vec3(position.z), shadowDistances), vec3(1.0, 1.0, 1.0))); - vec3 texCoord = vec3(dot(gl_EyePlaneS[shadowIndex], position), dot(gl_EyePlaneT[shadowIndex], position), - dot(gl_EyePlaneR[shadowIndex], position)); - gl_FragColor = mix(shadowColor, gl_Color, shadow2D(shadowMap, texCoord).r); + gl_FragColor = mix(shadowColor, gl_Color, 0.25 * + (shadow2D(shadowMap, gl_TexCoord[0].stp + vec3(-shadowScale, -shadowScale, 0.0)).r + + shadow2D(shadowMap, gl_TexCoord[0].stp + vec3(-shadowScale, shadowScale, 0.0)).r + + shadow2D(shadowMap, gl_TexCoord[0].stp + vec3(shadowScale, -shadowScale, 0.0)).r + + shadow2D(shadowMap, gl_TexCoord[0].stp + vec3(shadowScale, shadowScale, 0.0)).r)); } diff --git a/interface/resources/shaders/shadow_map.vert b/interface/resources/shaders/shadow_map.vert index dcc5324927..5d2affba98 100644 --- a/interface/resources/shaders/shadow_map.vert +++ b/interface/resources/shaders/shadow_map.vert @@ -14,9 +14,6 @@ // the color in shadow varying vec4 shadowColor; -// the interpolated position -varying vec4 position; - void main(void) { // the shadow color includes only the ambient terms shadowColor = gl_Color * (gl_LightModel.ambient + gl_LightSource[0].ambient); @@ -26,7 +23,9 @@ void main(void) { gl_FrontColor = shadowColor + gl_Color * (gl_LightSource[0].diffuse * max(0.0, dot(normal, gl_LightSource[0].position))); // generate the shadow texture coordinates using the eye position - position = gl_ModelViewMatrix * gl_Vertex; + vec4 eyePosition = gl_ModelViewMatrix * gl_Vertex; + gl_TexCoord[0] = vec4(dot(gl_EyePlaneS[0], eyePosition), dot(gl_EyePlaneT[0], eyePosition), + dot(gl_EyePlaneR[0], eyePosition), 1.0); // use the fixed function transform gl_Position = ftransform(); diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index a2892eb003..af94ddba01 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -616,7 +616,7 @@ void Application::paintGL() { whichCamera = _viewFrustumOffsetCamera; } - if (Menu::getInstance()->isOptionChecked(MenuOption::Shadows)) { + if (Menu::getInstance()->getShadowsEnabled()) { updateShadowMap(); } @@ -2263,13 +2263,20 @@ void Application::updateShadowMap() { const glm::vec2 MAP_COORDS[] = { glm::vec2(0.0f, 0.0f), glm::vec2(0.5f, 0.0f), glm::vec2(0.0f, 0.5f), glm::vec2(0.5f, 0.5f) }; - int halfSize = fbo->width() / 2; float frustumScale = 1.0f / (_viewFrustum.getFarClip() - _viewFrustum.getNearClip()); loadViewFrustum(_myCamera, _viewFrustum); - for (int i = 0; i < SHADOW_MATRIX_COUNT; i++) { + int matrixCount = 1; + int targetSize = fbo->width(); + float targetScale = 1.0f; + if (Menu::getInstance()->isOptionChecked(MenuOption::CascadedShadows)) { + matrixCount = CASCADED_SHADOW_MATRIX_COUNT; + targetSize = fbo->width() / 2; + targetScale = 0.5f; + } + for (int i = 0; i < matrixCount; i++) { const glm::vec2& coord = MAP_COORDS[i]; - glViewport(coord.s * fbo->width(), coord.t * fbo->height(), halfSize, halfSize); + glViewport(coord.s * fbo->width(), coord.t * fbo->height(), targetSize, targetSize); float nearScale = SHADOW_MATRIX_DISTANCES[i] * frustumScale; float farScale = SHADOW_MATRIX_DISTANCES[i + 1] * frustumScale; @@ -2294,7 +2301,7 @@ void Application::updateShadowMap() { center = inverseRotation * center; // to reduce texture "shimmer," move in texel increments - float texelSize = (2.0f * radius) / halfSize; + float texelSize = (2.0f * radius) / targetSize; center = glm::vec3(roundf(center.x / texelSize) * texelSize, roundf(center.y / texelSize) * texelSize, roundf(center.z / texelSize) * texelSize); @@ -2306,7 +2313,8 @@ void Application::updateShadowMap() { maxima.z += _viewFrustum.getFarClip() * 0.5f; // save the combined matrix for rendering - _shadowMatrices[i] = glm::transpose(glm::translate(glm::vec3(coord, 0.0f)) * glm::scale(glm::vec3(0.5f, 0.5f, 1.0f)) * + _shadowMatrices[i] = glm::transpose(glm::translate(glm::vec3(coord, 0.0f)) * + glm::scale(glm::vec3(targetScale, targetScale, 1.0f)) * glm::translate(glm::vec3(0.5f, 0.5f, 0.5f)) * glm::scale(glm::vec3(0.5f, 0.5f, 0.5f)) * glm::ortho(minima.x, maxima.x, minima.y, maxima.y, -maxima.z, -minima.z) * glm::mat4_cast(inverseRotation)); @@ -2433,6 +2441,20 @@ void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly) { // Setup 3D lights (after the camera transform, so that they are positioned in world space) setupWorldLight(); + // setup shadow matrices (again, after the camera transform) + int shadowMatrixCount = 0; + if (Menu::getInstance()->isOptionChecked(MenuOption::SimpleShadows)) { + shadowMatrixCount = 1; + } else if (Menu::getInstance()->isOptionChecked(MenuOption::CascadedShadows)) { + shadowMatrixCount = CASCADED_SHADOW_MATRIX_COUNT; + } + for (int i = shadowMatrixCount - 1; i >= 0; i--) { + glActiveTexture(GL_TEXTURE0 + i); + glTexGenfv(GL_S, GL_EYE_PLANE, (const GLfloat*)&_shadowMatrices[i][0]); + glTexGenfv(GL_T, GL_EYE_PLANE, (const GLfloat*)&_shadowMatrices[i][1]); + glTexGenfv(GL_R, GL_EYE_PLANE, (const GLfloat*)&_shadowMatrices[i][2]); + } + if (!selfAvatarOnly && Menu::getInstance()->isOptionChecked(MenuOption::Stars)) { PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), "Application::displaySide() ... stars..."); diff --git a/interface/src/Application.h b/interface/src/Application.h index 59f9ad4e15..68d437815b 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -126,7 +126,6 @@ static const float MIRROR_REARVIEW_DISTANCE = 0.65f; static const float MIRROR_REARVIEW_BODY_DISTANCE = 2.3f; static const float MIRROR_FIELD_OF_VIEW = 30.0f; -static const int SHADOW_MATRIX_COUNT = 4; static const float SHADOW_MATRIX_DISTANCES[] = { 0.0f, 2.0f, 6.0f, 14.0f, 30.0f }; class Application : public QApplication { @@ -264,8 +263,6 @@ public: /// result from matrix multiplication at high translation magnitudes. void loadTranslatedViewMatrix(const glm::vec3& translation); - const glm::mat4* getShadowMatrices() const { return _shadowMatrices; } - void getModelViewMatrix(glm::dmat4* modelViewMatrix); void getProjectionMatrix(glm::dmat4* projectionMatrix); @@ -494,7 +491,8 @@ private: float _rotateMirror; float _raiseMirror; - glm::mat4 _shadowMatrices[SHADOW_MATRIX_COUNT]; + static const int CASCADED_SHADOW_MATRIX_COUNT = 4; + glm::mat4 _shadowMatrices[CASCADED_SHADOW_MATRIX_COUNT]; Environment _environment; diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 45b4089a11..ef5ffeaaf1 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -303,7 +303,12 @@ Menu::Menu() : appInstance->getGlowEffect(), SLOT(cycleRenderMode())); - addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::Shadows, 0, false); + QMenu* shadowMenu = renderOptionsMenu->addMenu("Shadows"); + QActionGroup* shadowGroup = new QActionGroup(shadowMenu); + shadowGroup->addAction(addCheckableActionToQMenuAndActionHash(shadowMenu, "None", 0, true)); + shadowGroup->addAction(addCheckableActionToQMenuAndActionHash(shadowMenu, MenuOption::SimpleShadows, 0, false)); + shadowGroup->addAction(addCheckableActionToQMenuAndActionHash(shadowMenu, MenuOption::CascadedShadows, 0, false)); + addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::Metavoxels, 0, true); addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::BuckyBalls, 0, false); addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::Particles, 0, true); @@ -666,6 +671,10 @@ void Menu::scanMenu(QMenu* menu, settingsAction modifySetting, QSettings* set) { set->endGroup(); } +bool Menu::getShadowsEnabled() const { + return isOptionChecked(MenuOption::SimpleShadows) || isOptionChecked(MenuOption::CascadedShadows); +} + void Menu::handleViewFrustumOffsetKeyModifier(int key) { const float VIEW_FRUSTUM_OFFSET_DELTA = 0.5f; const float VIEW_FRUSTUM_OFFSET_UP_DELTA = 0.05f; @@ -836,8 +845,8 @@ void Menu::setIsOptionChecked(const QString& menuOption, bool isChecked) { } } -bool Menu::isOptionChecked(const QString& menuOption) { - QAction* menu = _actionHash.value(menuOption); +bool Menu::isOptionChecked(const QString& menuOption) const { + const QAction* menu = _actionHash.value(menuOption); if (menu) { return menu->isChecked(); } diff --git a/interface/src/Menu.h b/interface/src/Menu.h index 012dc1662c..e973ae88b3 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -102,6 +102,8 @@ public: int getMaxVoxels() const { return _maxVoxels; } QAction* getUseVoxelShader() const { return _useVoxelShader; } + bool getShadowsEnabled() const; + void handleViewFrustumOffsetKeyModifier(int key); // User Tweakable LOD Items @@ -170,7 +172,7 @@ public slots: void removeSeparator(const QString& menuName, const QString& separatorName); void addMenuItem(const MenuItemProperties& properties); void removeMenuItem(const QString& menuName, const QString& menuitem); - bool isOptionChecked(const QString& menuOption); + bool isOptionChecked(const QString& menuOption) const; void setIsOptionChecked(const QString& menuOption, bool isChecked); private slots: @@ -301,6 +303,7 @@ namespace MenuOption { const QString Bandwidth = "Bandwidth Display"; const QString BandwidthDetails = "Bandwidth Details"; const QString BuckyBalls = "Bucky Balls"; + const QString CascadedShadows = "Cascaded"; const QString Chat = "Chat..."; const QString ChatCircling = "Chat Circling"; const QString CollideWithAvatars = "Collide With Avatars"; @@ -376,7 +379,7 @@ namespace MenuOption { const QString ScriptEditor = "Script Editor..."; const QString SettingsExport = "Export Settings"; const QString SettingsImport = "Import Settings"; - const QString Shadows = "Shadows"; + const QString SimpleShadows = "Simple"; const QString ShowBordersVoxelNodes = "Show Voxel Nodes"; const QString ShowBordersModelNodes = "Show Model Nodes"; const QString ShowBordersParticleNodes = "Show Particle Nodes"; diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index 7c9ba50346..1839e20ef7 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -508,7 +508,7 @@ bool Model::render(float alpha, RenderMode mode, bool receiveShadows) { glEnable(GL_ALPHA_TEST); glAlphaFunc(GL_GREATER, 0.5f * alpha); - receiveShadows &= Menu::getInstance()->isOptionChecked(MenuOption::Shadows); + receiveShadows &= Menu::getInstance()->getShadowsEnabled(); renderMeshes(alpha, mode, false, receiveShadows); glDisable(GL_ALPHA_TEST); @@ -1508,14 +1508,6 @@ void Model::renderMeshes(float alpha, RenderMode mode, bool translucent, bool re const FBXGeometry& geometry = _geometry->getFBXGeometry(); const QVector& networkMeshes = _geometry->getMeshes(); - if (receiveShadows) { - for (int i = SHADOW_MATRIX_COUNT - 1; i >= 0; i--) { - glActiveTexture(GL_TEXTURE0 + i); - glTexGenfv(GL_S, GL_EYE_PLANE, (const GLfloat*)&Application::getInstance()->getShadowMatrices()[i][0]); - glTexGenfv(GL_T, GL_EYE_PLANE, (const GLfloat*)&Application::getInstance()->getShadowMatrices()[i][1]); - glTexGenfv(GL_R, GL_EYE_PLANE, (const GLfloat*)&Application::getInstance()->getShadowMatrices()[i][2]); - } - } for (int i = 0; i < networkMeshes.size(); i++) { // exit early if the translucency doesn't match what we're drawing const NetworkMesh& networkMesh = networkMeshes.at(i); diff --git a/interface/src/voxels/VoxelSystem.cpp b/interface/src/voxels/VoxelSystem.cpp index 11bd47b7e4..3525a086b4 100644 --- a/interface/src/voxels/VoxelSystem.cpp +++ b/interface/src/voxels/VoxelSystem.cpp @@ -518,9 +518,19 @@ void VoxelSystem::initVoxelMemory() { _shadowMapProgram.bind(); _shadowMapProgram.setUniformValue("shadowMap", 0); - _shadowMapProgram.setUniformValue("shadowDistances", -SHADOW_MATRIX_DISTANCES[1], - -SHADOW_MATRIX_DISTANCES[2], -SHADOW_MATRIX_DISTANCES[3]); _shadowMapProgram.release(); + + _cascadedShadowMapProgram.addShaderFromSourceFile(QGLShader::Vertex, + Application::resourcesPath() + "shaders/cascaded_shadow_map.vert"); + _cascadedShadowMapProgram.addShaderFromSourceFile(QGLShader::Fragment, + Application::resourcesPath() + "shaders/cascaded_shadow_map.frag"); + _cascadedShadowMapProgram.link(); + + _cascadedShadowMapProgram.bind(); + _cascadedShadowMapProgram.setUniformValue("shadowMap", 0); + _cascadedShadowMapProgram.setUniformValue("shadowDistances", -SHADOW_MATRIX_DISTANCES[1], + -SHADOW_MATRIX_DISTANCES[2], -SHADOW_MATRIX_DISTANCES[3]); + _cascadedShadowMapProgram.release(); } } _renderer = new PrimitiveRenderer(_maxVoxels); @@ -1168,6 +1178,7 @@ glm::vec3 VoxelSystem::computeVoxelVertex(const glm::vec3& startVertex, float vo ProgramObject VoxelSystem::_perlinModulateProgram; ProgramObject VoxelSystem::_shadowMapProgram; +ProgramObject VoxelSystem::_cascadedShadowMapProgram; void VoxelSystem::init() { if (_initialized) { @@ -1488,16 +1499,14 @@ void VoxelSystem::render() { void VoxelSystem::applyScaleAndBindProgram(bool texture) { - if (Menu::getInstance()->isOptionChecked(MenuOption::Shadows)) { - _shadowMapProgram.bind(); + if (Menu::getInstance()->getShadowsEnabled()) { + if (Menu::getInstance()->isOptionChecked(MenuOption::CascadedShadows)) { + _cascadedShadowMapProgram.bind(); + } else { + _shadowMapProgram.bind(); + } glBindTexture(GL_TEXTURE_2D, Application::getInstance()->getTextureCache()->getShadowDepthTextureID()); - for (int i = SHADOW_MATRIX_COUNT - 1; i >= 0; i--) { - glActiveTexture(GL_TEXTURE0 + i); - glTexGenfv(GL_S, GL_EYE_PLANE, (const GLfloat*)&Application::getInstance()->getShadowMatrices()[i][0]); - glTexGenfv(GL_T, GL_EYE_PLANE, (const GLfloat*)&Application::getInstance()->getShadowMatrices()[i][1]); - glTexGenfv(GL_R, GL_EYE_PLANE, (const GLfloat*)&Application::getInstance()->getShadowMatrices()[i][2]); - } } else if (texture) { _perlinModulateProgram.bind(); glBindTexture(GL_TEXTURE_2D, Application::getInstance()->getTextureCache()->getPermutationNormalTextureID()); @@ -1511,11 +1520,14 @@ void VoxelSystem::removeScaleAndReleaseProgram(bool texture) { // scale back down to 1 so heads aren't massive glPopMatrix(); - if (Menu::getInstance()->isOptionChecked(MenuOption::Shadows)) { - _shadowMapProgram.release(); + if (Menu::getInstance()->getShadowsEnabled()) { + if (Menu::getInstance()->isOptionChecked(MenuOption::CascadedShadows)) { + _cascadedShadowMapProgram.release(); + } else { + _shadowMapProgram.release(); + } glBindTexture(GL_TEXTURE_2D, 0); - } else if (texture) { _perlinModulateProgram.release(); glBindTexture(GL_TEXTURE_2D, 0); diff --git a/interface/src/voxels/VoxelSystem.h b/interface/src/voxels/VoxelSystem.h index 15e2b20a75..acd0cd170a 100644 --- a/interface/src/voxels/VoxelSystem.h +++ b/interface/src/voxels/VoxelSystem.h @@ -233,6 +233,7 @@ private: static ProgramObject _perlinModulateProgram; static ProgramObject _shadowMapProgram; + static ProgramObject _cascadedShadowMapProgram; int _hookID; std::vector _freeIndexes; From 391902f79bfdd5ffea0956d1fc525537cbfbf4fa Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Thu, 29 May 2014 15:30:40 -0700 Subject: [PATCH 5/9] Cascaded shadow maps for models. --- .../shaders/cascaded_shadow_map.frag | 15 +- .../shaders/model_cascaded_shadow_map.frag | 56 ++++++ .../model_cascaded_shadow_normal_map.frag | 69 +++++++ ...l_cascaded_shadow_normal_specular_map.frag | 72 ++++++++ .../model_cascaded_shadow_specular_map.frag | 59 ++++++ interface/src/renderer/Model.cpp | 170 ++++++++++++++++-- interface/src/renderer/Model.h | 16 ++ 7 files changed, 440 insertions(+), 17 deletions(-) create mode 100644 interface/resources/shaders/model_cascaded_shadow_map.frag create mode 100644 interface/resources/shaders/model_cascaded_shadow_normal_map.frag create mode 100644 interface/resources/shaders/model_cascaded_shadow_normal_specular_map.frag create mode 100644 interface/resources/shaders/model_cascaded_shadow_specular_map.frag diff --git a/interface/resources/shaders/cascaded_shadow_map.frag b/interface/resources/shaders/cascaded_shadow_map.frag index 9b3e8f7cc7..337f98a228 100644 --- a/interface/resources/shaders/cascaded_shadow_map.frag +++ b/interface/resources/shaders/cascaded_shadow_map.frag @@ -11,10 +11,15 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +// the shadow texture uniform sampler2DShadow shadowMap; +// the distances to the cascade sections uniform vec3 shadowDistances; +// the inverse of the size of the shadow map +const float shadowScale = 1.0 / 2048.0; + // the color in shadow varying vec4 shadowColor; @@ -22,8 +27,14 @@ varying vec4 shadowColor; varying vec4 position; void main(void) { + // compute the index of the cascade to use and the corresponding texture coordinates int shadowIndex = int(dot(step(vec3(position.z), shadowDistances), vec3(1.0, 1.0, 1.0))); - vec3 texCoord = vec3(dot(gl_EyePlaneS[shadowIndex], position), dot(gl_EyePlaneT[shadowIndex], position), + vec3 shadowTexCoord = vec3(dot(gl_EyePlaneS[shadowIndex], position), dot(gl_EyePlaneT[shadowIndex], position), dot(gl_EyePlaneR[shadowIndex], position)); - gl_FragColor = mix(shadowColor, gl_Color, shadow2D(shadowMap, texCoord).r); + + gl_FragColor = mix(shadowColor, gl_Color, 0.25 * + (shadow2D(shadowMap, shadowTexCoord + vec3(-shadowScale, -shadowScale, 0.0)).r + + shadow2D(shadowMap, shadowTexCoord + vec3(-shadowScale, shadowScale, 0.0)).r + + shadow2D(shadowMap, shadowTexCoord + vec3(shadowScale, -shadowScale, 0.0)).r + + shadow2D(shadowMap, shadowTexCoord + vec3(shadowScale, shadowScale, 0.0)).r)); } diff --git a/interface/resources/shaders/model_cascaded_shadow_map.frag b/interface/resources/shaders/model_cascaded_shadow_map.frag new file mode 100644 index 0000000000..720c43b656 --- /dev/null +++ b/interface/resources/shaders/model_cascaded_shadow_map.frag @@ -0,0 +1,56 @@ +#version 120 + +// +// model_cascaded_shadow_map.frag +// fragment shader +// +// Created by Andrzej Kapolka on 5/29/14. +// Copyright 2014 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +// the diffuse texture +uniform sampler2D diffuseMap; + +// the shadow texture +uniform sampler2DShadow shadowMap; + +// the distances to the cascade sections +uniform vec3 shadowDistances; + +// the inverse of the size of the shadow map +const float shadowScale = 1.0 / 2048.0; + +// the interpolated position +varying vec4 position; + +// the interpolated normal +varying vec4 normal; + +void main(void) { + // compute the index of the cascade to use and the corresponding texture coordinates + int shadowIndex = int(dot(step(vec3(position.z), shadowDistances), vec3(1.0, 1.0, 1.0))); + vec3 shadowTexCoord = vec3(dot(gl_EyePlaneS[shadowIndex], position), dot(gl_EyePlaneT[shadowIndex], position), + dot(gl_EyePlaneR[shadowIndex], position)); + + // compute the base color based on OpenGL lighting model + vec4 normalizedNormal = normalize(normal); + float diffuse = dot(normalizedNormal, gl_LightSource[0].position); + float facingLight = step(0.0, diffuse) * 0.25 * + (shadow2D(shadowMap, shadowTexCoord + vec3(-shadowScale, -shadowScale, 0.0)).r + + shadow2D(shadowMap, shadowTexCoord + vec3(-shadowScale, shadowScale, 0.0)).r + + shadow2D(shadowMap, shadowTexCoord + vec3(shadowScale, -shadowScale, 0.0)).r + + shadow2D(shadowMap, shadowTexCoord + vec3(shadowScale, shadowScale, 0.0)).r); + vec4 base = gl_Color * (gl_FrontLightModelProduct.sceneColor + gl_FrontLightProduct[0].ambient + + gl_FrontLightProduct[0].diffuse * (diffuse * facingLight)); + + // compute the specular component (sans exponent) + float specular = facingLight * max(0.0, dot(normalize(gl_LightSource[0].position - normalize(vec4(position.xyz, 0.0))), + normalizedNormal)); + + // modulate texture by base color and add specular contribution + gl_FragColor = base * texture2D(diffuseMap, gl_TexCoord[0].st) + + vec4(pow(specular, gl_FrontMaterial.shininess) * gl_FrontLightProduct[0].specular.rgb, 0.0); +} diff --git a/interface/resources/shaders/model_cascaded_shadow_normal_map.frag b/interface/resources/shaders/model_cascaded_shadow_normal_map.frag new file mode 100644 index 0000000000..5758333392 --- /dev/null +++ b/interface/resources/shaders/model_cascaded_shadow_normal_map.frag @@ -0,0 +1,69 @@ +#version 120 + +// +// model_cascaded_shadow_normal_map.frag +// fragment shader +// +// Created by Andrzej Kapolka on 5/29/14. +// Copyright 2014 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +// the diffuse texture +uniform sampler2D diffuseMap; + +// the normal map texture +uniform sampler2D normalMap; + +// the shadow texture +uniform sampler2DShadow shadowMap; + +// the distances to the cascade sections +uniform vec3 shadowDistances; + +// the inverse of the size of the shadow map +const float shadowScale = 1.0 / 2048.0; + +// the interpolated position +varying vec4 interpolatedPosition; + +// the interpolated normal +varying vec4 interpolatedNormal; + +// the interpolated tangent +varying vec4 interpolatedTangent; + +void main(void) { + vec3 normalizedNormal = normalize(vec3(interpolatedNormal)); + vec3 normalizedTangent = normalize(vec3(interpolatedTangent)); + vec3 normalizedBitangent = normalize(cross(normalizedNormal, normalizedTangent)); + vec3 localNormal = vec3(texture2D(normalMap, gl_TexCoord[0].st)) * 2.0 - vec3(1.0, 1.0, 1.0); + + // compute the index of the cascade to use and the corresponding texture coordinates + int shadowIndex = int(dot(step(vec3(interpolatedPosition.z), shadowDistances), vec3(1.0, 1.0, 1.0))); + vec3 shadowTexCoord = vec3(dot(gl_EyePlaneS[shadowIndex], interpolatedPosition), + dot(gl_EyePlaneT[shadowIndex], interpolatedPosition), + dot(gl_EyePlaneR[shadowIndex], interpolatedPosition)); + + // compute the base color based on OpenGL lighting model + vec4 viewNormal = vec4(normalizedTangent * localNormal.x + + normalizedBitangent * localNormal.y + normalizedNormal * localNormal.z, 0.0); + float diffuse = dot(viewNormal, gl_LightSource[0].position); + float facingLight = step(0.0, diffuse) * 0.25 * + (shadow2D(shadowMap, shadowTexCoord + vec3(-shadowScale, -shadowScale, 0.0)).r + + shadow2D(shadowMap, shadowTexCoord + vec3(-shadowScale, shadowScale, 0.0)).r + + shadow2D(shadowMap, shadowTexCoord + vec3(shadowScale, -shadowScale, 0.0)).r + + shadow2D(shadowMap, shadowTexCoord + vec3(shadowScale, shadowScale, 0.0)).r); + vec4 base = gl_Color * (gl_FrontLightModelProduct.sceneColor + gl_FrontLightProduct[0].ambient + + gl_FrontLightProduct[0].diffuse * (diffuse * facingLight)); + + // compute the specular component (sans exponent) + float specular = facingLight * max(0.0, dot(normalize(gl_LightSource[0].position - + normalize(vec4(vec3(interpolatedPosition), 0.0))), viewNormal)); + + // modulate texture by base color and add specular contribution + gl_FragColor = base * texture2D(diffuseMap, gl_TexCoord[0].st) + + vec4(pow(specular, gl_FrontMaterial.shininess) * gl_FrontLightProduct[0].specular.rgb, 0.0); +} diff --git a/interface/resources/shaders/model_cascaded_shadow_normal_specular_map.frag b/interface/resources/shaders/model_cascaded_shadow_normal_specular_map.frag new file mode 100644 index 0000000000..2b949710f3 --- /dev/null +++ b/interface/resources/shaders/model_cascaded_shadow_normal_specular_map.frag @@ -0,0 +1,72 @@ +#version 120 + +// +// model_cascaded_shadow_normal_specular_map.frag +// fragment shader +// +// Created by Andrzej Kapolka on 5/29/14. +// Copyright 2014 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +// the diffuse texture +uniform sampler2D diffuseMap; + +// the normal map texture +uniform sampler2D normalMap; + +// the specular map texture +uniform sampler2D specularMap; + +// the shadow texture +uniform sampler2DShadow shadowMap; + +// the distances to the cascade sections +uniform vec3 shadowDistances; + +// the inverse of the size of the shadow map +const float shadowScale = 1.0 / 2048.0; + +// the interpolated position +varying vec4 interpolatedPosition; + +// the interpolated normal +varying vec4 interpolatedNormal; + +// the interpolated tangent +varying vec4 interpolatedTangent; + +void main(void) { + vec3 normalizedNormal = normalize(vec3(interpolatedNormal)); + vec3 normalizedTangent = normalize(vec3(interpolatedTangent)); + vec3 normalizedBitangent = normalize(cross(normalizedNormal, normalizedTangent)); + vec3 localNormal = vec3(texture2D(normalMap, gl_TexCoord[0].st)) * 2.0 - vec3(1.0, 1.0, 1.0); + + // compute the index of the cascade to use and the corresponding texture coordinates + int shadowIndex = int(dot(step(vec3(interpolatedPosition.z), shadowDistances), vec3(1.0, 1.0, 1.0))); + vec3 shadowTexCoord = vec3(dot(gl_EyePlaneS[shadowIndex], interpolatedPosition), + dot(gl_EyePlaneT[shadowIndex], interpolatedPosition), + dot(gl_EyePlaneR[shadowIndex], interpolatedPosition)); + + // compute the base color based on OpenGL lighting model + vec4 viewNormal = vec4(normalizedTangent * localNormal.x + + normalizedBitangent * localNormal.y + normalizedNormal * localNormal.z, 0.0); + float diffuse = dot(viewNormal, gl_LightSource[0].position); + float facingLight = step(0.0, diffuse) * 0.25 * + (shadow2D(shadowMap, shadowTexCoord + vec3(-shadowScale, -shadowScale, 0.0)).r + + shadow2D(shadowMap, shadowTexCoord + vec3(-shadowScale, shadowScale, 0.0)).r + + shadow2D(shadowMap, shadowTexCoord + vec3(shadowScale, -shadowScale, 0.0)).r + + shadow2D(shadowMap, shadowTexCoord + vec3(shadowScale, shadowScale, 0.0)).r); + vec4 base = gl_Color * (gl_FrontLightModelProduct.sceneColor + gl_FrontLightProduct[0].ambient + + gl_FrontLightProduct[0].diffuse * (diffuse * facingLight)); + + // compute the specular component (sans exponent) + float specular = facingLight * max(0.0, dot(normalize(gl_LightSource[0].position - + normalize(vec4(interpolatedPosition.xyz, 0.0))), viewNormal)); + + // modulate texture by base color and add specular contribution + gl_FragColor = base * texture2D(diffuseMap, gl_TexCoord[0].st) + vec4(pow(specular, gl_FrontMaterial.shininess) * + gl_FrontLightProduct[0].specular.rgb * texture2D(specularMap, gl_TexCoord[0].st).rgb, 0.0); +} diff --git a/interface/resources/shaders/model_cascaded_shadow_specular_map.frag b/interface/resources/shaders/model_cascaded_shadow_specular_map.frag new file mode 100644 index 0000000000..ba8ba6b85b --- /dev/null +++ b/interface/resources/shaders/model_cascaded_shadow_specular_map.frag @@ -0,0 +1,59 @@ +#version 120 + +// +// model_cascaded_shadow_specular_map.frag +// fragment shader +// +// Created by Andrzej Kapolka on 5/29/14. +// Copyright 2014 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +// the diffuse texture +uniform sampler2D diffuseMap; + +// the specular texture +uniform sampler2D specularMap; + +// the shadow texture +uniform sampler2DShadow shadowMap; + +// the distances to the cascade sections +uniform vec3 shadowDistances; + +// the inverse of the size of the shadow map +const float shadowScale = 1.0 / 2048.0; + +// the interpolated position in view space +varying vec4 position; + +// the interpolated normal +varying vec4 normal; + +void main(void) { + // compute the index of the cascade to use and the corresponding texture coordinates + int shadowIndex = int(dot(step(vec3(position.z), shadowDistances), vec3(1.0, 1.0, 1.0))); + vec3 shadowTexCoord = vec3(dot(gl_EyePlaneS[shadowIndex], position), dot(gl_EyePlaneT[shadowIndex], position), + dot(gl_EyePlaneR[shadowIndex], position)); + + // compute the base color based on OpenGL lighting model + vec4 normalizedNormal = normalize(normal); + float diffuse = dot(normalizedNormal, gl_LightSource[0].position); + float facingLight = step(0.0, diffuse) * 0.25 * + (shadow2D(shadowMap, gl_TexCoord[1].stp + vec3(-shadowScale, -shadowScale, 0.0)).r + + shadow2D(shadowMap, gl_TexCoord[1].stp + vec3(-shadowScale, shadowScale, 0.0)).r + + shadow2D(shadowMap, gl_TexCoord[1].stp + vec3(shadowScale, -shadowScale, 0.0)).r + + shadow2D(shadowMap, gl_TexCoord[1].stp + vec3(shadowScale, shadowScale, 0.0)).r); + vec4 base = gl_Color * (gl_FrontLightModelProduct.sceneColor + gl_FrontLightProduct[0].ambient + + gl_FrontLightProduct[0].diffuse * (diffuse * facingLight)); + + // compute the specular component (sans exponent) + float specular = facingLight * max(0.0, dot(normalize(gl_LightSource[0].position - normalize(vec4(position.xyz, 0.0))), + normalizedNormal)); + + // modulate texture by base color and add specular contribution + gl_FragColor = base * texture2D(diffuseMap, gl_TexCoord[0].st) + vec4(pow(specular, gl_FrontMaterial.shininess) * + gl_FrontLightProduct[0].specular.rgb * texture2D(specularMap, gl_TexCoord[0].st).rgb, 0.0); +} diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index 1839e20ef7..a550064ef1 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -65,6 +65,11 @@ ProgramObject Model::_shadowNormalMapProgram; ProgramObject Model::_shadowSpecularMapProgram; ProgramObject Model::_shadowNormalSpecularMapProgram; +ProgramObject Model::_cascadedShadowMapProgram; +ProgramObject Model::_cascadedShadowNormalMapProgram; +ProgramObject Model::_cascadedShadowSpecularMapProgram; +ProgramObject Model::_cascadedShadowNormalSpecularMapProgram; + ProgramObject Model::_shadowProgram; ProgramObject Model::_skinProgram; @@ -77,12 +82,19 @@ ProgramObject Model::_skinShadowNormalMapProgram; ProgramObject Model::_skinShadowSpecularMapProgram; ProgramObject Model::_skinShadowNormalSpecularMapProgram; +ProgramObject Model::_skinCascadedShadowMapProgram; +ProgramObject Model::_skinCascadedShadowNormalMapProgram; +ProgramObject Model::_skinCascadedShadowSpecularMapProgram; +ProgramObject Model::_skinCascadedShadowNormalSpecularMapProgram; + ProgramObject Model::_skinShadowProgram; int Model::_normalMapTangentLocation; int Model::_normalSpecularMapTangentLocation; int Model::_shadowNormalMapTangentLocation; int Model::_shadowNormalSpecularMapTangentLocation; +int Model::_cascadedShadowNormalMapTangentLocation; +int Model::_cascadedShadowNormalSpecularMapTangentLocation; Model::SkinLocations Model::_skinLocations; Model::SkinLocations Model::_skinNormalMapLocations; @@ -92,6 +104,10 @@ Model::SkinLocations Model::_skinShadowMapLocations; Model::SkinLocations Model::_skinShadowNormalMapLocations; Model::SkinLocations Model::_skinShadowSpecularMapLocations; Model::SkinLocations Model::_skinShadowNormalSpecularMapLocations; +Model::SkinLocations Model::_skinCascadedShadowMapLocations; +Model::SkinLocations Model::_skinCascadedShadowNormalMapLocations; +Model::SkinLocations Model::_skinCascadedShadowSpecularMapLocations; +Model::SkinLocations Model::_skinCascadedShadowNormalSpecularMapLocations; Model::SkinLocations Model::_skinShadowLocations; void Model::setScale(const glm::vec3& scale) { @@ -132,6 +148,8 @@ void Model::initSkinProgram(ProgramObject& program, Model::SkinLocations& locati program.setUniformValue("normalMap", 1); program.setUniformValue("specularMap", specularTextureUnit); program.setUniformValue("shadowMap", shadowTextureUnit); + program.setUniformValue("shadowDistances", -SHADOW_MATRIX_DISTANCES[1], + -SHADOW_MATRIX_DISTANCES[2], -SHADOW_MATRIX_DISTANCES[3]); program.release(); } @@ -229,7 +247,7 @@ void Model::init() { _normalSpecularMapProgram.setUniformValue("diffuseMap", 0); _normalSpecularMapProgram.setUniformValue("normalMap", 1); _normalSpecularMapProgram.setUniformValue("specularMap", 2); - _normalSpecularMapTangentLocation = _normalMapProgram.attributeLocation("tangent"); + _normalSpecularMapTangentLocation = _normalSpecularMapProgram.attributeLocation("tangent"); _normalSpecularMapProgram.release(); @@ -279,10 +297,69 @@ void Model::init() { _shadowNormalSpecularMapProgram.setUniformValue("normalMap", 1); _shadowNormalSpecularMapProgram.setUniformValue("specularMap", 2); _shadowNormalSpecularMapProgram.setUniformValue("shadowMap", 3); - _shadowNormalSpecularMapTangentLocation = _normalMapProgram.attributeLocation("tangent"); + _shadowNormalSpecularMapTangentLocation = _shadowNormalSpecularMapProgram.attributeLocation("tangent"); _shadowNormalSpecularMapProgram.release(); + _cascadedShadowMapProgram.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() + + "shaders/model.vert"); + _cascadedShadowMapProgram.addShaderFromSourceFile(QGLShader::Fragment, Application::resourcesPath() + + "shaders/model_cascaded_shadow_map.frag"); + _cascadedShadowMapProgram.link(); + + _cascadedShadowMapProgram.bind(); + _cascadedShadowMapProgram.setUniformValue("diffuseMap", 0); + _cascadedShadowMapProgram.setUniformValue("shadowMap", 1); + _cascadedShadowMapProgram.setUniformValue("shadowDistances", -SHADOW_MATRIX_DISTANCES[1], + -SHADOW_MATRIX_DISTANCES[2], -SHADOW_MATRIX_DISTANCES[3]); + _cascadedShadowMapProgram.release(); + + _cascadedShadowNormalMapProgram.addShaderFromSourceFile(QGLShader::Vertex, + Application::resourcesPath() + "shaders/model_normal_map.vert"); + _cascadedShadowNormalMapProgram.addShaderFromSourceFile(QGLShader::Fragment, + Application::resourcesPath() + "shaders/model_cascaded_shadow_normal_map.frag"); + _cascadedShadowNormalMapProgram.link(); + + _cascadedShadowNormalMapProgram.bind(); + _cascadedShadowNormalMapProgram.setUniformValue("diffuseMap", 0); + _cascadedShadowNormalMapProgram.setUniformValue("normalMap", 1); + _cascadedShadowNormalMapProgram.setUniformValue("shadowMap", 2); + _cascadedShadowNormalMapProgram.setUniformValue("shadowDistances", -SHADOW_MATRIX_DISTANCES[1], + -SHADOW_MATRIX_DISTANCES[2], -SHADOW_MATRIX_DISTANCES[3]); + _cascadedShadowNormalMapTangentLocation = _cascadedShadowNormalMapProgram.attributeLocation("tangent"); + _cascadedShadowNormalMapProgram.release(); + + _cascadedShadowSpecularMapProgram.addShaderFromSourceFile(QGLShader::Vertex, + Application::resourcesPath() + "shaders/model.vert"); + _cascadedShadowSpecularMapProgram.addShaderFromSourceFile(QGLShader::Fragment, + Application::resourcesPath() + "shaders/model_cascaded_shadow_specular_map.frag"); + _cascadedShadowSpecularMapProgram.link(); + + _cascadedShadowSpecularMapProgram.bind(); + _cascadedShadowSpecularMapProgram.setUniformValue("diffuseMap", 0); + _cascadedShadowSpecularMapProgram.setUniformValue("specularMap", 1); + _cascadedShadowSpecularMapProgram.setUniformValue("shadowMap", 2); + _cascadedShadowSpecularMapProgram.setUniformValue("shadowDistances", -SHADOW_MATRIX_DISTANCES[1], + -SHADOW_MATRIX_DISTANCES[2], -SHADOW_MATRIX_DISTANCES[3]); + _cascadedShadowSpecularMapProgram.release(); + + _cascadedShadowNormalSpecularMapProgram.addShaderFromSourceFile(QGLShader::Vertex, + Application::resourcesPath() + "shaders/model_normal_map.vert"); + _cascadedShadowNormalSpecularMapProgram.addShaderFromSourceFile(QGLShader::Fragment, + Application::resourcesPath() + "shaders/model_cascaded_shadow_normal_specular_map.frag"); + _cascadedShadowNormalSpecularMapProgram.link(); + + _cascadedShadowNormalSpecularMapProgram.bind(); + _cascadedShadowNormalSpecularMapProgram.setUniformValue("diffuseMap", 0); + _cascadedShadowNormalSpecularMapProgram.setUniformValue("normalMap", 1); + _cascadedShadowNormalSpecularMapProgram.setUniformValue("specularMap", 2); + _cascadedShadowNormalSpecularMapProgram.setUniformValue("shadowMap", 3); + _cascadedShadowNormalSpecularMapProgram.setUniformValue("shadowDistances", -SHADOW_MATRIX_DISTANCES[1], + -SHADOW_MATRIX_DISTANCES[2], -SHADOW_MATRIX_DISTANCES[3]); + _cascadedShadowNormalSpecularMapTangentLocation = _cascadedShadowNormalSpecularMapProgram.attributeLocation("tangent"); + _cascadedShadowNormalSpecularMapProgram.release(); + + _shadowProgram.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() + "shaders/model_shadow.vert"); _shadowProgram.addShaderFromSourceFile(QGLShader::Fragment, Application::resourcesPath() + "shaders/model_shadow.frag"); @@ -353,6 +430,39 @@ void Model::init() { initSkinProgram(_skinShadowNormalSpecularMapProgram, _skinShadowNormalSpecularMapLocations, 2, 3); + _skinCascadedShadowMapProgram.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() + + "shaders/skin_model.vert"); + _skinCascadedShadowMapProgram.addShaderFromSourceFile(QGLShader::Fragment, Application::resourcesPath() + + "shaders/model_cascaded_shadow_map.frag"); + _skinCascadedShadowMapProgram.link(); + + initSkinProgram(_skinCascadedShadowMapProgram, _skinCascadedShadowMapLocations); + + _skinCascadedShadowNormalMapProgram.addShaderFromSourceFile(QGLShader::Vertex, + Application::resourcesPath() + "shaders/skin_model_normal_map.vert"); + _skinCascadedShadowNormalMapProgram.addShaderFromSourceFile(QGLShader::Fragment, + Application::resourcesPath() + "shaders/model_cascaded_shadow_normal_map.frag"); + _skinCascadedShadowNormalMapProgram.link(); + + initSkinProgram(_skinCascadedShadowNormalMapProgram, _skinCascadedShadowNormalMapLocations, 1, 2); + + _skinCascadedShadowSpecularMapProgram.addShaderFromSourceFile(QGLShader::Vertex, + Application::resourcesPath() + "shaders/skin_model.vert"); + _skinCascadedShadowSpecularMapProgram.addShaderFromSourceFile(QGLShader::Fragment, + Application::resourcesPath() + "shaders/model_cascaded_shadow_specular_map.frag"); + _skinCascadedShadowSpecularMapProgram.link(); + + initSkinProgram(_skinCascadedShadowSpecularMapProgram, _skinCascadedShadowSpecularMapLocations, 1, 2); + + _skinCascadedShadowNormalSpecularMapProgram.addShaderFromSourceFile(QGLShader::Vertex, + Application::resourcesPath() + "shaders/skin_model_normal_map.vert"); + _skinCascadedShadowNormalSpecularMapProgram.addShaderFromSourceFile(QGLShader::Fragment, + Application::resourcesPath() + "shaders/model_cascaded_shadow_normal_specular_map.frag"); + _skinCascadedShadowNormalSpecularMapProgram.link(); + + initSkinProgram(_skinCascadedShadowNormalSpecularMapProgram, _skinCascadedShadowNormalSpecularMapLocations, 2, 3); + + _skinShadowProgram.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() + "shaders/skin_model_shadow.vert"); _skinShadowProgram.addShaderFromSourceFile(QGLShader::Fragment, @@ -1508,6 +1618,7 @@ void Model::renderMeshes(float alpha, RenderMode mode, bool translucent, bool re const FBXGeometry& geometry = _geometry->getFBXGeometry(); const QVector& networkMeshes = _geometry->getMeshes(); + bool cascadedShadows = Menu::getInstance()->isOptionChecked(MenuOption::CascadedShadows); for (int i = 0; i < networkMeshes.size(); i++) { // exit early if the translucency doesn't match what we're drawing const NetworkMesh& networkMesh = networkMeshes.at(i); @@ -1529,6 +1640,7 @@ void Model::renderMeshes(float alpha, RenderMode mode, bool translucent, bool re ProgramObject* program = &_program; ProgramObject* skinProgram = &_skinProgram; SkinLocations* skinLocations = &_skinLocations; + int tangentLocation = _normalMapTangentLocation; GLenum specularTextureUnit = 0; GLenum shadowTextureUnit = 0; if (mode == SHADOW_RENDER_MODE) { @@ -1539,21 +1651,38 @@ void Model::renderMeshes(float alpha, RenderMode mode, bool translucent, bool re } else if (!mesh.tangents.isEmpty()) { if (mesh.hasSpecularTexture()) { if (receiveShadows) { - program = &_shadowNormalSpecularMapProgram; - skinProgram = &_skinShadowNormalSpecularMapProgram; - skinLocations = &_skinShadowNormalSpecularMapLocations; + if (cascadedShadows) { + program = &_cascadedShadowNormalSpecularMapProgram; + skinProgram = &_skinCascadedShadowNormalSpecularMapProgram; + skinLocations = &_skinCascadedShadowNormalSpecularMapLocations; + tangentLocation = _cascadedShadowNormalSpecularMapTangentLocation; + } else { + program = &_shadowNormalSpecularMapProgram; + skinProgram = &_skinShadowNormalSpecularMapProgram; + skinLocations = &_skinShadowNormalSpecularMapLocations; + tangentLocation = _shadowNormalSpecularMapTangentLocation; + } shadowTextureUnit = GL_TEXTURE3; } else { program = &_normalSpecularMapProgram; skinProgram = &_skinNormalSpecularMapProgram; skinLocations = &_skinNormalSpecularMapLocations; + tangentLocation = _normalSpecularMapTangentLocation; } specularTextureUnit = GL_TEXTURE2; } else if (receiveShadows) { - program = &_shadowNormalMapProgram; - skinProgram = &_skinShadowNormalMapProgram; - skinLocations = &_skinShadowNormalMapLocations; + if (cascadedShadows) { + program = &_cascadedShadowNormalMapProgram; + skinProgram = &_skinCascadedShadowNormalMapProgram; + skinLocations = &_skinCascadedShadowNormalMapLocations; + tangentLocation = _cascadedShadowNormalMapTangentLocation; + } else { + program = &_shadowNormalMapProgram; + skinProgram = &_skinShadowNormalMapProgram; + skinLocations = &_skinShadowNormalMapLocations; + tangentLocation = _shadowNormalMapTangentLocation; + } shadowTextureUnit = GL_TEXTURE2; } else { program = &_normalMapProgram; @@ -1562,9 +1691,15 @@ void Model::renderMeshes(float alpha, RenderMode mode, bool translucent, bool re } } else if (mesh.hasSpecularTexture()) { if (receiveShadows) { - program = &_shadowSpecularMapProgram; - skinProgram = &_skinShadowSpecularMapProgram; - skinLocations = &_skinShadowSpecularMapLocations; + if (cascadedShadows) { + program = &_cascadedShadowSpecularMapProgram; + skinProgram = &_skinCascadedShadowSpecularMapProgram; + skinLocations = &_skinCascadedShadowSpecularMapLocations; + } else { + program = &_shadowSpecularMapProgram; + skinProgram = &_skinShadowSpecularMapProgram; + skinLocations = &_skinShadowSpecularMapLocations; + } shadowTextureUnit = GL_TEXTURE2; } else { program = &_specularMapProgram; @@ -1574,15 +1709,20 @@ void Model::renderMeshes(float alpha, RenderMode mode, bool translucent, bool re specularTextureUnit = GL_TEXTURE1; } else if (receiveShadows) { - program = &_shadowMapProgram; - skinProgram = &_skinShadowMapProgram; - skinLocations = &_skinShadowMapLocations; + if (cascadedShadows) { + program = &_cascadedShadowMapProgram; + skinProgram = &_skinCascadedShadowMapProgram; + skinLocations = &_skinCascadedShadowMapLocations; + } else { + program = &_shadowMapProgram; + skinProgram = &_skinShadowMapProgram; + skinLocations = &_skinShadowMapLocations; + } shadowTextureUnit = GL_TEXTURE1; } const MeshState& state = _meshStates.at(i); ProgramObject* activeProgram = program; - int tangentLocation = _normalMapTangentLocation; glPushMatrix(); Application::getInstance()->loadTranslatedViewMatrix(_translation); diff --git a/interface/src/renderer/Model.h b/interface/src/renderer/Model.h index a4e45287dd..5561855afb 100644 --- a/interface/src/renderer/Model.h +++ b/interface/src/renderer/Model.h @@ -280,6 +280,11 @@ private: static ProgramObject _shadowSpecularMapProgram; static ProgramObject _shadowNormalSpecularMapProgram; + static ProgramObject _cascadedShadowMapProgram; + static ProgramObject _cascadedShadowNormalMapProgram; + static ProgramObject _cascadedShadowSpecularMapProgram; + static ProgramObject _cascadedShadowNormalSpecularMapProgram; + static ProgramObject _shadowProgram; static ProgramObject _skinProgram; @@ -292,12 +297,19 @@ private: static ProgramObject _skinShadowSpecularMapProgram; static ProgramObject _skinShadowNormalSpecularMapProgram; + static ProgramObject _skinCascadedShadowMapProgram; + static ProgramObject _skinCascadedShadowNormalMapProgram; + static ProgramObject _skinCascadedShadowSpecularMapProgram; + static ProgramObject _skinCascadedShadowNormalSpecularMapProgram; + static ProgramObject _skinShadowProgram; static int _normalMapTangentLocation; static int _normalSpecularMapTangentLocation; static int _shadowNormalMapTangentLocation; static int _shadowNormalSpecularMapTangentLocation; + static int _cascadedShadowNormalMapTangentLocation; + static int _cascadedShadowNormalSpecularMapTangentLocation; class SkinLocations { public: @@ -315,6 +327,10 @@ private: static SkinLocations _skinShadowNormalMapLocations; static SkinLocations _skinShadowSpecularMapLocations; static SkinLocations _skinShadowNormalSpecularMapLocations; + static SkinLocations _skinCascadedShadowMapLocations; + static SkinLocations _skinCascadedShadowNormalMapLocations; + static SkinLocations _skinCascadedShadowSpecularMapLocations; + static SkinLocations _skinCascadedShadowNormalSpecularMapLocations; static SkinLocations _skinShadowLocations; static void initSkinProgram(ProgramObject& program, SkinLocations& locations, From 0b4484a153ec22e58f7a244d9e0e2bc6fdb14d10 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Thu, 29 May 2014 16:49:51 -0700 Subject: [PATCH 6/9] Trying a different way of determining the cascade threshold distances. --- interface/src/Application.cpp | 3 +++ interface/src/Application.h | 3 +++ interface/src/voxels/VoxelSystem.cpp | 5 +++-- interface/src/voxels/VoxelSystem.h | 1 + 4 files changed, 10 insertions(+), 2 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index af94ddba01..bcb52cfabc 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2298,6 +2298,9 @@ void Application::updateShadowMap() { for (size_t j = 0; j < sizeof(points) / sizeof(points[0]); j++) { radius = qMax(radius, glm::distance(points[j], center)); } + if (i < 3) { + _shadowDistances[i] = -glm::distance(_viewFrustum.getPosition(), center) - radius; + } center = inverseRotation * center; // to reduce texture "shimmer," move in texel increments diff --git a/interface/src/Application.h b/interface/src/Application.h index 68d437815b..3fcf40b95b 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -266,6 +266,8 @@ public: void getModelViewMatrix(glm::dmat4* modelViewMatrix); void getProjectionMatrix(glm::dmat4* projectionMatrix); + const glm::vec3& getShadowDistances() const { return _shadowDistances; } + /// Computes the off-axis frustum parameters for the view frustum, taking mirroring into account. void computeOffAxisFrustum(float& left, float& right, float& bottom, float& top, float& nearVal, float& farVal, glm::vec4& nearClipPlane, glm::vec4& farClipPlane) const; @@ -493,6 +495,7 @@ private: static const int CASCADED_SHADOW_MATRIX_COUNT = 4; glm::mat4 _shadowMatrices[CASCADED_SHADOW_MATRIX_COUNT]; + glm::vec3 _shadowDistances; Environment _environment; diff --git a/interface/src/voxels/VoxelSystem.cpp b/interface/src/voxels/VoxelSystem.cpp index 3525a086b4..2b86a58d9b 100644 --- a/interface/src/voxels/VoxelSystem.cpp +++ b/interface/src/voxels/VoxelSystem.cpp @@ -528,8 +528,7 @@ void VoxelSystem::initVoxelMemory() { _cascadedShadowMapProgram.bind(); _cascadedShadowMapProgram.setUniformValue("shadowMap", 0); - _cascadedShadowMapProgram.setUniformValue("shadowDistances", -SHADOW_MATRIX_DISTANCES[1], - -SHADOW_MATRIX_DISTANCES[2], -SHADOW_MATRIX_DISTANCES[3]); + _shadowDistancesLocation = _cascadedShadowMapProgram.uniformLocation("shadowDistances"); _cascadedShadowMapProgram.release(); } } @@ -1179,6 +1178,7 @@ glm::vec3 VoxelSystem::computeVoxelVertex(const glm::vec3& startVertex, float vo ProgramObject VoxelSystem::_perlinModulateProgram; ProgramObject VoxelSystem::_shadowMapProgram; ProgramObject VoxelSystem::_cascadedShadowMapProgram; +int VoxelSystem::_shadowDistancesLocation; void VoxelSystem::init() { if (_initialized) { @@ -1502,6 +1502,7 @@ void VoxelSystem::applyScaleAndBindProgram(bool texture) { if (Menu::getInstance()->getShadowsEnabled()) { if (Menu::getInstance()->isOptionChecked(MenuOption::CascadedShadows)) { _cascadedShadowMapProgram.bind(); + _cascadedShadowMapProgram.setUniform(_shadowDistancesLocation, Application::getInstance()->getShadowDistances()); } else { _shadowMapProgram.bind(); } diff --git a/interface/src/voxels/VoxelSystem.h b/interface/src/voxels/VoxelSystem.h index acd0cd170a..71abc9ca93 100644 --- a/interface/src/voxels/VoxelSystem.h +++ b/interface/src/voxels/VoxelSystem.h @@ -234,6 +234,7 @@ private: static ProgramObject _perlinModulateProgram; static ProgramObject _shadowMapProgram; static ProgramObject _cascadedShadowMapProgram; + static int _shadowDistancesLocation; int _hookID; std::vector _freeIndexes; From 12beef7fec0a8e958c77a82a11b5322696917be4 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Thu, 29 May 2014 17:08:36 -0700 Subject: [PATCH 7/9] Apply the new shadow distances to the models, too. --- interface/src/renderer/Model.cpp | 32 +++++++++++++++++++++----------- interface/src/renderer/Model.h | 6 ++++++ 2 files changed, 27 insertions(+), 11 deletions(-) diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index a550064ef1..85392bd353 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -96,6 +96,11 @@ int Model::_shadowNormalSpecularMapTangentLocation; int Model::_cascadedShadowNormalMapTangentLocation; int Model::_cascadedShadowNormalSpecularMapTangentLocation; +int Model::_cascadedShadowMapDistancesLocation; +int Model::_cascadedShadowNormalMapDistancesLocation; +int Model::_cascadedShadowSpecularMapDistancesLocation; +int Model::_cascadedShadowNormalSpecularMapDistancesLocation; + Model::SkinLocations Model::_skinLocations; Model::SkinLocations Model::_skinNormalMapLocations; Model::SkinLocations Model::_skinSpecularMapLocations; @@ -144,12 +149,11 @@ void Model::initSkinProgram(ProgramObject& program, Model::SkinLocations& locati locations.clusterIndices = program.attributeLocation("clusterIndices"); locations.clusterWeights = program.attributeLocation("clusterWeights"); locations.tangent = program.attributeLocation("tangent"); + locations.shadowDistances = program.uniformLocation("shadowDistances"); program.setUniformValue("diffuseMap", 0); program.setUniformValue("normalMap", 1); program.setUniformValue("specularMap", specularTextureUnit); program.setUniformValue("shadowMap", shadowTextureUnit); - program.setUniformValue("shadowDistances", -SHADOW_MATRIX_DISTANCES[1], - -SHADOW_MATRIX_DISTANCES[2], -SHADOW_MATRIX_DISTANCES[3]); program.release(); } @@ -310,8 +314,7 @@ void Model::init() { _cascadedShadowMapProgram.bind(); _cascadedShadowMapProgram.setUniformValue("diffuseMap", 0); _cascadedShadowMapProgram.setUniformValue("shadowMap", 1); - _cascadedShadowMapProgram.setUniformValue("shadowDistances", -SHADOW_MATRIX_DISTANCES[1], - -SHADOW_MATRIX_DISTANCES[2], -SHADOW_MATRIX_DISTANCES[3]); + _cascadedShadowMapDistancesLocation = _cascadedShadowMapProgram.uniformLocation("shadowDistances"); _cascadedShadowMapProgram.release(); _cascadedShadowNormalMapProgram.addShaderFromSourceFile(QGLShader::Vertex, @@ -324,8 +327,7 @@ void Model::init() { _cascadedShadowNormalMapProgram.setUniformValue("diffuseMap", 0); _cascadedShadowNormalMapProgram.setUniformValue("normalMap", 1); _cascadedShadowNormalMapProgram.setUniformValue("shadowMap", 2); - _cascadedShadowNormalMapProgram.setUniformValue("shadowDistances", -SHADOW_MATRIX_DISTANCES[1], - -SHADOW_MATRIX_DISTANCES[2], -SHADOW_MATRIX_DISTANCES[3]); + _cascadedShadowNormalMapDistancesLocation = _cascadedShadowNormalMapProgram.uniformLocation("shadowDistances"); _cascadedShadowNormalMapTangentLocation = _cascadedShadowNormalMapProgram.attributeLocation("tangent"); _cascadedShadowNormalMapProgram.release(); @@ -339,8 +341,7 @@ void Model::init() { _cascadedShadowSpecularMapProgram.setUniformValue("diffuseMap", 0); _cascadedShadowSpecularMapProgram.setUniformValue("specularMap", 1); _cascadedShadowSpecularMapProgram.setUniformValue("shadowMap", 2); - _cascadedShadowSpecularMapProgram.setUniformValue("shadowDistances", -SHADOW_MATRIX_DISTANCES[1], - -SHADOW_MATRIX_DISTANCES[2], -SHADOW_MATRIX_DISTANCES[3]); + _cascadedShadowSpecularMapDistancesLocation = _cascadedShadowSpecularMapProgram.uniformLocation("shadowDistances"); _cascadedShadowSpecularMapProgram.release(); _cascadedShadowNormalSpecularMapProgram.addShaderFromSourceFile(QGLShader::Vertex, @@ -354,8 +355,8 @@ void Model::init() { _cascadedShadowNormalSpecularMapProgram.setUniformValue("normalMap", 1); _cascadedShadowNormalSpecularMapProgram.setUniformValue("specularMap", 2); _cascadedShadowNormalSpecularMapProgram.setUniformValue("shadowMap", 3); - _cascadedShadowNormalSpecularMapProgram.setUniformValue("shadowDistances", -SHADOW_MATRIX_DISTANCES[1], - -SHADOW_MATRIX_DISTANCES[2], -SHADOW_MATRIX_DISTANCES[3]); + _cascadedShadowNormalSpecularMapDistancesLocation = + _cascadedShadowNormalSpecularMapProgram.uniformLocation("shadowDistances"); _cascadedShadowNormalSpecularMapTangentLocation = _cascadedShadowNormalSpecularMapProgram.attributeLocation("tangent"); _cascadedShadowNormalSpecularMapProgram.release(); @@ -1641,6 +1642,7 @@ void Model::renderMeshes(float alpha, RenderMode mode, bool translucent, bool re ProgramObject* skinProgram = &_skinProgram; SkinLocations* skinLocations = &_skinLocations; int tangentLocation = _normalMapTangentLocation; + int shadowDistancesLocation = _cascadedShadowMapDistancesLocation; GLenum specularTextureUnit = 0; GLenum shadowTextureUnit = 0; if (mode == SHADOW_RENDER_MODE) { @@ -1656,6 +1658,7 @@ void Model::renderMeshes(float alpha, RenderMode mode, bool translucent, bool re skinProgram = &_skinCascadedShadowNormalSpecularMapProgram; skinLocations = &_skinCascadedShadowNormalSpecularMapLocations; tangentLocation = _cascadedShadowNormalSpecularMapTangentLocation; + shadowDistancesLocation = _cascadedShadowNormalSpecularMapDistancesLocation; } else { program = &_shadowNormalSpecularMapProgram; skinProgram = &_skinShadowNormalSpecularMapProgram; @@ -1677,6 +1680,7 @@ void Model::renderMeshes(float alpha, RenderMode mode, bool translucent, bool re skinProgram = &_skinCascadedShadowNormalMapProgram; skinLocations = &_skinCascadedShadowNormalMapLocations; tangentLocation = _cascadedShadowNormalMapTangentLocation; + shadowDistancesLocation = _cascadedShadowNormalMapDistancesLocation; } else { program = &_shadowNormalMapProgram; skinProgram = &_skinShadowNormalMapProgram; @@ -1695,6 +1699,7 @@ void Model::renderMeshes(float alpha, RenderMode mode, bool translucent, bool re program = &_cascadedShadowSpecularMapProgram; skinProgram = &_skinCascadedShadowSpecularMapProgram; skinLocations = &_skinCascadedShadowSpecularMapLocations; + shadowDistancesLocation = _cascadedShadowSpecularMapDistancesLocation; } else { program = &_shadowSpecularMapProgram; skinProgram = &_skinShadowSpecularMapProgram; @@ -1740,10 +1745,15 @@ void Model::renderMeshes(float alpha, RenderMode mode, bool translucent, bool re skinProgram->enableAttributeArray(skinLocations->clusterWeights); activeProgram = skinProgram; tangentLocation = skinLocations->tangent; - + if (cascadedShadows) { + program->setUniform(skinLocations->shadowDistances, Application::getInstance()->getShadowDistances()); + } } else { glMultMatrixf((const GLfloat*)&state.clusterMatrices[0]); program->bind(); + if (cascadedShadows) { + program->setUniform(shadowDistancesLocation, Application::getInstance()->getShadowDistances()); + } } if (mesh.blendshapes.isEmpty()) { diff --git a/interface/src/renderer/Model.h b/interface/src/renderer/Model.h index 5561855afb..5aa2c2160b 100644 --- a/interface/src/renderer/Model.h +++ b/interface/src/renderer/Model.h @@ -311,12 +311,18 @@ private: static int _cascadedShadowNormalMapTangentLocation; static int _cascadedShadowNormalSpecularMapTangentLocation; + static int _cascadedShadowMapDistancesLocation; + static int _cascadedShadowNormalMapDistancesLocation; + static int _cascadedShadowSpecularMapDistancesLocation; + static int _cascadedShadowNormalSpecularMapDistancesLocation; + class SkinLocations { public: int clusterMatrices; int clusterIndices; int clusterWeights; int tangent; + int shadowDistances; }; static SkinLocations _skinLocations; From 34091128d8ce1d27a8a0d08ae924f50afc559a71 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Thu, 29 May 2014 17:22:59 -0700 Subject: [PATCH 8/9] Distance tweak. --- interface/src/Application.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index ba3904d44e..152b780363 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2349,7 +2349,8 @@ void Application::updateShadowMap() { radius = qMax(radius, glm::distance(points[j], center)); } if (i < 3) { - _shadowDistances[i] = -glm::distance(_viewFrustum.getPosition(), center) - radius; + const float RADIUS_SCALE = 0.5f; + _shadowDistances[i] = -glm::distance(_viewFrustum.getPosition(), center) - radius * RADIUS_SCALE; } center = inverseRotation * center; From 1eace78e4740db99652def5dd70db11f68b5b2ed Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Thu, 29 May 2014 17:46:25 -0700 Subject: [PATCH 9/9] Hide distances; they no longer need to be publicly visible. --- interface/src/Application.cpp | 1 + interface/src/Application.h | 2 -- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 152b780363..b4659cb828 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2310,6 +2310,7 @@ void Application::updateShadowMap() { glm::quat rotation = rotationBetween(IDENTITY_FRONT, lightDirection); glm::quat inverseRotation = glm::inverse(rotation); + const float SHADOW_MATRIX_DISTANCES[] = { 0.0f, 2.0f, 6.0f, 14.0f, 30.0f }; const glm::vec2 MAP_COORDS[] = { glm::vec2(0.0f, 0.0f), glm::vec2(0.5f, 0.0f), glm::vec2(0.0f, 0.5f), glm::vec2(0.5f, 0.5f) }; diff --git a/interface/src/Application.h b/interface/src/Application.h index c89c324ab1..f3d9c0fd27 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -126,8 +126,6 @@ static const float MIRROR_REARVIEW_DISTANCE = 0.65f; static const float MIRROR_REARVIEW_BODY_DISTANCE = 2.3f; static const float MIRROR_FIELD_OF_VIEW = 30.0f; -static const float SHADOW_MATRIX_DISTANCES[] = { 0.0f, 2.0f, 6.0f, 14.0f, 30.0f }; - class Application : public QApplication { Q_OBJECT