Real World Light Attenuation

Started by
11 comments, last by Merlz 17 years, 2 months ago
I allways thought that light attenuation was equal to Lumens/(Distance*Distance). What I'm reading right now is that light attenuation is equal to Lumens*e^(-k*Distance) where k is that attenuation coefficient for the substance the light is traveling through. Is the second equation more realistic? If so why haven't I ever seen it used in any real time 3D graphics application.
Advertisement
Quote:Original post by Grasshopper
I allways thought that light attenuation was equal to Lumens/(Distance*Distance). What I'm reading right now is that light attenuation is equal to Lumens*e^(-k*Distance) where k is that attenuation coefficient for the substance the light is traveling through. Is the second equation more realistic? If so why haven't I ever seen it used in any real time 3D graphics application.

Light attenuates over distance for two reasons: Because the beam spreads out, and because some of the energy is absorbed. In air, though, the second part (which your equation relates to) is negligible except over extreme distances.
Thanks for the insight. So if i'm trying to do point light attenuation in water would k = (Beam Spread Coefficient)*(Abosorption Coefficient).
Eh. Even then, coefficient of absorption is pretty low. If you want the extra attenuation, just do an extra little bit of linear dark blue fog, which will look nicer because it better simulates the scattering that's going on.
There are 2 different effects you're talking about.

1) Light falloff follows an inverse-square curve. Check the diagram here for a fairly intuitive explanation http://en.wikipedia.org/wiki/Inverse_square

2) The second formula is a general formula for decay. It can be applied to light attenuation in a participating medium such as fog.

So basically, you want to use both of them, but only use the second if you want to simulate the effect of light being attenuated by fog.
But wouldn't light traveling in air or water still be subject to the decay formula? If light falloff allways follows a inverse-square curve then wouldn't it attenuate super fast in air?
Quote:Original post by Grasshopper
But wouldn't light traveling in air or water still be subject to the decay formula? If light falloff allways follows a inverse-square curve then wouldn't it attenuate super fast in air?
Yeah. And it actually does. This doesn't work quite like you might be assuming, though.

Here's an example of how this is weird-sounding. Consider a lightbulb one foot away from your eye. Consider a second lightbulb two feet away from your eye. By the inverse square law, the second light bulb should be only one fourth as bright. But obviously that isn't true! The lightbulbs look exactly the same! Whaaaa!?

Here's the thing. When you're thinking of "brightness" as it relates to a lightbulb, you're thinking about energy per solid angle. That is, given a particular light receptor on your retina, you're thinking about how much the lightbulb is affecting that receptor. "Brightness".

What the inverse square law represents, though, is absolute energy being transmitted. Although the lightbulb is just as bright, since it appears smaller, there is less energy TOTAL being transmitted to your eye. Consider a heat lamp a foot away from a glass of water, and another heat lamp two feet away from a second glass of water. As you might guess, the first glass is heated four times as fast as the second. Likewise, consider a lightbulb a foot away from a piece of paper, and a second lightbulb two feet away from a second piece of paper. The second paper only appears a fourth as bright.

Bottom line: Inverse square law tells you how much your objects are illuminated by a point light source. Exponential decay law tells you how much light "just disappears" when flying through the air. Because the inverse square law is a much "stronger" effect than absorption you pretty much ignore it when computing illumination of a surface, but it can become an issue when looking at the illuminated object (which is where fog/depth cueing comes into play).
As others said before, 1/r² is the "official" attenuation function. If you try this in your average engine, it will appear very dark, though. The reason is a bit complicated to explain. Maybe a english native speaker can clean it up after me :-)

The human eye senses light not linearly, but logarithmically. That means twice the light intensity is not perceived twice as bright by a human but only a bit brighter. This is also true for the light emitted by your screen. For most uses of the computer, a linear percepted scale is more useful. That's why graphics card companies implemented a so called gamma correction long time ago. This is a strongly non-linear correction formula that makes the bright parts even brighter so that your eye does perceive the whole 0.0f - 1.0f range as a brightness range of linear scale. A nice invention, so far. The correction formula is "pow( value, 2.2f)" to my knowledge.

For 3D graphics, most of the rules how light spreads, reacts with surfaces and so on are known. One of those rules is the attenuation named above. Another rule is "the light from two sources overlaps additivly". But if you implement those rules straightforward into your engine, it doesn't look right. The built-in gamma correction trashes your results. If you have two lights of the same brightness in reality, the light arriving from both sources at a surface adds up. In reality it doesn't look twice as bright afterwards. But the gamma correction of the gfx board corrects the brightness so that it is perceived twice as bright by your eye. If you want to achieve an impression close to reality, you have to compensate that gamma correction. Among many others, that is, but this is off-topic. The 1/r_squared formula mentioned earlier is the same case: if you use it, it appears way too dark. The gamma correction-correction makes dark places appear brighter so that the attenuation should look better.

The easiest way to achieve this would be a simple "pow( result, 0.45f)" in a post process. The problem is: the textures you use are already pre-corrected so that they appear the same at the screen they appear in reality. Either you pre-decorrect your textures, most propably in a offline precalculation. You possibly run into precision problems when using only 8 Bit per channel. Or you render out the brightness in a separate buffer, correct only the values of this buffer and recombine it afterwards with the textures. If you use multiple passes to add multiple lights, make sure you apply the correction only after all light sources are done. The additive blending function would trash your efforts else.

I for myself am heading for the "pre-correct textures, apply correction in a post-processing step" way. I can't tell any story, though, I haven't had the time to actually try it. Sorry. I've read that the Unreal 3 engine uses this gamma correction, it's listed in their features list as "gamma-correct lighting". Halo 3 does use it as well. I'm not aware of other engines supporting it.

Bye, Thomas
----------
Gonna try that "Indie" stuff I keep hearing about. Let's start with Splatter.
Great responses. I feel enlightened
Just to clear up terminology: attenuation through matter is the exponential decay formula you found; radiation from a point is the formula we use to calculate lighting normally. Attenuation usually refers to how much gets blocked, whereas radiation talks about how the light spreads out. For instance, lasers don't radiate outwards much so Lumens/dist^2 is a really bad approximation of how they work. Streetlights and our sun, on the other hand, behave properly (for the way we model light, anyway) and follow Lumens/dist^2. ( this is physics... I guess in graphics we can call radiation attenuation, but then it confuses real attenuation :) )

I think openGL has an exponential fog equation to simulate this attenuation effect too - if you ever do need it. IMO, it's prettier than linear fog, but it's much more expensive to calculate so games typically don't use it as much.

In air and even water, the coefficient of decay is small enough that you'll only notice any effect over long distances, so we usually ignore it altogether in games. To see the effect in real life, have a look at how mountains in the far distance turn bluish ;)

This topic is closed to new replies.

Advertisement