PSSM / CSM shadows

Started by
5 comments, last by martinperry 14 years, 5 months ago
I am trying to implement PSSM (http://http.developer.nvidia.com/GPUGems3/gpugems3_ch10.html - I implemented Scene-Independent method for now) Inspiration for me was also this article: http://hax.fi/asko/PSSM.html But I dont know, what i am doing wrong. I got this. Shadow error - light goes from left part of the image. Shadow is white. But I have left side of car "in shadow" and shadow also on lightened side of car I think, that my C# impl. should be correct. But maybe my HLSL code is wrong. (Map generation works fine, I use code from Standard one SM generation)

Texture xShadowMapText0;
Texture xShadowMapText1;
Texture xShadowMapText2;
sampler ShadowMapSamplerPssm[3] = {
	{sampler_state { Texture = <xShadowMapText0> ; magfilter = LINEAR; minfilter = LINEAR; mipfilter=NONE; AddressU = clamp; AddressV = clamp;}},
	{sampler_state { Texture = <xShadowMapText1> ; magfilter = LINEAR; minfilter = LINEAR; mipfilter=NONE; AddressU = clamp; AddressV = clamp;}},
	{sampler_state { Texture = <xShadowMapText2> ; magfilter = LINEAR; minfilter = LINEAR; mipfilter=NONE; AddressU = clamp; AddressV = clamp;}}
};

struct PSSMVertexToPixel 
{
	float4 Position		: POSITION;	
	float3 Normal 		: TEXCOORD0;
	float3 Position3D   : TEXCOORD1;
	float2 TexCoords    : TEXCOORD2;
	float4 texCoord[3 + 1] : TEXCOORD3;
	
};

struct PSSMPixelToFrame
{
	float4 Color	:	COLOR0;
};


PSSMVertexToPixel RenderPSSMSceneVS( float4 inPos : POSITION, float2 inTexCoords : TEXCOORD0, float3 inNormal : NORMAL)
{
	PSSMVertexToPixel Output = (PSSMVertexToPixel)0;
    
	float4 posInWorld = mul(inPos, xWorld); 
	Output.Position = CalcPositionInWorld(inPos);
	
	
	Output.texCoord[0] = mul(posInWorld, xCamView);
	for (int i = 0; i < 3; i++)
	{
		Output.texCoord = mul(posInWorld, textureMatrix<span style="font-weight:bold;">);
	}
	
	<span class="cpp-comment">//— if i want to use textures later</span>
	Output.TexCoords = inTexCoords;
	Output.Normal = normalize(mul(inNormal, xWorld));
	Output.Position3D = mul(inPos, xWorld);
	
	<span class="cpp-keyword">return</span> Output;
}

PSSMPixelToFrame RenderPSSMScenePS(PSSMVertexToPixel PSIn)
{
	PSSMPixelToFrame Output = (PSSMPixelToFrame)<span class="cpp-number">0</span>;

<span class="cpp-comment">//Nvidia part of code</span>
	<span class="cpp-keyword">float</span> light = <span class="cpp-number">1</span>.0f;
	<span class="cpp-keyword">float</span> distance = PSIn.texCoord[<span class="cpp-number">0</span>].z / PSIn.texCoord[<span class="cpp-number">0</span>].w;
	<span class="cpp-keyword">for</span>(<span class="cpp-keyword">int</span> i = <span class="cpp-number">0</span>; i &lt; <span class="cpp-number">3</span>; i++)  
    {  
     	<span class="cpp-keyword">if</span>(distance &lt; splitPlane<span style="font-weight:bold;">)  
		 
		{  
			<span class="cpp-keyword">float</span> depth = PSIn.texCoord[i+<span class="cpp-number">1</span>].z / PSIn.texCoord[i+<span class="cpp-number">1</span>].w;  
		   	<span class="cpp-keyword">float</span> depthSM = tex2Dproj(ShadowMapSamplerPssm<span style="font-weight:bold;">, PSIn.texCoord);  
 
			light = (depth &lt; depthSM) ? <span class="cpp-number">1</span>.0f : <span class="cpp-number">0</span>.5f; 
		   	<span class="cpp-keyword">break</span>;  
		}  
    }  
	Output.Color = light;
	
	<span class="cpp-keyword">return</span> Output;
}


technique PSSM
{
	pass Pass0
	{
		<span class="cpp-comment">//CullMode = CCW; //doesnt effect</span>
		VertexShader = compile vs_2_0 RenderPSSMSceneVS();
		PixelShader = compile ps_2_0 RenderPSSMScenePS();
	}
}



</pre></div><!–ENDSCRIPT–> 
Advertisement
Maybe bias issue, do you have any depth bias added during depth compare?
Quote:
Maybe bias issue, do you have any depth bias added during depth compare?


No.. I don´t added any bias. Where should I put that ?
To this line: if(distance < splitPlane) ?
Sorry for being slightly offtopic, but is PSSM and CSM the same?
Yes, PSSM and CSM si more or less the same thing.
Nope, here:
light = (depth < depthSM) ? 1.0f : 0.5f;

due limited precision of stored depth that expression will be true in many cases. So try something like this:
light = (depth < (depthSM + 0.001)) ? 1.0f : 0.5f;
No.. it has no effect ;(

Maybe my crop matrix calc. is wrong. I calc that matrix this way.
Matrix lightViewProjection = lightViewMatrix * lightProjectionMatrix;			/*			BoundingBox box = BoundingBox.FromPoints(frustrumCorners);			frustrumCorners = box.GetCorners();			*/			Vector3[] transformedCorners = new Vector3[frustrumCorners.Length];						for (int i = 0; i < this.corners.Length; i++)			{				Vector4 tmp = Vector3.Transform(frustrumCorners, lightViewProjection);				transformedCorners.X = tmp.X / tmp.W;				transformedCorners.Y = tmp.Y / tmp.W;				transformedCorners.Z = tmp.Z / tmp.W;							}			 			cropBox = BoundingBox.FromPoints(transformedCorners);						//cropBox = BoundingBox.FromPoints(this.corners);						//Console.WriteLine("" + cropBox + "|***|");			cropBox.Minimum.Z = 0.0f;						float scaleX, scaleY, scaleZ;			float offsetX, offsetY, offsetZ;			scaleX = 2.0f / (cropBox.Maximum.X - cropBox.Minimum.X);			scaleY = 2.0f / (cropBox.Maximum.Y - cropBox.Minimum.Y);			scaleZ = 1.0f / (cropBox.Maximum.Z - cropBox.Minimum.Z);			offsetX = -0.5f * (cropBox.Maximum.X + cropBox.Minimum.X) * scaleX;			offsetY = -0.5f * (cropBox.Maximum.Y + cropBox.Minimum.Y) * scaleY;			offsetZ = -cropBox.Minimum.Z * scaleZ;			Matrix cropMatrix = Matrix.Identity;						cropMatrix.M11 = scaleX;			cropMatrix.M22 = scaleY;			cropMatrix.M33 = scaleZ;			cropMatrix.M41 = offsetX;			cropMatrix.M42 = offsetY;			cropMatrix.M43 = offsetZ;						return cropMatrix;


And with this crop matrix I simply do this
textureMatrix = Matrix() * TexScaleMatrix

and texture matrix goes to shader.

[Edited by - martinperry on October 30, 2009 2:19:29 PM]

This topic is closed to new replies.

Advertisement