Attenuation based on a light radius

This question has appeared often enough that I decided to put together a small demo showing how it’s done. Nothing new…just putting a modern (as in GLSL shaders) spin on an old topic.

Further details and download links can be found here.

I know this is probably just example code, but you can optimize it a lot:

Take this code:


    vec3 l = gl_LightSource[0].position.xyz - position;
    float d = length(l);
    float atten = 1.0 - ((d * d) / (lightRadius * lightRadius));

= d^2 / lightRadius^2
= (d/lightRadius) ^2


    vec3 l = gl_LightSource[0].position.xyz - position;
    float d = length(l / lightRadius );
    float atten = 1.0 - (d * d);

As length(l) ^2 = dot(l,l)


    vec3 l = (gl_LightSource[0].position.xyz - position) / lightRadius;
    float atten = 1.0 - dot(l,l);

Finally, you can move the distance and divide calculation to the vertex shader. Also, you don’t clamp the attenuation value (so negative attenuation values will be sucking ambient from the scene)

Vertex shader


varying vec3 lVec;

    lVec = (gl_LightSource[0].position.xyz - position) / lightRadius;

Fragment shader


varying vec3 lVec;
    float atten = max(0.0, 1.0 - dot(lVec,lVec));

Yeah this was something I put together in a hurry sqrt[-1]. It was written for clarity/educational purposes so there’s a lot of room for optimization. Thanks for pointing out the optimizations. I’ll update the shaders and repost the demo.

Edit: New version of demo released. Use the same link as in the original post. Includes optimizations described by sqrt[-1].

This topic was automatically closed 183 days after the last reply. New replies are no longer allowed.