# Mathematics behind Phong shading and additive blending

I'm confused about the mathematics behind additive blending used in conjunction with Phong shading. Intuitively, it seems like you would need to use a floating-point framebuffer and some sort of tone-mapping to achieve the actual approximation of many lights. Since the lighting values are computed as diffuse + specular, multiple lights can be encoded as:

finalColor = ambient
for light in lights:
finalColor += light.specular + light.diffuse


Now, suppose you have multiple white lights shining on a perfectly diffuse, but mostly red sphere. The more lights you add, the closer the final rendered sphere should get to the actual color of the sphere. In this case, if you use an 8-bit RGBA framebuffer, then rendering with glBlend(GL_ONE, GL_ONE) will actually cause the sphere to reach a white color in the limit, similar to the effect outlined in this question.

My question is twofold:

1. Is my intuition here correct?
2. If so, how do you combat this situation? If not, why not?

## 3 Answers

The problem isn't particularly with the additive math. Contributions from multiple light sources is resolved by addition. We can clearly see that in the rendering equation.

As we see in the equation light contributions is integrated over the unit hemisphere containing all possible values for all light directions(Wi). In real time computer graphics we only take into consideration the directions(Wi) that are directly connected to the lights and not taking into consideration the full hemisphere, hence this equation is converted into summation for all light contributions.

My point is: nothing wrong with the additive math. The problem is with the small dynamic range for 8-bit numbers. Representing sun light and light bulb as Color(1,1,1) doesn't particularly reflect real world radiance/luminance values. For this tone-mapping and other techniques were invented to be able to render high dynamic range images and map it to the limited range of a 32bit frame buffer.

• That was my intuition. I'm still not sure how this problem would be resolved. Would you render to a HDR framebuffer and then tonemap the result? Would you apply tone-mapping beforehand? How would you read the proper range of values without scanning each of the pixels via some sort of expensive glReadPixels call? – Mokosha Sep 30 '14 at 22:25
• @Mokosha You don't need a glReadPixels call, you either render to HDR render buffer then tonemapping it or do the tonemapping it in a shader. – concept3d Oct 1 '14 at 5:38

I dont think that would happen, i havent use it how ever, but if u think about it, you are multiplying the light contribution with the object color as the equation you provide

finalColor = ambient
for light in lights:
finalColor += light.specular + light.diffuse
finalColor *= objectColor;


and even in real live if you have a very shiny object like car chasis after waxing it if you sees it then it would look white, so you just have to mix the setting to match your needs, one hint what you are doing now called Forward Rendering, gool luck :).

.

The final color in Phong model depends on glossiness and specular reflectance of the material. If glossiness is very high or specular reflectance is low then the final color approaches albedo of the sphere. Otherwise the color approaches light color.

If you render in low dynamic range (LDR) though you may get color saturation and unexpected results, e.g. adding reddish color like rgb=[1, 0.5, 0.5] will result white because rgb components are clamped to range [0, 1]. With HDR you get values beyond that range and they are remapped with global tonemapping operator to LDR [0, 1] range to be displayed on regular monitors.

Some games used to render to LDR target but perform tonemapping in a shader before writing the results out to get around the more costly and memory heavy HDR rendertargets and blending. It had the obvious issue with blending though, e.g. transparent objects blended over the regular lighting weren't tonemapped and all lighting had to be done in one pass.