Modern approach for rendering hard shadows?
category: code [glöplog]
I want to render high quality dynamic, hard shadows and was wondering what is the best approach to do it on semi-modern hardware (I'm targetting OpenGL 3.3/DX10 GPUs).
Basically I have two types of scenes:
- Large outdoor environment with kinda high-poly terrain and single directional light (sun).
- Small closed environments with many point lights.
The possible approaches I can think of are:
- Shadow volumes for either point lights or everything (with shadow shilouette generation offloaded to a geometry shader).
- Cubemap omni-directional shadow maps for point lights.
- Cascaded shadow maps for the sun in the outdoor scene.
I'm worried that I will end up with more or less pixelated/blurry shadow edges when using shadow maps. On the other hand the high-poly terrain might be a performance hog for shadow volumes due to shilouette generation.
What would be your approach on this? Any suggestions?
Thanks.
Basically I have two types of scenes:
- Large outdoor environment with kinda high-poly terrain and single directional light (sun).
- Small closed environments with many point lights.
The possible approaches I can think of are:
- Shadow volumes for either point lights or everything (with shadow shilouette generation offloaded to a geometry shader).
- Cubemap omni-directional shadow maps for point lights.
- Cascaded shadow maps for the sun in the outdoor scene.
I'm worried that I will end up with more or less pixelated/blurry shadow edges when using shadow maps. On the other hand the high-poly terrain might be a performance hog for shadow volumes due to shilouette generation.
What would be your approach on this? Any suggestions?
Thanks.
Optimally ask yourself first, how much of your lights are dynamic?
What about voxelizing the scene in a distance field and raytracing them ? (and do much more with it)
@MsK`: Uh, 3d distance fields is pretty damn costy for a high-poly terrain. At least compared to a shadow-map.
masterm: Using a bit of acceleration-structures, you should be able to cast rays directly in the heightmap reasonably efficiently. That should give razor-sharp shadows (accurate to whatever degree you decide). For the "closed environments with many point lights", I'd try stencil shadows with silhouette-extraction in the geometry shader (draw your meshes twice, once as triangles and once as edges - the triangles cap your shadow volumes, and the edges conditionally expand to bridge the caps).
masterm: Using a bit of acceleration-structures, you should be able to cast rays directly in the heightmap reasonably efficiently. That should give razor-sharp shadows (accurate to whatever degree you decide). For the "closed environments with many point lights", I'd try stencil shadows with silhouette-extraction in the geometry shader (draw your meshes twice, once as triangles and once as edges - the triangles cap your shadow volumes, and the edges conditionally expand to bridge the caps).
@gargaj: Unfortunately most of them are.
@MsK': I want this to run on commodity hardware rather than your usual high-end demobox and as kusma said raytracing/raymarching distance fields is too expensive.
@kusma: The problem with the terrain is that it is based on heightmap data but then further processed to the point that its topology does not quite "match" the heightmap anymore. Besides I wish to support shadowing for regular meshes on top of the terrain.
@MsK': I want this to run on commodity hardware rather than your usual high-end demobox and as kusma said raytracing/raymarching distance fields is too expensive.
@kusma: The problem with the terrain is that it is based on heightmap data but then further processed to the point that its topology does not quite "match" the heightmap anymore. Besides I wish to support shadowing for regular meshes on top of the terrain.
For the terrain you could go with prebaked lightmaps, especially if you say you want it to run on mediocre hardware. Assuming the dynamic lights dont change the lighting of far away geometry. Also you can add the dynamic shadows on top of the prebaked stuff.
@hArDy.: Well I guess I forgot to mention that I plan to have day/night cycle. So the sun will be moving (albeit quite slowly).
shadows are the real problem. each algorithm has random stuffs to not work properly.
for example, skyrim uses shadow mapping, but it gives artefacts when changing.
I've built my engine for stencil shadowing and I've added a new approach instead of carmack/reverse algorithm that never works with open meshes. my approach runs with any kind of meshes at little artefact close if the meshes is really exotic.
shadow mapping is implemented too with shaders and secondary render buffers.
for some games I've created I use projections on topological bsp to upgrade face to face projections. but more, I've built a world single bsp algorithm to do some precalculations with shadows for objects that are not moving.
then, I can use bsp to discretize quick shadows in realtime, of stencil shadows mixed with.
for example, skyrim uses shadow mapping, but it gives artefacts when changing.
I've built my engine for stencil shadowing and I've added a new approach instead of carmack/reverse algorithm that never works with open meshes. my approach runs with any kind of meshes at little artefact close if the meshes is really exotic.
shadow mapping is implemented too with shaders and secondary render buffers.
for some games I've created I use projections on topological bsp to upgrade face to face projections. but more, I've built a world single bsp algorithm to do some precalculations with shadows for objects that are not moving.
then, I can use bsp to discretize quick shadows in realtime, of stencil shadows mixed with.
To add to kusma's idea: you can also do silhouette-extraction in vertex shaders. This means you have even lower hardware requirements (even DX8-level hardware can do this, all you need is VS1.1).
And while it sounds less optimal (you need to perform per-triangle calculations on a per-vertex basis, so you have redundant calculations), in practice this was actually faster, at least on early DX10-hardware, because the geometry shader performance was so poor. I haven't tested on more modern hardware, because shadow volumes were pretty much obsolete by then.
3DMark03 used the approach of extracting silhouettes in vertex shaders, to give you an idea. They performed this on skinned models too!
I implemented that algo myself as well: http://bohemiq.scali.eu.org/forum/viewtopic.php?f=4&t=35
And while it sounds less optimal (you need to perform per-triangle calculations on a per-vertex basis, so you have redundant calculations), in practice this was actually faster, at least on early DX10-hardware, because the geometry shader performance was so poor. I haven't tested on more modern hardware, because shadow volumes were pretty much obsolete by then.
3DMark03 used the approach of extracting silhouettes in vertex shaders, to give you an idea. They performed this on skinned models too!
I implemented that algo myself as well: http://bohemiq.scali.eu.org/forum/viewtopic.php?f=4&t=35
Scali: In my experience, early DX10 hw really only performed poorly on GS when the maximum-output count wasn't tiny. It should be tiny in this case. The vertex-shader silhouette extraction technique is a fillrate-killer for anything beyond tiny triangle counts.
@Nitro: Yeah, SPSM might be a good fit. It's not at all perfect, but it sounds like that might not be a major concern here.
kusma: Not sure what 'tiny' means in your world, but 3DMark03 ran quite well with polycounts of ~250,000 in test 2 and ~560,000 in test 3: http://s3.amazonaws.com/download-aws.futuremark.com/3dmark03-whitepaper.pdf
Scali: that's 250k polycounts *after* expansion for test 2, not before.
That is, after expansion per light. The scene-complexity is ridiculously low.
Depends on what you're aiming for... I'm just putting some numbers on it, to give you an idea...
Quote:
@kusma: The problem with the terrain is that it is based on heightmap data but then further processed to the point that its topology does not quite "match" the heightmap anymore. Besides I wish to support shadowing for regular meshes on top of the terrain.
In our game we use cascading shadowmaps for such a scenario, works reasonably well.