Shadow mapping help

Started by
15 comments, last by solinent 15 years, 5 months ago
I have implemented shadow mapping in my engine, and I understand the basic principles, however I have some problems: 1) My game is a car game, and cars travel far. I was hoping to have shadows for long distances (2km (1 opengl unit is a meter for me) approx.). When I render the depth map, I only render looking at the origin, so its impossible for me to also render the car, unless I make the perspective really wide (like 160 degrees viewing angle from the light). If I do this, then I lose resolution, and I get huge aliasing (obviously). How does one render a pont light, or even a directional light long-range? 2) I think the solution to #1 would be PSM, and I don't mind rendering only close to the car, because I only want dynamic shadows on the car, for the environment I could use static or pre-baked lighting (if I figure it out). If PSM (perspective shadow mapping) is the solution, then does anyone have a good resource other than the paper (goes over my head) for understanding how opengl does perspective transforms, and what this "unit cube" everything I read is talking about? I can't find (don't know where to look) a good resource for learning how perspective transformations are used in opengl. Thanks! PS: I was thinking of a simple idea where I would use a directional light (so orthographic projection) to render the lightmap from an offset of the car's position so that no clipping happens, but I don't know how I would correctly set up glOrtho and use it with gluLookAt, or why I haven't read about this (maybe because it may not shadow other objects?).
Advertisement
Read about PSSM (Parallel-Split Shadow Maps). The main idea is to use, for example 3 shadow maps - one works for objects near the camera, the second for those in larger distance, and the third works for thos that are far away from camera. You could combine this with VSM (Variance Shadow Maps; very easy to implement) and have quit fast and nice-looking sun shadows.
As for PSSM, many game use them today. So far I have noticed Crysis, Assassin'Creed, Call of Duty 4 use it.
That's interesting, Ill definitely implement it once I understand it!

From what I understand: you split the scene based on some heuristic, and then I get lost.

It's not a surprise, since I have no clue as to how glFrustum works (I use gluPerspective), and would love to know, however everything I see doesn't explain it well. Could you possibly point me to somewhere that does?
PSSM or PSM is not a solution for your first question. You need at least to focus the shadow map on the current view frustum, so You will render into the shadow map only the relevant stuff. There is no point in redering shadows for something what isn't visible :). For focusing, just see "Parallel-Split Shadow Maps" by Zhang at al. and/or "Light Space Perspective Shadow Maps" by Wimmer et al.

About VSM, IMHO it isn't very useful, as it introduces some artifacts and requires additional GPU power.

About perspective matrix (the one build by the gluPerspective), just read some math/graphic programming book. Like "3D Math Primer for Graphics and Game Development" or "Real time rendering".

[Edited by - krisiun on November 15, 2008 1:46:27 PM]
Quote:
About VSM, IMHO it isn't very useful, as it introduces some artifacts and requires additional GPU power.

It indeed is a lot useful. Light-bleeding isn't a big problem - at first you may just cut off "the tail" from variance. Besides Lauritzen writes about (GPU Gems 3) Summed-Area VSM which gives great results and no artifacts.

Quote:
Could you possibly point me to somewhere that does?

Lets forget about any other than of light than the sun :). So, you have sun. You use gluLookAt and put it somewhere on the scene. Then you use glOrtho (not gluPerspective) to create projection for parallel light (sun is actaully parallel light for us). And right now you can, for example multiply this matrix by, for example, scale matrix (10, 10, 10). After this every object in the shadow map will get larger (you get better shadows quality). Some of them will disappear because of that. You may also want to do a translation of the shadow map to and center the look at camera position. This translation and scaling allows you to "focus" the shadow map.
I realize it is not easy at the beginning and you get confused - everyone gets :P. I would advice you to start here [http://developer.download.nvidia.com/SDK/10.5/opengl/src/cascaded_shadow_maps/doc/cascaded_shadow_maps.pdf] (Cascaded Shadow Maps == Parallel-Split Shadow Maps). Try to understand whats going on with this focusing and try to implement shadow map tracing the camera position (because that's what we want - focus the shadow map at the area close to the camera).
At first try to derive a standard shadow map matrix, and after gluLookAt and glOrtho, multiply it by:
1. glScale(5, 5, 5)
2. glTranslate(0.5, 0, 0)
See how shadow map will look after one of these additional transformations
Ok, I'll try to combine your description with my knowledge later, for now I'm thinking about VSM, since it seems easier (and looks very nice).

I've come up with a solution for the resolution of the shadow map, that will work as long as I only have shadows for one object at a time :), but I will implement PSSM later when I finish the physics behind my game (I didn't expect shadow algorithms to be so complex, its alot easier in a raytracer). (I just render an orthogonal light and keep it looking at the car at the same angle).

