Skip to main content
GameDev.net gamedev.net
🔒 Locked

Shadow projection problem

Started by ayush3017 Sep 15, 2010 at 12:44 PM 1 replies 1.4k views
Original Post
ayush3017
ayush3017
Ok, well I have successfully uh, correction partially done Parallel Split Variance shadow map. I have got the split working with transition between the shadows. However I am having a problem like this:
Image

You can see that in the above image the palm's shadow appear 2 times. The shadow which is on the bottom of the scrren should not be there. Also it moves as my camera moves. Other shadow(the correct one) is stable.
What could be the problem?? Also the game uses deferred rendering..
Here is the code:
ClearTexture(materialMap, device, 0xFFFFFFFF);	ClearTexture(normalMap, device, 0xFFFFFFFF);	ClearTexture(positionXYMap, device, 0xFFFFFFFF);	ClearTexture(shadowOcclusionMap, device, 0xFFFFFFFF);	ClearTexture(positionZMap, device, 0xFFFFFFFF);			LPDIRECT3DSURFACE9 bb;	device->GetRenderTarget(0, &bb);	SetRenderTarget(0, materialMap, device);	SetRenderTarget(1, normalMap, device);	SetRenderTarget(2, positionXYMap, device);	DrawDefferedGeometry(device, V, projectionMatrix);			device->SetRenderTarget(0, bb);		device->SetRenderTarget(1, NULL);	device->SetRenderTarget(2, NULL);	//device->GetDepthStencilSurface(&oldDepthStencilSurface);	//device->SetDepthStencilSurface(depthStencilSurface);	D3DVIEWPORT9 oldViewPort;	SetRenderTarget(0, positionZMap, device);		for(int splitCount = 0 ; splitCount < _iNumSplits ; splitCount++)	{		float fNear = _pSplitDistances[splitCount];		float fFar  = _pSplitDistances[splitCount + 1];		float fScale=1.1f;		D3DXVECTOR3 pCorners[8];		CalculateFrustumCorners(pCorners, TheCamera.cameraPosition, TheCamera.cameraPosition+TheCamera.look, 								TheCamera.up, fNear,fFar,45,w/h,fScale, V);		CalculateLightForFrustum(pCorners);		lightVM[splitCount] = lightViewMatrix;		lightPM[splitCount] = lightProjectionMatrix;		D3DVIEWPORT9 CameraViewport;		device->GetViewport(&CameraViewport);				CameraViewport.MinZ=splitCount/(float)_iNumSplits;		CameraViewport.MaxZ=(splitCount+1)/(float)_iNumSplits;		CameraViewport.Width = 1024;		CameraViewport.Height = 1024;		device->SetViewport(&CameraViewport);		DrawShadowedGeometry(device);	}	device->SetViewport(&oldViewPort);	device->Clear(0, 0,D3DCLEAR_ZBUFFER, 0xFFFFFFFF, 1.f, 0);		//device->SetDepthStencilSurface(oldDepthStencilSurface);	SetRenderTarget(0, shadowOcclusionMap, device);	DrawShadowOcclusionMap(device, V);		device->SetRenderTarget(0, bb);	        //Draw Full Screen Quad//....//....


DrawShadowOcclusionMap function:

