Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

I use a common attenuation equation for point lights: attenuation = 1 / kc + kl * d + kq * d^2.

I use deferred rendering so I need to know a light radius. An example light has following intensity: vec3(10, 1, 8). RGB components can be greater than 1.0 beacuase of HDR/Tone Mapping. How to calculate a light radius ?

Edit1 An attenuation equation can be defined this way (link) and we get following equations:

  • attenuation = 1 / ( (d / r) + 1) ^ 2
  • attenuation = (attenuation - cutoff) / ( 1 - cutoff)
  • attenuation = max(attenuation, 0)
  • lightRadius = r * (sqrt(Li / cutoff) - 1)
  • cutoff = minLuminance / lightLuminance
  • Li = lightLuminance

Let's assume that d = 40, r = 1, lightLuminance = 10 and minLuminance = 0.01. Then: lightRadius = 99 but attenuation = 0. What is wrong ?

share|improve this question
    
Re: Edit1, I think your equation for lightRadius should be r * (sqrt(1 / cutoff) - 1). The light luminance is not needed there since it is already incorporated in the definition of cutoff. –  Nathan Reed Mar 19 '13 at 23:20
    

1 Answer 1

up vote 6 down vote accepted

The attenuation equation you posted, strictly speaking, does not allow for any finite light radius, since the attenuation will not go to zero at any finite distance.

However, in practical terms there will be some distance at which the light becomes too dim to see. If you define a luminance threshold, you can plug this into the attenuation formula and solve to see where the light crosses this threshold. In pseudocode:

// Get light's luminance using Rec 709 luminance formula
lightLuminance = dot(lightColor, vec3(0.2126, 0.7152, 0.0722))

// Minimum luminance threshold - tweak to taste
minLuminance = 0.01

// Solve attenuation equation to get radius where it falls to minLuminance
lightRadius = solveQuadratic(kc - lightLuminance / minLuminance, kl, kq)

In an HDR context, you might have variable exposure - in that case, minLuminance should probably be scaled inversely by exposure so that it represents a consistent display-referred luminance. This means lights will have different radius at different exposures though, which might be undesirable (e.g. you're putting them into a spatial subdivision structure).

On the other hand, you might want to tweak the attenuation so that it actually falls off to zero at a finite distance. A common way to do this is define an inner radius and outer radius, and multiply the attenuation function by a linear ramp that fades the light down to zero between the inner and outer radius, such as

attenuation *= saturate((radiusOuter - d) / (radiusOuter - radiusInner));

(In the shader, of course you should transform this into just saturate(d * a + b) and precalculate a and b to match the previous formula, rather than doing the subtractions and divide per pixel.)

share|improve this answer
    
Can I also express kl and kq as here: [link] (imdoingitwrong.wordpress.com/2011/01/31/light-attenuation) ? Then attenuation = 1 / ((d/r) + 1) ^ 2 and is scaled this way: attenuation = (attenuation - cutoff) / (1 - cutoff) where cutoff = minLuminance, right ? –  Irbis Mar 18 '13 at 23:48
    
Sure. That's another way of enforcing a finite radius. The only quibble I have with that is that it will cut off each of the RGB channels at slightly different places, if you have a colored light source. However in practice this may not be noticeable. –  Nathan Reed Mar 19 '13 at 0:12
    
What do you mean by cut off each of the RGB channels at slightly different places ? illumination I at distance d = intensity (rgb) Li * attenuation (defined as above) so where does it take place ? –  Irbis Mar 19 '13 at 0:49
    
Hmm, actually, never mind. I was thinking of ((lightColor * attenuation) - cutoff) / (1 - cutoff). But if it's lightColor * (attenuation - cutoff) / (1 - cutoff) that's fine. (But note that cutoff then is minLuminance / lightLuminance, not just minLuminance. That is, the cutoff has to scale inversely with the light luminance, rather than being a fixed constant.) –  Nathan Reed Mar 19 '13 at 3:25
    
Ok. Attenuation is calculated and scaled based on luminance so maybe light color (Li) should be convert to CIE xyY space and Y component should be used during calculations ? After that a result can be converted back to RGB space. –  Irbis Mar 19 '13 at 13:48

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.