Sign in to follow this  

Speed difference in shadow mapping, nonlinear vs. linear depth?

This topic is 2831 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi, I observed a curious thing about shadow mapping using HLSL. If I store nonlinear depth (ie. projected z/w) in the shadow map I get approximately a 5% speedup compared to storing linear depth. According to my limited tests, it's the shadow caster code that makes the difference, which is 2 matrix multiplies in the VS for linear versus just 1 for nonlinear, but on the other hand linear depth PS just writes out the value produced by the VS, while nonlinear depth PS has to do a divide. Should the matrix multiply (considering it's just for each vertex) make that much of a difference, or is there some other reason? Relevant shader code: Shadow caster, nonlinear depth:
VS:
oPos = mul(iPos, cModelViewProj);
oDepth = oPos.zw;

PS:
oColor = iDepth.x / iDepth.y;
Shadow caster, linear depth:
VS:
oPos = mul(iPos, cModelViewProj);
oDepth = mul(iPos, cShadowProj).z;

PS:
oColor = iDepth;
Shadow receiver, nonlinear depth:
VS:
oShadowPos = mul(iPos, cShadowProj);

PS:
float3 shadowPos = iShadowPos.xyz / iShadowPos.w;
float inLight = evaluateShadow(shadowPos.z, shadowPos.xy);
Shadow receiver, linear depth:
VS:
oShadowPos = mul(iPos, cShadowProj);

PS:
float2 shadowPos = iShadowPos.xy / iShadowPos.w;
float inLight = evaluateShadow(iShadowPos.z, shadowPos);
(evaluateShadow is exactly same for both linear & nonlinear depth, as is the shadow receiver vertex shader)

Share this post


Link to post
Share on other sites
It really depends on the GPU. I usually find that I'm bound by the input assembler or triangle setup unit during shadow map generation...I would suggest that you use a program like PerfHUD and find out exactly what your bottleneck is.

Also...if you want linear depth, you can try this method.

Share this post


Link to post
Share on other sites
Thanks for the suggestion! By implementing linear Z in the way described I got a speedup over nonlinear depth :)

Ah, of course now I understand where (part) of the speed difference probably comes, in addition to actual shader code: whether one has to update 1 matrix uniform or 2, for each shadowcasting object.

EDIT: when rendering point light shadow maps, using the linear Z method resulted in some odd artifacts: objects off to the sides got rendered through walls that were closer :) I guess that's a side-effect of pre-multiplying Z by W, and having geometry that's not very well tessellated. In the end I wrote different vertex shaders for perspective & orthographic shadow projection, so that the actual projection can remain unmodified, but still only 1 matrix is needed for calculating both the vertex position, and linear depth.

[Edited by - AgentC on March 14, 2010 3:00:32 PM]

Share this post


Link to post
Share on other sites

This topic is 2831 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this