-
Notifications
You must be signed in to change notification settings - Fork 63
Description
In computeLight_fp.glsl
in computeDynamicLight()
function we have this code:
if( light.type == 0.0 ) {
// point light
L = light.center.xyz - P;
// 2.57 ~= 8.0 ^ ( 1.0 / 2.2 ), adjusted after overbright changes
float t = 1.0 + 2.57 * length( L ) / light.radius;
// Quadratic attenuation function instead of linear because of overbright changes
attenuation = 1.0 / ( t * t );
L = normalize( L );
} else if( light.type == 1.0 ) {
// spot light
L = light.center - P;
// 2.57 ~= 8.0 ^ ( 1.0 / 2.2 ), adjusted after overbright changes
float t = 1.0 + 2.57 * length( L ) / light.radius;
// Quadratic attenuation function instead of linear because of overbright changes
attenuation = 1.0 / ( t * t );
L = normalize( L );
if( dot( L, light.direction ) <= light.angle ) {
attenuation = 0.0;
}
}
The comments suggest the code was modified from using a linear attenuation function to a quadratic attenuation once the complete overbright had been unlocked.
That may be wrong because if the light was not properly displayed with a not-clamped overbright, it means that maybe the values were wrong to begin with and that clamping was hiding the bug.
But my main concern isn't that. On this page we can read:
Something else that's different with gamma correction is lighting attenuation. In the real physical world, lighting attenuates closely inversely proportional to the squared distance from a light source. In normal English it simply means that the light strength is reduced over the distance to the light source squared, like below:
float attenuation = 1.0 / (distance * distance);However, when using this equation the attenuation effect is usually way too strong, giving lights a small radius that doesn't look physically right. For that reason other attenuation functions were used (like we discussed in the basic lighting chapter) that give much more control, or the linear equivalent is used:
float attenuation = 1.0 / distance;The linear equivalent gives more plausible results compared to its quadratic variant without gamma correction, but when we enable gamma correction the linear attenuation looks too weak and the physically correct quadratic attenuation suddenly gives the better results. The image below shows the differences:
The cause of this difference is that light attenuation functions change brightness, and as we weren't visualizing our scene in linear space we chose the attenuation functions that looked best on our monitor, but weren't physically correct. Think of the squared attenuation function: if we were to use this function without gamma correction, the attenuation function effectively becomes:
(1.0/distance²)²·²
when displayed on a monitor. This creates a much larger attenuation from what we originally anticipated. This also explains why the linear equivalent makes much more sense without gamma correction as this effectively becomes(1.0/distance)²·² = 1.0/distance²·²
which resembles its physical equivalent a lot more.
-- https://learnopengl.com/Advanced-Lighting/Gamma-Correction
So, if I understand it correctly, the light attenuation function should be currently linear, it should be linear when loading all our Tremulous and current Unvanquished maps, and it should be quadratic only when loading the future maps that will be processed in linear space.
That code already using the quadratic function means we can't convert it from linear to quadratic…