Shadow Mapping

Started by
6 comments, last by kultys 12 years ago
Hi, i implemante im my framework this shadow mapping: http://www.riemers.n...shing_touch.php.
Screen show results:

screenio.jpg

This shadow is very bad :D ? How too implemant blur shadow mapps ? Please help me. THX for all.

This is code to HLSL VS/PS :
struct SMapVertexToPixel
{
float4 Position : POSITION;
float3 Position2D : TEXCOORD0;
};
struct SMapPixelToFrame
{
float4 Color : COLOR0;
float Depth : DEPTH;
};
struct SSceneVertexToPixel
{
float4 Position : POSITION;
float4 ShadowMapSamplingPos : TEXCOORD0;
float4 RealDistance : TEXCOORD1;
float2 TexCoords : TEXCOORD2;
float3 Normal : TEXCOORD3;
float3 Position3D : TEXCOORD4;
};
struct SScenePixelToFrame
{
float4 Color : COLOR0;
};

struct AmbientVertexToPixel
{
float4 Position : POSITION;
float2 TexCoords : TEXCOORD0;
float4 Position2D : TEXCOORD1;
};

struct AmbientPixelToFrame
{
float4 Color : COLOR0;
};

//------- Constants --------
float4x4 xCameraViewProjection;
float4x4 xLightViewProjection[3];
float4x4 xRotate;
float4x4 xTranslateAndScale;
float4 xLightPos[3];
float4 xCameraPos;
float xLightPower[3];
float xMaxDepth;
float xAmbient;
//------- Texture Samplers --------
Texture xColoredTexture;
sampler ColoredTextureSampler = sampler_state { texture = <xColoredTexture> ; magfilter = LINEAR; minfilter = LINEAR; mipfilter=LINEAR; AddressU = mirror; AddressV = mirror;};
Texture xShadowMap;
sampler ShadowMapSampler = sampler_state { texture = <xShadowMap> ; magfilter = LINEAR; minfilter = LINEAR; mipfilter=LINEAR; AddressU = clamp; AddressV = clamp;};
Texture xCarLightTexture;
sampler CarLightSampler = sampler_state { texture = <xCarLightTexture> ; magfilter = LINEAR; minfilter=LINEAR; mipfilter = LINEAR; AddressU = clamp; AddressV = clamp;};
Texture xSpotLightTexture;
sampler SpotLightSampler = sampler_state { texture = <xSpotLightTexture> ; magfilter = LINEAR; minfilter=LINEAR; mipfilter = LINEAR; AddressU = clamp; AddressV = clamp;};
//------- Vertex Shaders --------
SMapVertexToPixel ShadowMapVertexShader( float4 inPos : POSITION, uniform int CurrentLight)
{
SMapVertexToPixel Output = (SMapVertexToPixel)0;
float4x4 preWorld = mul(xRotate, xTranslateAndScale);
float4x4 preLightWorldViewProjection = mul (preWorld, xLightViewProjection[CurrentLight]);

Output.Position = mul(inPos, preLightWorldViewProjection);
Output.Position2D = Output.Position;

return Output;
}
SSceneVertexToPixel ShadowedSceneVertexShader( float4 inPos : POSITION, float2 inTexCoords : TEXCOORD0, float3 inNormal : NORMAL, uniform int CurrentLight)
{
SSceneVertexToPixel Output = (SSceneVertexToPixel)0;
float4x4 preWorld = mul(xRotate, xTranslateAndScale);
float4x4 preCameraWorldViewProjection = mul (preWorld, xCameraViewProjection);
float4x4 preLightWorldViewProjection = mul (preWorld, xLightViewProjection[CurrentLight]);

Output.Position = mul(inPos, preCameraWorldViewProjection);
Output.ShadowMapSamplingPos = mul(inPos, preLightWorldViewProjection);
Output.RealDistance = Output.ShadowMapSamplingPos.z/xMaxDepth;
Output.TexCoords = inTexCoords;
Output.Normal = mul(inNormal, xRotate);
Output.Position3D = inPos;

return Output;
}

AmbientVertexToPixel AmbientVertexShader( float4 inPos : POSITION, float4 inTexCoords : TEXCOORD0)
{
AmbientVertexToPixel Output = (AmbientVertexToPixel)0;
float4x4 preWorld = mul(xRotate, xTranslateAndScale);
float4x4 preCameraWorldViewProjection = mul (preWorld, xCameraViewProjection);

Output.Position = mul(inPos, preCameraWorldViewProjection);
Output.Position2D = Output.Position;
Output.TexCoords = inTexCoords;
return Output;
}

//------- Pixel Shaders --------
float DotProduct(float4 LightPos, float3 Pos3D, float3 Normal)
{
float3 LightDir = normalize(LightPos - Pos3D);
return dot(LightDir, Normal);
}
SMapPixelToFrame ShadowMapPixelShader(SMapVertexToPixel PSIn, uniform int CurrentLight)
{
SMapPixelToFrame Output = (SMapPixelToFrame)0;
Output.Color[CurrentLight] = PSIn.Position2D.z/xMaxDepth;
Output.Depth = Output.Color[CurrentLight]/3.0f + (2-CurrentLight)*0.33f;
return Output;
}

