Instead of using if statements while looping through split indices get the correct split index by adding up conditional statements for all the split tests. This does away with the need for branching.

...

thanks

So here's my last version [EDITED] :

#define CSM_MAXSPLITS 8 SamplerState shadowMapSampler { Filter = MIN_MAG_MIP_POINT; AddressU = BORDER; AddressV = BORDER; BorderCOLOR = float4(1.0f,1.0f,1.0f,1.0f); }; float3 sampleColorCSM(in float posProjZ,in float3 posWorld,in float3 normalWorld) { float3 uv; float bias; uint split=0; float4 posLight; if (posProjZ<g_CSM_depths[0].x || posProjZ>g_CSM_depths[g_CSM_nbSplits].x) return float3(1.0,1.0f,1.0f); [unroll (CSM_MAXSPLITS)] for (uint i=1;i<=g_CSM_nbSplits;i++) split+=posProjZ>g_CSM_depths[i].x; posLight=mul(float4(posWorld,1.0f),g_CSM_VP[split]); posLight/=posLight.w; bias=dot(normalWorld,-g_vDirectionalLightDirection); bias=clamp(g_CSM_depths[split].y*sqrt(1.0f-bias*bias)/bias,g_CSM_depths[split].y,g_CSM_depths[split].z); uv=float3(posLight.xy*float2(0.5f,-0.5f)+0.5f,split); return (g_CSMMaps.Sample(shadowMapSampler,uv).x+bias>posLight.z)*g_ColorCSMMaps.Sample(shadowMapSampler,uv).xyz; } float sampleCSM(in float posProjZ,in float3 posWorld,in float3 normalWorld) { float3 uv; float bias; uint split=0; float4 posLight; if (posProjZ<g_CSM_depths[0].x || posProjZ>g_CSM_depths[g_CSM_nbSplits].x) return 1.0f; [unroll (CSM_MAXSPLITS)] for (uint i=1;i<=g_CSM_nbSplits;i++) split+=posProjZ>g_CSM_depths[i].x; posLight=mul(float4(posWorld,1.0f),g_CSM_VP[split]); posLight/=posLight.w; bias=dot(normalWorld,-g_vDirectionalLightDirection); bias=clamp(g_CSM_depths[split].y*sqrt(1.0f-bias*bias)/bias,g_CSM_depths[split].y,g_CSM_depths[split].z); uv=float3(posLight.xy*float2(0.5f,-0.5f)+0.5f,split); return g_CSMMaps.Sample(shadowMapSampler,uv).x+bias>posLight.z; }

g_CSM_depths[split].x is the minimal depth of the #split map, g_CSM_depths[split+1].x is the maximal depth of the #split map.

g_CSM_depths[split].y is the minimal depth bias of the #split map

*(remove acne on flat surfaces)*

g_CSM_depths[split].z is the maximal depth bias of the #split map

*(remove acne on bumped surfaces)*

*Thanks for reading*