Transform into Light Space?

Started by
6 comments, last by Funkymunky 12 years, 9 months ago
I'm currently working on Perspective Shadow Mapping. I'm at the point where I want to transform the camera frustum corners into light space, so that I can call glOrtho to create the optimal projection matrix. How do I actually do that, though? I have calculated the world space locations of the frustum corners, and I have a modelview matrix for the light space (created via gluLookAt). How do I then "transform" these points by this matrix, such that they will be accurate in "Light Space"?

Is it simply multiplying a vector by a matrix, ie

Vector:
x, y, z

Matrix:
a, b, c, 0,
d, e, f, 0
g, h, i, 0
0, 0, 0, 1

Resulting Vector:
ax + by + cz, dx + ey + fz, gx + hy + iz

...?
Advertisement
A transformation matrix will transform a 3D position vector from one coordinate space to another, if you perform matrix multiplication. This is exactly what happens in your standard rendering pipeline when when rendering triangles: you multiply the vertex positions of the triangles by one or more transformation matrices that take you from object space, to world space, to view space, to clip space in one or more steps. Using gluLookAt creates a matrix that performs the inverse of the transformation specified by the position and direction supplied. So if you supply world-space camera position and direction, you get a matrix that transforms from world space to view space. By the same token if you supply the position and direction of a light, you get a matrix that transforms from world space to light space.

Note that in your example you can't transform a 3-component vector by a 4x4 matrix. Either you have to truncate the matrix to 3x3, or you have to extend the vector to 4 components. Typically this is done by adding a 0 or a 1. Using a 0 will cause the 4th column of the matrix (or row, if using row-major matrices) to essentially have no effect. Since the 4th column typically contains the translation of the transformation, adding a 0 will cause only rotation and scaling to be applied to the vector. Adding a 1 will allow translation to occur. For this reason it's common to use a 0 for direction vectors, and a 1 for position vectors.

If you're not already, I strongly suggest that you use a proper math library that has support for common matrix/vector math operations.
I'm currently working on Perspective Shadow Mapping.

Do you mind if I ask why you are choosing to implement perspective shadow maps (instead of just using cascades)?

Do you mind if I ask why you are choosing to implement perspective shadow maps (instead of just using cascades)?


Every where I go to look up information about shadow mapping, someone says "I started to implement PSM but decided to just go with CSM/PSSM/etc." Maybe I just don't understand the techniques, but it seems like the fundamentals of PSM are used in CSM/PSSM/etc. I'm trying to get the basics down before I move on to the more advanced techniques, since they'll be necessary to get them working anyway. I certainly don't want to just use PSM, because of the various issues with it, but I didn't think I could do those other techs without first implementing PSM.

...?
it seems like the fundamentals of PSM are used in CSM/PSSM

Sort of. CSM/PSSM can be viewed as a discretization of Perspective Shadow Maps.

I'm trying to get the basics down before I move on to the more advanced techniques

CSMs were proposed after PSMs were, but that doesn't mean that they are more complex.

I would say that Cascaded Shadow Maps are easier to implement than Perspective Shadow Maps.

In my opinion, you should just implement CSMs.


Do you have regular shadow mapping implemented?

I would say that Cascaded Shadow Maps are easier to implement than Perspective Shadow Maps.

In my opinion, you should just implement CSMs.


Do you have regular shadow mapping implemented?


Yes, I have the whole system of rendering the depths to a texture, supplying a matrix to the shader so as to sample the correct location from the light's POV to render shadows. It's pretty much just the perspective aspect of it that I'm working on now.

I still don't see how cascaded shadow maps would be easier to implement; It seems like they're the same thing as PSM, except you split the frustum up and perform multiple renders to reduce aliasing.
I still don't see how cascaded shadow maps would be easier to implement; It seems like they're the same thing as PSM, except you split the frustum up and perform multiple renders to reduce aliasing.


For cascades with one split, you just do the exact same thing as regular shadow mapping, except you do it twice for two different frustums. Then supply a matrix as you normally would for the first shadow map frustum, plus a second matrix for the next frustum, and the depth of the split in the light shader.

Drawing the shadow map is exactly the same, you just do it twice, once for each frustum.

Reading from the shadow map when rendering the light is exactly the same as before except if(depth < splitDepth) do the normal shadow mapping as you always do, else do the shadow mapping that you always do with the second matrix instead.

So as you can see, it's very simple with very few changes to your existing implementation (we're talking about ~6 lines of shader code, and maybe a dozen lines of CPU side code for the basic implementation). Culling objects correctly is very simple because you are just doing a frustum-object test for each object to draw into the shadow map as normal.
Isn't that essentially doing PSM with multiple frustums?

(coincidentally, I got PSM working)

This topic is closed to new replies.

Advertisement