From 8f84e5fbed3c592a73621e01723dca3b4bb7f81c Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Fri, 10 Nov 2017 15:39:26 +0100 Subject: [PATCH] Added sampler array in shader to support future cascades --- .../src/DeferredLightingEffect.cpp | 15 ++++--- libraries/render-utils/src/Shadow.slh | 44 ++++++++++--------- 2 files changed, 33 insertions(+), 26 deletions(-) diff --git a/libraries/render-utils/src/DeferredLightingEffect.cpp b/libraries/render-utils/src/DeferredLightingEffect.cpp index a99eb5ffed..831dc86452 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.cpp +++ b/libraries/render-utils/src/DeferredLightingEffect.cpp @@ -58,7 +58,7 @@ enum DeferredShader_MapSlot { DEFERRED_BUFFER_DEPTH_UNIT = 3, DEFERRED_BUFFER_OBSCURANCE_UNIT = 4, SHADOW_MAP_UNIT = 5, - SKYBOX_MAP_UNIT = 6, + SKYBOX_MAP_UNIT = SHADOW_MAP_UNIT + SHADOW_CASCADE_MAX_COUNT, DEFERRED_BUFFER_LINEAR_DEPTH_UNIT, DEFERRED_BUFFER_CURVATURE_UNIT, DEFERRED_BUFFER_DIFFUSED_CURVATURE_UNIT, @@ -156,7 +156,7 @@ static gpu::ShaderPointer makeLightProgram(const char* vertSource, const char* f slotBindings.insert(gpu::Shader::Binding(std::string("specularMap"), DEFERRED_BUFFER_EMISSIVE_UNIT)); slotBindings.insert(gpu::Shader::Binding(std::string("depthMap"), DEFERRED_BUFFER_DEPTH_UNIT)); slotBindings.insert(gpu::Shader::Binding(std::string("obscuranceMap"), DEFERRED_BUFFER_OBSCURANCE_UNIT)); - slotBindings.insert(gpu::Shader::Binding(std::string("shadowMap"), SHADOW_MAP_UNIT)); + slotBindings.insert(gpu::Shader::Binding(std::string("shadowMaps"), SHADOW_MAP_UNIT)); slotBindings.insert(gpu::Shader::Binding(std::string("skyboxMap"), SKYBOX_MAP_UNIT)); slotBindings.insert(gpu::Shader::Binding(std::string("linearZeyeMap"), DEFERRED_BUFFER_LINEAR_DEPTH_UNIT)); @@ -501,9 +501,11 @@ void RenderDeferredSetup::run(const render::RenderContextPointer& renderContext, auto lightAndShadow = lightStage->getCurrentKeyLightAndShadow(); const auto& globalShadow = lightAndShadow.second; - // Bind the shadow buffer + // Bind the shadow buffers if (globalShadow) { - batch.setResourceTexture(SHADOW_MAP_UNIT, globalShadow->getCascade(0).map); + for (auto i = 0; i < globalShadow->getCascadeCount(); i++) { + batch.setResourceTexture(SHADOW_MAP_UNIT+i, globalShadow->getCascade(i).map); + } } auto& program = deferredLightingEffect->_directionalSkyboxLight; @@ -567,8 +569,9 @@ void RenderDeferredSetup::run(const render::RenderContextPointer& renderContext, deferredLightingEffect->unsetKeyLightBatch(batch, locations->lightBufferUnit, locations->ambientBufferUnit, SKYBOX_MAP_UNIT); - - batch.setResourceTexture(SHADOW_MAP_UNIT, nullptr); + for (auto i = 0; i < SHADOW_CASCADE_MAX_COUNT; i++) { + batch.setResourceTexture(SHADOW_MAP_UNIT+i, nullptr); + } } } diff --git a/libraries/render-utils/src/Shadow.slh b/libraries/render-utils/src/Shadow.slh index 1f819e95c9..46661b3b8a 100644 --- a/libraries/render-utils/src/Shadow.slh +++ b/libraries/render-utils/src/Shadow.slh @@ -11,38 +11,38 @@ <@if not SHADOW_SLH@> <@def SHADOW_SLH@> -// the shadow texture -uniform sampler2DShadow shadowMap; - <@include Shadows_shared.slh@> +// the shadow texture +uniform sampler2DShadow shadowMaps[SHADOW_CASCADE_MAX_COUNT]; + uniform shadowTransformBuffer { ShadowParameters shadow; }; -mat4 getShadowReprojection() { - return shadow.cascades[0].reprojection; +mat4 getShadowReprojection(int cascadeIndex) { + return shadow.cascades[cascadeIndex].reprojection; } float getShadowScale() { return shadow.invMapSize; } -float getShadowBias() { - return shadow.cascades[0].bias; +float getShadowBias(int cascadeIndex) { + return shadow.cascades[cascadeIndex].bias; } // Compute the texture coordinates from world coordinates -vec4 evalShadowTexcoord(vec4 position) { - float bias = -getShadowBias(); +vec4 evalShadowTexcoord(int cascadeIndex, vec4 position) { + float bias = -getShadowBias(cascadeIndex); - vec4 shadowCoord = getShadowReprojection() * position; + vec4 shadowCoord = getShadowReprojection(cascadeIndex) * position; return vec4(shadowCoord.xy, shadowCoord.z + bias, 1.0); } // Sample the shadowMap with PCF (built-in) -float fetchShadow(vec3 shadowTexcoord) { - return texture(shadowMap, shadowTexcoord); +float fetchShadow(int cascadeIndex, vec3 shadowTexcoord) { + return texture(shadowMaps[cascadeIndex], shadowTexcoord); } vec2 PCFkernel[4] = vec2[4]( @@ -52,24 +52,24 @@ vec2 PCFkernel[4] = vec2[4]( vec2(0.5, -1.5) ); -float evalShadowAttenuationPCF(vec4 position, vec4 shadowTexcoord) { +float evalShadowAttenuationPCF(int cascadeIndex, vec4 position, vec4 shadowTexcoord) { float shadowScale = getShadowScale(); // Offset for efficient PCF, see http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html vec2 offset = step(fract(position.xy), vec2(0.5, 0.5)); float shadowAttenuation = (0.25 * ( - fetchShadow(shadowTexcoord.xyz + shadowScale * vec3(offset + PCFkernel[0], 0.0)) + - fetchShadow(shadowTexcoord.xyz + shadowScale * vec3(offset + PCFkernel[1], 0.0)) + - fetchShadow(shadowTexcoord.xyz + shadowScale * vec3(offset + PCFkernel[2], 0.0)) + - fetchShadow(shadowTexcoord.xyz + shadowScale * vec3(offset + PCFkernel[3], 0.0)) + fetchShadow(cascadeIndex, shadowTexcoord.xyz + shadowScale * vec3(offset + PCFkernel[0], 0.0)) + + fetchShadow(cascadeIndex, shadowTexcoord.xyz + shadowScale * vec3(offset + PCFkernel[1], 0.0)) + + fetchShadow(cascadeIndex, shadowTexcoord.xyz + shadowScale * vec3(offset + PCFkernel[2], 0.0)) + + fetchShadow(cascadeIndex, shadowTexcoord.xyz + shadowScale * vec3(offset + PCFkernel[3], 0.0)) )); return shadowAttenuation; } -float evalShadowAttenuation(vec4 position) { - vec4 shadowTexcoord = evalShadowTexcoord(position); +float evalShadowCascadeAttenuation(int cascadeIndex, vec4 position) { + vec4 shadowTexcoord = evalShadowTexcoord(cascadeIndex, position); if (shadowTexcoord.x < 0.0 || shadowTexcoord.x > 1.0 || shadowTexcoord.y < 0.0 || shadowTexcoord.y > 1.0 || shadowTexcoord.z < 0.0 || shadowTexcoord.z > 1.0) { @@ -77,7 +77,11 @@ float evalShadowAttenuation(vec4 position) { return 1.0; } - return evalShadowAttenuationPCF(position, shadowTexcoord); + return evalShadowAttenuationPCF(cascadeIndex, position, shadowTexcoord); +} + +float evalShadowAttenuation(vec4 position) { + return evalShadowCascadeAttenuation(0, position); } <@endif@>