Added sampler array in shader to support future cascades

This commit is contained in:
Olivier Prat 2017-11-10 15:39:26 +01:00
parent e0b36b800f
commit 8f84e5fbed
2 changed files with 33 additions and 26 deletions

View file

@ -58,7 +58,7 @@ enum DeferredShader_MapSlot {
DEFERRED_BUFFER_DEPTH_UNIT = 3, DEFERRED_BUFFER_DEPTH_UNIT = 3,
DEFERRED_BUFFER_OBSCURANCE_UNIT = 4, DEFERRED_BUFFER_OBSCURANCE_UNIT = 4,
SHADOW_MAP_UNIT = 5, 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_LINEAR_DEPTH_UNIT,
DEFERRED_BUFFER_CURVATURE_UNIT, DEFERRED_BUFFER_CURVATURE_UNIT,
DEFERRED_BUFFER_DIFFUSED_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("specularMap"), DEFERRED_BUFFER_EMISSIVE_UNIT));
slotBindings.insert(gpu::Shader::Binding(std::string("depthMap"), DEFERRED_BUFFER_DEPTH_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("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("skyboxMap"), SKYBOX_MAP_UNIT));
slotBindings.insert(gpu::Shader::Binding(std::string("linearZeyeMap"), DEFERRED_BUFFER_LINEAR_DEPTH_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(); auto lightAndShadow = lightStage->getCurrentKeyLightAndShadow();
const auto& globalShadow = lightAndShadow.second; const auto& globalShadow = lightAndShadow.second;
// Bind the shadow buffer // Bind the shadow buffers
if (globalShadow) { 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; 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); deferredLightingEffect->unsetKeyLightBatch(batch, locations->lightBufferUnit, locations->ambientBufferUnit, SKYBOX_MAP_UNIT);
for (auto i = 0; i < SHADOW_CASCADE_MAX_COUNT; i++) {
batch.setResourceTexture(SHADOW_MAP_UNIT, nullptr); batch.setResourceTexture(SHADOW_MAP_UNIT+i, nullptr);
}
} }
} }

View file

@ -11,38 +11,38 @@
<@if not SHADOW_SLH@> <@if not SHADOW_SLH@>
<@def SHADOW_SLH@> <@def SHADOW_SLH@>
// the shadow texture
uniform sampler2DShadow shadowMap;
<@include Shadows_shared.slh@> <@include Shadows_shared.slh@>
// the shadow texture
uniform sampler2DShadow shadowMaps[SHADOW_CASCADE_MAX_COUNT];
uniform shadowTransformBuffer { uniform shadowTransformBuffer {
ShadowParameters shadow; ShadowParameters shadow;
}; };
mat4 getShadowReprojection() { mat4 getShadowReprojection(int cascadeIndex) {
return shadow.cascades[0].reprojection; return shadow.cascades[cascadeIndex].reprojection;
} }
float getShadowScale() { float getShadowScale() {
return shadow.invMapSize; return shadow.invMapSize;
} }
float getShadowBias() { float getShadowBias(int cascadeIndex) {
return shadow.cascades[0].bias; return shadow.cascades[cascadeIndex].bias;
} }
// Compute the texture coordinates from world coordinates // Compute the texture coordinates from world coordinates
vec4 evalShadowTexcoord(vec4 position) { vec4 evalShadowTexcoord(int cascadeIndex, vec4 position) {
float bias = -getShadowBias(); float bias = -getShadowBias(cascadeIndex);
vec4 shadowCoord = getShadowReprojection() * position; vec4 shadowCoord = getShadowReprojection(cascadeIndex) * position;
return vec4(shadowCoord.xy, shadowCoord.z + bias, 1.0); return vec4(shadowCoord.xy, shadowCoord.z + bias, 1.0);
} }
// Sample the shadowMap with PCF (built-in) // Sample the shadowMap with PCF (built-in)
float fetchShadow(vec3 shadowTexcoord) { float fetchShadow(int cascadeIndex, vec3 shadowTexcoord) {
return texture(shadowMap, shadowTexcoord); return texture(shadowMaps[cascadeIndex], shadowTexcoord);
} }
vec2 PCFkernel[4] = vec2[4]( vec2 PCFkernel[4] = vec2[4](
@ -52,24 +52,24 @@ vec2 PCFkernel[4] = vec2[4](
vec2(0.5, -1.5) vec2(0.5, -1.5)
); );
float evalShadowAttenuationPCF(vec4 position, vec4 shadowTexcoord) { float evalShadowAttenuationPCF(int cascadeIndex, vec4 position, vec4 shadowTexcoord) {
float shadowScale = getShadowScale(); float shadowScale = getShadowScale();
// Offset for efficient PCF, see http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html // 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)); vec2 offset = step(fract(position.xy), vec2(0.5, 0.5));
float shadowAttenuation = (0.25 * ( float shadowAttenuation = (0.25 * (
fetchShadow(shadowTexcoord.xyz + shadowScale * vec3(offset + PCFkernel[0], 0.0)) + fetchShadow(cascadeIndex, shadowTexcoord.xyz + shadowScale * vec3(offset + PCFkernel[0], 0.0)) +
fetchShadow(shadowTexcoord.xyz + shadowScale * vec3(offset + PCFkernel[1], 0.0)) + fetchShadow(cascadeIndex, shadowTexcoord.xyz + shadowScale * vec3(offset + PCFkernel[1], 0.0)) +
fetchShadow(shadowTexcoord.xyz + shadowScale * vec3(offset + PCFkernel[2], 0.0)) + fetchShadow(cascadeIndex, 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[3], 0.0))
)); ));
return shadowAttenuation; return shadowAttenuation;
} }
float evalShadowAttenuation(vec4 position) { float evalShadowCascadeAttenuation(int cascadeIndex, vec4 position) {
vec4 shadowTexcoord = evalShadowTexcoord(position); vec4 shadowTexcoord = evalShadowTexcoord(cascadeIndex, position);
if (shadowTexcoord.x < 0.0 || shadowTexcoord.x > 1.0 || if (shadowTexcoord.x < 0.0 || shadowTexcoord.x > 1.0 ||
shadowTexcoord.y < 0.0 || shadowTexcoord.y > 1.0 || shadowTexcoord.y < 0.0 || shadowTexcoord.y > 1.0 ||
shadowTexcoord.z < 0.0 || shadowTexcoord.z > 1.0) { shadowTexcoord.z < 0.0 || shadowTexcoord.z > 1.0) {
@ -77,7 +77,11 @@ float evalShadowAttenuation(vec4 position) {
return 1.0; return 1.0;
} }
return evalShadowAttenuationPCF(position, shadowTexcoord); return evalShadowAttenuationPCF(cascadeIndex, position, shadowTexcoord);
}
float evalShadowAttenuation(vec4 position) {
return evalShadowCascadeAttenuation(0, position);
} }
<@endif@> <@endif@>