Jump to content
  • Advertisement
Sign in to follow this  
bjarnia

Shadow mapping: Receiver Plane Depth Bias?

This topic is 3071 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

I have stumbled upon references to the use of "Receiver Plane Depth Bias" to alleviate errors in traditional shadow maps. Such as here (page 37): http://ati.amd.com/developer/gdc/2006/Isidoro-ShadowMapping.pdf As well as realizing that there is a DX renderstate that seems to set "SlopeScaleDepthBias" which to my understanding is the same thing. I have tried to integrate the implementation in the above presentation with no luck at all, as well as trying a lot of different values for that renderstate with little effect. Can someone point me to a simple sample or a paper that uses this technique properly? Maybe my googling skills are just wearing thin :P I am using an orthographic light if that makes a difference. This is how my very naive implementation looks: http://www.steik.org/dump/Cosmopolis2010-02-1718-56-36-56.png I'll just include my HLSL code too... What is confusing me the most is if I can just use my normal shadow texture coordinates? I'm thinking not? I am anyway :) The code has been modified slightly to account for lack of Fetch4 that the presentation assumes.

float2 quadOffsets[] = { float2( 0,  0), float2( 1,  0), float2( 1,  1), float2( 1,  0), float2( 1, -1), float2( 0, -1), float2(-1, -1), float2(-1,  0), float2(-1,  1)};


float SamplePCFSlope(sampler2D depthSampler, float4 texCoord, float bias, float texelSize, float mapSize)
{
    //Packing derivatives of u,v, and distance to light source w.r.t. screen space x, and y
    float4 duvdist_dx = ddx(texCoord);
    float4 duvdist_dy = ddy(texCoord);

    //Invert texture Jacobian and use chain rule to compute ddist/du and ddist/dv
    // |ddist/du| = |du/dx du/dy|-T * |ddist/dx|
    // |ddist/dv| |dv/dx dv/dy| |ddist/dy|
    
    //Multiply ddist/dx and ddist/dy by inverse transpose of Jacobian
    float invDet = 1 / ((duvdist_dx.x * duvdist_dy.y) - (duvdist_dx.y * duvdist_dy.x) );
    
    //Top row of 2x2
    float2 ddist_duv;
    ddist_duv.x = duvdist_dy.y * duvdist_dx.w ; // invJtrans[0][0] * ddist_dx
    ddist_duv.x -= duvdist_dx.y * duvdist_dy.w ; // invJtrans[0][1] * ddist_dy
    
    //Bottom row of 2x2
    ddist_duv.y = duvdist_dx.x * duvdist_dy.w ; // invJtrans[1][1] * ddist_dy
    ddist_duv.y -= duvdist_dy.x * duvdist_dx.w ; // invJtrans[1][0] * ddist_dx

    ddist_duv *= invDet;

    float percentInLight = 0;
    float2 texCoordOffset;
    float shadowMapVals;
    float dist;
    float4 inLight;
    float invNumTaps = 1.0 / 9.0f;

    // Not ideal, too lazy to set in code for now
    float2 g_vFullTexelOffset = float2(texelSize, texelSize);

    //compute depth offset and PCF taps 4 at a time
    for(int i=0; i < 9; i++)
    {
        //offset of texel quad in texture coordinates;
        texCoordOffset = (g_vFullTexelOffset * quadOffsets );

        //shadow map values
        shadowMapVals = tex2D(depthSampler, texCoord.xy + texCoordOffset.xy ).r;
        
        //Apply receiver plane depth offset
        dist = texCoord.w + (ddist_duv.x * texCoordOffset.x) + (ddist_duv.y * texCoordOffset.y);
        //dist = texCoord.z + bias; // Normal shadow mapping.. Works fine
        inLight = ( dist < shadowMapVals );

        percentInLight += inLight * invNumTaps;
    }

    return percentInLight;
}

Share this post


Link to post
Share on other sites
Advertisement
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!