shadow refactor, optimization

This commit is contained in:
Turanszki Janos
2019-12-17 22:34:04 +00:00
parent ae7f078c58
commit 7c44a3e88d
9 changed files with 58 additions and 39 deletions
+4
View File
@@ -112,6 +112,10 @@ struct ShaderEntity
inline float GetWidth() { return texMulAdd.y; }
inline float GetHeight() { return texMulAdd.z; }
// Load cubemap depth remap props:
inline float GetCubemapDepthRemapNear() { return texMulAdd.w; }
inline float GetCubemapDepthRemapFar() { return coneAngleCos; }
// Load decal props:
inline float GetEmissive() { return energy; }
};
+16 -23
View File
@@ -45,9 +45,9 @@ inline LightingPart CombineLighting(in Surface surface, in Lighting lighting)
inline float3 shadowCascade(float3 shadowPos, float2 ShTex, float shadowKernel, float bias, float slice)
inline float3 shadowCascade(in ShaderEntity light, in float3 shadowPos, in float2 shadowUV, in uint cascade)
{
const float realDistance = shadowPos.z + bias;
const float realDistance = shadowPos.z + light.shadowBias;
float3 shadow = 0;
#ifndef DISABLE_SHADOWMAPS
#ifndef DISABLE_SOFT_SHADOWS
@@ -58,13 +58,13 @@ inline float3 shadowCascade(float3 shadowPos, float2 ShTex, float shadowKernel,
[loop]
for (float x = -range; x <= range; x += 1.0f)
{
shadow.x += texture_shadowarray_2d.SampleCmpLevelZero(sampler_cmp_depth, float3(ShTex + float2(x, y) * shadowKernel, slice), realDistance).r;
shadow.x += texture_shadowarray_2d.SampleCmpLevelZero(sampler_cmp_depth, float3(shadowUV + float2(x, y) * light.shadowKernel, light.GetShadowMapIndex() + cascade), realDistance).r;
shadow.y++;
}
}
shadow = shadow.x / shadow.y;
#else
shadow = texture_shadowarray_2d.SampleCmpLevelZero(sampler_cmp_depth, float3(ShTex, slice), realDistance).r;
shadow = texture_shadowarray_2d.SampleCmpLevelZero(sampler_cmp_depth, float3(shadowUV, light.GetShadowMapIndex() + cascade), realDistance).r;
#endif
#ifndef DISABLE_TRANSPARENT_SHADOWMAP
@@ -73,7 +73,7 @@ inline float3 shadowCascade(float3 shadowPos, float2 ShTex, float shadowKernel,
// unfortunately transparents will not receive transparent shadow map
// because we cannot distinguish without using secondary depth buffer for transparents
// but I don't wanna do that, not overly important for now
float4 transparent_shadowmap = texture_shadowarray_transparent.SampleLevel(sampler_linear_clamp, float3(ShTex, slice), 0).rgba;
float4 transparent_shadowmap = texture_shadowarray_transparent.SampleLevel(sampler_linear_clamp, float3(shadowUV, light.GetShadowMapIndex() + cascade), 0).rgba;
// Tint the shadow:
shadow *= transparent_shadowmap.rgb;
// Reduce shadow by caustics (caustics can also increase total light above maximum):
@@ -87,17 +87,10 @@ inline float3 shadowCascade(float3 shadowPos, float2 ShTex, float shadowKernel,
return shadow;
}
inline float shadowCube(float3 Lunnormalized, float range, float bias, uint slice)
inline float shadowCube(in ShaderEntity light, float3 Lunnormalized)
{
float projectedDistance = max(max(abs(Lunnormalized.x), abs(Lunnormalized.y)), abs(Lunnormalized.z));
float FarZ = 0.1f; // watch out: reversed depth buffer! Also, light near plane is constant for simplicity, this should match on cpu side!
float NearZ = max(1, range); // watch out: reversed depth buffer!
float fRange = FarZ / (FarZ - NearZ);
float a = fRange;
float b = -fRange * NearZ;
float z = projectedDistance * a + b;
float dbDistance = z / projectedDistance;
return texture_shadowarray_cube.SampleCmpLevelZero(sampler_cmp_depth, float4(-Lunnormalized, slice), dbDistance + bias).r;
const float remappedDistance = light.GetCubemapDepthRemapNear() + light.GetCubemapDepthRemapFar() / max(max(abs(Lunnormalized.x), abs(Lunnormalized.y)), abs(Lunnormalized.z));
return texture_shadowarray_cube.SampleCmpLevelZero(sampler_cmp_depth, float4(-Lunnormalized, light.GetShadowMapIndex()), remappedDistance + light.shadowBias).r;
}
@@ -127,7 +120,7 @@ inline void DirectionalLight(in ShaderEntity light, in Surface surface, inout Li
[branch]
if (is_saturated(ShTex))
{
const float3 shadow_main = shadowCascade(ShPos, ShTex.xy, light.shadowKernel, light.shadowBias, light.GetShadowMapIndex() + cascade);
const float3 shadow_main = shadowCascade(light, ShPos, ShTex.xy, cascade);
const float3 cascade_edgefactor = saturate(saturate(abs(ShPos)) - 0.8f) * 5.0f; // fade will be on edge and inwards 20%
const float cascade_fade = max(cascade_edgefactor.x, max(cascade_edgefactor.y, cascade_edgefactor.z));
@@ -139,7 +132,7 @@ inline void DirectionalLight(in ShaderEntity light, in Surface surface, inout Li
cascade += 1;
ShPos = mul(MatrixArray[light.GetShadowMatrixIndex() + cascade], float4(surface.P, 1)).xyz;
ShTex = ShPos * float3(0.5f, -0.5f, 0.5f) + 0.5f;
const float3 shadow_fallback = shadowCascade(ShPos, ShTex.xy, light.shadowKernel, light.shadowBias, light.GetShadowMapIndex() + cascade);
const float3 shadow_fallback = shadowCascade(light, ShPos, ShTex.xy, cascade);
sh *= lerp(shadow_main, shadow_fallback, cascade_fade);
}
@@ -186,7 +179,7 @@ inline void PointLight(in ShaderEntity light, in Surface surface, inout Lighting
#ifndef DISABLE_SHADOWMAPS
[branch]
if (light.IsCastingShadow()) {
sh *= shadowCube(Lunnormalized, light.range, light.shadowBias, light.GetShadowMapIndex());
sh *= shadowCube(light, Lunnormalized);
}
#endif // DISABLE_SHADOWMAPS
@@ -240,7 +233,7 @@ inline void SpotLight(in ShaderEntity light, in Surface surface, inout Lighting
[branch]
if (is_saturated(ShTex))
{
sh *= shadowCascade(ShPos.xyz, ShTex.xy, light.shadowKernel, light.shadowBias, light.GetShadowMapIndex());
sh *= shadowCascade(light, ShPos.xyz, ShTex.xy, 0);
}
}
#endif // DISABLE_SHADOWMAPS
@@ -439,7 +432,7 @@ inline void SphereLight(in ShaderEntity light, in Surface surface, inout Lightin
#ifndef DISABLE_SHADOWMAPS
[branch]
if (light.IsCastingShadow()) {
fLight = shadowCube(Lunnormalized, light.range, light.shadowBias, light.GetShadowMapIndex());
fLight = shadowCube(light, Lunnormalized);
}
#endif
@@ -488,7 +481,7 @@ inline void DiscLight(in ShaderEntity light, in Surface surface, inout Lighting
#ifndef DISABLE_SHADOWMAPS
[branch]
if (light.IsCastingShadow()) {
fLight = shadowCube(Lunnormalized, light.range, light.shadowBias, light.GetShadowMapIndex());
fLight = shadowCube(light, Lunnormalized);
}
#endif
@@ -544,7 +537,7 @@ inline void RectangleLight(in ShaderEntity light, in Surface surface, inout Ligh
#ifndef DISABLE_SHADOWMAPS
[branch]
if (light.IsCastingShadow()) {
fLight = shadowCube(Lunnormalized, light.range, light.shadowBias, light.GetShadowMapIndex());
fLight = shadowCube(light, Lunnormalized);
}
#endif
@@ -659,7 +652,7 @@ inline void TubeLight(in ShaderEntity light, in Surface surface, inout Lighting
#ifndef DISABLE_SHADOWMAPS
[branch]
if (light.IsCastingShadow()) {
fLight = shadowCube(Lunnormalized, light.range, light.shadowBias, light.GetShadowMapIndex());
fLight = shadowCube(light, Lunnormalized);
}
#endif
+3 -3
View File
@@ -99,7 +99,7 @@ void main(PSInput input)
[branch]if ((saturate(ShTex.x) == ShTex.x) && (saturate(ShTex.y) == ShTex.y) && (saturate(ShTex.z) == ShTex.z))
{
lightColor *= shadowCascade(ShPos, ShTex.xy, light.shadowKernel, light.shadowBias, light.GetShadowMapIndex() + cascade);
lightColor *= shadowCascade(light, ShPos, ShTex.xy, cascade);
}
}
@@ -126,7 +126,7 @@ void main(PSInput input)
[branch]
if (light.IsCastingShadow() >= 0) {
lightColor *= shadowCube(Lunnormalized, light.range, light.shadowBias, light.GetShadowMapIndex());
lightColor *= shadowCube(light, Lunnormalized);
}
lighting.direct.diffuse += lightColor;
@@ -166,7 +166,7 @@ void main(PSInput input)
[branch]
if ((saturate(ShTex.x) == ShTex.x) && (saturate(ShTex.y) == ShTex.y))
{
lightColor *= shadowCascade(ShPos.xyz, ShTex.xy, light.shadowKernel, light.shadowBias, light.GetShadowMapIndex());
lightColor *= shadowCascade(light, ShPos.xyz, ShTex.xy, 0);
}
}
@@ -42,7 +42,7 @@ float4 main(VertexToPixel input) : SV_TARGET
[branch]if (is_saturated(ShTex))
{
float3 attenuation = shadowCascade(ShPos, ShTex.xy, light.shadowKernel, light.shadowBias, light.GetShadowMapIndex() + cascade);
float3 attenuation = shadowCascade(light, ShPos, ShTex.xy, cascade);
attenuation *= GetFog(cameraDistance - marchedDistance);
+1 -1
View File
@@ -42,7 +42,7 @@ float4 main(VertexToPixel input) : SV_TARGET
[branch]
if (light.IsCastingShadow()) {
attenuation *= shadowCube(Lunnormalized, light.range, light.shadowBias, light.GetShadowMapIndex());
attenuation *= shadowCube(light, Lunnormalized);
}
attenuation *= GetFog(cameraDistance - marchedDistance);
+1 -1
View File
@@ -50,7 +50,7 @@ float4 main(VertexToPixel input) : SV_TARGET
[branch]
if ((saturate(ShTex.x) == ShTex.x) && (saturate(ShTex.y) == ShTex.y))
{
attenuation *= shadowCascade(ShPos.xyz, ShTex.xy, light.shadowKernel, light.shadowBias, light.GetShadowMapIndex());
attenuation *= shadowCascade(light, ShPos.xyz, ShTex.xy, 0);
}
}
+20 -1
View File
@@ -3995,6 +3995,25 @@ void UpdateRenderData(CommandList cmd)
break;
}
switch (light.GetType())
{
case LightComponent::POINT:
case LightComponent::SPHERE:
case LightComponent::DISC:
case LightComponent::RECTANGLE:
case LightComponent::TUBE:
{
const float FarZ = 0.1f; // watch out: reversed depth buffer! Also, light near plane is constant for simplicity, this should match on cpu side!
const float NearZ = std::max(1.0f, entityArray[entityCounter].range); // watch out: reversed depth buffer!
const float fRange = FarZ / (FarZ - NearZ);
const float cubemapDepthRemapNear = fRange;
const float cubemapDepthRemapFar = -fRange * NearZ;
entityArray[entityCounter].texMulAdd.w = cubemapDepthRemapNear;
entityArray[entityCounter].coneAngleCos = cubemapDepthRemapFar;
}
break;
}
if (light.IsStatic())
{
entityArray[entityCounter].SetFlags(ENTITY_FLAG_LIGHT_STATIC);
@@ -5155,7 +5174,7 @@ void DrawShadowmaps(const CameraComponent& camera, CommandList cmd, uint32_t lay
if (!renderQueue.empty())
{
MiscCB miscCb;
miscCb.g_xColor = float4(light.position.x, light.position.y, light.position.z, 1.0f / light.GetRange()); // reciprocal range, to avoid division in shader
miscCb.g_xColor = float4(light.position.x, light.position.y, light.position.z, 0);
device->UpdateBuffer(&constantBuffers[CBTYPE_MISC], &miscCb, cmd);
device->BindConstantBuffer(VS, &constantBuffers[CBTYPE_MISC], CB_GETBINDSLOT(MiscCB), cmd);
device->BindConstantBuffer(PS, &constantBuffers[CBTYPE_MISC], CB_GETBINDSLOT(MiscCB), cmd);
+11 -8
View File
@@ -493,15 +493,18 @@ namespace wiScene
}
}
if (archive.GetVersion() < 33 &&
(GetType() == POINT ||
GetType() == SPHERE ||
GetType() == DISC ||
GetType() == RECTANGLE ||
GetType() == TUBE)
)
if (archive.GetVersion() < 33)
{
shadowBias = 0.0001f;
switch (GetType())
{
case LightComponent::POINT:
case LightComponent::SPHERE:
case LightComponent::DISC:
case LightComponent::RECTANGLE:
case LightComponent::TUBE:
shadowBias = 0.0001f;
break;
}
}
}
+1 -1
View File
@@ -9,7 +9,7 @@ namespace wiVersion
// minor features, major updates
const int minor = 36;
// minor bug fixes, alterations, refactors, updates
const int revision = 9;
const int revision = 10;
long GetVersion()