PDA

View Full Version : Bizarre order dependency with directional and projective lighting



raga34
10-11-2014, 07:23 AM
Hi.

I was surprised today to find a strange issue with my renderer.

The way the renderer works is that lights are added to the scene, and the renderer will apply the lights in an arbitrary order each frame (they're inserted into a data structure that doesn't guarantee any particular order, and the order will typically change every frame). This is all fine, because the light contributions are effectively summed with (GL_ONE, GL_ONE) additive blending, and addition is commutative, so the order that light contributions are applied makes no difference to the resulting image...

... Until today!

Using apitrace, I've stepped through the rendering of the scene. Here's the state of the scene with no lights applied:

http://waste.io7m.com/2014/10/11/scene_B_0.png

Here's the scene after the projective light is applied:

http://waste.io7m.com/2014/10/11/scene_B_1.png

Here's the scene after the directional light is applied:

http://waste.io7m.com/2014/10/11/scene_B_2.png

Fine. That's the result I'd expect. Now let's try applying the exact same lights in reverse order...

(continued in next post due to image limit)

raga34
10-11-2014, 07:24 AM
First, the empty scene:

http://waste.io7m.com/2014/10/11/scene_A_0.png

Directional:

http://waste.io7m.com/2014/10/11/scene_A_1.png

Projective:

http://waste.io7m.com/2014/10/11/scene_A_2.png

Ouch!

Why does the order that the lights are applied matter?

The render target is an ordinary RGBA8 texture, and blending is always enabled and the equation never changes from (GL_ONE, GL_ONE).

raga34
10-11-2014, 08:05 AM
To clarify: The issue only occurs in scenes containing the combination of projective and directional lights. It doesn't occur with spherical/point and projective lights, or spherical/point and directional lights.

raga34
10-12-2014, 07:54 AM
Found it.

When a directional light is evaluated, it disables culling (as directional lights are implemented by rendering fullscreen quads). The code path for the projective light case forgot to turn front-face culling back on (as projective lights are rendered using frustum-shaped light volumes), so the lighting was applied twice.