Polar Projection Shadow Maps

Started by
12 comments, last by Hodgman 12 years, 4 months ago
Has anyone ever tried using spherically projected shadow maps for point lights?

You would subdivide the geometry surrounding the light up so the projection is more accurate, then project the depth from the subdivided scene onto a single depth map instead of throwing 6 regular shadow maps at it. It just seems wasteful.

I'd be interested in seeing how bad the artifacts are, and if the extra computation would even be worth it. It might be worth it for static scenes, but I don't think it would handle lots of dynamic objects very well.  
Advertisement
To my knowledge, yes. But I don't remember what the problem with it was. Regardless the "popular" thing to do is still a cubemap, but with the geometry shader you can do it in a single pass anyway.
This is a similar idea to the dual-paraboloid map (which is basically two hemispheres). It has the same problem that the projection is not linear, so there are major artefacts on meshes that aren't tessellated enough. On DX11, you can use the hardware tessellator to help with this.

With a single spherical projection, the distortion at the poles becomes extreme, and I would expect there to be quite major artefacts, even with well-tessellated meshes.

This is a similar idea to the dual-paraboloid map (which is basically two hemispheres). It has the same problem that the projection is not linear, so there are major artefacts on meshes that aren't tessellated enough. On DX11, you can use the hardware tessellator to help with this.

With a single spherical projection, the distortion at the poles becomes extreme, and I would expect there to be quite major artefacts, even with well-tessellated meshes.


That was it! There was a paper based on spherical projection and the where the poles met up looked awful, terrible artefacts. That's also why the cubemap is the most preferred (if you can do it in a single pass versus the normal 6). Overall it has the least obvious amount of distortion.


How would you do the shadow map in a single pass with a geometry shader anyway?

How would you do the shadow map in a single pass with a geometry shader anyway?


For every input primitive, a geometry shader can output 0, 1, or multiple primitives. So it can take 1 triangle, and 6 triangles that are transformed for each cubemap face. Then you can combine this with render target arrays and SV_RenderTargetArrayIndex to have each triangle get rasterized to the corresponding face of the cubemap.

I wouldn't really recommend it though...it sounds nice on paper but in practice using a geometry shader can really hurt your GPU performance.

[quote name='magicstix' timestamp='1323655415' post='4892963']
How would you do the shadow map in a single pass with a geometry shader anyway?


For every input primitive, a geometry shader can output 0, 1, or multiple primitives. So it can take 1 triangle, and 6 triangles that are transformed for each cubemap face. Then you can combine this with render target arrays and SV_RenderTargetArrayIndex to have each triangle get rasterized to the corresponding face of the cubemap.

I wouldn't really recommend it though...it sounds nice on paper but in practice using a geometry shader can really hurt your GPU performance.
[/quote]

Sure sure, but you're not doing that much really. It's not like your trying to do some sort of tessellation or other things that just end up being too expensive. In theory this still sounds good, but I don't know of any game that's implemented it yet. It would be nice to check some real game scenarios and see if it's actually faster to just have a single pass and render target or do a point light shadowmap a more traditional way.


http://www.gamedev.net/page/reference/index.html/_/technical/graphics-programming-and-theory/cube-map-rendering-techniques-for-direct3d10-r2735
The performance of a GS is inversely proportional to the output size (in scalars) declared in the Geometry Shader, which is the product of the vertex size and the number of vertices (maxvertexcount). This performance degradation however occurs at particular output sizes, and is not smooth. For example, on a GeForce 8800 GTX a GS that outputs at most 1 to 20 scalars in total would run at peak performance, whereas a GS would run at 50% of peak performance if the total maximum output was declared to be between 27 and 40 scalars.[/quote]^^ The performance impact of using a GS to amplify input data depends on the size of the data structure AND the amount of amplification.
If you've got small vertex structs (e.g. just position and normal), it will run well. If you've got large vertex structs (e.g. pos, normal, tangent, uv0, uv1, joint indices, joint weights, etc...), then it will run poorly. If you're creating 1 output for every 1 input, it will run well. If you're creating 6 outputs for every 1 input, it will run poorly.

Rendering cube-maps in 1 pass via a GS is a CPU optimisation -- you're reducing the amount of work that the CPU has to do (less draw-calls), but you're increasing the GPU's workload.

If your game is CPU-bound, this is a good idea. If your game is GPU-bound, this is a bad idea.

[quote name='MJP' timestamp='1323659349' post='4892976']
[quote name='magicstix' timestamp='1323655415' post='4892963']
How would you do the shadow map in a single pass with a geometry shader anyway?


For every input primitive, a geometry shader can output 0, 1, or multiple primitives. So it can take 1 triangle, and 6 triangles that are transformed for each cubemap face. Then you can combine this with render target arrays and SV_RenderTargetArrayIndex to have each triangle get rasterized to the corresponding face of the cubemap.

I wouldn't really recommend it though...it sounds nice on paper but in practice using a geometry shader can really hurt your GPU performance.
[/quote]

Sure sure, but you're not doing that much really. It's not like your trying to do some sort of tessellation or other things that just end up being too expensive. In theory this still sounds good, but I don't know of any game that's implemented it yet. It would be nice to check some real game scenarios and see if it's actually faster to just have a single pass and render target or do a point light shadowmap a more traditional way.

[/quote]

I recommend you try it...the results may surprise you. I tried it with 4 shadow cascades and it wasn't anywhere close to being worth it.

[quote name='Frenetic Pony' timestamp='1323736816' post='4893328']
[quote name='MJP' timestamp='1323659349' post='4892976']
[quote name='magicstix' timestamp='1323655415' post='4892963']
How would you do the shadow map in a single pass with a geometry shader anyway?


For every input primitive, a geometry shader can output 0, 1, or multiple primitives. So it can take 1 triangle, and 6 triangles that are transformed for each cubemap face. Then you can combine this with render target arrays and SV_RenderTargetArrayIndex to have each triangle get rasterized to the corresponding face of the cubemap.

I wouldn't really recommend it though...it sounds nice on paper but in practice using a geometry shader can really hurt your GPU performance.
[/quote]

Sure sure, but you're not doing that much really. It's not like your trying to do some sort of tessellation or other things that just end up being too expensive. In theory this still sounds good, but I don't know of any game that's implemented it yet. It would be nice to check some real game scenarios and see if it's actually faster to just have a single pass and render target or do a point light shadowmap a more traditional way.

[/quote]

I recommend you try it...the results may surprise you. I tried it with 4 shadow cascades and it wasn't anywhere close to being worth it.
[/quote]

Not talking about cascades, and cloning all that geometry. I know that doesn't work. But I do remember running some code a while ago and I got better results, but it wasn't an actual game scene and was just against a naive implementation of a multipass cubemap.

This topic is closed to new replies.

Advertisement