Jump to content
  • Advertisement
Sign in to follow this  
Armagedon

Shadows

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

Hello,
I'm fighting for long time with shadows in my projects. Spent on it a lot of time and slowly getting angry and annoyed. I encountered two problems with two shadow mapping technique in Deferred Rendering:

1.
Pic.1
Pic.2

VSM: First image is non blurred vsm, only with linear filtering. Doesn't look so bad.
But on second there's blurred one. And there comes the problem. Shadow looks is not even blurred, whole penumbra which should be soft is 'eaten', and pixel is not shadowed. I'm using G16R16F format. Really don't know what cause this error. Here is code:
Generating vsm:

VSOUTPUT_SHADOW VS_Shadow( float4 inPosition : POSITION )
{
// Output struct
VSOUTPUT_SHADOW OUT = (VSOUTPUT_SHADOW)0;

float4 worldPos = mul( inPosition, matWorld );

// Output the transformed position
OUT.vPosition = mul( worldPos, matLightViewProj );

// Output the scene depth
OUT.fDepth = length(mul(worldPos, matLightView).xyz) / 2048.0f;

return OUT;
}

float4 PS_Shadow( VSOUTPUT_SHADOW IN ) : COLOR0
{
// Output the scene depth
return float4(IN.fDepth, (IN.fDepth*IN.fDepth), 0.0f, 1.0f );
}


Drawing vsm

float Vsm( float2 tex, float fragDepth )
{
fragDepth /= 2048.0f;
fragDepth -= 0.00001;

float lit = (float)0.0f;
float2 moments = tex2D(ShadowSampler, tex);

float E_x2 = moments.y;
float Ex_2 = moments.x * moments.x;
float variance = min(max(E_x2 - Ex_2, 0.0f) + 0.00001f, 1.0f);
float mD = (moments.x - fragDepth );
float mD_2 = mD * mD;
float p = variance / (variance + mD_2 );
lit = max( p, fragDepth <= moments.x );

return lit;
}

...
float fDepth = length( vLightPosition - vWorldPos );
float4 vProjCoord = mul( float4(vWorldPos, 1.0f), matLightViewProj );
vProjCoord /= vProjCoord.w;

// Rescale viewport to be [0,1] (texture coordinate space)
float2 shadowTex = vProjCoord.xy * float2(0.5, -0.5) + 0.5f;

float ShadowTerm = Vsm(shadowTex, fDepth);
ShadowTerm = saturate(ShadowTerm*2-1);
...


2. Pic.1
Pic.2

Second problems is with standard PCF Shadow Maps. Since i'm trying to get them working under deferred renderer, they're not working as they should.
On first pic there's really high biasing, caused by... don't know what. After huge increase of bias(Second Pic) removes biasing but shadow looks poorly and there is no PCF. Using R32F for shadow map.
Generating:

// Shadow generation vertex shader
VSOUTPUT_SHADOW VS_Shadow( float4 inPosition : POSITION )
{
// Output struct
VSOUTPUT_SHADOW OUT = (VSOUTPUT_SHADOW)0;

float4 worldPos = mul( inPosition, matWorld );

// Output the transformed position
OUT.vPosition = mul( worldPos, matLightViewProj );

// Output the scene depth
OUT.fDepth = OUT.vPosition.z;

return OUT;
}

float4 PS_Shadow( VSOUTPUT_SHADOW IN ) : COLOR
{
// Output the scene depth
return float4( IN.fDepth, IN.fDepth, IN.fDepth, 1.0f );
}


Drawing:

float ShadowPCF(float4 vProjCoord)
{
// Generate the 9 texture co-ordinates for a 3x3 PCF kernel
float4 vTexCoords[9];

// Texel size
float fTexelSize = 1.0f / 512.0f;

// Grab the shadow term
float fShadowTerm = 0.0f;

vTexCoords[0] = vProjCoord;

vTexCoords[1] = vProjCoord + float4( -fTexelSize, 0.0f, 0.0f, 0.0f );
vTexCoords[2] = vProjCoord + float4( fTexelSize, 0.0f, 0.0f, 0.0f );
vTexCoords[3] = vProjCoord + float4( 0.0f, -fTexelSize, 0.0f, 0.0f );
vTexCoords[6] = vProjCoord + float4( 0.0f, fTexelSize, 0.0f, 0.0f );

vTexCoords[4] = vProjCoord + float4( -fTexelSize, -fTexelSize, 0.0f, 0.0f );
vTexCoords[5] = vProjCoord + float4( fTexelSize, -fTexelSize, 0.0f, 0.0f );
vTexCoords[7] = vProjCoord + float4( -fTexelSize, fTexelSize, 0.0f, 0.0f );
vTexCoords[8] = vProjCoord + float4( fTexelSize, fTexelSize, 0.0f, 0.0f );

// Sample each of them checking whether the pixel under test is shadowed or not
for( int j = 0; j < 9; j++ )
{
float A = tex2Dproj( ShadowSampler, vTexCoords[j] ).r;
float B = vProjCoord.z - 0.0001f;

// Texel is shadowed
fShadowTerm += A < B ? 0.1f : 1.0f;
}

// Get the average
return fShadowTerm = fShadowTerm / 9.0f;
};

...
float4 posInShadow = mul( float4(vWorldPos,1), matTexture );
float ShadowTerm = ShadowPCF(posInShadow);
...


Hope somebody will help me ;) One day more on this and i'm gonna explode :P.

Thanks.

Share this post


Link to post
Share on other sites
Advertisement
try using a R32G32 format for your VSM's.

In your PCF prpoblem, i see this

// Output the transformed position
OUT.vPosition = mul( worldPos, matLightViewProj );

// Output the scene depth
OUT.fDepth = OUT.vPosition.z;

return OUT;

you should divide z by w to put it into projected space. At least, that is what is normally done. You didnt post the entire shader, so its just a guess.

OUT.fDepth = OUT.vPosition.z/OUT.vPosition.w;

Or, you can let the hardware do it for you and access the z component in your pixel shader without passing the depth in an extra parameter.


Share this post


Link to post
Share on other sites

try using a R32G32 format for your VSM's.


Tried it, but shadow look even worse. Pic!


In your PCF prpoblem, i see this

// Output the transformed position
OUT.vPosition = mul( worldPos, matLightViewProj );

// Output the scene depth
OUT.fDepth = OUT.vPosition.z;

return OUT;

you should divide z by w to put it into projected space. At least, that is what is normally done. You didnt post the entire shader, so its just a guess.

OUT.fDepth = OUT.vPosition.z/OUT.vPosition.w;

Or, you can let the hardware do it for you and access the z component in your pixel shader without passing the depth in an extra parameter.



I tried:
OUT.fDepth = OUT.vPosition.z/OUT.vPosition.w;

But then, scene is unshadowed. Storing only .z component i saw in this tut: http://www.gamedev.net/page/resources/_/reference/programming/special-effects/shadows/soft-edged-shadows-r2193

And that's whole shader. Only:
matLightViewProj - View*Proj Light Matrix
matTexture - matLightViewProj * matTexAdjency

float fTexOffs = 0.5 + (0.5 / 512.0f);
matTexAdj = D3DXMATRIX( 0.5f, 0.0f, 0.0f, 0.0f,
0.0f, -0.5f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f,
fTexOffs, fTexOffs, -0.05f, 1.0f );

vWorldPos - position from deferred position texture

Share this post


Link to post
Share on other sites
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!