Sign in to follow this  

Deferred shadow map.

This topic is 3092 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

Hello! Forced to make a second pass,now i have got a scene completely drawn using GBuffers and it's ok, and now it's time to apply shadows. At first i made the usual ZOnly pass and set it as a texture. http://img44.imageshack.us/img44/4048/porcesco.jpg This is a projection of light on the scene, and it is not good, but really (i'm working too much) i do not remember what's going wrong.

Share this post


Link to post
Share on other sites
Hi,

I think that you are trying to generate shadow map by using your original depth texture. Or, you're trying to perform shadowing after your deferred rendering (onto your result render target image).

Generating shadow map must be done before filling g-buffer. And shadowing must be done in your deferred rendering shader (where you use your g-buffer render target textures and performing your lighting calculations). At least that's the way I do it.

Regards,
Rohat.

Share this post


Link to post
Share on other sites
Quote:
Original post by programci_84
Generating shadow map must be done before filling g-buffer.

But that doesn't work with several different lights. At least not if you want to reuse the shadowbuffers.

XVincentX, please try to explain your problem a little better and I think we should be able to help you.

Share this post


Link to post
Share on other sites
Hint: Shadow mapping involves comparisons. ;)

You appear to have your depth buffer set up just fine; AFAIK you seem to just have overlaid it on top of your previous work. Believe it or not, the hard work is pretty much done. All you need to do now is generate a perspective matrix for your shadow map; this will be used to determine where you need to sample on that depth texture. The rough process is as follows--

Unproject the point you want to shade back into world space; you do this with the inverse of your VP matrix. There's plenty of documentation on how this is done, and I leave the specifics up to you.

Now that you have the world-space position, you need to reproject it into shadow map space using the shadow matrix from before. The whole process for this is almost identical to what you do for a regular camera, right down to the up, right and forward vectors.

Finally, read the depth out of the shadow map and compare it against the distance from the light to the point being shaded. If this distance is greater than that which we got from the shadow map, the point shouldn't receive anything from the current light. This should be pretty intuitive.

EDIT: There are also plenty of optimizations possible within that explanation (optimizing out the de-/reprojection, for starters) but hopefully that should be enough to get you going.

@programci_84-- Why do you think that, exactly? Is there a reason why you can't
- Generate the G-buffers for the current view
- Render a shadow map for a light
- Shade for one light, using the shadow map
- Render a shadow map for the next light
- Shade for the new light with the second shadow map (rendered to the same spot in memory, even)
- Repeat until all lights are done

Share this post


Link to post
Share on other sites
Hi,

Quote:
by InvalidPointer
Why do you think that, exactly? Is there a reason why you can't
- Generate the G-buffers for the current view
- Render a shadow map for a light
- Shade for one light, using the shadow map
- Render a shadow map for the next light
- Shade for the new light with the second shadow map (rendered to the same spot in memory, even)
- Repeat until all lights are done


Of course not. I know that this approach is simpler and will work fine. But in my deferred renderer, I'm filling shadow maps for every caster light before filling G-Buffers (Of course I don't fill g-buffers for every light). I have point (not caster), directional(caster) and spotlights(caster). This works fine for me. So I said "you must generate shadowmaps before filling g-buffer" because this is the way I do it. Performance is good enough and I didn't get any bad result(s) for now.

Quote:
by B_old
But that doesn't work with several different lights. At least not if you want to reuse the shadowbuffers.

I don't know anything about shadowbuffers that you pointed out. But I have 3 types of light and 2 of'em are casters. Works fine for now with several effects.

Now I see that I should say "You must generate shadowmaps before shading" instead of "... before filling g-buffer".

Thanks anyway.

Share this post


Link to post
Share on other sites
Really thank you for all your answers.
I'm not a very nice english-speaker, i will do my best to let you understand my sentences.

Quote:

I think that you are trying to generate shadow map by using your original depth texture. Or, you're trying to perform shadowing after your deferred rendering (onto your result render target image).
Generating shadow map must be done before filling g-buffer.


It's what i'm doing. I tryed to fill the shadowmap from FillGBufferShader, but it's impossible becouse it was required to output different projected position (GeometryShader and Texture2DArray) and different colors(Multiple Render Target) ,but D3D10 supports one of this for Draw call.

So at first i fill GBuffers (all ok), and after i draw using a ZOnly pass.
This pass is performed in D3D10 using a Texture2D with R32_TYPELESS and bound in 2 pipeline objects (Shader Resource View and DepthStencilView) using D3D10 casts to R32_FLOAT and D32_FLOAT.

So there is no render target bound in ZOnly pass, as this code says.


device->OMSetRenderTargets(5,&SRenderTarget[1],ShadowDS);


