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_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);
}
}
}

View file

@ -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@>