From 7c44a3e88dfef901405e461663a8cf61c1d219a1 Mon Sep 17 00:00:00 2001 From: Turanszki Janos Date: Tue, 17 Dec 2019 22:34:04 +0000 Subject: [PATCH] shadow refactor, optimization --- WickedEngine/ShaderInterop_Renderer.h | 4 ++ WickedEngine/lightingHF.hlsli | 39 ++++++++----------- WickedEngine/objectPS_voxelizer.hlsl | 6 +-- .../volumetricLight_DirectionalPS.hlsl | 2 +- WickedEngine/volumetricLight_PointPS.hlsl | 2 +- WickedEngine/volumetricLight_SpotPS.hlsl | 2 +- WickedEngine/wiRenderer.cpp | 21 +++++++++- WickedEngine/wiScene_Serializers.cpp | 19 +++++---- WickedEngine/wiVersion.cpp | 2 +- 9 files changed, 58 insertions(+), 39 deletions(-) diff --git a/WickedEngine/ShaderInterop_Renderer.h b/WickedEngine/ShaderInterop_Renderer.h index 0ea5c32d4..bdfa2e465 100644 --- a/WickedEngine/ShaderInterop_Renderer.h +++ b/WickedEngine/ShaderInterop_Renderer.h @@ -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; } }; diff --git a/WickedEngine/lightingHF.hlsli b/WickedEngine/lightingHF.hlsli index efc0cd3ad..d87f390ff 100644 --- a/WickedEngine/lightingHF.hlsli +++ b/WickedEngine/lightingHF.hlsli @@ -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 diff --git a/WickedEngine/objectPS_voxelizer.hlsl b/WickedEngine/objectPS_voxelizer.hlsl index e445c839b..96ad1cdbd 100644 --- a/WickedEngine/objectPS_voxelizer.hlsl +++ b/WickedEngine/objectPS_voxelizer.hlsl @@ -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); } } diff --git a/WickedEngine/volumetricLight_DirectionalPS.hlsl b/WickedEngine/volumetricLight_DirectionalPS.hlsl index 1e6cf3c41..d80ff9118 100644 --- a/WickedEngine/volumetricLight_DirectionalPS.hlsl +++ b/WickedEngine/volumetricLight_DirectionalPS.hlsl @@ -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); diff --git a/WickedEngine/volumetricLight_PointPS.hlsl b/WickedEngine/volumetricLight_PointPS.hlsl index 2e9985491..e89ad4c4d 100644 --- a/WickedEngine/volumetricLight_PointPS.hlsl +++ b/WickedEngine/volumetricLight_PointPS.hlsl @@ -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); diff --git a/WickedEngine/volumetricLight_SpotPS.hlsl b/WickedEngine/volumetricLight_SpotPS.hlsl index 0ae87695a..f89192153 100644 --- a/WickedEngine/volumetricLight_SpotPS.hlsl +++ b/WickedEngine/volumetricLight_SpotPS.hlsl @@ -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); } } diff --git a/WickedEngine/wiRenderer.cpp b/WickedEngine/wiRenderer.cpp index 71df06605..c43162e46 100644 --- a/WickedEngine/wiRenderer.cpp +++ b/WickedEngine/wiRenderer.cpp @@ -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); diff --git a/WickedEngine/wiScene_Serializers.cpp b/WickedEngine/wiScene_Serializers.cpp index 3b7f702d4..1b5404dd8 100644 --- a/WickedEngine/wiScene_Serializers.cpp +++ b/WickedEngine/wiScene_Serializers.cpp @@ -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; + } } } diff --git a/WickedEngine/wiVersion.cpp b/WickedEngine/wiVersion.cpp index 851f5664d..0e3c790c6 100644 --- a/WickedEngine/wiVersion.cpp +++ b/WickedEngine/wiVersion.cpp @@ -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()