   simple Shadowmapping
  My renderToTexture system finally works so i decided to start trying to add some fany graphics to my engine. I *thought* shadowmapping shouldn't be so hard to implement but i just can't get the texture projected onto the scene correctly. It's all colored with the same color. What i'm doing is passing the matrix i transformed the vertices on the light's nearplane with to the shader and transform the vertices with that matrix. Now the x,y coords of that transformed point should be the texture coords i have to use for my shadowmap but this is where my first problem resides. I don't know if i have to divide those coordinates by the texture size(uv.u=pos.x/512.0f;uv.v=pos.y/512.0f;). It makes sense to me because usually projected vertices use x,y-coords between (0|0) and (XRES|YRES)(and not (1|1). Anyway dividing or not doesn't change anything to me output. For testing purpose i didn't render the (squared) depth to the shadowmap but the normals(because they have more colors, not just shades of grey). But everything is just plain green.The shaders are written in HLSL:For rendering to the shadowmap:float3 lightVector;float4x4 matView : View;float4x4 matProjection : Projection;float4x4 matWorld : World;float4x4 matWorldViewProjection : WorldViewProjection;struct VS_INPUT {   float3 Position : POSITION0;   float2 uv : TEXCOORD0;   float3 Normal : NORMAL0;};struct VS_OUTPUT {   float3 normal : TEXCOORD1;   float dist : TEXCOORD2;   float2 uv : TEXCOORD0;   float4 Position : POSITION0;   };struct PS_INPUT {   float3 normal : TEXCOORD1;   float dist : TEXCOORD2;   float2 uv : TEXCOORD0;   float4 Position : POSITION0;   };VS_OUTPUT Position_Pass_0_Vertex_Shader_vs_main( VS_INPUT Input ){   VS_OUTPUT Output;   Output.uv=Input.uv;   Output.normal=Input.Normal;   Output.Position = mul(float4(Input.Position,1.0f),matWorldViewProjection);   Output.dist=Output.Position.z;// /Output.Position.w;   return( Output );   }float4 Position_Pass_0_Pixel_Shader_ps_main(PS_INPUT Input) : COLOR0{float dist=Input.dist;  //return float4(dist,dist,dist,1.0f);   return (float4(Input.normal,1.0f)+float4(1.0f,1.0f,1.0f,1.0f))/2.0f;}//--------------------------------------------------------------//// Technique Section for Position//--------------------------------------------------------------//technique Position{   pass Pass_0   { PixelShader = compile ps_2_0 Position_Pass_0_Pixel_Shader_ps_main(); VertexShader = compile vs_2_0 Position_Pass_0_Vertex_Shader_vs_main();   }}and the sahder for rendering the scene:float3 lightVector;float4x4 matView : View;float4x4 matProjection : Projection;float4x4 matWorld : World;float4x4 matWorldViewProjection : WorldViewProjection;float4x4 matLight : MATRIX0;float BIAS=0.0f;texture tex0:PASST0;sampler2D baseMap = sampler_state{   Texture = (tex0);   ADDRESSU = WRAP;   ADDRESSV = WRAP;   MINFILTER = LINEAR;   MAGFILTER = LINEAR;};struct VS_INPUT {   float3 Position : POSITION0;   float2 uv : TEXCOORD0;   float3 Normal : NORMAL0;};struct VS_OUTPUT {   float3 normal : TEXCOORD1;   float2 uv : TEXCOORD0;   float4 smUV : TEXCOORD2;   float4 Position : POSITION0;   };struct PS_INPUT {   float4 smUV : TEXCOORD2;   float3 normal : TEXCOORD1;   float2 uv : TEXCOORD0;   float4 Position : POSITION0;   };VS_OUTPUT Position_Pass_0_Vertex_Shader_vs_main( VS_INPUT Input ){   VS_OUTPUT Output;   float4 n=mul(float4(Input.Normal,1.0f), matWorld);   Output.smUV=mul(float4(Input.Position,1.0f), matLight);   Output.uv=Input.uv;   Output.normal=float3(0.0f,1.0f,0.0f);   Output.Position = mul(float4(Input.Position,1.0f),matWorldViewProjection);   return( Output );   }float4 Position_Pass_0_Pixel_Shader_ps_main(PS_INPUT Input) : COLOR0{   return tex2D(baseMap,float2(Input.smUV.x/512.0f,Input.smUV.y/512.0f)); //divide by 512 or not?  return float4(1.0f,0.0f,0.0f,1.0f)*dot(float3(Input.normal.x,Input.normal.y,Input.normal.z),lightVector);}//--------------------------------------------------------------//// Technique Section for Position//--------------------------------------------------------------//technique Position{   pass Pass_0   { PixelShader = compile ps_2_0 Position_Pass_0_Pixel_Shader_ps_main(); VertexShader = compile vs_2_0 Position_Pass_0_Vertex_Shader_vs_main();   }}regards,m4gnus   
  try this :float4 Position_Pass_0_Pixel_Shader_ps_main(PS_INPUT Input) : COLOR0{   return tex2D(baseMap,float2(0.5 * Input.smUV.xy / Input.smUV.w + float2( 0.5, 0.5 )); // -1_1 => -0.5_0.5 => 0_1}on DX the proj matrix map into -1, 1and into 0,1 for opengland you will certainly have to swap vertically the projectionhope it helps   ;  First question I have is why in your shadow depth generation code are you writing out the normal + (1,1,1,1)?I see that you were previously writing out the depth, but have it commented out.   ;  thx 4 the replies.Quote: return tex2D(baseMap,float2(0.5 * Input.smUV.xy / Input.smUV.w + float2( 0.5, 0.5 )); // -1_1 => -0.5_0.5 => 0_1ok i tried that(btw there's missing a ')' at the end),now i get a solid green scene with ca 100 very small triangles on it.Quote:First question I have is why in your shadow depth generation code are you writing out the normal + (1,1,1,1)?As mentionend before, i use the normal for testing purposes.btw maybe it does matter that i use a texture with just one channel(a 32 bit float[D3DFMT_R32F]) as the shadowmap.Quote:on DX the proj matrix map into -1, 1i'm using directX so what does that mean? your comment said that you remap some values from -1,1 to 0,1 but do i need that if i use directX? And i don't understand when to divide by w i've seen it a couple of times. I just know that when you multiply a point with the projection matrix everything gets divided by w but what's the use of the division here?(btw i'm still wondering if i have to divide by the texture size after transforming a point into light space(see original post))Edit: When i move the light far away from the scene the projection is better but still way off. The farer i zoom in the oftner the shadowmap get's tiled. Btw the solid green is just the ground plane i have in my scene.Edit2: Wow by doing texCoord.y=1.0f-texCoord.y everything works fine for distant lights. So the problem seems to be the projectionmatrix.Edit3: i think the projection is correct, but i still have problems trying to get the shadow mapping to workregards,m4gnus[Edited by - m4gnus on May 12, 2006 6:16:40 AM];  can you post a screen shot ?it should so be easier to find your bug ! in fact here are the steps you have to follow :1) render the scene in the shadow map with the modelLightViewProj matrix like thatmodelLightViewProjMtx = ModelMtx * LightViewMtx => transform from model space to light spacemodelLightViewProjMtx *= LightProjMtx => do the light proji guess your matrices are okyou have to know that DX use a homogenous coordinate system to store different that openglon DX the proj cube goes from -1 to 1 (and this is 0 to 1 for opengl)this is how the sdk store and manages internally when you write in a frame buffer or render targetthis is why you have to remap (for DX) from -1,1 to 0,1 (because texture mapping is in the 0,1 range)2) render the scene in screen space using the shadow map generatedyou can use exactly the same matrix if you want and do all the specifix SDK stuff in shader or directly multiply you final matrix by a scaleAndInvertY matrix like it's done in the SoftShadows sample from nvidia SDKthis matrix should be something like that    float fOffsetY = 0.5f + (0.5f / (float)TEXDEPTH_HEIGHT);    unsigned int range = 1;  //note different scale in DX9!    float fBias    = 0.0f;    D3DXMATRIX texScaleBiasMat( 0.5f,0.0f,0.0f,    0.0f,  0.0f,    -0.5f,0.0f,    0.0f,  0.0f,0.0f,(float)range, 0.0f,  fOffsetX, fOffsetY, fBias,   1.0f );or you can do it directly in the sahder like i show in my first posthope it helps;  you need to see it in action. i think a screenshot wouldn't help.I can post the executable but i only tested the app on my machine and it could be very unfriendly to other computers(and it doesn't clean up it's ressources properly). Anyway my status:The projection of the shadowmap back on my scene works correctly! i can project a greyscale of my normals back onto the scene. But i really get problems when storing the depth in it.Just after the light is near enough for the scene not being clipped by the light's near plane everything is just white(as long as i don't scale it by 0.5 as in the screen).Do i probably exceed the highest value that can be stored in the texture?Screenshot(light from above)When the light intersects the scene other strange artifacts appear:Screenshotshaders:shadowmap:float3 lightVector;float4x4 matView : View;float4x4 matProjection : Projection;float4x4 matWorld : World;float4x4 matWorldViewProjection : WorldViewProjection;struct VS_INPUT {   float3 Position : POSITION0;   float2 uv : TEXCOORD0;   float3 Normal : NORMAL0;};struct VS_OUTPUT {   float3 normal : TEXCOORD1;   float2 dist : TEXCOORD2;   float2 uv : TEXCOORD0;   float4 Position : POSITION0;   };struct PS_INPUT {   float3 normal : TEXCOORD1;   float2 dist : TEXCOORD2;   float2 uv : TEXCOORD0;   float4 Position : POSITION0;   };VS_OUTPUT Position_Pass_0_Vertex_Shader_vs_main( VS_INPUT Input ){   VS_OUTPUT Output;   Output.uv=Input.uv;   Output.normal=Input.Normal;   Output.Position = mul(float4(Input.Position,1.0f),matWorldViewProjection);   Output.dist.xy=Output.Position.zw;   return( Output );   }float4 Position_Pass_0_Pixel_Shader_ps_main(PS_INPUT Input) : COLOR0{ float dist=(Input.dist.x/Input.dist.y);lightVector=float3(1.0f,0.0f,0.0f);    return float4(dist,dist,dist,1.0f);}//--------------------------------------------------------------//// Technique Section for Position//--------------------------------------------------------------//technique Position{   pass Pass_0   { PixelShader = compile ps_2_0 Position_Pass_0_Pixel_Shader_ps_main(); VertexShader = compile vs_2_0 Position_Pass_0_Vertex_Shader_vs_main();   }}scene.float3 lightVector;float4x4 matView : View;float4x4 matProjection : Projection;float4x4 matWorld : World;float4x4 matWorldViewProjection : WorldViewProjection;float4x4 matLight : MATRIX0;float4x4 matLightProj : MATRIX1;float4x4 matLightView : MATRIX2;float BIAS=0.0f;texture tex0:PASST0;sampler2D baseMap = sampler_state{   Texture = (tex0);   ADDRESSU = CLAMP;   ADDRESSV = CLAMP;   MINFILTER = LINEAR;   MAGFILTER = LINEAR;};struct VS_INPUT {   float3 Position : POSITION0;   float2 uv : TEXCOORD0;   float3 Normal : NORMAL0;};struct VS_OUTPUT {   float3 normal : TEXCOORD1;   float2 uv : TEXCOORD0;   float4 smUV : TEXCOORD2;   float4 Position : POSITION0;   };struct PS_INPUT {   float4 smUV : TEXCOORD2;   float3 normal : TEXCOORD1;   float2 uv : TEXCOORD0;   float4 Position : POSITION0;   };VS_OUTPUT Position_Pass_0_Vertex_Shader_vs_main( VS_INPUT Input ){   VS_OUTPUT Output;   float4 n=mul(float4(Input.Normal,1.0f), matWorld);   float4x4 lightCompl=mul(matLightView,matLightProj);   Output.smUV=mul(float4(Input.Position,1.0f), lightCompl);   Output.uv=Input.uv;   Output.normal=float3(0.0f,1.0f,0.0f);   Output.Position = mul(float4(Input.Position,1.0f),matWorldViewProjection);   return( Output );   }float4 Position_Pass_0_Pixel_Shader_ps_main(PS_INPUT Input) : COLOR0{float2 texCoord=float2(0.5 * Input.smUV.xy / Input.smUV.w + float2( 0.5, 0.5 ));  texCoord.y=1.0f-texCoord.y;  float shMap=tex2D(baseMap,texCoord).r;float diff=abs(tex2D(baseMap,texCoord)-Input.smUV.z/Input.smUV.w);  return float4(shMap*0.5,shMap*0.5,shMap*0.5,1.0f);}//--------------------------------------------------------------//// Technique Section for Position//--------------------------------------------------------------//technique Position{   pass Pass_0   { PixelShader = compile ps_2_0 Position_Pass_0_Pixel_Shader_ps_main(); VertexShader = compile vs_2_0 Position_Pass_0_Vertex_Shader_vs_main();   }}regards,m4gnus   ;  did you try to scale the z too ?D3DXMATRIX texScaleBiasMat( 0.5f, 0.0f, 0.0f, 0.0f,0.0f, -0.5f, 0.0f, 0.0f,0.0f, 0.0f, 0.5f, 0.0f,fOffsetX, fOffsetY, 0.5f-fBias, 1.0f );note the -0.5 in texScaleBiasMat(1,1) which will invert Y directly by the matrix transform   ;Quote:did you try to scale the z too ?D3DXMATRIX texScaleBiasMat( 0.5f, 0.0f, 0.0f, 0.0f,0.0f, -0.5f, 0.0f, 0.0f,0.0f, 0.0f, 0.5f, 0.0f,fOffsetX, fOffsetY, 0.5f-fBias, 1.0f );note the -0.5 in texScaleBiasMat(1,1) which will invert Y directly by the matrix transformno. i didn't change anything with the matrices. I just gave the light's view+projection matrix to the shader. And the rest is all in the shader. What am i supposed to do with the matrix you provided?regards,m4gnus   ;  you can replace this in your shaderfloat2 texCoord=float2(0.5 * Input.smUV.xy / Input.smUV.w + float2( 0.5, 0.5 ));texCoord.y=1.0f-texCoord.y; by the appropriate matrix like i say in my second post wich will do exactly the samedo you have installed the DX9 SDK ?the shadow map sample does that in the shader, like youfrom the nvidia SDK the softshadowsample use a matrixin fact you can use the both methods, it's like you want !:)the DX sample has an enxcellent trick to simulate bilinear filtering   ;Quote:do you have installed the DX9 SDK ?the shadow map sample does that in the shader, like youyes i have it installed but it didn't help me getting my own shadowmapping working :(Quote:the DX sample has an enxcellent trick to simulate bilinear filteringyes i know.they are checking the adjacent pixels for shadow and average the values.but my problem is still that the depth values in the texture are wrong(all the same most the time).regards,m4gnus