I am create a modern Unity based client of an old MMO from 2000, and I am working on implementing their lighting system. Based on the data I have reverse engineered, it looks like they used a custom attenuation formula. The original client uses DirectX 7. I have found a reference sheet for DX7 light.


The relevant info starts at page 17. In the URP, in Lighting.hlsl, I have set up linear attenuation:

float range = rsqrt(distanceAndSpotAttenuation.x);
float dist = distance( positionWS, lightPositionWS);
half attenuation = 1.0f - dist/range;        

Looks good! https://i.sstatic.net/Mpq7S.png

Everything looks good. Now I am trying to (based on the document) recreate the same linear attenuation. It should look something like this:

// DX 7
float range = rsqrt(distanceAndSpotAttenuation.x);
float dist = distance( positionWS, lightPositionWS);
half c0 = 1.0f;
half c1 = 1.0f;
half c2 = 0.0f;
half d = dist/range;
half attenuation = 1.0f / ( c0 + c1 * d + c2 * d * d );

This should give me linear attenuation according to the doc, but it ends up bleeding light way past the range of the light. So I am convinced the distance is wrong. What kind of value is expected here? Normalized distance? It doesn't specify. I have played around with the distance a lot. Set it to the attenuation in the first code example, to the raw value, and a bunch of other values. No luck: https://i.sstatic.net/b7T2t.png

Does anyone have any ideas?

  • \$\begingroup\$ We have some existing Q&A about that attenuation formula here, which might give you some insights into how it's used here. Note that this formula has no conception of a "limiting range" of a light - mathematically, it never reaches zero (though rendering with a fixed colour depth, it will eventually round to zero). \$\endgroup\$
    – DMGregory
    Commented Nov 19, 2020 at 22:34
  • \$\begingroup\$ @DMGregory Thanks for the link! That does explain a lot about the origins and usefulness of that formula. I appreciate the link. What it doesn't do though is explain how exactly it's anticipated that distance is specified? Is it a normalized value with 0 meaning it's at the center and 1 at the radius, or is it reversed? Or is it used another way? That's the issue I am having; translating Unity lighting variables to work with it. \$\endgroup\$ Commented Nov 19, 2020 at 22:54
  • \$\begingroup\$ There's no such thing as radius in this formula. Distance goes from 0 to infinity. You can adjust the parameters c1 and c2 to get the same output no matter what unit you measure distance in. \$\endgroup\$
    – DMGregory
    Commented Nov 19, 2020 at 23:49
  • \$\begingroup\$ @DMGregory I think I finally understand. I am trying to force this algorithm to work with a radius, when c1 and c2 indirectly control the distance that it shines. Where would I look for an example of a square falloff but including a radius component? \$\endgroup\$ Commented Nov 20, 2020 at 6:44
  • \$\begingroup\$ There was a similar question here about limiting the angle of a spotlight. I think you could apply a similar technique, finding the value of your existing falloff function at your desired radius, then remapping its output so that value is mapped to zero. \$\endgroup\$
    – DMGregory
    Commented Nov 20, 2020 at 10:25


You must log in to answer this question.

Browse other questions tagged .