tonemapNeutral function

Vector3 tonemapNeutral(
  1. Vector3 color
)

The Khronos PBR Neutral tone mapper, from composite.frag.

Transcribed rather than replaced with something simpler: this is the one part of the chain that is pure arithmetic on a colour, so a Reinhard curve here would make every cell of the comparison differ for a reason that has nothing to do with the backend.

Implementation

Vector3 tonemapNeutral(Vector3 color) {
  const startCompression = 0.8 - 0.04;
  const desaturation = 0.15;

  final minChannel = math.min(color.x, math.min(color.y, color.z));
  final offset = minChannel < 0.08
      ? minChannel - 6.25 * minChannel * minChannel
      : 0.04;
  final c = Vector3(color.x - offset, color.y - offset, color.z - offset);

  final peak = math.max(c.x, math.max(c.y, c.z));
  if (peak < startCompression) return c;

  const d = 1.0 - startCompression;
  final newPeak = 1.0 - d * d / (peak + d - startCompression);
  c.scale(newPeak / peak);

  final desaturate = 1.0 - 1.0 / (desaturation * (peak - newPeak) + 1.0);
  return Vector3(
    c.x + (newPeak - c.x) * desaturate,
    c.y + (newPeak - c.y) * desaturate,
    c.z + (newPeak - c.z) * desaturate,
  );
}