SScenePixelToFrame ShadowedScenePixelShader(SSceneVertexToPixel PSIn, uniform int CurrentLight)
{
SScenePixelToFrame Output = (SScenePixelToFrame)0;

float2 ProjectedTexCoords;
ProjectedTexCoords[0] = PSIn.ShadowMapSamplingPos.x/PSIn.ShadowMapSamplingPos.w/2.0f +0.5f;
ProjectedTexCoords[1] = -PSIn.ShadowMapSamplingPos.y/PSIn.ShadowMapSamplingPos.w/2.0f +0.5f;

if ((saturate(ProjectedTexCoords.x) == ProjectedTexCoords.x) && (saturate(ProjectedTexCoords.y) == ProjectedTexCoords.y))
{
float StoredDepthInShadowMap = tex2D(ShadowMapSampler, ProjectedTexCoords)[CurrentLight];

if ((PSIn.RealDistance.x - 1.0f/100.0f) <= StoredDepthInShadowMap)
{
float LightTextureFactor;
if (CurrentLight == 0)
{
LightTextureFactor = tex2D(CarLightSampler, ProjectedTexCoords).r;
}else{
LightTextureFactor = tex2D(SpotLightSampler, ProjectedTexCoords).r;
}


float DiffuseLightingFactor = DotProduct(xLightPos[CurrentLight], PSIn.Position3D, PSIn.Normal);
float4 ColorComponent = tex2D(ColoredTextureSampler, PSIn.TexCoords);
Output.Color = ColorComponent*LightTextureFactor*DiffuseLightingFactor*xLightPower[CurrentLight];

}
}


return Output;
}

AmbientPixelToFrame AmbientPixelShader(AmbientVertexToPixel PSIn)
{
AmbientPixelToFrame Output = (AmbientPixelToFrame)0;

Output.Color = tex2D(ColoredTextureSampler, PSIn.TexCoords)*xAmbient;

float2 ScreenPos;
ScreenPos[0] = PSIn.Position2D.x/PSIn.Position2D.w/2.0f +0.5f;
ScreenPos[1] = -PSIn.Position2D.y/PSIn.Position2D.w/2.0f +0.5f;

for (int CurrentLight=1; CurrentLight<3; CurrentLight++)
{
float4 Light3DPos = mul(xLightPos[CurrentLight],xCameraViewProjection);
float2 LightScreenPos;
LightScreenPos[0] = Light3DPos.x/Light3DPos.w/2.0f +0.5f;
LightScreenPos[1] = -Light3DPos.y/Light3DPos.w/2.0f +0.5f;

float dist = distance(ScreenPos, LightScreenPos);
float radius = 3.5f/distance(xCameraPos, xLightPos[CurrentLight]);
if (dist < radius)
{
Output.Color.rgb += (radius-dist)*8.0f;
}
}

return Output;
}
//------- Techniques --------
technique ShadowMap
{
pass Pass0
{
cullmode = ccw;
colorwriteenable = red;
VertexShader = compile vs_2_0 ShadowMapVertexShader(0);
PixelShader = compile ps_2_0 ShadowMapPixelShader(0);
}
pass Pass1
{
colorwriteenable = green;
VertexShader = compile vs_2_0 ShadowMapVertexShader(1);
PixelShader = compile ps_2_0 ShadowMapPixelShader(1);
}
pass Pass2
{
colorwriteenable = blue;
VertexShader = compile vs_2_0 ShadowMapVertexShader(2);
PixelShader = compile ps_2_0 ShadowMapPixelShader(2);
}
}
technique ShadowedScene
{
pass Pass0
{
VertexShader = compile vs_2_0 ShadowedSceneVertexShader(0);
PixelShader = compile ps_2_0 ShadowedScenePixelShader(0);
}
pass Pass1
{
SRCBLEND = ONE;
DESTBLEND = ONE;
ALPHABLENDENABLE = true;

VertexShader = compile vs_2_0 ShadowedSceneVertexShader(1);
PixelShader = compile ps_2_0 ShadowedScenePixelShader(1);
}
pass Pass2
{
VertexShader = compile vs_2_0 ShadowedSceneVertexShader(2);
PixelShader = compile ps_2_0 ShadowedScenePixelShader(2);
}
pass Pass3
{
VertexShader = compile vs_2_0 AmbientVertexShader();
PixelShader = compile ps_2_0 AmbientPixelShader();
}
}
Advertisement
I changed the size of texture and light setting.
No have this result:
screenxe.jpg
This problem exist only light 0 ([font=Arial][size=2][color="#030752"]direction light).[/font]
Please help. What is bad in my code ?
Good shadows are difficult to achieve. And sometimes the result is more an artistic work than a technical one.

Questions:

