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 ?

  • \$\begingroup\$ 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. \$\endgroup\$ Mar 19, 2013 at 23:20
  • \$\begingroup\$ gamedev.net/page/resources/_/technical/opengl/… \$\endgroup\$
    – danijar
    Mar 28, 2013 at 18:30

1 Answer 1


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.)

  • \$\begingroup\$ 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 ? \$\endgroup\$
    – Irbis
    Mar 18, 2013 at 23:48
  • \$\begingroup\$ 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. \$\endgroup\$ Mar 19, 2013 at 0:12
  • \$\begingroup\$ 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 ? \$\endgroup\$
    – Irbis
    Mar 19, 2013 at 0:49
  • \$\begingroup\$ 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.) \$\endgroup\$ Mar 19, 2013 at 3:25
  • \$\begingroup\$ 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. \$\endgroup\$
    – Irbis
    Mar 19, 2013 at 13:48

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .