Shadow mapping advice
#1 Members - Reputation: 219
Posted 01 September 2012 - 12:54 AM
The theory makes sense to me, but I find it slightly surprising that it uses a full scene render per light-source. I've noticed that modern games seem to use a pretty high number of light sources! Is this technique advisible for a large number of lights?
Moreover, the method works by rendering from the lamps point of view, so the light is limited to a frustum pointing in one specific direction. I presume you would have to do multiple renders for a light spreading out in all directions?
I read some hardware offers 'shadow mapping support'. What kind of support is available? I'm using OpenGL/GLSL
#2 Moderators - Reputation: 13550
Posted 01 September 2012 - 01:12 AM
Yes, some new games do use as many as a thousand dynamic lights, however, only a small number of them will actually be shadow-casting lights.I find it slightly surprising that it uses a full scene render per light-source. I've noticed that modern games seem to use a pretty high number of light sources
Also, in specific scenes / specific scenarios, you don't need a "full scene" render per light.
e.g. I once worked on a racing game where all of the environment shadows used static light-map techniques, so only the dynamic cars themselves needed shadow mapping. We also used "deferred shadow maps" where you accumulate the shadow information into a full-screen texture. We would render each car individually into it's own shadow map (which makes good use of low resolution shadow textures), and then composited each single shadow into the full-screen texture. This meant we had to render (at most) an extra numCars * numLights for shadows -- not wholeScene * numLights.
You should also perform frustum culling (and full visibility culling if your scene supports it) on the light, so that you're only rendering objects that are visible from it's viewpoint. If no cars were visible from a particular light, then no extra rendering was performed for it.
Yes, the most obvious solution is 6 different 90º frustums rendered to a "cube-shadow-map". There's also hemisphere-based solutions that use fewer frustums (Dual-Paraboloid SM or Dual Sphere-Unfolding SM), or complex distortion methods like CSSM, but these alternatives generally exhibit more distortion than the basic solution.Moreover, the method works by rendering from the lamps point of view, so the light is limited to a frustum pointing in one specific direction. I presume you would have to do multiple renders for a light spreading out in all directions?
Edited by Hodgman, 01 September 2012 - 01:20 AM.
#3 Moderators - Reputation: 5419
Posted 01 September 2012 - 12:35 PM
#4 Members - Reputation: 431
Posted 01 September 2012 - 03:07 PM
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
Then, in your shader, you should give your shadowmap uniform the type sampler2DShadow. This will allow you to call the regular texture function, or one of its variants, with a 3 dimensional texture coordinate. The third coordinate is the depth value used for comparison.
#5 Members - Reputation: 219
Posted 15 September 2012 - 11:12 PM
To avoid excessive extra-rendering, I am planning on enclosing each lamp in a bounding volume (i.e. an Axis Aligned Bounding Box) and checking for intersections with each models bounding volume. I admit I haven't read up much on this just yet, there's something called 'Cascaded Shadows' that I need to look into, but I wanted to get your input on the algorithm I came up with today.
Here's the psuedo-code. Should be pretty self explanatory:
Algorithm:
PositionModels()
PositionsLights()
/////////////////
// SHADOW PASS //
/////////////////
for light in AllLights
{
// determine which models are hit by the light
for model in AllModels:
{
if (collision(light.volume, model.volume)
{
light.modelsInView.add(model);
// give model access to light data, including its shadow map
model.shadowCasters.add(light);
}
}
// if any models were hit by the light
if (light.modelsInView.Count > 0)
{
prepareShadowRender(light);
// render all models in this light's view to the light's shadowmap
for model in light.modelsInView
{
model.render();
}
}
}
//////////////////
// FINAL RENDER //
//////////////////
for model in models:
{
for light in model.shadowCasters:
{
shaderSetupShadowMap(light)
}
model.render();
}
Obviously the relevant lists need to be cleared after each rendered. Further optimizations can obviously be made, such as caching shadows for stable objects. But I think the general structure is captured here, wouldn't you say?
Any input/feedback would be appreciated.
Edited by mv348, 15 September 2012 - 11:23 PM.
#6 Members - Reputation: 218
Posted 16 September 2012 - 12:36 PM
//Generating shadows
if(shadows)
{
foreach light
{
foreach object
{
if(distance(object,light)<30
{
render object to shadowmap for this light
}
}
}
}
//Rendering lights with shadows
foreach light
{
if(shadows && cameradistance<***)
{
render light with shadow map
}
else
{
render light
}
}
Edited by RetroIP, 16 September 2012 - 12:38 PM.
#7 Members - Reputation: 219
Posted 17 September 2012 - 08:25 PM
I have a question though. The algorithm I outlined should work fine provided I am using spot-lamps with a relatively small area of effect. However, using directional lights, such as sunlight, poses a bit of a problem. I would have to render the entire scene from a sufficient distance to capture everything. A single shadow-map spread out over an entire scene is going to look awful pixelated for large, outdoor environments.
How can I address this issue?
#9 Members - Reputation: 219
Posted 18 September 2012 - 11:19 PM
So I started reading through this article by Nvidia. I'm making some headway with it, but its a bit difficult to follow at times. Some of the details are posted in the references, but require a subscription to read.
Any particular tutorial or paper suggestions would be welcome.
#10 Crossbones+ - Reputation: 5164
Posted 19 September 2012 - 05:01 AM
For directional lights, I have written a tutorial on how to “capture” only objects that are inside the camera frustum or could cast shadows into the camera’s frustum, tightly excluding all other objects.To avoid excessive extra-rendering, I am planning on enclosing each lamp in a bounding volume (i.e. an Axis Aligned Bounding Box) and checking for intersections with each models bounding volume.
Tutorial: Tightly Culling Shadow Casters for Directional Lights (Part 1)
Tutorial: Tightly Culling Shadow Casters for Directional Lights (Part 2)
L. Spiro
I spent most of my life learning the courage it takes to go out and get what I want. Now that I have it, I am not sure exactly what it is that I want. - L. Spiro 2013
L. Spiro Engine: http://lspiroengine.com
L. Spiro Engine Forums: http://lspiroengine.com/forums