I'm going to try doing VSM, and I found a great thread on VSM here.

I understand it, just need to worry about how to actually render into the shadow map the depth and depth squared values. Right now I'm using DEPTH_COMPONENT FBO which handles this all for me, but I guess I'll need to encode the info in a color texture.

Thanks for the help!


edit

I think I understand your description, scaling objects doesn't affect the orthographic projection. So the rest is simply spliting the view and find the specific scaling in order to keep everything in view, then sample that depth texture. It makes more sense now.

edit2

I think I've realized a way to do the depth thing, use glsl shader to render depth values to r, and depthsquared values to g. Only problem is that how do I find the depth values? I just looked it up, and it seems gl_FragCoord.z is the answer I want! So I just gotta render gl_FragCoord.z to r, and gl_FragCoord.z^2 to g, and the texture I render should contain the proper stuff. Time to try it!

[Edited by - solinent on November 15, 2008 8:17:52 PM]
Certainly Parallel-Split Shadow Maps aka Cascaded Shadow Maps are a great and simple solution to resolution problems.

Quote:Original post by solinent
I think I've realized a way to do the depth thing, use glsl shader to render depth values to r, and depthsquared values to g. Only problem is that how do I find the depth values? I just looked it up, and it seems gl_FragCoord.z is the answer I want! So I just gotta render gl_FragCoord.z to r, and gl_FragCoord.z^2 to g, and the texture I render should contain the proper stuff. Time to try it!

That should work, but you can also just pass the light space position (i.e. "view space" of the light) into the fragment shader, then evaluate whatever depth metric you want. For instance, length(PosInLightSpace) or just PosInLightSpace.z.

There's sample code on the GPU Gems 3 DVD if you have access to that. It's DirectX, but the concepts are the same in OpenGL.

Also just a side note, if you run into any problems with light bleeding, you can look into "Exponential Variance Shadow Maps"... as small variation on VSMs that almost completely eliminates any light bleeding and has fewer artifacts than pretty much any shadow filtering technique out there currently. More info in my thesis here and some discussion in the thread here.

Cheers,
Andrew
Great, it works (some problems that I have right now will be solved when I figure out PSSM).

I want to do soft shadows now, but I can't figure out how to blur the opengl texture. I guess that's beyond the scope of this forum though?

EDIT: Yeah, sounds good andy, I'll probably implement PSSM. I'm going to uwaterloo next year, hopefully!
Quote:Original post by solinent
Great, it works (some problems that I have right now will be solved when I figure out PSSM).

The aforementioned sample code actually includes a simple implementation of PSSM + VSM as well. It also has blurring code to do edge softening.

Quote:Original post by solinent
EDIT: Yeah, sounds good andy, I'll probably implement PSSM. I'm going to uwaterloo next year, hopefully!

Cool! It's a good school :)
Quote:Original post by AndyTX
Quote:Original post by solinent
Great, it works (some problems that I have right now will be solved when I figure out PSSM).

The aforementioned sample code actually includes a simple implementation of PSSM + VSM as well. It also has blurring code to do edge softening.

Quote:Original post by solinent
EDIT: Yeah, sounds good andy, I'll probably implement PSSM. I'm going to uwaterloo next year, hopefully!

Cool! It's a good school :)


I have no books, it's just me and the computer screen.

In all honesty, I've always found resources online and never had to refer to books for most things. I don't really have much of a budget, with me buying all these games :)

I would understand how to do blur on an image if I had the pixels, but blurring a vram texture is another thing. Do I really have to retrieve the texture, blur it, then upload it, or is there a way to iterate over the texture with a pixel shader?

This topic is closed to new replies.

Advertisement