After thinking about it for a while, there is also another aspect about multipass lighting I always feared, and its really trivial to handle, just like fog.
Transparent objects are rendered the same way as fogged objects: the final shaded pixel is linearly interpolated with a color, just like fog, but this time the color comes from the destination pixel. If you do the math,or if you take a look at my previews post, it becomes clear that transparent objects can easily be multiopass lit. Both techniques can also be combined as well.
In the case of both transparent and fogged objects the final color is calculated like this:
final_color = lerp(dest_color, fogged_shaded_color, alpha)
final_color = dest_color * (1-alpha) + fogged_shaded_color * alpha (1)
Let A = dest_color * (1-alpha), (1) becomes:
final_color = A + fogged_shaded_color * alpha (2)
fogged_shaded_color = lerp(fog_color, P1 + … + Pn, fog_factor) (P1 = first pass shaded color, Pn = nth pass)
fogged_shaded_color = fog_color * (1 – fog_factor) + ( P1 + … + Pn) * fog_factor (3)
Let F = fog_color * (1 – fog_factor), (3) becomes:
fogged_shaded_color = F + ( P1 + … + Pn) * fog_factor (4)
Combine (2) with (4):
final_color = A + (F + ( P1 + … + Pn) * fog_factor) * alpha
final_color = A + F * alpha + ( P1 + … + Pn) * fog_factor * alpha
final_color = A + F * alpha + P1*fog_factor*alpha + … + Pn*fog_factor*alpha
Substitute A and F again:
final_color = dest_color * (1-alpha) + ( fog_color * (1 – fog_factor) + P1*fog_factor) * alpha + … + Pn*fog_factor*alpha
final_color = lerp(dest_color, lerp(fog_color, P1, fog_factor), alpha) + … + Pn*fog_factor*alpha
“lerp(dest_color, lerp(fog_color, P1, fog_factor), alpha)” is a normal pass with fog and dest_color terms intact (not zeroed). So the first pass is performed normally.
Now let’s see what happens with the subsequent passes. They are of the form:
additive_pass_n = Pn * fog_factor * alpha
which is equivalent to:
additive_pass_n = lerp(ZERO, Pn, fog_factor) * alpha
Which is a little different pass, with fog_color = black as we already saw, the dst blend factor set to GL_ONE, as usually is the case with additive passes, but the src blend factor set to GL_SRC_ALPHA instead of the typical GL_ONE, because we want our shaded result multiplied by the alpha value.
So in short:
- Multipass fogging is as easy as setting the fog color to black after the first normal pass.
- Multipass alpha blending is done in essentially the same way, just do the first pass normally, and then do the subsequent passes with src blend factor set to GL_SRC_ALPHA and dst blend factor set to GL_ONE.
- Both techniques can be combined together.
So after all multipass lighting is not so difficult to program! Actually it is easier than trying to add all the lights affecting an object to the same shader. The latter aproach may be more optimized but it’s very troublesome to manage (or generate?) the combinational explosion of shaders having 1, 2 ,3 or more lights where each of the lights can be of any type.
PS: You can use these techniques even with what I call “semi-multipass” lighting, when 2 or more lights are rendered at the same pass. If you don’t believe me, just do the math 🙂