Deferred shadow map.

Started by
18 comments, last by XVincentX 14 years, 9 months ago
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.
Advertisement
Generating the shadowmap shouldn't change. Are you having trouble to calculate the shadow occlusion in the deferred lighting pass?
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.
There's no "hard", and "the impossible" takes just a little time.
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.
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
clb: At the end of 2012, the positions of jupiter, saturn, mercury, and deimos are aligned so as to cause a denormalized flush-to-zero bug when computing earth's gravitational force, slinging it to the sun.
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.
There's no "hard", and "the impossible" takes just a little time.
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!
mmm
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.
clb: At the end of 2012, the positions of jupiter, saturn, mercury, and deimos are aligned so as to cause a denormalized flush-to-zero bug when computing earth's gravitational force, slinging it to the sun.
I'm making the 100 division in order to clamp values in far clip range.

I will try your suggestions.

This topic is closed to new replies.

Advertisement