We are using Parallel Split Shadow Maps / Cascading Shadow maps in our new game, and I was pondering about the most optimal way to sample the shadowmap(s). I have read about using stencil, depth bounds, etc to speed up the process and multipass the scene (one depth region at time). But multipassing the scene costs performance, so I personally implemented PSSM like this:
1. I create a single depth texture to hold all of my 3 PSSM textures (3072x1024)
2. I render each 1024x1024 view cone partition to the same texture (shifting viewport or resolve position accordingly)
3. Instead of scaling the shadow map projection matrices to generate [0,1] range like in normal shadow mapping (or when using multiple textures on PSSM), I scale the x of the view cone partitions to [0,1/3], [1/3,2/3] and [2/3,1] range.
My pixel shader is like this (pseudo code):
With this setup I only have to sample one depth map texel per rendered pixel, and there is no need for dynamic branching. I am still a bit concerned about texture cache usage of this method, as the texture coordinates can vary a bit between adjacent pixels. However usually a single rendered object is inside a single viewport depth partition, and most of the sampled texels are from the same view partition.
Is this a good way to implement the PSSM texture sampling?
(Currently the shadowmap is stored on R16 (fixed point) texture, but this might change in the future as I implement support for better soft shadow technique.)
1. I create a single depth texture to hold all of my 3 PSSM textures (3072x1024)
2. I render each 1024x1024 view cone partition to the same texture (shifting viewport or resolve position accordingly)
3. Instead of scaling the shadow map projection matrices to generate [0,1] range like in normal shadow mapping (or when using multiple textures on PSSM), I scale the x of the view cone partitions to [0,1/3], [1/3,2/3] and [2/3,1] range.
My pixel shader is like this (pseudo code):
Code:
float shadowDepthIndex = saturate(log(psIn.posVS.z*0.1)*0.5)*2;
float4 posSM = psIn.posPSSM[shadowDepthIndex];
float3 texSM = posSM.xyz / posSM.w;
float lightZ = tex2D(shadowMapSampler, texSM.xy).x;
float lightMul = (lightZ <= texSM.z);
With this setup I only have to sample one depth map texel per rendered pixel, and there is no need for dynamic branching. I am still a bit concerned about texture cache usage of this method, as the texture coordinates can vary a bit between adjacent pixels. However usually a single rendered object is inside a single viewport depth partition, and most of the sampled texels are from the same view partition.
Is this a good way to implement the PSSM texture sampling?
(Currently the shadowmap is stored on R16 (fixed point) texture, but this might change in the future as I implement support for better soft shadow technique.)