Epic outlined another formula here:
Lighting Modelfalloff = (saturate(1 ? (distance/lightRadius)4)2) ÷ (distance2 + 1)
Here is a test scene with all 3 equations. There are 3 point lights.
#1: Physically correct quadratic fall-off (scaled by light radius).
float Falloff( in float _fDistance, in float _fRadius ) {
float fFalloff = 1.0 / Sqr( _fDistance );
return fFalloff;
}
[attachment=25241:FalloffD2.png]
It indeed never reaches 0, but all 3 lights have approximately the correct visible ranges (you would still see the cut-off if you dropped to 0 at “range” units though).
#2: Epic’s fall-off.
float Falloff( in float _fDistance, in float _fRadius ) {
float fFalloff = 0;
float fDistOverRadius = _fDistance / _fRadius;
float fDistOverRadius2 = Sqr( fDistOverRadius );
float fDistOverRadius4 = Sqr( fDistOverRadius2 );
fFalloff = Sqr( saturate( 1.0 - fDistOverRadius4 ) );
fFalloff /= Sqr( _fDistance ) + 1.0;
return fFalloff;
}
[attachment=25242:FalloffEpic.png]
Gives a very good fall-off. They outlined the artistic intent in the paper.
#3: The above formula.
float Falloff( in float _fDistance, in float _fRadius ) {
float fFalloff = max( 1.0 / Sqr( _fDistance ) - 1.0 / Sqr( _fRadius ), 0.0 );
return fFalloff;
}
[attachment=25240:FalloffMod.png]
Looks almost the same as Epic’s—only a few pixels in the specular around the headlights are different. The artistic intent is different however, and may give noticeably different results in other situations.
L. Spiro