Jump to content
  • Advertisement
Sign in to follow this  
dave

Omnidirectional Shadow Mapping Problem

This topic is 3163 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 am attempting to implement omnidirectional shadow maps. This is part of a deferred shadow implementation in a deferred pipeline. This is how the scene looks at the moment: It would appear that nearly everything being sampled from the depth map is closer than the world space pixel position. The renderer-side code used to produce the depths for the cube map faces is as follows:
D3DXMatrixPerspectiveFovLH( &m_CurrentLightProjectionMatrix, D3DX_PI / 2, 1, 1, 20 );
				
Vector3 Directions[] = { Vector3(1,0,0), Vector3(-1,0,0), Vector3(0,1,0), Vector3(0,-1,0), Vector3(0,0,1), Vector3(0,0,-1) };
Vector3 Ups[] = { Vector3(0,1,0), Vector3(0,1,0), Vector3(0,0,-1), Vector3(0,0,1), Vector3(0,1,0), Vector3(0,1,0) };

for ( UInt32 SideIndex(0); SideIndex < 6; ++SideIndex )
{
	//	View and projection matrix for the lights location.
	Matrix4x4 ViewMatrix;
	Matrix4x4 ProjectionMatrix;

	Vector4 vPosition(0,0,0,0);
	Vector3 vOrigin(0,0,0);

	D3DXVec3Transform(&vPosition, &vOrigin, &rLightJob.m_Transform);

	vOrigin = Vector3( vPosition.x, vPosition.y, vPosition.z );

	Vector3 vLookAt( vOrigin + Directions[SideIndex] );

	D3DXMatrixLookAtLH( &m_CurrentLightViewMatrix, &vOrigin, &vLookAt, &Ups[SideIndex] );

	const TextureCubeMap*	pTexture( dynamic_cast<const TextureCubeMap*>(pTextureInterface) );
	Direct3DCubeTexture9	Target( pTexture->GetTexture() );
					Direct3DSurface9		TargetSurface;

	D3DCUBEMAP_FACES	Face = static_cast<D3DCUBEMAP_FACES>(SideIndex);

	Target->GetCubeMapSurface( Face, 0, &TargetSurface );

	GetRenderer().GetDevice()->SetRenderTarget(0, TargetSurface);
	GetRenderer().GetDevice()->Clear( 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_ARGB( UInt32(0), UInt32(0), UInt32(0), UInt32(0) ), 1.0f, 0 );

	DrawModels();
				}




The shadow map creation shader looks like this:
VS_OUTPUT vs_main( VS_INPUT In )
{
	VS_OUTPUT Out;

	Out.Pos	= mul(float4(In.Pos,1.0), matWorldViewProjection);
	Out.PosInWorld = mul(float4(In.Pos,1.0), matWorldViewProjection);
	
	return Out;
}

PS_OUTPUT ps_main( VS_OUTPUT In )
{
	PS_OUTPUT Out;
	
	float fDepthValue = In.PosInWorld.z;
	Out.Depth = float4(fDepthValue, fDepthValue, fDepthValue, 1.0f);
   
	return Out;
}




The code that compiles a shadow map on to the shadow compile target for the deferred shadow phase is as follows for point lights:
	Vector4 vPosition(0,0,0,0);
	Vector3 vOrigin(0,0,0);

	D3DXVec3Transform(&vPosition, &vOrigin, &rLightJob.m_Transform);

	vOrigin = Vector3( vPosition.x, vPosition.y, vPosition.z );

	pEffect->GetEffect()->SetTexture("ShadowMap", rShadowMapTexture);
	pEffect->GetEffect()->SetFloatArray("LightPosition", &vOrigin.x, 3 );
	static float fDepthBias = 0.001f;

	pEffect->GetEffect()->SetFloat( "fDepthBias", fDepthBias );
	pEffect->GetEffect()->CommitChanges();

	GetRenderer().GetDevice()->DrawPrimitiveUP( D3DPT_TRIANGLELIST, 2, PositionBuffer, 20 );




and lastly the shader function that returns transparent for no shadow and black for shadow in the shadow compilation shader is as follows:
float4	GetColourContributionForShadowMapSamplerPoint(sampler Sampler, float4 Position, float4x4 LightView, float4x4 LightProjection)
{
	float4 Contribution = float4(0,0,0,0);
	float4 LightDirection = 0.0f;
	
	LightDirection.xyz = Position.xyz - LightPosition;
	float Distance = length( LightDirection.xyz );
		
	//	Sample the depth.
	float DepthColour = texCUBE(Sampler, normalize(LightDirection.xyz)).x;

	if ( (Distance + fDepthBias) > DepthColour )
	{
		Contribution = float4(0, 0, 0, 1.0f);
	}
	
	return Contribution;
}




FYI the depth bias is 0.001. I'm not really sure where i'm going wrong, i have dumped the shadow map to file and it looks fine and i have read every tutorial and they all follow the same pattern. I have been through it in PIX and can see that the reason nothing is lit is because everything is deemed further away than the sampled depth in the cube texture. I was wondering whether the world space pixel position needs to be transformed by the same projection matrix that is used to create the depths. I tried this and there was no improvement. Any ideas?

Share this post


Link to post
Share on other sites
Advertisement
In your lighting shader, you're computing the depth as "depth = length( lightPos - pixelPos )". However in your shader for generating the shadow map, you're using the z value of the projected pixel coordinate. For obvious reasons you need to use the same depth metric. Just change your shadow map shaders to this:


VS_OUTPUT vs_main( VS_INPUT In )
{
VS_OUTPUT Out;

Out.Pos = mul(float4(In.Pos,1.0), matWorldViewProjection);
Out.Depth = length(mul(float4(In.Pos,1.0), matWorldView).xyz);

return Out;
}

PS_OUTPUT ps_main( VS_OUTPUT In )
{
PS_OUTPUT Out;

float fDepthValue = In.Depth;
Out.Depth = float4(fDepthValue, fDepthValue, fDepthValue, 1.0f);

return Out;
}



The above shader is also equivalent to this, which might make more sense:


VS_OUTPUT vs_main( VS_INPUT In )
{
VS_OUTPUT Out;

Out.Pos = mul(float4(In.Pos,1.0), matWorldViewProjection);
float3 positionWS = mul(float4(In.Pos, 1.0), matWorld).xyz;
Out.Depth = length(lightPos - positionWS);

return Out;
}

PS_OUTPUT ps_main( VS_OUTPUT In )
{
PS_OUTPUT Out;

float fDepthValue = In.Depth;
Out.Depth = float4(fDepthValue, fDepthValue, fDepthValue, 1.0f);

return Out;
}



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.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!