Oklab

This shader applies the Oklab color space to create a smooth, visually appealing gradient effect. It demonstrates the use of perceptually uniform color spaces for more natural transitions.

OKLab is a perceptual color space designed to represent colors in a way that aligns more closely with human vision. Unlike RGB, it separates color into three components: L (lightness), a (green–red), and b (blue–yellow), making it ideal for smooth color transitions and perceptually uniform gradients.

OkLab was introduced by Björn Ottosson in 2020 and described in this article.

float3 linearToOklab(float3 c) {
  const float3x3 tm1 = { { 0.4122214708, 0.5363325363, 0.0514459929 },
                         { 0.2119034982, 0.6806995451, 0.1073969566 },
                         { 0.0883024619, 0.2817188376, 0.6299787005 } };

  const float3x3 tm2 = { { 0.2104542553, 0.7936177850, -0.0040720468f },
                         { 1.9779984951, -2.4285922050, 0.4505937099f },
                         { 0.0259040371, 0.7827717662, -0.8086757660f } };
  float3 lms = mul(tm1, c);
  lms = sign(lms) * pow(abs(lms), float3(1. / 3.));
  return mul(tm2, lms);
}

float3 oklabToLinear(float3 c) {
  const float3x3 tm1 = { { 1., 0.3963377774f, 0.2158037573 },
                         { 1., -0.1055613458, -0.0638541728 }, 
                         { 1, 0.0894841775, -1.2914855480 } };

  const float3x3 tm2 = { { 4.0767416621, -3.3077115913, 0.2309699292 },
                         { -1.2684380046, 2.6097574011, -0.3413193965 },
                         { -0.0041960863f, -0.7034186147, 1.7076147010 } };

  float3 lms = mul(tm1, c);
  return mul(tm2, lms * lms * lms);
}

You can mix two colors in the Oklab space to create a smooth gradient effect:

float3 oklabColor1 = linearToOklab(linearColor1.rgb);
float3 oklabColor2 = linearToOklab(linearColor2.rgb);

float3 mixedColor = mix(oklabColor1, oklabColor2, mixFactor);

float finalColor = oklabToLinear(mixedColor);