Dynamic lighting & sorting geometry to reduce switches

Started by
15 comments, last by spek 16 years, 6 months ago
Lighting isn't the problem, shadowing is :)

Ok, you dont need much for a lot of lights, here is some pseudo shader code:

>>> vertex_shader:

// calculate your position to render it normally
position =....

// calculate your position and normal in world space !
position_world_space = ...
normal_world_space = ...

>>> fragment_shader:

uniform vec3 light_color[MAX_NUMBER_OF_LIGHTS];
uniform vec3 light_direction[MAX_NUMBER_OF_LIGHTS]; // light direction in WORLD SPACE

...

// for lighting
vec3 final_light_color
for(i=0;i<MAX_NUMBER_OF_LIGHTS];i++)
{
// diffuse color
final_light_color += dot(normal_world_space,light_direction) * light_color;

//speculare ...
...
}



That's all, you dont need to transform the light_direction for each face, just transform the face to world space and set your light per shader once in world space.

However, this is just lighting, not shadowing. Shadowing with many light sources is quite difficult.

--
Ashaman
Advertisement
Of course :) Normally I translate to tangent space, but I already have my normal in world space inside the fragment shader, so why bothering.

I got a "ubershader", or whatever its called, now. Quite nice, just give some compiler options and it makes a specific shader. Not long ago I used to work with ten billion variants of each shader, you can imagine it's alot of work to maintain that. Only difficulty I expect to discover is adding a projected flashlight. I'm running out of texture channels. But that's another story.

Shadowing is indeed the problem. The dynamic lights won't do any shadows at all. Therefore I also use a lightMap. The lightMap contains the "global" lights that cast shadows. I'm using a directional map (like "Radiosity mapping" from HL2) so that I can still use some normalMapping on the pre-calculated lights as well. The dynamic lights are nearby sources. Together with reflections, parallax mapping, and some other stuff like detail normal Mapping, it can produce some really heavy shaders :) Luckily SM3.0 supports quite alot instructions. And maybe I still skip the "lighting loop", and do it after this stage with deffered lighting... If I can still do transparency with deffered lighting.

I'm not sure combining dynamic lights and a static lightMap is such a good idea. But I hate sharp stencil shadows. And only lightMapping looks a little bit dull too. I wonder how games like Bioshock or Farcry exactly combined the two though. That was basically my question in some other topic 1 or 2 weeks ago. Some people said lightMaps were out-dated and nowadays shadow maps are used more and more. But is that really true? I can imagine that for dynamic objects (characters, lockers, barrels, etc.), but for the static environment as well...?

Thanks,
Rick
using shadow mapping for static environemts works very well and looks good also; The way to do it is very simple; Render the shadow map for your static light just like you normally would, but only do that once. Since its static, you know nothing will change in the shadowmap so you dont even have to render it again, you can just use the same old one every frame. Dynamic objects can even recieve the shadows from the static light (cant cast them though unless you re-render the shadow map).
You can even do some very nice filtering on the shadowmap to create penumbra accurate soft shadows...but that takes a little more work to get looking nice

If you want to be super efficient, you can keep that static shadowmap for the static environments, and allocate a separate, dynamic shadow map just for your dynamic objects; that way you aoid re-rendering the static environment (when dealing with static lights) all together
...you can just use the same old one every frame...

That's true of course, I forgot about that. However, shadow maps still won't simulate indirect lighting of course. Although you could combine it with a simple lightMap that only measures light bounced of from other surfaces to add some "ambient" to prevent pitch black area's.

But I see some other problems. First, I have multiple lights in most cases, so that means multiple shadowmaps as well. I need to do multipassing / adding everything together. Well, like discussed earlier in this topic, I could handle multiple shadow maps in one 1 shader, but its still limited of course. Another problem, how to define which surfaces should use a shadow map casted from light X? In larger scenes, you don't want to use all shadow maps of course.

And last but not least, the detail. The further away from the lightSource, the less pixels an object-shadow gets. I read that there are tricks to improve that, but would that still be a fast solution (can I still use the same map every frame?).

I dunno... It sounds interesting though. Is this technique really used in modern games for the static environment? How do they deal with these problems?

Greetings,
Rick
Hmmm... I've been thinking about shadowMaps. I think I can do it like this:
pass1, the diffuse/phong specular lighting pass- Handle up to 4 shadowMaps- The other 4 textures are for normals, albedo, maybe parallax, etc.- This pass does the diffuse/specular lighting per source, including the shadowMappass2, ambient / emmissive / reflections- Fog- Add ambient (via a lightMap or occlusion map) / emmissive- Add cubeMap / mirror reflections- Transparency / reflections- Other material specific effectsPass1 and 2 are combined with additive blend


I'm limited to 4 lights then, but I think that should be enough. If not, I could make an extra pass between that does the same as pass1. Some operations are done twice in this case, but what the heck. I'll have to accept not everything is possible :)

But now the difficult part comes. How to assign (dynammically) 4 shadowMaps / lights to a surface? Most lights aren't moving, but a dynamic solution would still be nice. I assume a shadowMap should be used for all geometry that is (partially) inside its "view frustum". However, since the limitation, I must assign the most "important" sources to a surface.

The other difficult part remains the quality. In most cases the light won't be shining far, so a 512x512 map would give a good result. But for large lights far away...

Greetings,
Rick
sounds like a good outline; i think with all the features you plan on implementing, 2 passes is a minimum; though you could squeez it into one if you pull some strings.

Im guessing you have some type of scene organizational structure, like an octree. You can use that to determine what lights are affecting what surfaces.

Regarding shadows;
I personally would do away with any kind of precomputed lightmap texture and use shadow maps globally. You could still use lightmaps or something similar to get the global illumination effect, but if you want nice crisp (but not too crisp) shadows your better of unifying it and use shadowmaps for everything. For spot lights, a single shadow map should be sufficient. For directional lights, you can use parallel split shadow maps (you can use this technique for spot lights also). For point lights, you can tile the 6 maps needed into a single texture.
If the PSSM's dont give you good enough quality, you can add some kind of perspective correction onto that. Further, if you want it to be softer, you can use PCF filtering, or if you want super soft but fast shadows, use variance shadow mapping.

Most commercial games dont even have very nice looking shadow maping (in my opinion), so its not a trivial process to get working and looking good; I think variance shadow maps combined with some perspective correction and PSSM for directional lights is the way to go. Just a couple minutes ago i noticed someone posted about some kind of new shadow mapping thing that makes it pixel perfect; there are all kinds of neat shadow mapping approaches out there, so there are tons of options and potential.
I think you convinced me. I should try it.

The lightMap is indeed only for indirect lighting now. Unless 4 lights is too little, in that case I could let the lightMap help a little bit. But yes, it's more an ambient thing now.

I was about to ask how to do pointlights, but you answered that already. Just make 6 textures. I only need to figure out which from the 6 a face is receiving (or in the worst case it receives multiple... could become a little problem, especially when I have a limit of 3 or 4 maps per surface (light4 is also used for my flashlight).

I should use my portal culling and add an octree for light management. Well, I should just start and try it. I did shadowmapping 5 years ago... I think I have to learn it again :). I think I can get more quality with it indeed. A 512x512 shadowMap contains pretty much pixels comparing to a lightMap that gave way less pixels to the average polygon(the complete lightMap used 1024x766 in my case). Only problem are the surfaces litten far away from its lightSource when using shadowmaps. I shall look into the available techniques.

Thanks for helping everybody,
Rick

This topic is closed to new replies.

Advertisement