From b30f845924376b29e51308c6eb80dd0dad3d1a23 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Fri, 12 May 2023 12:22:04 +0200 Subject: [PATCH] Simplify radial light attenuation in shaders #1094 --- Content/Shaders/Lights.flax | 4 ++-- Content/Shaders/VolumetricFog.flax | 4 ++-- Source/Shaders/Lighting.hlsl | 5 ++--- Source/Shaders/LightingCommon.hlsl | 23 +++++++++++------------ Source/Shaders/VolumetricFog.shader | 11 ++++------- 5 files changed, 21 insertions(+), 26 deletions(-) diff --git a/Content/Shaders/Lights.flax b/Content/Shaders/Lights.flax index 34e8c9a8c..ea30cd9f7 100644 --- a/Content/Shaders/Lights.flax +++ b/Content/Shaders/Lights.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b405f5698304e87e6f510c49a0cea3817c9a1a00d7ba63ef4027ac49ba7cc7a4 -size 5299 +oid sha256:83cb261770aba2813f85063f987032f9914387f4011474b0fe347c42522116b4 +size 5122 diff --git a/Content/Shaders/VolumetricFog.flax b/Content/Shaders/VolumetricFog.flax index 18eddae16..eb3ca9f2c 100644 --- a/Content/Shaders/VolumetricFog.flax +++ b/Content/Shaders/VolumetricFog.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:72415ba69a685e9a739d1a08d08c6eb9efd3cab31d8cc0c949cb187a9bad19a5 -size 13841 +oid sha256:4ab2c2551ce9cce0355c92f4f6499858e04e4bf764900b305273a7d57b887596 +size 13633 diff --git a/Source/Shaders/Lighting.hlsl b/Source/Shaders/Lighting.hlsl index d4b9da107..4b909c024 100644 --- a/Source/Shaders/Lighting.hlsl +++ b/Source/Shaders/Lighting.hlsl @@ -129,9 +129,8 @@ float4 GetLighting(float3 viewPos, LightData lightData, GBufferSample gBuffer, f toLight = lightData.Position - gBuffer.WorldPos; float distanceSqr = dot(toLight, toLight); L = toLight * rsqrt(distanceSqr); - float distanceAttenuation = 1, lightRadiusMask = 1, spotAttenuation = 1; - GetRadialLightAttenuation(lightData, isSpotLight, N, distanceSqr, 1, toLight, L, NoL, distanceAttenuation, lightRadiusMask, spotAttenuation); - float attenuation = distanceAttenuation * lightRadiusMask * spotAttenuation; + float attenuation = 1; + GetRadialLightAttenuation(lightData, isSpotLight, N, distanceSqr, 1, toLight, L, NoL, attenuation); shadow.SurfaceShadow *= attenuation; shadow.TransmissionShadow *= attenuation; } diff --git a/Source/Shaders/LightingCommon.hlsl b/Source/Shaders/LightingCommon.hlsl index bb7a6ce7e..3479157b5 100644 --- a/Source/Shaders/LightingCommon.hlsl +++ b/Source/Shaders/LightingCommon.hlsl @@ -63,10 +63,9 @@ void GetRadialLightAttenuation( float3 toLight, float3 L, inout float NoL, - inout float distanceAttenuation, - inout float lightRadiusMask, - inout float spotAttenuation) + inout float attenuation) { + // Distance attenuation if (lightData.InverseSquared) { BRANCH @@ -77,29 +76,31 @@ void GetRadialLightAttenuation( float3 l1 = toLight + 0.5 * l01; float lengthL0 = length(l0); float lengthL1 = length(l1); - distanceAttenuation = rcp((lengthL0 * lengthL1 + dot(l0, l1)) * 0.5 + distanceBiasSqr); + attenuation = rcp((lengthL0 * lengthL1 + dot(l0, l1)) * 0.5 + distanceBiasSqr); NoL = saturate(0.5 * (dot(N, l0) / lengthL0 + dot(N, l1) / lengthL1)); } else { - distanceAttenuation = rcp(distanceSqr + distanceBiasSqr); + attenuation = rcp(distanceSqr + distanceBiasSqr); NoL = saturate(dot(N, L)); } - lightRadiusMask = Square(saturate(1 - Square(distanceSqr * Square(lightData.RadiusInv)))); + attenuation *= Square(saturate(1 - Square(distanceSqr * Square(lightData.RadiusInv)))); } else { - distanceAttenuation = 1; + attenuation = 1; NoL = saturate(dot(N, L)); float3 worldLightVector = toLight * lightData.RadiusInv; float t = dot(worldLightVector, worldLightVector); - lightRadiusMask = pow(1.0f - saturate(t), lightData.FalloffExponent); + attenuation *= pow(1.0f - saturate(t), lightData.FalloffExponent); } + // Spot mask attenuation if (isSpotLight) { - // SpotAngles.x is CosOuterCone, SpotAngles.y is InvCosConeDifference - spotAttenuation = Square(saturate((dot(normalize(-L), lightData.Direction) - lightData.SpotAngles.x) * lightData.SpotAngles.y)); + float cosOuterCone = lightData.SpotAngles.x; + float invCosConeDifference = lightData.SpotAngles.y; + attenuation *= Square(saturate((dot(normalize(-L), lightData.Direction) - cosOuterCone) * invCosConeDifference)); } } @@ -107,7 +108,6 @@ void GetRadialLightAttenuation( float AreaLightSpecular(LightData lightData, float roughness, inout float3 toLight, inout float3 L, float3 V, half3 N) { float energy = 1; - float m = roughness * roughness; float3 r = reflect(-V, N); float invDistToLight = rsqrt(dot(toLight, toLight)); @@ -137,7 +137,6 @@ float AreaLightSpecular(LightData lightData, float roughness, inout float3 toLig } L = normalize(toLight); - return energy; } diff --git a/Source/Shaders/VolumetricFog.shader b/Source/Shaders/VolumetricFog.shader index 2f5103736..b97fede24 100644 --- a/Source/Shaders/VolumetricFog.shader +++ b/Source/Shaders/VolumetricFog.shader @@ -205,9 +205,6 @@ float4 PS_InjectLight(Quad_GS2PS input) : SV_Target0 uint samplesCount = historyAlpha < 0.001f ? MissedHistorySamplesCount : 1; float NoL = 0; - float distanceAttenuation = 1; - float lightRadiusMask = 1; - float spotAttenuation = 1; bool isSpotLight = LocalLight.SpotAngles.x > -2.0f; float4 scattering = 0; for (uint sampleIndex = 0; sampleIndex < samplesCount; sampleIndex++) @@ -224,19 +221,19 @@ float4 PS_InjectLight(Quad_GS2PS input) : SV_Target0 float3 L = toLight * rsqrt(distanceSqr); // Calculate the light attenuation - GetRadialLightAttenuation(LocalLight, isSpotLight, float3(0, 0, 1), distanceSqr, distanceBias * distanceBias, toLight, L, NoL, distanceAttenuation, lightRadiusMask, spotAttenuation); - float combinedAttenuation = distanceAttenuation * lightRadiusMask * spotAttenuation; + float attenuation = 1; + GetRadialLightAttenuation(LocalLight, isSpotLight, float3(0, 0, 1), distanceSqr, distanceBias * distanceBias, toLight, L, NoL, attenuation); // Peek the shadow float shadowFactor = 1.0f; #if USE_SHADOW - if (combinedAttenuation > 0) + if (attenuation > 0) { shadowFactor = ComputeVolumeShadowing(positionWS, isSpotLight); } #endif - scattering.rgb += LocalLight.Color * (GetPhase(PhaseG, dot(L, -cameraVector)) * combinedAttenuation * shadowFactor * LocalLightScatteringIntensity); + scattering.rgb += LocalLight.Color * (GetPhase(PhaseG, dot(L, -cameraVector)) * attenuation * shadowFactor * LocalLightScatteringIntensity); } scattering.rgb /= (float)samplesCount;