shadow mapping questions

Started by
7 comments, last by Yours3!f 11 years, 10 months ago
Hi,

I'm planning to implement some kind of shadow mapping, but I'm completely noob in this topic. I've read quite a few articles (including the wikipedia :) ) and I think I understood most of the stuff involved in this. I'm planning to include this into my already working deferred shading rendering.

So in my understanding to do shadow mapping I have to do the following steps:

Shadow map generation:

For point lights:
-render the scene from 6 angles, and from the middle of the light source, culling objects that are further than the radius of the point light (set far plane to that maybe? and near to the light bulb's surface?)
-this has to be done with perspective projection with camera angle of 45 degrees

For spot lights:
-render the scene from 1 angle, from the beginning of the spot light, culling objects that are further than the end of the spot light, again set near and far plane as for point lights
-again perspective projection, but what camera angle should be used? the spot lights have a cutoff angle, should I use that?

For directional lights:
-render the scene from 1 angle, no culling
-this time using orthographic projection, but what values should I use?

for all the above steps I should only render to the depth buffer, using only a vertex shader.

Shadowing pass:

For all shadow maps:
-render the scene from the viewer's point of view (done in the deferred pass).
-in the fragment shader use the depth information to calculate NDC coordinates in range [0..1], and use this to sample the shadow maps
-compare the scene's NDC z value (in range [0...1]) with the normalized depth values that were sampled from the shadow maps
-if the normalized depth value is greater than, or equals the z value then discard that pixel, else write 1 to the generated "final" shadow map, that I can use in the deferred lighting pass to decide if for the given pixel lighting should be calculated or not.

Is this a correct way of going about this? I know it doesn't include any filtering or cascading or such, but for now I just want basic shadowing.
Advertisement
You can always cull, and should. So for directional shadows, you still cull. Now if its a huge sun and it wraps around your whole scene, then nothing would be culled, but first:
A shadow map that big will not work anyway. Usually a local shadow map is applied that covers a portion of the scene around the player. With cascading, you will have the local shadow map + some other ones for shadows far away.

Forget the technical NDC stuff. If you are doing deferred, an point in the real world snapshot can be described relative to you(camera), an airplane, the sun etc. So when drawing deferred from the camera, you take that pixel and put it relative to the sun. If something in the suns view is closer/blocking that point, its shadowed.

You still need a pixel shader. just make it a single line that writes whatever color. Also turn of color writing so that the pixel strictly writes depth only. glColorMask I believe is the function you want. If you have used shaders its really simple to make a shadow map.

NBA2K, Madden, Maneater, Killing Floor, Sims http://www.pawlowskipinball.com/pinballeternal


You can always cull, and should. So for directional shadows, you still cull. Now if its a huge sun and it wraps around your whole scene, then nothing would be culled, but first:
A shadow map that big will not work anyway. Usually a local shadow map is applied that covers a portion of the scene around the player. With cascading, you will have the local shadow map + some other ones for shadows far away.
[/quote]
Ok, so I plan to use the directional light as the sun, so it affects everything. So as you say implementing cascading later will solve this problem, so I think I won't deal with it now, only when I implement cascading.


Forget the technical NDC stuff. If you are doing deferred, an point in the real world snapshot can be described relative to you(camera), an airplane, the sun etc. So when drawing deferred from the camera, you take that pixel and put it relative to the sun. If something in the suns view is closer/blocking that point, its shadowed.
[/quote]

So are you suggesting transforming the given pixel to the sun's (light's) view space? How do I do that?


You still need a pixel shader. just make it a single line that writes whatever color. Also turn of color writing so that the pixel strictly writes depth only. glColorMask I believe is the function you want. If you have used shaders its really simple to make a shadow map.
[/quote]

thanks, I wasn't aware of that.
So are you suggesting transforming the given pixel to the sun's (light's) view space? How do I do that?[/quote]

The sun is just another camera that renders objects and uses depth testing. So get a camera setup where you want the sun to be. First to debug, set your camera to the sun camera so that you can verify it is above your scene and rendering properly.

So the theory is you render a pixel from the viewer, that pixel has a 3d position. You take that pixels and (re-render) it into the suns depth buffer. Is there something already closer to the sun? Then this is in shadow because there is something between that pixel and the sun. When I say re-render what really happens is u just take the pixels depth, convert it to what its depth would be relative to the sun, and then sample the suns depth buffer and compare.

NBA2K, Madden, Maneater, Killing Floor, Sims http://www.pawlowskipinball.com/pinballeternal


So are you suggesting transforming the given pixel to the sun's (light's) view space? How do I do that?


The sun is just another camera that renders objects and uses depth testing. So get a camera setup where you want the sun to be. First to debug, set your camera to the sun camera so that you can verify it is above your scene and rendering properly.

So the theory is you render a pixel from the viewer, that pixel has a 3d position. You take that pixels and (re-render) it into the suns depth buffer. Is there something already closer to the sun? Then this is in shadow because there is something between that pixel and the sun. When I say re-render what really happens is u just take the pixels depth, convert it to what its depth would be relative to the sun, and then sample the suns depth buffer and compare.
[/quote]

so just map the viewers depth values to the sun's using some matrix tricks, then do simple compare, right?
Drawing to a camera:
CameraProjection1*CameraView1*Model*gl_Vertex;
CameraProjection2*CameraView2*Model*gl_Vertex;

In GL CameraView*Model is combined to one matrix, so you need to extract it for the shadow camera. For each model you draw you construct a single matrix:

ShadowCameraProjection2*ShadowCameraView2*Model;
You can pass this to your shader as a uniform. So you have the same vertex in the world, but then the thing that changes is how it would display on each camera's screen. So you transform and do your shader normal, just add in a "Vec3 shadowMapPos = shadowMatrix*gl_Vertex;

Then you use that as your texture coord to look up into the shadow map, because after projection this fragment is a pixel that has a x,y position in the shadow map.
shadow2DProj(shadowMapPos);

One thing to note, glTexParameter CLAMP_TO_BORDER, and set a border color to 1,1,1,1. Just look it up. This will make is so that anything 3d point that you can see that is outside of the what the sun can see, will not be all black.

NBA2K, Madden, Maneater, Killing Floor, Sims http://www.pawlowskipinball.com/pinballeternal

thank you, I think I now understand it :)
one more question, is shadow2DProj the same as textureProj? I didn't find shadow2DProj in the 4.2 GLSL spec.
should, i'm not sure what the difference was in the original spec.

NBA2K, Madden, Maneater, Killing Floor, Sims http://www.pawlowskipinball.com/pinballeternal

well, thank you for the help, I'm currently rewriting libmymath so that it is more usable, then I'll proceed to implement shadow mapping with culling.

This topic is closed to new replies.

Advertisement