void DrawShadowOcclusionMap(LPDIRECT3DDEVICE9 device, D3DXMATRIX V){	static float fWidth = params.BackBufferWidth;	static float fHeight = params.BackBufferHeight;		static PlaneVertex axPlaneVertices[] =	{		{ 0,		 0,		  .5f, 1, 0 + .5f / fWidth,	0 + .5f / fHeight },		{ fWidth, 0,		  .5f, 1, 1 + .5f / fWidth,	0 + .5f / fHeight },		{ fWidth, fHeight,    .5f, 1, 1 + .5f / fWidth,	1 + .5f / fHeight },		{ 0,		 fHeight, .5f, 1, 0 + .5f / fWidth,	1 + .5f / fHeight }	};	D3DXVECTOR4 lightClipPlanes[_iNumSplits];	for(int splitCount = 0 ; splitCount < _iNumSplits ; splitCount++)	{		lightClipPlanes[splitCount].x = _pSplitDistances[splitCount];		lightClipPlanes[splitCount].y = _pSplitDistances[splitCount + 1];			}	D3DXMATRIX inverseView;	D3DXMatrixInverse(&inverseView, NULL, &V);	effect->SetTechnique("ShadowTech");			effect->SetMatrixArray("lightView", lightVM, _iNumSplits);	effect->SetMatrixArray("lightProjection", lightPM, _iNumSplits);			effect->SetVectorArray("g_vClipPlanes", lightClipPlanes, _iNumSplits);	effect->SetTexture("scenePositionXYMap", positionXYMap);	effect->SetTexture("shadowMap", positionZMap);	effect->SetTexture("sceneMaterialMap", materialMap);	effect->SetMatrix("inverseView", &inverseView);		effect->SetValue("farFrustumCoords", &farFrustumCoords, sizeof(D3DXVECTOR3) * 4);			D3DXMATRIX TexProj;	float tex_offset = 0.5f + (0.5f / 1024);	TexProj = D3DXMATRIX(	0.5f,			0.0f,		0.0,	0.0f,							0.0f,			-0.5f,		0.0f,	0.0f,							0.0f,			0.0f,		1.0f,	0.0f,							tex_offset,		tex_offset, 0.0f,	1.0f);	effect->SetMatrix("TexProj", &TexProj);		UINT numPasses;	effect->Begin(&numPasses, 0);	effect->BeginPass(0);	effect->CommitChanges();	device->SetFVF(D3DFVF_XYZRHW | D3DFVF_TEX1);	device->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, axPlaneVertices, sizeof(PlaneVertex));	effect->EndPass();	effect->End();		}


