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);