Perfect resolution shadow maps

Started by
14 comments, last by Krohm 12 years, 6 months ago
Morning everyone.. My first topic for a good year or so, after a break from my engine I've reignited the passion and I'm revisiting some code.

I thought the topic title might get some attention but it's only a theory. Whilst not working on my engine I've had several ideas for various thing but I kept coming back to the problem of shadow maps and shadow map resolution near the camera. I've done a little research on perspective and trapezoidal shadow maps and with my limited math, they're similar but still talk of resolution issues (I'm talking about directional lights, eg the sun).

I've implemented cascaded shadow maps in my engine which I'm relatively pleased with but there are still resolution issues and I feel it's computationally very expensive what with all the light frustums, multiple scene draws, etc
So how about a one-to-one correlation between every single drawn pixel in the camera view and a pixel from a shadowmap that represents the depth from the sun to that point in perspective space. It sounds like any other shadow map right away, but if my overall view resolution is 1920x1200, why can't my shadow map be 1920x1200 with every pixel representing a depth value to the sun for every pixel in the final drawn image.

Surely this way there would be zero resolution issues? My engine is pretty nice at the moment, framework-wise, but my matrix math isn't that great. I can see the theory I'm just not sure if it can be implemented.

Any views?
Advertisement
Your shadow map requires a completely different projection compared to the camera used for rendering the scene, it's impossible to them both map to the same texels when rasterizing. Techniques like cascaded shadow maps and trapezoidal shadow maps attempt to reduce the perspective aliasing that results from having two different projections, but they obviously don't fix it completely.

I always thought that this was a pretty interesting approach, but haven't gotten around to expierimenting with it muself.
Trace the frustum formed by a single screen pixel into your scene. As it intersects a wall that is close to the camera, let's say the frustum is 1cm across, but as it continues and intersects with a wall that is far away, the pixel's frustum is now 10cm across.
When trying to form a projection for the shadow map that perfectly matches screen-space, the world-space sizes of each shadow-texel are random with respect to each other. One texel might cover 1cm, the next 100cm, the next 1mm... No linear projection can cope with that.

Some papers that might be of interest though:
"Pixel Accurate Shadows with Shadow Mapping"
"Resolution-Matched Shadow Maps"
"Pixel-Correct Shadow Maps with Temporal Reprojection"
"Adaptive Shadow Maps"
"Dynamic Adaptive Shadow Maps on Graphics Hardware"
Thanks for the quick responses... Hodgman, I understand what you're saying but if you render your scene depth only from the eye position, in a shader you can calculate the original world position of every single pixel. So if you have the wall at 100m away, the pixel on the wall in the depth buffer (from eye position), is still effectively a pixel (in screen space) as well ad a definite position in space. All you need to do then is to look up that position in a same-sized shadow map.

Think of view post projection space as orthogonal screen space and it's easier to conceptualise it. From the eye positon's depth map, you basically have access to every single viewable pixel's world position. I'm sure you must be able to map that exactly to a pixel in the shadow map. If you render the shadow map from the light position, every single pixel in it would correlate to each world position that is being viewed from the eye position.

Does that make any sense?
Your idea is too simple to work. If it would be that simple, I had been already invented long ago.

"So if you have the wall at 100m away, the pixel on the wall in the depth buffer (from eye position), is still effectively a pixel (in screen space) as well ad a definite position in space. All you need to do then is to look up that position in a same-sized shadow map"

You can't transform the screen coordinates of all fragments to SM coordinates or (the opposite way) with a single transformation. You'd need different transformations for every single pixels (and you'd have to render the whole scene's depth into that pixel). That is almost ray-tracing.

"Think of view post projection space as orthogonal screen space and it's easier to conceptualise it. From the eye positon's depth map, you basically have access to every single viewable pixel's world position. I'm sure you must be able to map that exactly to a pixel in the shadow map. If you render the shadow map from the light position, every single pixel in it would correlate to each world position that is being viewed from the eye position."

Imagine the points that have "definite positions in space". Now rotate that point-cloud. The only position from where the point-cloud looks like a perfectly filled rectangle again is the camera's position. All other views (like a general light-view) will be totally random, lots of points overlapping, lots of empty spaces etc.

Just think about it, you basically say that always the same pixels are visible from any arbitrary position.
"You can't transform the screen coordinates of all fragments to SM coordinates or (the opposite way) with a single transformation. You'd need different transformations for every single pixels (and you'd have to render the whole scene's depth into that pixel). That is almost ray-tracing."

Why not? If you can easily map a screen pixel back to its original world position with one transformation (as long as you have depth) I would have thought it possible to then map that world position into the shadow map? We just need a transformation matrix that draws a shadow map containing depth pixels representing the world position of every visible pixel in the eye position screen.

I can see the theory I just don't know if the transformation is possible.
... I understand what you're saying but if you render your scene depth only from the eye position, in a shader you can calculate the original world position of every single pixel. So if you have the wall at 100m away, the pixel on the wall in the depth buffer (from eye position), is still effectively a pixel (in screen space) as well ad a definite position in space. All you need to do then is to look up that position in a same-sized shadow map.
...
I'm sure you must be able to map that exactly to a pixel in the shadow map.
...
If you render the shadow map from the light position...
Yes, you can map every 1 screen pixel to a unique pixel a shadow map of the same resolution. This is as easy as stating shadow.UV == screen.UV. Now, the bit you missed is that this is a non-linear mapping, and thus you can't render from the light's perspective using a linear projection matrix that performs this mapping.
Yes, there are methods to make this work, but there is simply no way to perform that mapping with your usual type of matrices.

For example, take this input data-set and the outputs we wish to transform it into:
Inputs: 1,2,3,4,5
Desired Outputs: 6,8,10,12,14

Expressing this transformation is simple: out = (in-1)*2+6

Now, take this data-set:
Inputs: 1,2,3,4,5
Outputs: 100, 42, 76, 0, 3

...and construct a linear equation that performs the mapping
There may be a transformation, just a very huge and nasty non-linear one (or maybe a 1920x1200x16 matrix?), that needs to be recomputed every time something changes. A simple ray-casting seems to be a simpler and faster solution.

Did you rotate/scale/skew/translate/whatever mentally the point-cloud (fragments) I mentioned?
Even if you could reorder the fragments to form a perfectly filled rectangle again in light-space, I'll say it, no such single transformation (that is usable in any ways) exist, that defines that reordering for every fragments.
Do you understand why that reordering is needed? Do you understand that every single fragment needs to be reordered uniquely?

AFAIK the only way to do perfect resolution shadow mapping for general purpose is ray-casting (or similar, render the scene's depth in light space for every single pixels on screen). (and that nasty non-linear transform I mentioned in the first paragraph would basically do the same)
Ok... I see that now. It's frustrating not being able to visualise it so well mathematically. My idea was more like drawing the shadowmap using values from the eye position's depth buffer. Every world pixel (which let's say is the world position of every pixel seen in eye's view). I get that if you visualise it as a point cloud, from the eye camera's point of view, it's a square (i.e. the view panel), but from the light's perspective it would be from a different angle, but even from that angle, each point in the 1920x1200 point cloud has a direct line to the light source, regardless of whether lots of points lie on the same line - the shadow map would just look very skewed to the human eye.

I thought there just might be some matrix math we could do when drawing the shadow map to map each pixel to the world coordinate of the screen pixel - obviously not.

I may just not be explaining myself very well but it's so close to effectively what perspective shadow maps do that I thought it would be possible. Thanks for the input guys.
Yes, I see it clearly now. And there's me thinking matrices can do anything...

Thanks very much for all the detailed responses, back to the drawing board.

This topic is closed to new replies.

Advertisement