Deferred lighting over-saturates the scene

Started by
4 comments, last by Hodgman 12 years, 2 months ago
All of the deferred shading tutorials I've read use blending (glBlend) to blend the illumination of each light onto the final image. For a single light, this looks great. However, when multiple lights are in close proximity, they blend together and end up over-saturating the scene. With enough lights, all you end up seeing is the light color. However, in reality, additional lights wouldn't end up obscuring the diffuse color, you would just get a bright unlit copy of the diffuse image.

I've tried changing the blending method (GL_ONE,GL_ONE and GL_ONE,GL_ONE_MINUS_SRC_ALPHA), but the result is the same.

How can I blend the lighting passes without distorting the diffuse coloring of the scene?
Advertisement
The colors are clamped in the range 0-1. So if you add enough eventually everything will become one. You probably want to look into high dynamic range lighting. (hdr) (unless I'm misunderstanding what you said completely)
Yeah, if you're adding a lot of lights on top of each other so that the result becomes >1, you need to use a higher-range texture format, such as FP16.
Is that how most other deferred shading games handle it? With HDR? Or do they just somehow balance the amount of light shining on any given point? I know games like Starcraft 2 use deferred shading, and you can see the glow of lights on the scene, but it never looks over-saturated from too many lights in close proximity.

Another idea I had was to apply the light attenuation to a separate render texture, then use that texture as a mask to blend all lights in the scene at once, to avoid over-saturation. But that would involve another pass and wouldn't work very well for multi-colored lights.

Is there any way to clamp the amount of light being blended in without resorting to HDR? Or am I incorrect in assuming that HDR is an expensive operation?
umm yes, that's how they do it.

"but it never looks over-saturated from too many lights in close proximity"

yep, that's the point of HDR rendering.

you may tinker around with the lighting but HDR is the ultimate solution to your problem.

HDR isn't that expensive... nowadays. (if implemented properly!!!)
N.B. this happens in forward renderers as well as deferred renderers. This isn't a problem of deferred VS forward renderers -- it's a problem of low-range VS HDR lighting.
e.g.given a forward-rendering pixel shader snippet like:float3 result = (float3)0;
result += diffuse * nDotL0 * lightColor0;
result += diffuse * nDotL1 * lightColor1;
result += diffuse * nDotL2 * lightColor2;
return result;
if diffuse was white, color0 was pink(255,192,192), color1 was grey(128,128,128) and color2 was green(0,255,0), then the end result can be as high as (383,575,320), however when you output it to an 8-bit render target it gets clamped to white (255,255,255).
If your forward renderer used HDR, then after tone-mapping you would instead end up with a greenish-whiteish colour.


Another idea I had was to apply the light attenuation to a separate render texture, then use that texture as a mask to blend all lights in the scene at once, to avoid over-saturation. But that would involve another pass and wouldn't work very well for multi-colored lights.
This sounds a bit like "light pre pass" (or some call it "deferred lighting" instead of "deferred shading"). If you implemented this method with low-range (non-HDR) buffers, then when you place too many lights in one area, the result will look ok, but the artefact will be that your lights lose colour, because at some point they will clamp at white.

This topic is closed to new replies.

Advertisement