* What is the surface format of the depth map from the light source?

* How far is the light “camera” from the objects?

* What are the near and far planes of the light frustum?

There are several ways to improve shadows. One is applying PCF (a blur when you sample the light depth texture). Another is to apply a blur pass in the final result (in this case you should have deferred shadows, see MJP example). Also you could use more sophisticated shadow techniques like cascaded shadows, etc.

But this is “For Beginners” section, so probably the last paragraph was too much information.

[size=1]Project page: [size=1]<

[size=1] XNA FINAL Engine[size=1] [size=1]>
* What is the surface format of the depth map from the light source?
X8R8G8B8
If i change to R16F dont see another shadows for lights (1 and 2):

http://desmond.imageshack.us/Himg521/scaled.php?server=521&filename=screentz.jpg&res=landing

* How far is the light “camera” from the objects?
Object:
Flor is 0F
Boy is 0F
Light is:
LightPos(0) = New Vector3(-12.0F, 10.0F, 3.0F)
LightPos(1) = New Vector3(-5, 5, 11.5F)
LightPos(2) = New Vector3(-5, 35, 11.5F)

and send to effect this:
LightViewProjection(0) = Matrix.LookAtLH(LightPos(0), New Vector3(2, 10, 0), New Vector3(0, 0, 1)) * Matrix.PerspectiveFovLH(CSng(Math.PI) / 2, Me.Width / Me.Height, 1.0F, 100.0F)
LightViewProjection(1) = Matrix.LookAtLH(LightPos(1), New Vector3(-5, 5, 0), New Vector3(0, 1, 0)) * Matrix.PerspectiveFovLH(CSng(Math.PI) / 1.9F, Me.Width / Me.Height, 0.3F, 100.0F)
LightViewProjection(2) = Matrix.LookAtLH(LightPos(2), New Vector3(-5, 35, 0), New Vector3(0, 1, 0)) * Matrix.PerspectiveFovLH(CSng(Math.PI) / 1.9F, Me.Width / Me.Height, 0.3F, 100.0F)


Camera:
Matrix.PerspectiveFovLH((CType(Math.PI, Single) / 4), (Me.Width / Me.Height), 1.0F, 1024.0F)

* What is the surface format of the depth map from the light source?
X8R8G8B8
If i change to R16F dont see another shadows for lights (1 and 2):



If you store the light depth buffer in 8 bits you will probably suffer precision artifacts. You should try R32F or another floating point format. The problem with R16F or R32F is that you have only one channel, so you will have only shadows for one light. But there are floating point formats for 4 channels.



* How far is the light “camera” from the objects?
Object:
Flor is 0F
Boy is 0F
Light is:
LightPos(0) = New Vector3(-12.0F, 10.0F, 3.0F)
LightPos(1) = New Vector3(-5, 5, 11.5F)
LightPos(2) = New Vector3(-5, 35, 11.5F)

and send to effect this:
LightViewProjection(0) = Matrix.LookAtLH(LightPos(0), New Vector3(2, 10, 0), New Vector3(0, 0, 1)) * Matrix.PerspectiveFovLH(CSng(Math.PI) / 2, Me.Width / Me.Height, 1.0F, 100.0F)
LightViewProjection(1) = Matrix.LookAtLH(LightPos(1), New Vector3(-5, 5, 0), New Vector3(0, 1, 0)) * Matrix.PerspectiveFovLH(CSng(Math.PI) / 1.9F, Me.Width / Me.Height, 0.3F, 100.0F)
LightViewProjection(2) = Matrix.LookAtLH(LightPos(2), New Vector3(-5, 35, 0), New Vector3(0, 1, 0)) * Matrix.PerspectiveFovLH(CSng(Math.PI) / 1.9F, Me.Width / Me.Height, 0.3F, 100.0F)


Camera:
Matrix.PerspectiveFovLH((CType(Math.PI, Single) / 4), (Me.Width / Me.Height), 1.0F, 1024.0F)



The near plane, far plane and distance of the light are perfect. So the problem is mostly accuracy. Try another floating point format and try point sampler if you don’t see anything (magfilter = POINT; minfilter = POINT).

[size=1]Project page: [size=1]<

[size=1] XNA FINAL Engine[size=1] [size=1]>
For now is better, i change this value effect.SetValue("xMaxDepth", 60) to 20.
I use this format: A16B16G16R16F
Now effect is good:
http://desmond.image...jpg&res=landing

How to implement PCF ?
Thanx for help.
Great!!

I don’t remember where I read about PCF. Sorry. I remember that I read a lot (the only way to learn properly) and adapted a MJP example to implement my shadow system.

http://mynameismjp.w...ow-maps-sample/

You can find my shadow system in my signature (download the source code from the source tab). I have to do some optimizations but for the most part works well.

Good luck!!!

[size=1]Project page: [size=1]<

[size=1] XNA FINAL Engine[size=1] [size=1]>
THX i try :D

This topic is closed to new replies.

Advertisement