SRenderTarget is a NULL array.
The Shadow Map has got SAME backbuffer's size, so there is no projection to change.
Now that i have got ShadowMap and ALSO GBuffers, i have to perform rendering on FrameBuffer.

Current code is this:


float4 ps_draw(in float4 Pos:SV_POSITION, in float2 Tex:TEXCOORD) : SV_TARGET
{
float4 TexC = BaseColor.Sample(SamplText,Tex);
float3 Norm = 2.0f * Normal.Sample(SamplText,Tex).xyz - 1.0f;
float NdotL = max(0.0f,dot(Norm,normalize(LightPointFrom.xyz-LightPointTo.xyz).xyz));

float4 V = (EyePosition - Position.Sample(SamplText,Tex));
float3 R = reflect(Norm.xyz,normalize(LightPointFrom.xyz-LightPointTo.xyz).xyz);
float Specular = max(0.0f,dot(R,V));

float Shadow = Shadow1.Sample(SamplText,Tex).x;
float3 LightToVec = Position.Sample(SamplText,Tex) - LightPointFrom.xyz;
float LightToVecDist = length(LightToVec);

int ShadowValue = step(LightToVecDist/100.0f,Shadow);

return (Shadow) * TexC * ShadowValue;

}




It uses a simple Phong Shading.
In return statement i do a mul with shadow to make sense of where shadow was projected (as you can see from first image).
I'm just blocked here (and really do not know why, i really have got from 2 days a complete lapsus!!!!)

Thank you!

Share this post


Link to post
Share on other sites
Yep. That's what I thought. Your problem is thus:
float Shadow = Shadow1.Sample(SamplText,Tex).x;


You're sampling the shadow map from the wrong spot here; you need to plug the world-space position from this
Position.Sample(SamplText,Tex)


into the shadow VP matrix, then use the result for your texture coordinates for the shadow map sample after doing the W divide.

Also, why are you dividing the length by 100? This will screw up the comparison. D3D10 can also automate the test process for you by using one of the so-called 'comparison samplers' that were introduced.

Share this post


Link to post
Share on other sites
Sorry for no answers in these days but i've got a lot of exams at university.
Today i had 5 minutes and so i decided to make something.

I just modified the shader in order to follow your advices

float4 ps_draw(in float4 Pos:SV_POSITION, in float2 Tex:TEXCOORD) : SV_TARGET
{
float4 TexC = BaseColor.Sample(SamplText,Tex);
float3 Norm = 2.0f * Normal.Sample(SamplText,Tex).xyz - 1.0f;
float NdotL = max(0.0f,dot(Norm,normalize(LightPointFrom.xyz-LightPointTo.xyz).xyz));

float4 V = (EyePosition - Position.Sample(SamplText,Tex));
float3 R = reflect(Norm.xyz,normalize(LightPointFrom.xyz-LightPointTo.xyz).xyz);
float Specular = max(0.0f,dot(R,V));

float4 NewPos = mul(mul(Position.Sample(SamplText,Tex),ViewMatrix),ProjMatrix);
NewPos /= NewPos.w;

float Shadow = Shadow1.Sample(SamplText,NewPos.xyz).x;
float3 LightToVec = Position.Sample(SamplText,Tex) - LightPointFrom.xyz;
float LightToVecDist = length(LightToVec);

int ShadowValue = step(LightToVecDist/100.0f,Shadow);

return (Shadow) * TexC;

}




