From 709314d0655e651c88797c67c02fd72b671589a9 Mon Sep 17 00:00:00 2001 From: "Alan D. Tse" Date: Fri, 27 Jun 2025 14:13:08 -0700 Subject: [PATCH 1/7] refactor: refactor LANDSCAPE layer blending --- package/Shaders/Lighting.hlsl | 414 ++++++++++++++++------------------ 1 file changed, 189 insertions(+), 225 deletions(-) diff --git a/package/Shaders/Lighting.hlsl b/package/Shaders/Lighting.hlsl index de1a54a7a1..da4b29cff8 100644 --- a/package/Shaders/Lighting.hlsl +++ b/package/Shaders/Lighting.hlsl @@ -1037,6 +1037,99 @@ float GetSnowParameterY(float texProjTmp, float alpha) # include "IBL/IBL.hlsli" # endif +#if defined(LANDSCAPE) +inline void SampleLandscapeLayer( + float2 uv, + float viewDistance, + float screenNoise, + float mipLevel, + float weight, + Texture2D texColor, + Texture2D texNormal, + SamplerState sampColor, + SamplerState sampNormal, +# if defined(TERRAIN_VARIATION) + StochasticOffsets sharedOffset, + float2 dx, + float2 dy, +# endif +# if defined(TRUE_PBR) + Texture2D texRMAOS, + SamplerState sampRMAOS, + float3 pbrParams, + inout float4 blendedRMAOS, +# endif + inout float3 blendedRGB, + inout float blendedAlpha, + inout float3 blendedNormalRGB, + inout float blendedNormalAlpha) +{ + // Sample color +# if defined(TERRAIN_VARIATION) + float4 diffuse = StochasticEffect(screenNoise, mipLevel, texColor, sampColor, uv, sharedOffset, dx, dy, viewDistance); +# else + float distanceFactor = smoothstep(0.0, 2048.0, viewDistance); + float4 diffuse = lerp( + texColor.SampleBias(sampColor, uv, SharedData::MipBias), + texColor.SampleLevel(sampColor, uv, distanceFactor * 3.0), + distanceFactor); +# endif + float3 diffuseRGB = diffuse.rgb; +# if defined(TRUE_PBR) + // Check if this texture is not PBR (pbrParams.x == 0 means non-PBR texture) + if (pbrParams.x == 0) { + diffuseRGB = diffuseRGB / Color::PBRLightingScale; + } +# endif + float alpha = diffuse.a; + + // Sample normal +# if defined(TERRAIN_VARIATION) + float4 normal = StochasticEffect(screenNoise, mipLevel, texNormal, sampNormal, uv, sharedOffset, dx, dy, viewDistance); +# else + float4 normal = lerp( + texNormal.SampleBias(sampNormal, uv, SharedData::MipBias), + texNormal.SampleLevel(sampNormal, uv, distanceFactor * 3.0), + distanceFactor); +# endif + float3 normalRGB = normal.rgb; + float normalAlpha = normal.a; + +# if defined(TRUE_PBR) + // Sample RMAOS +# if defined(TERRAIN_VARIATION) + float4 rmaos = StochasticEffect(screenNoise, mipLevel, texRMAOS, sampRMAOS, uv, sharedOffset, dx, dy, viewDistance); +# else + float4 rmaos = lerp( + texRMAOS.SampleBias(sampRMAOS, uv, SharedData::MipBias), + texRMAOS.SampleLevel(sampRMAOS, uv, distanceFactor * 3.0), + distanceFactor); +# endif + rmaos *= float4(pbrParams.x, 1, 1, pbrParams.z); + blendedRMAOS += rmaos * weight; +# endif + + blendedRGB += diffuseRGB * weight; + blendedAlpha += alpha * weight; + blendedNormalRGB += normalRGB * weight; + blendedNormalAlpha += normalAlpha * weight; +} + +# if defined(TRUE_PBR) +inline void AccumulateLandscapeGlints(float weight, float4 glintParams, inout float4 glintParameters) +{ + glintParameters += weight * glintParams; +} +# endif + +# if defined(SNOW) && !defined(TRUE_PBR) +inline void AccumulateLandscapeSnow(float weight, float mask, float blendWeight, float landSnowMaskValue, inout float landSnowMask) +{ + landSnowMask += mask * blendWeight * landSnowMaskValue; +} +# endif +# endif // LANDSCAPE + PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) { PS_OUTPUT psout; @@ -1371,295 +1464,166 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) // Layer 1 (LandBlendWeights1.x) if (input.LandBlendWeights1.x > 0.01) { float weight = input.LandBlendWeights1.x * invwsum; + SampleLandscapeLayer( + uv, viewDistance, screenNoise, mipLevels[0], weight, + TexColorSampler, TexNormalSampler, + SampColorSampler, SampNormalSampler, # if defined(TERRAIN_VARIATION) - float4 diffuse1 = StochasticEffect(screenNoise, mipLevels[0], TexColorSampler, SampColorSampler, uv, sharedOffset, dx, dy, viewDistance); -# else - float distanceFactor = smoothstep(0.0, 2048.0, viewDistance); - float4 diffuse1 = lerp( - TexColorSampler.SampleBias(SampColorSampler, uv, SharedData::MipBias), - TexColorSampler.SampleLevel(SampColorSampler, uv, distanceFactor * 3.0), - distanceFactor); + sharedOffset, dx, dy, # endif - float3 diffuseRGB1 = diffuse1.rgb; # if defined(TRUE_PBR) - [branch] if ((PBRFlags & PBR::TerrainFlags::LandTile0PBR) == 0) - { - diffuseRGB1 = diffuseRGB1 / Color::PBRLightingScale; - } + TexRMAOSSampler, SampRMAOSSampler, PBRParams1, blendedRMAOS, # endif - float alpha1 = diffuse1.a; - -# if defined(TERRAIN_VARIATION) - float4 normal1 = StochasticEffect(screenNoise, mipLevels[0], TexNormalSampler, SampNormalSampler, uv, sharedOffset, dx, dy, viewDistance); -# else - float4 normal1 = lerp( - TexNormalSampler.SampleBias(SampNormalSampler, uv, SharedData::MipBias), - TexNormalSampler.SampleLevel(SampNormalSampler, uv, distanceFactor * 3.0), - distanceFactor); + blendedRGB, blendedAlpha, blendedNormalRGB, blendedNormalAlpha); +# if defined(SNOW) && !defined(TRUE_PBR) + float landSnowMask1 = GetLandSnowMaskValue(baseColor.w); + AccumulateLandscapeSnow(weight, LandscapeTexture1to4IsSnow.x, input.LandBlendWeights1.x, landSnowMask1, landSnowMask); # endif - float3 normalRGB1 = normal1.rgb; - float normalAlpha1 = normal1.a; # if defined(TRUE_PBR) -# if defined(TERRAIN_VARIATION) - float4 rmaos1 = StochasticEffect(screenNoise, mipLevels[0], TexRMAOSSampler, SampRMAOSSampler, uv, sharedOffset, dx, dy, viewDistance); -# else - float4 rmaos1 = lerp( - TexRMAOSSampler.SampleBias(SampRMAOSSampler, uv, SharedData::MipBias), - TexRMAOSSampler.SampleLevel(SampRMAOSSampler, uv, distanceFactor * 3.0), - distanceFactor); -# endif - rmaos1 *= float4(PBRParams1.x, 1, 1, PBRParams1.z); - blendedRMAOS += rmaos1 * weight; // Blending Within Layers (Same for the rest of layers 2-6) + [branch] if ((PBRFlags & PBR::TerrainFlags::LandTile0HasGlint) != 0) + { + AccumulateLandscapeGlints(input.LandBlendWeights1.x, LandscapeTexture1GlintParameters, glintParameters); + } # endif - blendedRGB += diffuseRGB1 * weight; - blendedAlpha += alpha1 * weight; - blendedNormalRGB += normalRGB1 * weight; - blendedNormalAlpha += normalAlpha1 * weight; } // Layer 2 (LandBlendWeights1.y) if (input.LandBlendWeights1.y > 0.01) { float weight = input.LandBlendWeights1.y * invwsum; + SampleLandscapeLayer( + uv, viewDistance, screenNoise, mipLevels[1], weight, + TexLandColor2Sampler, TexLandNormal2Sampler, + SampColorSampler, SampNormalSampler, # if defined(TERRAIN_VARIATION) - float4 diffuse2 = StochasticEffect(screenNoise, mipLevels[1], TexLandColor2Sampler, SampColorSampler, uv, sharedOffset, dx, dy, viewDistance); -# else - float distanceFactor = smoothstep(0.0, 2048.0, viewDistance); - float4 diffuse2 = lerp( - TexLandColor2Sampler.SampleBias(SampColorSampler, uv, SharedData::MipBias), - TexLandColor2Sampler.SampleLevel(SampColorSampler, uv, distanceFactor * 3.0), - distanceFactor); + sharedOffset, dx, dy, # endif - float3 diffuseRGB2 = diffuse2.rgb; # if defined(TRUE_PBR) - [branch] if ((PBRFlags & PBR::TerrainFlags::LandTile1PBR) == 0) - { - diffuseRGB2 = diffuseRGB2 / Color::PBRLightingScale; - } + TexLandRMAOS2Sampler, SampRMAOSSampler, LandscapeTexture2PBRParams, blendedRMAOS, # endif - float alpha2 = diffuse2.a; + blendedRGB, blendedAlpha, blendedNormalRGB, blendedNormalAlpha -# if defined(TERRAIN_VARIATION) - float4 normal2 = StochasticEffect(screenNoise, mipLevels[1], TexLandNormal2Sampler, SampNormalSampler, uv, sharedOffset, dx, dy, viewDistance); -# else - float4 normal2 = lerp( - TexLandNormal2Sampler.SampleBias(SampNormalSampler, uv, SharedData::MipBias), - TexLandNormal2Sampler.SampleLevel(SampNormalSampler, uv, distanceFactor * 3.0), - distanceFactor); + ); +# if defined(SNOW) && !defined(TRUE_PBR) + float landSnowMask2 = GetLandSnowMaskValue(baseColor.w); + AccumulateLandscapeSnow(weight, LandscapeTexture1to4IsSnow.y, input.LandBlendWeights1.y, landSnowMask2, landSnowMask); # endif - float3 normalRGB2 = normal2.rgb; - float normalAlpha2 = normal2.a; # if defined(TRUE_PBR) -# if defined(TERRAIN_VARIATION) - float4 rmaos2 = StochasticEffect(screenNoise, mipLevels[1], TexLandRMAOS2Sampler, SampRMAOSSampler, uv, sharedOffset, dx, dy, viewDistance); -# else - float4 rmaos2 = lerp( - TexLandRMAOS2Sampler.SampleBias(SampRMAOSSampler, uv, SharedData::MipBias), - TexLandRMAOS2Sampler.SampleLevel(SampRMAOSSampler, uv, distanceFactor * 3.0), - distanceFactor); -# endif - rmaos2 *= float4(LandscapeTexture2PBRParams.x, 1, 1, LandscapeTexture2PBRParams.z); - blendedRMAOS += rmaos2 * weight; + [branch] if ((PBRFlags & PBR::TerrainFlags::LandTile1HasGlint) != 0) + { + AccumulateLandscapeGlints(input.LandBlendWeights1.y, LandscapeTexture2GlintParameters, glintParameters); + } # endif - blendedRGB += diffuseRGB2 * weight; - blendedAlpha += alpha2 * weight; - blendedNormalRGB += normalRGB2 * weight; - blendedNormalAlpha += normalAlpha2 * weight; } // Layer 3 (LandBlendWeights1.z) if (input.LandBlendWeights1.z > 0.01) { float weight = input.LandBlendWeights1.z * invwsum; + SampleLandscapeLayer( + uv, viewDistance, screenNoise, mipLevels[2], weight, + TexLandColor3Sampler, TexLandNormal3Sampler, + + SampColorSampler, SampNormalSampler, # if defined(TERRAIN_VARIATION) - float4 diffuse3 = StochasticEffect(screenNoise, mipLevels[2], TexLandColor3Sampler, SampColorSampler, uv, sharedOffset, dx, dy, viewDistance); -# else - float distanceFactor = smoothstep(0.0, 2048.0, viewDistance); - float4 diffuse3 = lerp( - TexLandColor3Sampler.SampleBias(SampColorSampler, uv, SharedData::MipBias), - TexLandColor3Sampler.SampleLevel(SampColorSampler, uv, distanceFactor * 3.0), - distanceFactor); + + sharedOffset, dx, dy, # endif - float3 diffuseRGB3 = diffuse3.rgb; # if defined(TRUE_PBR) - [branch] if ((PBRFlags & PBR::TerrainFlags::LandTile2PBR) == 0) - { - diffuseRGB3 = diffuseRGB3 / Color::PBRLightingScale; - } + TexLandRMAOS3Sampler, SampRMAOSSampler, LandscapeTexture3PBRParams, blendedRMAOS, # endif - float alpha3 = diffuse3.a; - -# if defined(TERRAIN_VARIATION) - float4 normal3 = StochasticEffect(screenNoise, mipLevels[2], TexLandNormal3Sampler, SampNormalSampler, uv, sharedOffset, dx, dy, viewDistance); -# else - float4 normal3 = lerp( - TexLandNormal3Sampler.SampleBias(SampNormalSampler, uv, SharedData::MipBias), - TexLandNormal3Sampler.SampleLevel(SampNormalSampler, uv, distanceFactor * 3.0), - distanceFactor); + blendedRGB, blendedAlpha, blendedNormalRGB, blendedNormalAlpha); +# if defined(SNOW) && !defined(TRUE_PBR) + float landSnowMask3 = GetLandSnowMaskValue(baseColor.w); + AccumulateLandscapeSnow(weight, LandscapeTexture1to4IsSnow.z, input.LandBlendWeights1.z, landSnowMask3, landSnowMask); # endif - float3 normalRGB3 = normal3.rgb; - float normalAlpha3 = normal3.a; # if defined(TRUE_PBR) -# if defined(TERRAIN_VARIATION) - float4 rmaos3 = StochasticEffect(screenNoise, mipLevels[2], TexLandRMAOS3Sampler, SampRMAOSSampler, uv, sharedOffset, dx, dy, viewDistance); -# else - float4 rmaos3 = lerp( - TexLandRMAOS3Sampler.SampleBias(SampRMAOSSampler, uv, SharedData::MipBias), - TexLandRMAOS3Sampler.SampleLevel(SampRMAOSSampler, uv, distanceFactor * 3.0), - distanceFactor); -# endif - rmaos3 *= float4(LandscapeTexture3PBRParams.x, 1, 1, LandscapeTexture3PBRParams.z); - blendedRMAOS += rmaos3 * weight; + [branch] if ((PBRFlags & PBR::TerrainFlags::LandTile2HasGlint) != 0) + { + AccumulateLandscapeGlints(input.LandBlendWeights1.z, LandscapeTexture3GlintParameters, glintParameters); + } # endif - blendedRGB += diffuseRGB3 * weight; - blendedAlpha += alpha3 * weight; - blendedNormalRGB += normalRGB3 * weight; - blendedNormalAlpha += normalAlpha3 * weight; } // Layer 4 (LandBlendWeights1.w) if (input.LandBlendWeights1.w > 0.01) { float weight = input.LandBlendWeights1.w * invwsum; + SampleLandscapeLayer( + uv, viewDistance, screenNoise, mipLevels[3], weight, + TexLandColor4Sampler, TexLandNormal4Sampler, + SampColorSampler, SampNormalSampler, # if defined(TERRAIN_VARIATION) - float4 diffuse4 = StochasticEffect(screenNoise, mipLevels[3], TexLandColor4Sampler, SampColorSampler, uv, sharedOffset, dx, dy, viewDistance); -# else - float distanceFactor = smoothstep(0.0, 2048.0, viewDistance); - float4 diffuse4 = lerp( - TexLandColor4Sampler.SampleBias(SampColorSampler, uv, SharedData::MipBias), - TexLandColor4Sampler.SampleLevel(SampColorSampler, uv, distanceFactor * 3.0), - distanceFactor); + + sharedOffset, dx, dy, # endif - float3 diffuseRGB4 = diffuse4.rgb; # if defined(TRUE_PBR) - [branch] if ((PBRFlags & PBR::TerrainFlags::LandTile3PBR) == 0) - { - diffuseRGB4 = diffuseRGB4 / Color::PBRLightingScale; - } + TexLandRMAOS4Sampler, SampRMAOSSampler, LandscapeTexture4PBRParams, blendedRMAOS, # endif - float alpha4 = diffuse4.a; - -# if defined(TERRAIN_VARIATION) - float4 normal4 = StochasticEffect(screenNoise, mipLevels[3], TexLandNormal4Sampler, SampNormalSampler, uv, sharedOffset, dx, dy, viewDistance); -# else - float4 normal4 = lerp( - TexLandNormal4Sampler.SampleBias(SampNormalSampler, uv, SharedData::MipBias), - TexLandNormal4Sampler.SampleLevel(SampNormalSampler, uv, distanceFactor * 3.0), - distanceFactor); + blendedRGB, blendedAlpha, blendedNormalRGB, blendedNormalAlpha); +# if defined(SNOW) && !defined(TRUE_PBR) + float landSnowMask4 = GetLandSnowMaskValue(baseColor.w); + AccumulateLandscapeSnow(weight, LandscapeTexture1to4IsSnow.w, input.LandBlendWeights1.w, landSnowMask4, landSnowMask); # endif - float3 normalRGB4 = normal4.rgb; - float normalAlpha4 = normal4.a; # if defined(TRUE_PBR) -# if defined(TERRAIN_VARIATION) - float4 rmaos4 = StochasticEffect(screenNoise, mipLevels[3], TexLandRMAOS4Sampler, SampRMAOSSampler, uv, sharedOffset, dx, dy, viewDistance); -# else - float4 rmaos4 = lerp( - TexLandRMAOS4Sampler.SampleBias(SampRMAOSSampler, uv, SharedData::MipBias), - TexLandRMAOS4Sampler.SampleLevel(SampRMAOSSampler, uv, distanceFactor * 3.0), - distanceFactor); -# endif - rmaos4 *= float4(LandscapeTexture4PBRParams.x, 1, 1, LandscapeTexture4PBRParams.z); - blendedRMAOS += rmaos4 * weight; + [branch] if ((PBRFlags & PBR::TerrainFlags::LandTile3HasGlint) != 0) + { + AccumulateLandscapeGlints(input.LandBlendWeights1.w, LandscapeTexture4GlintParameters, glintParameters); + } # endif - blendedRGB += diffuseRGB4 * weight; - blendedAlpha += alpha4 * weight; - blendedNormalRGB += normalRGB4 * weight; - blendedNormalAlpha += normalAlpha4 * weight; } // Layer 5 (LandBlendWeights2.x) if (input.LandBlendWeights2.x > 0.01) { float weight = input.LandBlendWeights2.x * invwsum; + SampleLandscapeLayer( + uv, viewDistance, screenNoise, mipLevels[4], weight, + TexLandColor5Sampler, TexLandNormal5Sampler, + SampColorSampler, SampNormalSampler, # if defined(TERRAIN_VARIATION) - float4 diffuse5 = StochasticEffect(screenNoise, mipLevels[4], TexLandColor5Sampler, SampColorSampler, uv, sharedOffset, dx, dy, viewDistance); -# else - float distanceFactor = smoothstep(0.0, 2048.0, viewDistance); - float4 diffuse5 = lerp( - TexLandColor5Sampler.SampleBias(SampColorSampler, uv, SharedData::MipBias), - TexLandColor5Sampler.SampleLevel(SampColorSampler, uv, distanceFactor * 3.0), - distanceFactor); + + sharedOffset, dx, dy, # endif - float3 diffuseRGB5 = diffuse5.rgb; # if defined(TRUE_PBR) - [branch] if ((PBRFlags & PBR::TerrainFlags::LandTile4PBR) == 0) - { - diffuseRGB5 = diffuseRGB5 / Color::PBRLightingScale; - } + TexLandRMAOS5Sampler, SampRMAOSSampler, LandscapeTexture5PBRParams, blendedRMAOS, # endif - float alpha5 = diffuse5.a; - -# if defined(TERRAIN_VARIATION) - float4 normal5 = StochasticEffect(screenNoise, mipLevels[4], TexLandNormal5Sampler, SampNormalSampler, uv, sharedOffset, dx, dy, viewDistance); -# else - float4 normal5 = lerp( - TexLandNormal5Sampler.SampleBias(SampNormalSampler, uv, SharedData::MipBias), - TexLandNormal5Sampler.SampleLevel(SampNormalSampler, uv, distanceFactor * 3.0), - distanceFactor); + blendedRGB, blendedAlpha, blendedNormalRGB, blendedNormalAlpha); +# if defined(SNOW) && !defined(TRUE_PBR) + float landSnowMask5 = GetLandSnowMaskValue(baseColor.w); + AccumulateLandscapeSnow(weight, LandscapeTexture5to6IsSnow.x, input.LandBlendWeights2.x, landSnowMask5, landSnowMask); # endif - float3 normalRGB5 = normal5.rgb; - float normalAlpha5 = normal5.a; # if defined(TRUE_PBR) -# if defined(TERRAIN_VARIATION) - float4 rmaos5 = StochasticEffect(screenNoise, mipLevels[4], TexLandRMAOS5Sampler, SampRMAOSSampler, uv, sharedOffset, dx, dy, viewDistance); -# else - float4 rmaos5 = lerp( - TexLandRMAOS5Sampler.SampleBias(SampRMAOSSampler, uv, SharedData::MipBias), - TexLandRMAOS5Sampler.SampleLevel(SampRMAOSSampler, uv, distanceFactor * 3.0), - distanceFactor); -# endif - rmaos5 *= float4(LandscapeTexture5PBRParams.x, 1, 1, LandscapeTexture5PBRParams.z); - blendedRMAOS += rmaos5 * weight; + [branch] if ((PBRFlags & PBR::TerrainFlags::LandTile4HasGlint) != 0) + { + AccumulateLandscapeGlints(input.LandBlendWeights2.x, LandscapeTexture5GlintParameters, glintParameters); + } # endif - blendedRGB += diffuseRGB5 * weight; - blendedAlpha += alpha5 * weight; - blendedNormalRGB += normalRGB5 * weight; - blendedNormalAlpha += normalAlpha5 * weight; } // Layer 6 (LandBlendWeights2.y) if (input.LandBlendWeights2.y > 0.01) { float weight = input.LandBlendWeights2.y * invwsum; + SampleLandscapeLayer( + uv, viewDistance, screenNoise, mipLevels[5], weight, + TexLandColor6Sampler, TexLandNormal6Sampler, + SampColorSampler, SampNormalSampler, # if defined(TERRAIN_VARIATION) - float4 diffuse6 = StochasticEffect(screenNoise, mipLevels[5], TexLandColor6Sampler, SampColorSampler, uv, sharedOffset, dx, dy, viewDistance); -# else - float distanceFactor = smoothstep(0.0, 2048.0, viewDistance); - float4 diffuse6 = lerp( - TexLandColor6Sampler.SampleBias(SampColorSampler, uv, SharedData::MipBias), - TexLandColor6Sampler.SampleLevel(SampColorSampler, uv, distanceFactor * 3.0), - distanceFactor); + sharedOffset, dx, dy, # endif - float3 diffuseRGB6 = diffuse6.rgb; # if defined(TRUE_PBR) - [branch] if ((PBRFlags & PBR::TerrainFlags::LandTile5PBR) == 0) - { - diffuseRGB6 = diffuseRGB6 / Color::PBRLightingScale; - } + TexLandRMAOS6Sampler, SampRMAOSSampler, + LandscapeTexture6PBRParams, blendedRMAOS, # endif - float alpha6 = diffuse6.a; + blendedRGB, blendedAlpha, blendedNormalRGB, blendedNormalAlpha -# if defined(TERRAIN_VARIATION) - float4 normal6 = StochasticEffect(screenNoise, mipLevels[5], TexLandNormal6Sampler, SampNormalSampler, uv, sharedOffset, dx, dy, viewDistance); -# else - float4 normal6 = lerp( - TexLandNormal6Sampler.SampleBias(SampNormalSampler, uv, SharedData::MipBias), - TexLandNormal6Sampler.SampleLevel(SampNormalSampler, uv, distanceFactor * 3.0), - distanceFactor); + ); +# if defined(SNOW) && !defined(TRUE_PBR) + float landSnowMask6 = GetLandSnowMaskValue(baseColor.w); + AccumulateLandscapeSnow(weight, LandscapeTexture5to6IsSnow.y, input.LandBlendWeights2.y, landSnowMask6, landSnowMask); # endif - float3 normalRGB6 = normal6.rgb; - float normalAlpha6 = normal6.a; # if defined(TRUE_PBR) -# if defined(TERRAIN_VARIATION) - float4 rmaos6 = StochasticEffect(screenNoise, mipLevels[5], TexLandRMAOS6Sampler, SampRMAOSSampler, uv, sharedOffset, dx, dy, viewDistance); -# else - float4 rmaos6 = lerp( - TexLandRMAOS6Sampler.SampleBias(SampRMAOSSampler, uv, SharedData::MipBias), - TexLandRMAOS6Sampler.SampleLevel(SampRMAOSSampler, uv, distanceFactor * 3.0), - distanceFactor); -# endif - rmaos6 *= float4(LandscapeTexture6PBRParams.x, 1, 1, LandscapeTexture6PBRParams.z); - blendedRMAOS += rmaos6 * weight; + [branch] if ((PBRFlags & PBR::TerrainFlags::LandTile5HasGlint) != 0) + { + AccumulateLandscapeGlints(input.LandBlendWeights2.y, LandscapeTexture6GlintParameters, glintParameters); + } # endif - blendedRGB += diffuseRGB6 * weight; - blendedAlpha += alpha6 * weight; - blendedNormalRGB += normalRGB6 * weight; - blendedNormalAlpha += normalAlpha6 * weight; } float4 rawBaseColor = float4(blendedRGB, blendedAlpha); @@ -1677,8 +1641,8 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) # if defined(TRUE_PBR) rawRMAOS = TexRMAOSSampler.SampleBias(SampRMAOSSampler, diffuseUv, SharedData::MipBias) * float4(PBRParams1.x, 1, 1, PBRParams1.z); if ((PBRFlags & PBR::Flags::Glint) != 0) { - glintParameters = MultiLayerParallaxData; - } + glintParameters = MultiLayerParallaxData; + } # endif # endif @@ -1800,7 +1764,7 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) # if defined(TRUE_PBR) [branch] if ((PBRFlags & PBR::TerrainFlags::LandTile4HasGlint) != 0) { - glintParameters += input.LandBlendWeights2.x * LandscapeTexture5GlintParameters; + AccumulateLandscapeGlints(input.LandBlendWeights2.x, LandscapeTexture5GlintParameters, glintParameters); } # endif } @@ -1814,7 +1778,7 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) # if defined(TRUE_PBR) [branch] if ((PBRFlags & PBR::TerrainFlags::LandTile5HasGlint) != 0) { - glintParameters += input.LandBlendWeights2.y * LandscapeTexture6GlintParameters; + AccumulateLandscapeGlints(input.LandBlendWeights2.y, LandscapeTexture6GlintParameters, glintParameters); } # endif } @@ -2213,7 +2177,7 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) # endif float3 dirLightColor = Color::Light(DirLightColor.xyz); - float3 dirLightColorMultiplier = 1; + float dirLightColorMultiplier = 1; # if defined(WATER_EFFECTS) dirLightColorMultiplier *= WaterEffects::ComputeCaustics(waterData, input.WorldPosition.xyz, eyeIndex); From 7d92548dc81c25648d9bdfc96a8bcaf573030c20 Mon Sep 17 00:00:00 2001 From: Alan Tse Date: Sat, 28 Jun 2025 21:09:28 -0700 Subject: [PATCH 2/7] refactor: use ProcessPBRDirectLight --- package/Shaders/Common/PBR.hlsli | 108 +++++++++++++++++++++++++++++++ package/Shaders/Lighting.hlsl | 80 ++++++++++++++++------- package/Shaders/RunGrass.hlsl | 47 ++++++++++---- 3 files changed, 199 insertions(+), 36 deletions(-) diff --git a/package/Shaders/Common/PBR.hlsli b/package/Shaders/Common/PBR.hlsli index 24205e1f6d..5ce34576f9 100644 --- a/package/Shaders/Common/PBR.hlsli +++ b/package/Shaders/Common/PBR.hlsli @@ -384,6 +384,114 @@ namespace PBR } } + /** + * @brief Calculates and accumulates PBR direct lighting contributions for a single light source + * + * This function handles the core PBR lighting calculation that is identical across all call sites. + * It processes diffuse, specular, transmission, and coat lighting components for a given light + * and accumulates the results into the provided output variables. + * + * @note This function is designed to be called multiple times per pixel (once per light source) + * and accumulates results rather than returning them. All output parameters are modified in-place. + * + * @param[in] lightColor The RGB color of the light source (should be in linear space) + * @param[in] lightMultiplier Combined multiplier for light intensity (includes shadows, attenuation, etc.) + * @param[in] parallaxShadow Parallax occlusion mapping shadow factor (1.0 = no shadow) + * @param[in] N Surface normal vector in world space + * @param[in] N_coat Coat layer normal vector in world space (used for two-layer materials) + * @param[in] V_refracted View direction after refraction through coat layer + * @param[in] V Original view direction in world space + * @param[in] L_refracted Light direction after refraction through coat layer + * @param[in] L Original light direction in world space + * @param[in] surfaceProperties PBR material properties (roughness, metallic, F0, etc.) + * @param[in] tbnMatrix Transpose of the tangent-bitangent-normal matrix + * @param[in] texCoord Texture coordinates (used for feature texture sampling) + * @param[in,out] diffuseAccumulator Accumulated diffuse lighting contribution (modified in-place) + * @param[in,out] coatDiffuseAccumulator Accumulated coat layer diffuse lighting (modified in-place) + * @param[in,out] transmissionAccumulator Accumulated transmission/translucency contribution (modified in-place) + * @param[in,out] specularAccumulator Accumulated specular lighting contribution (modified in-place, automatically gated by interior status) + * + * @return PBR::LightProperties The calculated light properties, useful for additional effects like wetness + * + * @par Example Usage: + * @code + * // For directional light + * PBR::LightProperties lightProperties = PBR::ProcessPBRDirectLight( + * dirLightColor, + * dirLightColorMultiplier * dirDetailShadow, + * parallaxShadow, + * N, // Surface normal + * N_coat, // Coat normal + * V_refracted, // Refracted view direction + * V, // View direction + * L_refracted, // Refracted light direction + * L, // Light direction + * pbrSurfaceProperties, + * tbnMatrix, + * texCoord, + * lightsDiffuseColor, + * coatLightsDiffuseColor, + * transmissionColor, + * specularColorPBR); + * + * // Additional effects using the returned light properties + * if (waterRoughnessSpecular < 1.0) { + * specularColorPBR += PBR::GetWetnessDirectLightSpecularInput( + * wetnessNormal, V, L, + * lightProperties.CoatLightColor, waterRoughnessSpecular) * wetnessGlossinessSpecular; + * } + * @endcode + * + * @par Features Supported: + * - Standard PBR lighting (diffuse + specular) + * - Two-layer materials (coat layer) + * - Transmission/translucency effects + * - Interior/exterior lighting adjustments (specular automatically disabled in interiors) + * - Feature texture sampling + * + * @par Performance Notes: + * - Function is marked as @c inline for optimal performance + * - Designed to be called in tight loops for multiple light sources + * - Accumulates results to minimize memory bandwidth + * + * @see PBR::GetDirectLightInput + * @see PBR::InitLightProperties + * @see PBR::SurfaceProperties + */ + inline LightProperties ProcessPBRDirectLight( + float3 lightColor, + float lightMultiplier, + float parallaxShadow, + float3 N, + float3 N_coat, + float3 V_refracted, + float3 V, + float3 L_refracted, + float3 L, + SurfaceProperties surfaceProperties, + float3x3 tbnMatrix, + float2 texCoord, + inout float3 diffuseAccumulator, + inout float3 coatDiffuseAccumulator, + inout float3 transmissionAccumulator, + inout float3 specularAccumulator) + { + LightProperties lightProperties = InitLightProperties(lightColor, lightMultiplier, parallaxShadow); + float3 dirDiffuseColor, coatDirDiffuseColor, dirTransmissionColor, dirSpecularColor; + + GetDirectLightInput( + dirDiffuseColor, coatDirDiffuseColor, dirTransmissionColor, dirSpecularColor, + N, N_coat, V_refracted, V, + L_refracted, L, lightProperties, surfaceProperties, tbnMatrix, texCoord); + + diffuseAccumulator += dirDiffuseColor; + coatDiffuseAccumulator += coatDirDiffuseColor; + transmissionAccumulator += dirTransmissionColor; + specularAccumulator += dirSpecularColor * !SharedData::InInterior; + + return lightProperties; + } + float3 GetWetnessDirectLightSpecularInput(float3 N, float3 V, float3 L, float3 lightColor, float roughness) { const float wetnessStrength = 1; diff --git a/package/Shaders/Lighting.hlsl b/package/Shaders/Lighting.hlsl index da4b29cff8..2e71185cfa 100644 --- a/package/Shaders/Lighting.hlsl +++ b/package/Shaders/Lighting.hlsl @@ -1037,7 +1037,7 @@ float GetSnowParameterY(float texProjTmp, float alpha) # include "IBL/IBL.hlsli" # endif -#if defined(LANDSCAPE) +# if defined(LANDSCAPE) inline void SampleLandscapeLayer( float2 uv, float viewDistance, @@ -2284,13 +2284,24 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) # if defined(TRUE_PBR) { - PBR::LightProperties lightProperties = PBR::InitLightProperties(dirLightColor, dirLightColorMultiplier * dirDetailShadow, parallaxShadow); - float3 dirDiffuseColor, coatDirDiffuseColor, dirTransmissionColor, dirSpecularColor; - PBR::GetDirectLightInput(dirDiffuseColor, coatDirDiffuseColor, dirTransmissionColor, dirSpecularColor, modelNormal.xyz, coatModelNormal, refractedViewDirection, viewDirection, refractedDirLightDirection, DirLightDirection, lightProperties, pbrSurfaceProperties, tbnTr, uvOriginal); - lightsDiffuseColor += dirDiffuseColor; - coatLightsDiffuseColor += coatDirDiffuseColor; - transmissionColor += dirTransmissionColor; - specularColorPBR += dirSpecularColor * !SharedData::InInterior; + PBR::LightProperties lightProperties = PBR::ProcessPBRDirectLight( + dirLightColor, + dirLightColorMultiplier * dirDetailShadow, + parallaxShadow, + modelNormal.xyz, + coatModelNormal, + refractedViewDirection, + viewDirection, + refractedDirLightDirection, + DirLightDirection, + pbrSurfaceProperties, + tbnTr, + uvOriginal, + lightsDiffuseColor, + coatLightsDiffuseColor, + transmissionColor, + specularColorPBR); + # if defined(LOD_LAND_BLEND) lodLandDiffuseColor += dirLightColor / Math::PI * saturate(dirLightAngle) * dirLightColorMultiplier * dirDetailShadow * parallaxShadow; # endif @@ -2376,12 +2387,23 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) refractedLightDirection = -refract(-normalizedLightDirection, coatModelNormal, eta); } # endif - PBR::LightProperties lightProperties = PBR::InitLightProperties(lightColor, lightShadow, 1); - PBR::GetDirectLightInput(pointDiffuseColor, coatPointDiffuseColor, pointTransmissionColor, pointSpecularColor, modelNormal.xyz, coatModelNormal, refractedViewDirection, viewDirection, refractedLightDirection, normalizedLightDirection, lightProperties, pbrSurfaceProperties, tbnTr, uvOriginal); - lightsDiffuseColor += pointDiffuseColor; - coatLightsDiffuseColor += coatPointDiffuseColor; - transmissionColor += pointTransmissionColor; - specularColorPBR += pointSpecularColor; + PBR::ProcessPBRDirectLight( + lightColor, + lightShadow, + 1, + modelNormal.xyz, + coatModelNormal, + refractedViewDirection, + viewDirection, + refractedLightDirection, + normalizedLightDirection, + pbrSurfaceProperties, + tbnTr, + uvOriginal, + lightsDiffuseColor, + coatLightsDiffuseColor, + transmissionColor, + specularColorPBR); } # else lightColor *= lightShadow; @@ -2484,11 +2506,11 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) SharedData::lightLimitFixSettings.EnableContactShadows && !(light.lightFlags & LightLimitFix::LightFlags::Simple) && shadowComponent != 0.0 && -# if defined(HAIR) && defined(CS_HAIR) +# if defined(HAIR) && defined(CS_HAIR) true -# else +# else lightAngle > 0.0 -# endif +# endif ) { float3 normalizedLightDirectionVS = normalize(light.positionVS[eyeIndex].xyz - viewPosition.xyz); @@ -2537,13 +2559,23 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) # if defined(TRUE_PBR) { - PBR::LightProperties lightProperties = PBR::InitLightProperties(lightColor, lightShadow * contactShadow, parallaxShadow); - float3 pointDiffuseColor, coatPointDiffuseColor, pointTransmissionColor, pointSpecularColor; - PBR::GetDirectLightInput(pointDiffuseColor, coatPointDiffuseColor, pointTransmissionColor, pointSpecularColor, worldSpaceNormal.xyz, coatWorldNormal, refractedViewDirectionWS, worldSpaceViewDirection, refractedLightDirection, normalizedLightDirection, lightProperties, pbrSurfaceProperties, tbnTr, uvOriginal); - lightsDiffuseColor += pointDiffuseColor; - coatLightsDiffuseColor += coatPointDiffuseColor; - transmissionColor += pointTransmissionColor; - specularColorPBR += pointSpecularColor; + PBR::LightProperties lightProperties = PBR::ProcessPBRDirectLight( + lightColor, + lightShadow * contactShadow, + parallaxShadow, + worldSpaceNormal.xyz, + coatWorldNormal, + refractedViewDirectionWS, + worldSpaceViewDirection, + refractedLightDirection, + normalizedLightDirection, + pbrSurfaceProperties, + tbnTr, + uvOriginal, + lightsDiffuseColor, + coatLightsDiffuseColor, + transmissionColor, + specularColorPBR); # if defined(WETNESS_EFFECTS) if (waterRoughnessSpecular < 1.0) specularColorPBR += PBR::GetWetnessDirectLightSpecularInput(wetnessNormal, worldSpaceViewDirection, normalizedLightDirection, lightProperties.CoatLightColor, waterRoughnessSpecular) * wetnessGlossinessSpecular; diff --git a/package/Shaders/RunGrass.hlsl b/package/Shaders/RunGrass.hlsl index 793299d174..345c02581a 100644 --- a/package/Shaders/RunGrass.hlsl +++ b/package/Shaders/RunGrass.hlsl @@ -543,6 +543,7 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) float3 specularColorPBR = 0; float3 transmissionColor = 0; + float3 coatLightsDiffuseColor = 0; // unused - grass has no coat layer # endif // TRUE_PBR float3 dirLightColor = SharedData::DirLightColor.xyz; @@ -579,12 +580,23 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) # if defined(TRUE_PBR) { - PBR::LightProperties lightProperties = PBR::InitLightProperties(SharedData::DirLightColor.xyz, dirLightColorMultiplier * dirShadow, 1); - float3 dirDiffuseColor, coatDirDiffuseColor, dirTransmissionColor, dirSpecularColor; - PBR::GetDirectLightInput(dirDiffuseColor, coatDirDiffuseColor, dirTransmissionColor, dirSpecularColor, normal, normal, viewDirection, viewDirection, DirLightDirection, DirLightDirection, lightProperties, pbrSurfaceProperties, tbn, input.TexCoord.xy); - lightsDiffuseColor += dirDiffuseColor; - transmissionColor += dirTransmissionColor; - specularColorPBR += dirSpecularColor; + PBR::LightProperties lightProperties = PBR::ProcessPBRDirectLight( + SharedData::DirLightColor.xyz, + dirLightColorMultiplier * dirShadow, + 1.0f, // no parallax shadow - grass doesn't use POM + normal, + normal, + viewDirection, + viewDirection, + DirLightDirection, + DirLightDirection, + pbrSurfaceProperties, + tbn, + input.TexCoord.xy, + lightsDiffuseColor, + coatLightsDiffuseColor, // unused - grass has no coat layer + transmissionColor, + specularColorPBR); } # else dirLightColor *= dirLightColorMultiplier; @@ -662,12 +674,23 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) # if defined(TRUE_PBR) { - PBR::LightProperties lightProperties = PBR::InitLightProperties(lightColor, lightShadow, 1); - float3 pointDiffuseColor, coatDirDiffuseColor, pointTransmissionColor, pointSpecularColor; - PBR::GetDirectLightInput(pointDiffuseColor, coatDirDiffuseColor, pointTransmissionColor, pointSpecularColor, normal, normal, viewDirection, viewDirection, normalizedLightDirection, normalizedLightDirection, lightProperties, pbrSurfaceProperties, tbn, input.TexCoord.xy); - lightsDiffuseColor += pointDiffuseColor; - transmissionColor += pointTransmissionColor; - specularColorPBR += pointSpecularColor; + PBR::LightProperties lightProperties = PBR::ProcessPBRDirectLight( + lightColor, + lightShadow, + 1.0f, // no parallax shadow - grass doesn't use POM + normal, + normal, + viewDirection, + viewDirection, + normalizedLightDirection, + normalizedLightDirection, + pbrSurfaceProperties, + tbn, + input.TexCoord.xy, + lightsDiffuseColor, + coatLightsDiffuseColor, // unused - grass has no coat layer + transmissionColor, + specularColorPBR); } # else lightColor *= lightShadow; From 9c6b8ae5c5d32f775f3a8be97fdb4206f91e4765 Mon Sep 17 00:00:00 2001 From: Alan Tse Date: Sun, 29 Jun 2025 00:11:37 -0700 Subject: [PATCH 3/7] perf: optimize terrain sampling and lighting - Add LIGHT_INTENSITY_EARLY_EXIT_THRESHOLD (0.001) to skip dim light processing entirely - Add CONTACT_SHADOW_EARLY_EXIT_THRESHOLD (0.01) to skip contact shadows for dim lights - Add CONTACT_SHADOW_FULL_RAY_THRESHOLD (0.1) to use full ray marching only for bright lights - Add LANDSCAPE_DISTANCE_OPTIMIZATION_THRESHOLD (2048u) to optimize PBR RMAOS sampling for distant terrain - Add TERRAIN_DISTANT_MIP_LEVEL (6) for high-mip sampling of distant terrain - Optimize texture sampling for distant terrain - Skip expensive operations for lights with negligible contribution --- package/Shaders/Lighting.hlsl | 86 ++++++++++++++++++++++++----------- 1 file changed, 59 insertions(+), 27 deletions(-) diff --git a/package/Shaders/Lighting.hlsl b/package/Shaders/Lighting.hlsl index 2e71185cfa..d2c36be127 100644 --- a/package/Shaders/Lighting.hlsl +++ b/package/Shaders/Lighting.hlsl @@ -9,6 +9,12 @@ #include "Common/SharedData.hlsli" #include "Common/Skinned.hlsli" +#define LIGHT_INTENSITY_EARLY_EXIT_THRESHOLD 0.001f // Skip lights with negligible contribution +#define CONTACT_SHADOW_EARLY_EXIT_THRESHOLD 0.01f // Skip contact shadow ray marching for dim lights +#define CONTACT_SHADOW_FULL_RAY_THRESHOLD 0.1f // Only do full ray marching for significant lights +#define LANDSCAPE_BLEND_WEIGHT_THRESHOLD 0.01f // Minimum landscape blend weight to process layer +#define LANDSCAPE_DISTANCE_OPTIMIZATION_THRESHOLD 2048.0f // Switch to cheap sampling for distant terrain ~29m / 96ft +#define TERRAIN_DISTANT_MIP_LEVEL 6 // Mip level for distant terrain textures #define LIGHTING #if defined(FACEGEN) || defined(FACEGEN_RGB_TINT) @@ -750,17 +756,20 @@ float3 GetLightSpecularInput(PS_INPUT input, float3 L, float3 V, float3 N, float # endif # if defined(SPARKLE) && !defined(SNOW) - float3 sparkleUvScale = exp2(float3(1.3, 1.6, 1.9) * log2(abs(SparkleParams.x)).xxx); - - float sparkleColor1 = TexProjDetail.Sample(SampProjDetailSampler, uv * sparkleUvScale.xx).z; - float sparkleColor2 = TexProjDetail.Sample(SampProjDetailSampler, uv * sparkleUvScale.yy).z; - float sparkleColor3 = TexProjDetail.Sample(SampProjDetailSampler, uv * sparkleUvScale.zz).z; - float sparkleColor = ProcessSparkleColor(sparkleColor1) + ProcessSparkleColor(sparkleColor2) + ProcessSparkleColor(sparkleColor3); - float VdotN = dot(V, N); - V += N * -(2 * VdotN); - float sparkleMultiplier = exp2(SparkleParams.w * log2(saturate(dot(V, -L)))) * (SparkleParams.z * sparkleColor); - sparkleMultiplier = sparkleMultiplier >= 0.5 ? 1 : 0; - lightColorMultiplier += sparkleMultiplier * HdotN; + // Skip expensive sparkle texture sampling for dim lights + if (lightColor.x + lightColor.y + lightColor.z > CONTACT_SHADOW_EARLY_EXIT_THRESHOLD) { + float3 sparkleUvScale = exp2(float3(1.3, 1.6, 1.9) * log2(abs(SparkleParams.x)).xxx); + + float sparkleColor1 = TexProjDetail.Sample(SampProjDetailSampler, uv * sparkleUvScale.xx).z; + float sparkleColor2 = TexProjDetail.Sample(SampProjDetailSampler, uv * sparkleUvScale.yy).z; + float sparkleColor3 = TexProjDetail.Sample(SampProjDetailSampler, uv * sparkleUvScale.zz).z; + float sparkleColor = ProcessSparkleColor(sparkleColor1) + ProcessSparkleColor(sparkleColor2) + ProcessSparkleColor(sparkleColor3); + float VdotN = dot(V, N); + V += N * -(2 * VdotN); + float sparkleMultiplier = exp2(SparkleParams.w * log2(saturate(dot(V, -L)))) * (SparkleParams.z * sparkleColor); + sparkleMultiplier = sparkleMultiplier >= 0.5 ? 1 : 0; + lightColorMultiplier += sparkleMultiplier * HdotN; + } # endif return lightColor * lightColorMultiplier; } @@ -1068,12 +1077,16 @@ inline void SampleLandscapeLayer( # if defined(TERRAIN_VARIATION) float4 diffuse = StochasticEffect(screenNoise, mipLevel, texColor, sampColor, uv, sharedOffset, dx, dy, viewDistance); # else + // Non-TERRAIN_VARIATION path - gradual mip level increase based on distance float distanceFactor = smoothstep(0.0, 2048.0, viewDistance); + float aggressiveMipFactor = 6.0f; float4 diffuse = lerp( texColor.SampleBias(sampColor, uv, SharedData::MipBias), - texColor.SampleLevel(sampColor, uv, distanceFactor * 3.0), + texColor.SampleLevel(sampColor, uv, distanceFactor * aggressiveMipFactor), distanceFactor); # endif + + // Post-process diffuse sample for PBR compatibility float3 diffuseRGB = diffuse.rgb; # if defined(TRUE_PBR) // Check if this texture is not PBR (pbrParams.x == 0 means non-PBR texture) @@ -1083,32 +1096,41 @@ inline void SampleLandscapeLayer( # endif float alpha = diffuse.a; - // Sample normal + // Sample normal - same distance-based optimization as diffuse # if defined(TERRAIN_VARIATION) float4 normal = StochasticEffect(screenNoise, mipLevel, texNormal, sampNormal, uv, sharedOffset, dx, dy, viewDistance); # else float4 normal = lerp( texNormal.SampleBias(sampNormal, uv, SharedData::MipBias), - texNormal.SampleLevel(sampNormal, uv, distanceFactor * 3.0), + texNormal.SampleLevel(sampNormal, uv, distanceFactor * aggressiveMipFactor), distanceFactor); # endif float3 normalRGB = normal.rgb; float normalAlpha = normal.a; + float4 rmaos = 0.0.xxxx; +// Sample PBR material properties (RMAOS) - most expensive, so most aggressive optimization # if defined(TRUE_PBR) // Sample RMAOS # if defined(TERRAIN_VARIATION) - float4 rmaos = StochasticEffect(screenNoise, mipLevel, texRMAOS, sampRMAOS, uv, sharedOffset, dx, dy, viewDistance); + rmaos = StochasticEffect(screenNoise, mipLevel, texRMAOS, sampRMAOS, uv, sharedOffset, dx, dy, viewDistance); # else - float4 rmaos = lerp( - texRMAOS.SampleBias(sampRMAOS, uv, SharedData::MipBias), - texRMAOS.SampleLevel(sampRMAOS, uv, distanceFactor * 3.0), - distanceFactor); + if (viewDistance <= LANDSCAPE_DISTANCE_OPTIMIZATION_THRESHOLD) { + rmaos = lerp( + texRMAOS.SampleBias(sampRMAOS, uv, SharedData::MipBias), + texRMAOS.SampleLevel(sampRMAOS, uv, distanceFactor * aggressiveMipFactor), + distanceFactor); + } else { + // DISTANT TERRAIN: Skip PBR entirely + // PBR details are not visible at distance anyway + rmaos = texRMAOS.SampleLevel(sampRMAOS, uv, TERRAIN_DISTANT_MIP_LEVEL); + } # endif rmaos *= float4(pbrParams.x, 1, 1, pbrParams.z); blendedRMAOS += rmaos * weight; # endif + // Accumulate all samples into final blended result blendedRGB += diffuseRGB * weight; blendedAlpha += alpha * weight; blendedNormalRGB += normalRGB * weight; @@ -1435,7 +1457,7 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) # endif // EMAT // Initialize mip levels for non-EMAT case mipLevels[0] = mipLevels[1] = mipLevels[2] = mipLevels[3] = mipLevels[4] = mipLevels[5] = 0.0; -# endif // LANDSCAPE +# endif // LANDSCAPE # if defined(SPARKLE) diffuseUv = ProjectedUVParams2.yy * (input.TexCoord0.zw + (uv - uvOriginal)); @@ -1700,7 +1722,7 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) # endif // SNOW // Layer 1 (LandBlendWeights1.x) - if (input.LandBlendWeights1.x > 0.01) { + if (input.LandBlendWeights1.x > LANDSCAPE_BLEND_WEIGHT_THRESHOLD) { # if defined(SNOW) && !defined(TRUE_PBR) float landSnowMask1 = GetLandSnowMaskValue(baseColor.w); landSnowMask += LandscapeTexture1to4IsSnow.x * input.LandBlendWeights1.x * landSnowMask1; @@ -1714,7 +1736,7 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) } // Layer 2 (LandBlendWeights1.y) - if (input.LandBlendWeights1.y > 0.01) { + if (input.LandBlendWeights1.y > LANDSCAPE_BLEND_WEIGHT_THRESHOLD) { # if defined(SNOW) && !defined(TRUE_PBR) float landSnowMask2 = GetLandSnowMaskValue(baseColor.w); landSnowMask += LandscapeTexture1to4IsSnow.y * input.LandBlendWeights1.y * landSnowMask2; @@ -1728,7 +1750,7 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) } // Layer 3 (LandBlendWeights1.z) - if (input.LandBlendWeights1.z > 0.01) { + if (input.LandBlendWeights1.z > LANDSCAPE_BLEND_WEIGHT_THRESHOLD) { # if defined(SNOW) && !defined(TRUE_PBR) float landSnowMask3 = GetLandSnowMaskValue(baseColor.w); landSnowMask += LandscapeTexture1to4IsSnow.z * input.LandBlendWeights1.z * landSnowMask3; @@ -1742,7 +1764,7 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) } // Layer 4 (LandBlendWeights1.w) - if (input.LandBlendWeights1.w > 0.01) { + if (input.LandBlendWeights1.w > LANDSCAPE_BLEND_WEIGHT_THRESHOLD) { # if defined(SNOW) && !defined(TRUE_PBR) float landSnowMask4 = GetLandSnowMaskValue(baseColor.w); landSnowMask += LandscapeTexture1to4IsSnow.w * input.LandBlendWeights1.w * landSnowMask4; @@ -1756,7 +1778,7 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) } // Layer 5 (LandBlendWeights2.x) - if (input.LandBlendWeights2.x > 0.01) { + if (input.LandBlendWeights2.x > LANDSCAPE_BLEND_WEIGHT_THRESHOLD) { # if defined(SNOW) && !defined(TRUE_PBR) float landSnowMask5 = GetLandSnowMaskValue(baseColor.w); landSnowMask += LandscapeTexture5to6IsSnow.x * input.LandBlendWeights2.x * landSnowMask5; @@ -1770,7 +1792,7 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) } // Layer 6 (LandBlendWeights2.y) - if (input.LandBlendWeights2.y > 0.01) { + if (input.LandBlendWeights2.y > LANDSCAPE_BLEND_WEIGHT_THRESHOLD) { # if defined(SNOW) && !defined(TRUE_PBR) float landSnowMask6 = GetLandSnowMaskValue(baseColor.w); landSnowMask += LandscapeTexture5to6IsSnow.y * input.LandBlendWeights2.y * landSnowMask6; @@ -2367,6 +2389,9 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) float intensityMultiplier = 1 - intensityFactor * intensityFactor; float3 lightColor = Color::Light(PointLightColor[lightIndex].xyz) * intensityMultiplier; + if (lightColor.x + lightColor.y + lightColor.z < LIGHT_INTENSITY_EARLY_EXIT_THRESHOLD) { + continue; // Skip this dim light entirely + } float lightShadow = 1.f; if (Permutation::PixelShaderDescriptor & Permutation::LightingFlags::DefShadow) { if (lightIndex < numShadowLights) { @@ -2458,7 +2483,8 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) lightOffset = LightLimitFix::lightGrid[clusterIndex].offset; } - uint contactShadowSteps = round(4.0 * (1.0 - saturate(viewPosition.z / 1024.0))); + // Calculate once per pixel (outside all light loops) + uint baseContactShadowSteps = round(4.0 * (1.0 - saturate(viewPosition.z / 1024.0))); [loop] for (uint lightIndex = 0; lightIndex < totalLightCount; lightIndex++) { @@ -2489,6 +2515,10 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) # endif float3 lightColor = Color::Light(light.color.xyz) * intensityMultiplier; + if (lightColor.x + lightColor.y + lightColor.z < LIGHT_INTENSITY_EARLY_EXIT_THRESHOLD) { + continue; // Skip this dim light entirely + } + float lightShadow = 1.0; float shadowComponent = 1.0; @@ -2502,6 +2532,7 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) float contactShadow = 1.0; [branch] if ( + (lightColor.x + lightColor.y + lightColor.z) > CONTACT_SHADOW_EARLY_EXIT_THRESHOLD && // Early exit for dim lights inWorld && !FrameBuffer::FrameParams.z && SharedData::lightLimitFixSettings.EnableContactShadows && !(light.lightFlags & LightLimitFix::LightFlags::Simple) && @@ -2514,6 +2545,7 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) ) { float3 normalizedLightDirectionVS = normalize(light.positionVS[eyeIndex].xyz - viewPosition.xyz); + uint contactShadowSteps = (lightColor.x + lightColor.y + lightColor.z < CONTACT_SHADOW_FULL_RAY_THRESHOLD) ? 2 : baseContactShadowSteps; contactShadow = LightLimitFix::ContactShadows(viewPosition, screenNoise, normalizedLightDirectionVS, contactShadowSteps, eyeIndex); } From d165904261a9fea93bd4c34d028549d8bf2bcbce Mon Sep 17 00:00:00 2001 From: Alan Tse Date: Sun, 29 Jun 2025 01:51:26 -0700 Subject: [PATCH 4/7] fix: fix unintended swap to SharedData --- package/Shaders/RunGrass.hlsl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package/Shaders/RunGrass.hlsl b/package/Shaders/RunGrass.hlsl index 345c02581a..1882bb543c 100644 --- a/package/Shaders/RunGrass.hlsl +++ b/package/Shaders/RunGrass.hlsl @@ -581,7 +581,7 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) # if defined(TRUE_PBR) { PBR::LightProperties lightProperties = PBR::ProcessPBRDirectLight( - SharedData::DirLightColor.xyz, + DirLightColor.xyz, dirLightColorMultiplier * dirShadow, 1.0f, // no parallax shadow - grass doesn't use POM normal, From 4ddce62ebeda479ffb46ba39e2012abb7fbc14a7 Mon Sep 17 00:00:00 2001 From: Alan Tse Date: Sun, 29 Jun 2025 02:02:01 -0700 Subject: [PATCH 5/7] chore: remove light culling --- package/Shaders/Lighting.hlsl | 18 ++---------------- 1 file changed, 2 insertions(+), 16 deletions(-) diff --git a/package/Shaders/Lighting.hlsl b/package/Shaders/Lighting.hlsl index d2c36be127..65f7a73a09 100644 --- a/package/Shaders/Lighting.hlsl +++ b/package/Shaders/Lighting.hlsl @@ -9,9 +9,6 @@ #include "Common/SharedData.hlsli" #include "Common/Skinned.hlsli" -#define LIGHT_INTENSITY_EARLY_EXIT_THRESHOLD 0.001f // Skip lights with negligible contribution -#define CONTACT_SHADOW_EARLY_EXIT_THRESHOLD 0.01f // Skip contact shadow ray marching for dim lights -#define CONTACT_SHADOW_FULL_RAY_THRESHOLD 0.1f // Only do full ray marching for significant lights #define LANDSCAPE_BLEND_WEIGHT_THRESHOLD 0.01f // Minimum landscape blend weight to process layer #define LANDSCAPE_DISTANCE_OPTIMIZATION_THRESHOLD 2048.0f // Switch to cheap sampling for distant terrain ~29m / 96ft #define TERRAIN_DISTANT_MIP_LEVEL 6 // Mip level for distant terrain textures @@ -756,8 +753,6 @@ float3 GetLightSpecularInput(PS_INPUT input, float3 L, float3 V, float3 N, float # endif # if defined(SPARKLE) && !defined(SNOW) - // Skip expensive sparkle texture sampling for dim lights - if (lightColor.x + lightColor.y + lightColor.z > CONTACT_SHADOW_EARLY_EXIT_THRESHOLD) { float3 sparkleUvScale = exp2(float3(1.3, 1.6, 1.9) * log2(abs(SparkleParams.x)).xxx); float sparkleColor1 = TexProjDetail.Sample(SampProjDetailSampler, uv * sparkleUvScale.xx).z; @@ -769,7 +764,7 @@ float3 GetLightSpecularInput(PS_INPUT input, float3 L, float3 V, float3 N, float float sparkleMultiplier = exp2(SparkleParams.w * log2(saturate(dot(V, -L)))) * (SparkleParams.z * sparkleColor); sparkleMultiplier = sparkleMultiplier >= 0.5 ? 1 : 0; lightColorMultiplier += sparkleMultiplier * HdotN; - } + # endif return lightColor * lightColorMultiplier; } @@ -2389,9 +2384,6 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) float intensityMultiplier = 1 - intensityFactor * intensityFactor; float3 lightColor = Color::Light(PointLightColor[lightIndex].xyz) * intensityMultiplier; - if (lightColor.x + lightColor.y + lightColor.z < LIGHT_INTENSITY_EARLY_EXIT_THRESHOLD) { - continue; // Skip this dim light entirely - } float lightShadow = 1.f; if (Permutation::PixelShaderDescriptor & Permutation::LightingFlags::DefShadow) { if (lightIndex < numShadowLights) { @@ -2483,8 +2475,7 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) lightOffset = LightLimitFix::lightGrid[clusterIndex].offset; } - // Calculate once per pixel (outside all light loops) - uint baseContactShadowSteps = round(4.0 * (1.0 - saturate(viewPosition.z / 1024.0))); + uint contactShadowSteps = round(4.0 * (1.0 - saturate(viewPosition.z / 1024.0))); [loop] for (uint lightIndex = 0; lightIndex < totalLightCount; lightIndex++) { @@ -2515,9 +2506,6 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) # endif float3 lightColor = Color::Light(light.color.xyz) * intensityMultiplier; - if (lightColor.x + lightColor.y + lightColor.z < LIGHT_INTENSITY_EARLY_EXIT_THRESHOLD) { - continue; // Skip this dim light entirely - } float lightShadow = 1.0; @@ -2532,7 +2520,6 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) float contactShadow = 1.0; [branch] if ( - (lightColor.x + lightColor.y + lightColor.z) > CONTACT_SHADOW_EARLY_EXIT_THRESHOLD && // Early exit for dim lights inWorld && !FrameBuffer::FrameParams.z && SharedData::lightLimitFixSettings.EnableContactShadows && !(light.lightFlags & LightLimitFix::LightFlags::Simple) && @@ -2545,7 +2532,6 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) ) { float3 normalizedLightDirectionVS = normalize(light.positionVS[eyeIndex].xyz - viewPosition.xyz); - uint contactShadowSteps = (lightColor.x + lightColor.y + lightColor.z < CONTACT_SHADOW_FULL_RAY_THRESHOLD) ? 2 : baseContactShadowSteps; contactShadow = LightLimitFix::ContactShadows(viewPosition, screenNoise, normalizedLightDirectionVS, contactShadowSteps, eyeIndex); } From 13f0ac7f839705f7431a7171619ab1c2c86541bf Mon Sep 17 00:00:00 2001 From: Alan Tse Date: Sun, 29 Jun 2025 13:00:59 -0700 Subject: [PATCH 6/7] chore: fix type for dirLightColorMultiplier --- package/Shaders/RunGrass.hlsl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package/Shaders/RunGrass.hlsl b/package/Shaders/RunGrass.hlsl index 1882bb543c..2d86350528 100644 --- a/package/Shaders/RunGrass.hlsl +++ b/package/Shaders/RunGrass.hlsl @@ -547,7 +547,7 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) # endif // TRUE_PBR float3 dirLightColor = SharedData::DirLightColor.xyz; - float3 dirLightColorMultiplier = 1; + float dirLightColorMultiplier = 1; float dirLightAngle = dot(normal, SharedData::DirLightDirection.xyz); From 9e5112aeafb2e06f77a37d0df82fc4708f32cfe6 Mon Sep 17 00:00:00 2001 From: Alan Tse Date: Sun, 29 Jun 2025 15:56:42 -0700 Subject: [PATCH 7/7] revert: "perf: optimize terrain sampling and lighting" This reverts commit 9c6b8ae5c5d32f775f3a8be97fdb4206f91e4765. --- package/Shaders/Lighting.hlsl | 81 ++++++++++++++--------------------- 1 file changed, 32 insertions(+), 49 deletions(-) diff --git a/package/Shaders/Lighting.hlsl b/package/Shaders/Lighting.hlsl index 65f7a73a09..8cc31a41f4 100644 --- a/package/Shaders/Lighting.hlsl +++ b/package/Shaders/Lighting.hlsl @@ -10,8 +10,6 @@ #include "Common/Skinned.hlsli" #define LANDSCAPE_BLEND_WEIGHT_THRESHOLD 0.01f // Minimum landscape blend weight to process layer -#define LANDSCAPE_DISTANCE_OPTIMIZATION_THRESHOLD 2048.0f // Switch to cheap sampling for distant terrain ~29m / 96ft -#define TERRAIN_DISTANT_MIP_LEVEL 6 // Mip level for distant terrain textures #define LIGHTING #if defined(FACEGEN) || defined(FACEGEN_RGB_TINT) @@ -753,18 +751,17 @@ float3 GetLightSpecularInput(PS_INPUT input, float3 L, float3 V, float3 N, float # endif # if defined(SPARKLE) && !defined(SNOW) - float3 sparkleUvScale = exp2(float3(1.3, 1.6, 1.9) * log2(abs(SparkleParams.x)).xxx); - - float sparkleColor1 = TexProjDetail.Sample(SampProjDetailSampler, uv * sparkleUvScale.xx).z; - float sparkleColor2 = TexProjDetail.Sample(SampProjDetailSampler, uv * sparkleUvScale.yy).z; - float sparkleColor3 = TexProjDetail.Sample(SampProjDetailSampler, uv * sparkleUvScale.zz).z; - float sparkleColor = ProcessSparkleColor(sparkleColor1) + ProcessSparkleColor(sparkleColor2) + ProcessSparkleColor(sparkleColor3); - float VdotN = dot(V, N); - V += N * -(2 * VdotN); - float sparkleMultiplier = exp2(SparkleParams.w * log2(saturate(dot(V, -L)))) * (SparkleParams.z * sparkleColor); - sparkleMultiplier = sparkleMultiplier >= 0.5 ? 1 : 0; - lightColorMultiplier += sparkleMultiplier * HdotN; - + float3 sparkleUvScale = exp2(float3(1.3, 1.6, 1.9) * log2(abs(SparkleParams.x)).xxx); + + float sparkleColor1 = TexProjDetail.Sample(SampProjDetailSampler, uv * sparkleUvScale.xx).z; + float sparkleColor2 = TexProjDetail.Sample(SampProjDetailSampler, uv * sparkleUvScale.yy).z; + float sparkleColor3 = TexProjDetail.Sample(SampProjDetailSampler, uv * sparkleUvScale.zz).z; + float sparkleColor = ProcessSparkleColor(sparkleColor1) + ProcessSparkleColor(sparkleColor2) + ProcessSparkleColor(sparkleColor3); + float VdotN = dot(V, N); + V += N * -(2 * VdotN); + float sparkleMultiplier = exp2(SparkleParams.w * log2(saturate(dot(V, -L)))) * (SparkleParams.z * sparkleColor); + sparkleMultiplier = sparkleMultiplier >= 0.5 ? 1 : 0; + lightColorMultiplier += sparkleMultiplier * HdotN; # endif return lightColor * lightColorMultiplier; } @@ -1072,16 +1069,12 @@ inline void SampleLandscapeLayer( # if defined(TERRAIN_VARIATION) float4 diffuse = StochasticEffect(screenNoise, mipLevel, texColor, sampColor, uv, sharedOffset, dx, dy, viewDistance); # else - // Non-TERRAIN_VARIATION path - gradual mip level increase based on distance float distanceFactor = smoothstep(0.0, 2048.0, viewDistance); - float aggressiveMipFactor = 6.0f; float4 diffuse = lerp( texColor.SampleBias(sampColor, uv, SharedData::MipBias), - texColor.SampleLevel(sampColor, uv, distanceFactor * aggressiveMipFactor), + texColor.SampleLevel(sampColor, uv, distanceFactor * 3.0), distanceFactor); # endif - - // Post-process diffuse sample for PBR compatibility float3 diffuseRGB = diffuse.rgb; # if defined(TRUE_PBR) // Check if this texture is not PBR (pbrParams.x == 0 means non-PBR texture) @@ -1091,41 +1084,32 @@ inline void SampleLandscapeLayer( # endif float alpha = diffuse.a; - // Sample normal - same distance-based optimization as diffuse + // Sample normal # if defined(TERRAIN_VARIATION) float4 normal = StochasticEffect(screenNoise, mipLevel, texNormal, sampNormal, uv, sharedOffset, dx, dy, viewDistance); # else float4 normal = lerp( texNormal.SampleBias(sampNormal, uv, SharedData::MipBias), - texNormal.SampleLevel(sampNormal, uv, distanceFactor * aggressiveMipFactor), + texNormal.SampleLevel(sampNormal, uv, distanceFactor * 3.0), distanceFactor); # endif float3 normalRGB = normal.rgb; float normalAlpha = normal.a; - float4 rmaos = 0.0.xxxx; -// Sample PBR material properties (RMAOS) - most expensive, so most aggressive optimization # if defined(TRUE_PBR) // Sample RMAOS # if defined(TERRAIN_VARIATION) - rmaos = StochasticEffect(screenNoise, mipLevel, texRMAOS, sampRMAOS, uv, sharedOffset, dx, dy, viewDistance); + float4 rmaos = StochasticEffect(screenNoise, mipLevel, texRMAOS, sampRMAOS, uv, sharedOffset, dx, dy, viewDistance); # else - if (viewDistance <= LANDSCAPE_DISTANCE_OPTIMIZATION_THRESHOLD) { - rmaos = lerp( - texRMAOS.SampleBias(sampRMAOS, uv, SharedData::MipBias), - texRMAOS.SampleLevel(sampRMAOS, uv, distanceFactor * aggressiveMipFactor), - distanceFactor); - } else { - // DISTANT TERRAIN: Skip PBR entirely - // PBR details are not visible at distance anyway - rmaos = texRMAOS.SampleLevel(sampRMAOS, uv, TERRAIN_DISTANT_MIP_LEVEL); - } + float4 rmaos = lerp( + texRMAOS.SampleBias(sampRMAOS, uv, SharedData::MipBias), + texRMAOS.SampleLevel(sampRMAOS, uv, distanceFactor * 3.0), + distanceFactor); # endif rmaos *= float4(pbrParams.x, 1, 1, pbrParams.z); blendedRMAOS += rmaos * weight; # endif - // Accumulate all samples into final blended result blendedRGB += diffuseRGB * weight; blendedAlpha += alpha * weight; blendedNormalRGB += normalRGB * weight; @@ -1452,7 +1436,7 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) # endif // EMAT // Initialize mip levels for non-EMAT case mipLevels[0] = mipLevels[1] = mipLevels[2] = mipLevels[3] = mipLevels[4] = mipLevels[5] = 0.0; -# endif // LANDSCAPE +# endif // LANDSCAPE # if defined(SPARKLE) diffuseUv = ProjectedUVParams2.yy * (input.TexCoord0.zw + (uv - uvOriginal)); @@ -1479,7 +1463,7 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) # if defined(LANDSCAPE) // Layer 1 (LandBlendWeights1.x) - if (input.LandBlendWeights1.x > 0.01) { + if (input.LandBlendWeights1.x > LANDSCAPE_BLEND_WEIGHT_THRESHOLD) { float weight = input.LandBlendWeights1.x * invwsum; SampleLandscapeLayer( uv, viewDistance, screenNoise, mipLevels[0], weight, @@ -1505,7 +1489,7 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) } // Layer 2 (LandBlendWeights1.y) - if (input.LandBlendWeights1.y > 0.01) { + if (input.LandBlendWeights1.y > LANDSCAPE_BLEND_WEIGHT_THRESHOLD) { float weight = input.LandBlendWeights1.y * invwsum; SampleLandscapeLayer( uv, viewDistance, screenNoise, mipLevels[1], weight, @@ -1533,7 +1517,7 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) } // Layer 3 (LandBlendWeights1.z) - if (input.LandBlendWeights1.z > 0.01) { + if (input.LandBlendWeights1.z > LANDSCAPE_BLEND_WEIGHT_THRESHOLD) { float weight = input.LandBlendWeights1.z * invwsum; SampleLandscapeLayer( uv, viewDistance, screenNoise, mipLevels[2], weight, @@ -1561,7 +1545,7 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) } // Layer 4 (LandBlendWeights1.w) - if (input.LandBlendWeights1.w > 0.01) { + if (input.LandBlendWeights1.w > LANDSCAPE_BLEND_WEIGHT_THRESHOLD) { float weight = input.LandBlendWeights1.w * invwsum; SampleLandscapeLayer( uv, viewDistance, screenNoise, mipLevels[3], weight, @@ -1588,7 +1572,7 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) } // Layer 5 (LandBlendWeights2.x) - if (input.LandBlendWeights2.x > 0.01) { + if (input.LandBlendWeights2.x > LANDSCAPE_BLEND_WEIGHT_THRESHOLD) { float weight = input.LandBlendWeights2.x * invwsum; SampleLandscapeLayer( uv, viewDistance, screenNoise, mipLevels[4], weight, @@ -1615,7 +1599,7 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) } // Layer 6 (LandBlendWeights2.y) - if (input.LandBlendWeights2.y > 0.01) { + if (input.LandBlendWeights2.y > LANDSCAPE_BLEND_WEIGHT_THRESHOLD) { float weight = input.LandBlendWeights2.y * invwsum; SampleLandscapeLayer( uv, viewDistance, screenNoise, mipLevels[5], weight, @@ -1717,7 +1701,7 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) # endif // SNOW // Layer 1 (LandBlendWeights1.x) - if (input.LandBlendWeights1.x > LANDSCAPE_BLEND_WEIGHT_THRESHOLD) { + if (input.LandBlendWeights1.x > 0.01) { # if defined(SNOW) && !defined(TRUE_PBR) float landSnowMask1 = GetLandSnowMaskValue(baseColor.w); landSnowMask += LandscapeTexture1to4IsSnow.x * input.LandBlendWeights1.x * landSnowMask1; @@ -1731,7 +1715,7 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) } // Layer 2 (LandBlendWeights1.y) - if (input.LandBlendWeights1.y > LANDSCAPE_BLEND_WEIGHT_THRESHOLD) { + if (input.LandBlendWeights1.y > 0.01) { # if defined(SNOW) && !defined(TRUE_PBR) float landSnowMask2 = GetLandSnowMaskValue(baseColor.w); landSnowMask += LandscapeTexture1to4IsSnow.y * input.LandBlendWeights1.y * landSnowMask2; @@ -1745,7 +1729,7 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) } // Layer 3 (LandBlendWeights1.z) - if (input.LandBlendWeights1.z > LANDSCAPE_BLEND_WEIGHT_THRESHOLD) { + if (input.LandBlendWeights1.z > 0.01) { # if defined(SNOW) && !defined(TRUE_PBR) float landSnowMask3 = GetLandSnowMaskValue(baseColor.w); landSnowMask += LandscapeTexture1to4IsSnow.z * input.LandBlendWeights1.z * landSnowMask3; @@ -1759,7 +1743,7 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) } // Layer 4 (LandBlendWeights1.w) - if (input.LandBlendWeights1.w > LANDSCAPE_BLEND_WEIGHT_THRESHOLD) { + if (input.LandBlendWeights1.w > 0.01) { # if defined(SNOW) && !defined(TRUE_PBR) float landSnowMask4 = GetLandSnowMaskValue(baseColor.w); landSnowMask += LandscapeTexture1to4IsSnow.w * input.LandBlendWeights1.w * landSnowMask4; @@ -1773,7 +1757,7 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) } // Layer 5 (LandBlendWeights2.x) - if (input.LandBlendWeights2.x > LANDSCAPE_BLEND_WEIGHT_THRESHOLD) { + if (input.LandBlendWeights2.x > 0.01) { # if defined(SNOW) && !defined(TRUE_PBR) float landSnowMask5 = GetLandSnowMaskValue(baseColor.w); landSnowMask += LandscapeTexture5to6IsSnow.x * input.LandBlendWeights2.x * landSnowMask5; @@ -1787,7 +1771,7 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) } // Layer 6 (LandBlendWeights2.y) - if (input.LandBlendWeights2.y > LANDSCAPE_BLEND_WEIGHT_THRESHOLD) { + if (input.LandBlendWeights2.y > 0.01) { # if defined(SNOW) && !defined(TRUE_PBR) float landSnowMask6 = GetLandSnowMaskValue(baseColor.w); landSnowMask += LandscapeTexture5to6IsSnow.y * input.LandBlendWeights2.y * landSnowMask6; @@ -2506,7 +2490,6 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) # endif float3 lightColor = Color::Light(light.color.xyz) * intensityMultiplier; - float lightShadow = 1.0; float shadowComponent = 1.0;