Shader Code:
struct Mtrl{	float4 ambient;	float4 diffuse;	float4 spec;	float  specPower;};struct DirLight{	float4 ambient;	float4 diffuse;	float4 spec;	float3 dirW;  };float epsilon = 0.000000001f;float max_depth = 100;float offset_bias = 0.01f;static const int NUM_SPLITS = 2;uniform extern float	g_sample_rad;uniform extern float	g_scale;uniform extern float	g_bias;uniform extern float	g_intensity;uniform extern float4x4 InverseTransposeView;uniform extern float4x4 gWorld;uniform extern float4x4 gWorldInv;uniform extern float4x4 gWVP;uniform extern Mtrl     gMtrl;uniform extern DirLight gLight;uniform extern float3   gEyePosW;uniform extern texture  gTex;uniform extern texture  gNormalMap;uniform extern float4x4 gView;uniform extern float4x4 worldView;uniform extern float4x4 WorldViewProjection;float4x4				TexProj;float4x4				lightView [NUM_SPLITS];float4x4				lightProjection [NUM_SPLITS];float4					g_vClipPlanes[NUM_SPLITS];float4x4				inverseView;float3					farFrustumCoords [4];float3					cameraPosition;uniform extern texture	sceneMaterialMap, sceneNormalMap, scenePositionXYMap, scenePositionZMap, gEnvMap, randomNormalMap;texture shadowMap, shadowOcclusionMap;sampler shadowOcclusionMapSampler = sampler_state{	Texture = <shadowOcclusionMap>;	MinFilter = Anisotropic;	MagFilter = Linear;	MipFilter = Linear;	AddressU  = CLAMP;     AddressV  = CLAMP;    MaxAnisotropy = 16;    };sampler shadowMapSampler = sampler_state{		Texture = <shadowMap>;	MinFilter = ANISOTROPIC;	MaxAnisotropy = 16;	MagFilter = LINEAR;	MipFilter = POINT;	//AddressU  = WRAP;     //AddressV  = WRAP;       	/*MinFilter = Point;	MagFilter = Point;	MipFilter = None;	AddressU = Border;	AddressV = Border;	BorderColor = 0xFFFFFFFF;*/};sampler randomNormalSampler = sampler_state{    Texture   = <randomNormalMap>;    MinFilter = LINEAR;     MagFilter = LINEAR;    MipFilter = LINEAR;    AddressU  = WRAP;    AddressV  = WRAP;    };sampler EnvMapS = sampler_state{    Texture   = <gEnvMap>;    MinFilter = Anisotropic;     MagFilter = LINEAR;    MipFilter = LINEAR;    AddressU  = WRAP;    AddressV  = WRAP;};sampler textureSampler = sampler_state{	Texture = <sceneMaterialMap>;	MinFilter = ANISOTROPIC;	MaxAnisotropy = 16;	MagFilter = LINEAR;	MipFilter = LINEAR;	AddressU  = WRAP;    AddressV  = WRAP;};sampler normalSampler = sampler_state{	Texture = <sceneNormalMap>;	MinFilter = ANISOTROPIC;	MaxAnisotropy = 16;	MagFilter = LINEAR;	MipFilter = LINEAR;	AddressU  = WRAP;    AddressV  = WRAP;};sampler positionXYSampler = sampler_state{	Texture = <scenePositionXYMap>;	MinFilter = ANISOTROPIC;	MaxAnisotropy = 16;	MagFilter = LINEAR;	MipFilter = LINEAR;	AddressU  = CLAMP;    AddressV  = CLAMP;};sampler positionZSampler = sampler_state{	Texture = <scenePositionZMap>;	MinFilter = ANISOTROPIC;	MaxAnisotropy = 16;	MagFilter = LINEAR;	MipFilter = LINEAR;	AddressU  = CLAMP;    AddressV  = CLAMP;};sampler TexS = sampler_state{	Texture = <gTex>;	MinFilter = ANISOTROPIC;	MaxAnisotropy = 16;	MagFilter = LINEAR;	MipFilter = LINEAR;	AddressU  = WRAP;    AddressV  = WRAP;};sampler NormalMapS = sampler_state{	Texture = <gNormalMap>;	MinFilter = ANISOTROPIC;	MaxAnisotropy = 16;	MagFilter = LINEAR;	MipFilter = LINEAR;	//AddressU  = WRAP;	//AddressV  = WRAP;		}; struct OutputVS{	float4	vPos			: POSITION0;    float2  vTex0           : TEXCOORD0;	float3	vWorldPos		: TEXCOORD1;	float3	vWorldNrm		: TEXCOORD2;	};struct OutputPS{	float4	vMaterial		: COLOR0;	float4	vWorldNrm		: COLOR1;	float4	vWorldPosXY		: COLOR2;	};OutputVS NormalMapVS(float3 posL      : POSITION0,                      float3 tangentL  : TANGENT0,                     float3 binormalL : BINORMAL0,                     float3 normalL   : NORMAL0,                      float2 tex0      : TEXCOORD0){        	OutputVS outVS = (OutputVS)0;	float4x4 worldView = mul(gWorld, gView);		outVS.vWorldPos = mul(float4(posL, 1), worldView);	float3 vWorldPos1 = mul(float4(posL, 1), gWorld);	outVS.vPos = mul(float4(vWorldPos1, 1), gWVP);	outVS.vTex0 = tex0;	outVS.vWorldNrm = normalize(mul(float4(normalL, 0), (float3x3) InverseTransposeView));		return outVS;	}OutputPS NormalMapPS(OutputVS i) : COLOR{	OutputPS o;	float4 vDiffuseMaterial = tex2D(TexS, i.vTex0);	clip(vDiffuseMaterial.a - 0.2f);		o.vMaterial.rgb = vDiffuseMaterial;	o.vMaterial.a = 1.0;		o.vWorldNrm.xyz = 0.5f * (i.vWorldNrm  + 1.0);	o.vWorldNrm.w = 0.0;			o.vWorldPosXY = float4(i.vWorldPos.xyz, 0);	return o;	}float3 getPosition(in float2 texCoord){	float3 position;	position = tex2D(positionXYSampler, texCoord).xyz;	//position.z = tex2D(positionZSampler, texCoord).x;		return position;}float doAmbientOcclusion(in float2 tcoord,in float2 uv, in float3 p, in float3 cnorm){	float3 diff = getPosition( tcoord + uv ) - p;	const float3 v = normalize(diff);	const float d = length(diff)*g_scale;	return max( 0.0, dot(cnorm,v) - g_bias )*( 1.0 / (1.0+d) ) * g_intensity;}float4 deferredLightingAO(float2 tex0:TEXCOORD0):COLOR{	float3 diffuseMaterial = tex2D(textureSampler, tex0);	float3 worldNormal = 2*tex2D(normalSampler, tex0) - 1;				float3 worldPos;	worldPos = getPosition(tex0);	float2 rand = normalize(tex2D(randomNormalSampler, (1024 * 1024) * tex0 / (64 * 64)).xy * 2.0f - 1.0f);	float d = worldPos.z;	if (d < 2.0f)		discard;	d = max(d, 500.0);		float ao = 0.0f;	float rad = g_sample_rad / d;			int iterations = 16; 	float ang = 0.0;	for(int j=0 ; j < iterations ; ++j)	{		float a = radians(ang);		float2 b = float2(cos(a), sin(a));		float2 coord1 = reflect(b, rand/1024) * rad;		float2 coord2 = float2(coord1.x * 0.707f - coord1.y * 0.707f, coord1.x * 0.707f + coord1.y * 0.707f);				ao += doAmbientOcclusion( tex0, coord1 * 0.25f, worldPos, worldNormal );		/*ao += doAmbientOcclusion( tex0, coord2 * 0.50f, worldPos, worldNormal );		ao += doAmbientOcclusion( tex0, coord1 * 0.75f, worldPos, worldNormal );		ao += doAmbientOcclusion( tex0, coord2, worldPos, worldNormal );*/				ang+=360.0/16;	}		ao /= (float)iterations;			ao = (1 - ao) * (1 - ao) * (1 - ao);										float3 lightDir = mul(gLight.dirW , worldView);	lightDir = normalize(lightDir);	//float3 lightDir = normalize(gLight.dirW);	float4 color;	color.rgb =  ao  * diffuseMaterial +				saturate(dot(lightDir, worldNormal)) * gLight.diffuse * diffuseMaterial * 0.6f; 					//color.rgb =  ao;	color.a = 1.0f;			return color;	}float4 deferredLighting(float2 tex0:TEXCOORD0):COLOR{	float3 diffuseMaterial = tex2D(textureSampler, tex0);	float3 worldNormal = 2*tex2D(normalSampler, tex0) - 1;			float3 lightDir = mul(gLight.dirW , worldView);	lightDir = normalize(lightDir);		float shadowOcclusion = tex2D(shadowOcclusionMapSampler, tex0).r;	//if(shadowOcclusion <= 1.5f)	diffuseMaterial *= shadowOcclusion;				float4 color;	color.rgb =  float3(0.7f, 0.7f, 0.7f)  * diffuseMaterial +				saturate(dot(lightDir, worldNormal)) * gLight.diffuse * diffuseMaterial; 	color.a = 1.0f;			return color;	}struct VS_INPUT_Shadow{	float4 Pos : POSITION;	float2 Tex : TEXCOORD0;};struct VS_OUTPUT_Shadow{	float4 Pos : POSITION;	float2 Tex : TEXCOORD0;	float4 PosProj : TEXCOORD1;};struct PS_OUTPUT_Shadow{	float4 Color : COLOR0;};void ShadowTechVS (	in float3 in_vPositionOS				: POSITION,					in float3 in_vTexCoordAndCornerIndex	: TEXCOORD0,							out float4 out_vPositionCS				: POSITION,					out float2 out_vTexCoord				: TEXCOORD0,					out float3 out_vFrustumCornerVS			: TEXCOORD1	){	// Offset the position by half a pixel to correctly align texels to pixels	out_vPositionCS.x = in_vPositionOS.x - (1.0f / 1024);	out_vPositionCS.y = in_vPositionOS.y + (1.0f / 768);	out_vPositionCS.z = in_vPositionOS.z;	out_vPositionCS.w = 1.0f;		// Pass along the texture coordiante and the position of the frustum corner	out_vTexCoord = in_vTexCoordAndCornerIndex.xy;	out_vFrustumCornerVS = farFrustumCoords[in_vTexCoordAndCornerIndex.z];}	float4 ShadowTechPS(float2 tex0:TEXCOORD0, float3 a1:TEXCOORD1):COLOR0{		float3 diffuseMaterial = tex2D(textureSampler, tex0);	float3 position;	position = tex2D(positionXYSampler, tex0).xyz;		float d = tex2D(positionXYSampler, tex0).w;	float4 vPositionVS = float4(d * a1, 1.0f);			float4x4 lightVM = lightView[0];	float4x4 lightPM = lightProjection[0];		float fOffset = 0;	bool a = false;			/*if(position.z <= g_vClipPlanes[0].y)	{		lightVM = lightView[0];		lightPM = lightProjection[0];			}	else	{		lightVM = lightView[1];		lightPM = lightProjection[1];				}*/		for (int i = 1; i < NUM_SPLITS; i++)	{			if (position.z >= g_vClipPlanes.x && position.z <= g_vClipPlanes.y)		{			lightVM = lightView;			lightPM = lightProjection;						fOffset = i / (float)NUM_SPLITS;							a = true;			}							}			float4 lightViewPos = mul(float4(position, 1), inverseView);	lightViewPos = mul(lightViewPos, lightVM);		float4 TexLookUpPos = mul(mul(lightViewPos, lightPM), TexProj);			TexLookUpPos.x = (TexLookUpPos.x/NUM_SPLITS + fOffset);		float2 shadowCoords = TexLookUpPos.xy/TexLookUpPos.w;	shadowCoords.x = ddx(shadowCoords.x);	shadowCoords.y = ddy(shadowCoords.y);	float light;		float depth = (length(lightViewPos) - offset_bias) / max_depth;	float2 moments = tex2Dproj(shadowMapSampler, TexLookUpPos).rg;				if(depth <= moments.x)		light = 1;			else	{			float variance = moments.y - moments.x * moments.x;		variance = min(max(variance, 0.002) + epsilon, 1);		float depth_diff = moments.x - depth;		float p_max = variance/(variance + depth_diff * depth_diff);		light = max(depth <= moments.x, p_max);		light = max(0.2f, light);	}			float4 outColor;	outColor.rgb =  light;	outColor.a = 1.0f;	return outColor;}technique ShadowTech{	pass P0	{			CullMode = none;		FillMode = solid;		Zenable = false;								vertexShader = compile vs_3_0 ShadowTechVS();        pixelShader  = compile ps_3_0 ShadowTechPS();                      	}}technique NormalMapTech{    pass P0    {                vertexShader = compile vs_3_0 NormalMapVS();        pixelShader  = compile ps_3_0 NormalMapPS();    }}technique DeferredLightTechniqueWithAmbientOcclusion{    pass p0	{		VertexShader = NULL;		PixelShader = compile ps_3_0 deferredLightingAO();				CullMode = none;		FillMode = solid;		Zenable = false;		StencilEnable = false;				AlphaBlendEnable = true;		Srcblend = One;		Destblend = One;		AlphaTestEnable = false;				ColorWriteEnable = red | green | blue;	}}technique DeferredLightTechnique{    pass p0	{		VertexShader = NULL;		PixelShader = compile ps_3_0 deferredLighting();				CullMode = none;		FillMode = solid;		Zenable = false;		StencilEnable = true;		StencilFunc   = Always;		StencilPass   = Replace;		StencilRef    = 0; 			AlphaBlendEnable = true;		Srcblend = One;		Destblend = One;		AlphaTestEnable = false;				ColorWriteEnable = red | green | blue;	}}


Please help. Thanks.

[Edited by - ayush3017 on September 16, 2010 4:35:20 AM]
ayush3017
ayush3017
It appears that the shadow map of the secons plit is again drawn which is the problem. Because if I allow the first split to cover the whole are then the problem is gone. Here is the shader code of the depth map:
float4x4 lightView;float4x4 lightProjection;texture colorMap;float max_depth = 100;sampler colorMapSampler = sampler_state{	Texture = <colorMap>;	MinFilter = Anisotropic;	MipFilter = Point;	MagFilter = Linear;	MaxAnisotropy = 16;	};struct VS_SHADOW_OUTPUT{	float4 Pos				: POSITION;	float3 LightViewPos		: TEXCOORD0;	float2 texCoord			: TEXCOORD1;};VS_SHADOW_OUTPUT VS(float4 Position : POSITION, float2 texCoord : TEXCOORD0){	VS_SHADOW_OUTPUT o = (VS_SHADOW_OUTPUT)0;	float4 worldViewPos = mul(Position, lightView);	o.texCoord = texCoord;	o.Pos = mul(worldViewPos, lightProjection);	o.LightViewPos = worldViewPos.xyz;	//o.LightViewPos.z = worldViewPos.w * worldViewPos.z;		return o;}float4 PS(VS_SHADOW_OUTPUT In) : COLOR0{	if(tex2D(colorMapSampler, In.texCoord).a < 0.6f)		discard;	float depth = length(In.LightViewPos) / max_depth;	return float4(depth, depth * depth, 0, 1);		//return In.LightViewPos.z;	}technique shadowMapTechnique{	pass p0	{			ZEnable = false;   					vertexShader = compile vs_3_0 VS();		pixelShader = compile ps_3_0 PS();			}}

What should I do???

[Edited by - ayush3017 on September 15, 2010 1:54:53 PM]
ayush3017
ayush3017
Please help. I am done experimenting the code. Now only you can help..

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.