Fix: EEVEE-Next: Fix spherical harmonic clamping

The previous implementation was not considering each
channel magnitude, which was not rotationally
invariant. This fixes changes in lighting as the world
rotates (and if clamping is enabled).
This commit is contained in:
Clément Foucault
2024-04-25 16:21:33 +02:00
parent 5938ab099d
commit b49333a7a0
2 changed files with 7 additions and 5 deletions

View File

@@ -136,6 +136,7 @@ void main()
* Note that this is an approximation since the footprint of a thread-group is not
* necessarily a convex polygons (with center of gravity at midpoint).
* But the actual error introduce by this approximation is not perceivable. */
/* FIXME(fclem): The error IS very perceivable for resolution lower than a quadrant. */
ivec2 max_group_texel = local_texel + ivec2(gl_WorkGroupSize.xy);
/* Min direction is the local direction since this is only ran by thread 0. */
vec3 min_direction = normalize(direction);

View File

@@ -718,12 +718,13 @@ SphericalHarmonicL1 spherical_harmonics_clamp(SphericalHarmonicL1 sh, float clam
{
/* Convert coefficients to per channel column. */
mat4x4 per_channel = transpose(mat4x4(sh.L0.M0, sh.L1.Mn1, sh.L1.M0, sh.L1.Mp1));
/* Maximum per channel. */
vec3 max_L1 = vec3(reduce_max(abs(per_channel[0].yzw)),
reduce_max(abs(per_channel[1].yzw)),
reduce_max(abs(per_channel[2].yzw)));
/* Magnitute per channel. */
vec3 mag_L1;
mag_L1.r = length(per_channel[0].yzw);
mag_L1.g = length(per_channel[1].yzw);
mag_L1.b = length(per_channel[2].yzw);
/* Find maximum of the sh function over all channels. */
vec3 max_sh = abs(sh.L0.M0.rgb) * 0.282094792 + max_L1 * 0.488602512;
vec3 max_sh = abs(sh.L0.M0.rgb) * 0.282094792 + mag_L1 * 0.488602512;
float fac = clamp_value * safe_rcp(reduce_max(max_sh));
if (fac > 1.0) {