Mixing Ambient Lighting with Diffuse

Ok. This actually sounds like a simple topic, as for ambient all you seem to have to do is add ambient to the light intensity and you’re done … but all you do is actually “overlighting” everything. Which comes with all the drawbacks like missing normal map details etc … maybe I just do it wrong …

I have the following situation. I do have a directional light, it does all the magic with normal maps and so on and gives me a proper looking lighting model - except everything facing away from “the sun” is basically simply black.

Here we go, adding ambient. The usual (old days) approach is just to always add ambient. Let’s say ambient intensity is 0.3. So now the whole scene is sun + 0.3 which is fine. But it also means, that everything which comes out from the Light Calculation and being in the range of 0.7 - 1.0 will end up as 1 after adding ambient. Basically making normal mapped things just flat.

(there is shadow mapping as well, but I just clamp this to be minimum ambient, so no issue)

So what approach of ambient would actually preserve proper normal mapping in nicely lit areas (like facing the sun directly, where the result will be still 0.7+ after normal map) while maintaining features in dark area?

With just adding ambient, all you do is raising your intensity space to 1 + ambient and clamping it later back to 1 …

The best solution is to switch to a floating point surface format. The 8-bit per channel of the standard color surface format just doesn’t cut it. 256 brightness levels isn’t good enough to capture the dynamic range of real world lighting. A 16-bit per channel half format should be good enough.

You don’t have to worry about clamping to 1 anymore, you can go over now. In the end you use some kind of tone mapping post process to get things into the desired range. Because brightness levels are being preserved, you can use a bloom shader, and you will get nice halos around bright spots, like specular highlights.

1 Like

Yes, that would actual be the ideal approach to do it, especially because it can be used later for different effects. But my game is already pretty heavy on Rendertarget Usage (deferred) so I am not sure if I want to add even more load to it … at least not now.

What I currently do is, I apply the inverse intensity of the diffuse as ambient factor, this at least preserves the details bit better, but maybe ultimately I have to make something like HDR with color correction to get the desired result.

I wonder if nowadays just every game does it that way … things changed a lot since the big engines are around I guess.

I think modern graphics engines generally go beyond 8 bit per channel for render targets holding lighting information, if they support higher-end graphics.

If 16 bit per channel is too much for you, there’s also a floating point format that splits 32 bit over 3 channels:

DX: R11G11B10_FLOAT
GL: GL_R11F_G11F_B10F

It’s not part of standard MG, but adding new surface formats isn’t difficult.