But i did not saw any good result. Now the shadow is displayed in strange way.
Even removing /100.0f there is the same result (obiously, it's not used in return value !!!).
Was it correctly?

Share this post


Link to post
Share on other sites
Quote:
Original post by XVincentX
Sorry for no answers in these days but i've got a lot of exams at university.
Today i had 5 minutes and so i decided to make something.

I just modified the shader in order to follow your advices
*** Source Snippet Removed ***

But i did not saw any good result. Now the shadow is displayed in strange way.
Even removing /100.0f there is the same result (obiously, it's not used in return value !!!).
Was it correctly?

You should be multiplying that point by the VP matrix you used to generate the *shadow map.*

This should make intuitive sense when you think about it; what you're interested in is where the point to be shaded lies on the 2D shadow map texture. Recall that multiplying a world-space point by your camera's VP matrix determines where it'll end up on your screen. Same general idea here :)

Share this post


Link to post
Share on other sites
I did it.
Result is still completely wrong


float4 ps_draw(in float4 Pos:SV_POSITION, in float2 Tex:TEXCOORD) : SV_TARGET
{
float4 TexC = BaseColor.Sample(SamplText,Tex);
float3 Norm = 2.0f * Normal.Sample(SamplText,Tex).xyz - 1.0f;
float NdotL = max(0.0f,dot(Norm,normalize(LightPointFrom.xyz-LightPointTo.xyz).xyz));

float4 V = (EyePosition - Position.Sample(SamplText,Tex));
float3 R = reflect(Norm.xyz,normalize(LightPointFrom.xyz-LightPointTo.xyz).xyz);
float Specular = max(0.0f,dot(R,V));

float4 NewPos = mul(mul(Position.Sample(SamplText,Tex),LightView),ProjMatrix);
NewPos /= NewPos.w;

float Shadow = Shadow1.Sample(SamplText,NewPos.xy).x;
float3 LightToVec = Position.Sample(SamplText,Tex) - LightPointFrom.xyz;
float LightToVecDist = length(LightToVec);

int ShadowValue = step(LightToVecDist/100.0f,Shadow);

return ShadowValue * TexC;

}




Projmatrix is the same
I'm really going crazy.

I tried also projecting shadow map in screen space

float4 PSpot2D = mul(mul(Position.Sample(SamplText,Tex),LightView),ProjMatrix);
float2 VTexC = float2(PSpot2D.x/PSpot2D.w * 0.5f + 0.5f,-PSpot2D.y/PSpot2D.w * 0.5f + 0.5f);


[Edited by - XVincentX on June 18, 2009 2:12:24 PM]

Share this post


Link to post
Share on other sites
Quote:
Original post by XVincentX
I did it.
Result is still completely wrong

*** Source Snippet Removed ***

Projmatrix is the same
I'm really going crazy.

I tried also projecting shadow map in screen space

float4 PSpot2D = mul(mul(Position.Sample(SamplText,Tex),LightView),ProjMatrix);
float2 VTexC = float2(PSpot2D.x/PSpot2D.w * 0.5f + 0.5f,-PSpot2D.y/PSpot2D.w * 0.5f + 0.5f);


Screenshots are helpful, and I'm still convinced you don't need that extra division by 100.

Share this post


Link to post
Share on other sites
There are moments when nobody can help you and your shader code doesn't work -> Its time to use PIX and try to debug this shader.

I think that trying random changes in not working code isn't going help. Here is great tutorial how to debug shaders : Debugging Shaders

Looking at your shader code I couldn't see anything wrong so I suppose there's error somewhere else. Are you sure you're calculating everything in the same space?
This division by 100 is necessary only if you are writing depth to your shadow map like this : (PosInLight - PosOfLight) / 100.0f; Because you have to use the same method for estimating depth for position and for writing to shadow map. Also maybe you can try using some shadow epsilon in function step(). In my case shadows were very sensitive to that.

Share this post


Link to post
Share on other sites
Thank you again for all your answers.
For now, please, do not look these problems (/100.0f, or epsilon in step function) becouse the problem is not there.
Look at shader's code return.


return (Shadow) * TexC;


TexC is BaseColor and Shadow is the sample from shadow map. What i'm doing now (only for test purposes) is to project shadow with the scene to understand where map is placed in comparision to scene.

And, it is not right, so the problem it's above.
I think screenshot won't help becouse they are completely without sense.
However, you're the boss here :)

Using original texcoords:
http://img44.imageshack.us/img44/4048/porcesco.jpg

with this code:

float4 PSpot2D = mul(mul(Position.Sample(SamplText,Tex),LightView),ProjMatrix);

float Shadow = Shadow1.Sample(SamplText,PSpot2D).x;


http://img14.imageshack.us/img14/2521/67551848.jpg

using this other one

float4 PSpot2D = mul(mul(Position.Sample(SamplText,Tex),LightView),ProjMatrix);

float2 VTexC = float2(PSpot2D.x/PSpot2D.w * 0.5f + 0.5f,-PSpot2D.y/PSpot2D.w * 0.5f + 0.5f);
float Shadow = Shadow1.Sample(SamplText,PSpot2D).x;


http://img15.imageshack.us/img15/1271/51704351.jpg

Remember: THESE are NOT results of Shadow Lookup and comparision with camera distance. It' JUST a projection of Depth surface on the screen in order to verify it's position in comparision with original scene.
Really going crazy.

Share this post


Link to post
Share on other sites
code for sampling shadowmap should this look like:

float4 PSpot2D = mul(mul(Position.Sample(SamplText,Tex),LightView),ProjMatrix);

float2 VTexC = float2(PSpot2D.x/PSpot2D.w * 0.5f + 0.5f,-PSpot2D.y/PSpot2D.w * 0.5f + 0.5f);

float Shadow = Shadow1.Sample(SamplText,VTexC).x; // You were not sampling with proper texcoord.

Share this post


Link to post
Share on other sites

This topic is 3092 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.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this