yum/HLSL_OKLAB

HLSL conversion functions between LRGB and OKLAB/OKLCH, a perceptually uniform color space.

git clone https://git.yummers.dev/yum/HLSL_OKLAB

yumUpdate README81ac81b

main
1.7 KiB62 linesraw

An HLSL implementation of OKLAB

OKLAB is a perceptually uniform color space. That means that blending between colors in OKLAB space produces more perceptually uniform gradients, without weird transitional colors or changes in perceptual brightness or saturation.

HSV vs OKLCH gradient Top: HSV gradient varying only hue; Bottom: OKLCH gradient varying only hue.

The original OKLAB blog post explains its merits very well.

OKLAB should be supported in Unity 2022, but for us stuck on older versions, a library like this is necessary.

This code is not optimized. If using in a performance critical setting, you should premultiply all matrices in your desired transformation.

APIs provided:

float3 LRGBtoXYZ(float3 c);
float3 XYZtoLRGB(float3 c);

float3 XYZtoOKLAB(float3 c);
float3 OKLABtoXYZ(float3 c);

// Note: OKLCH hue is on the range [0, 2*PI], not [0, 1].
float3 OKLABtoOKLCH(float3 c);
float3 OKLCHtoOKLAB(float3 c);

// Everything below this line is unoptimized syntactic sugar.
float3 LRGBtoOKLAB(float3 c);
float3 OKLABtoLRGB(float3 c);

float3 LRGBtoOKLCH(float3 c);
float3 OKLCHtoLRGB(float3 c);

The gradient above was generated with this fragment shader:

fixed4 frag(v2f i) : SV_Target
{
  float4 albedo = 1;

  if (i.uv.y > 0.5) {
    // HSV gradient
    albedo.xyz = HSVtoRGB(float3(i.uv.x, 1.0, 1.0));
  } else {
    // OKLAB gradient
    float3 c0 = LRGBtoOKLCH(float3(1, 0, 0));
    c0.z += i.uv.x * 2 * 3.14159265;
    albedo.xyz = OKLCHtoLRGB(c0);
  }

  return albedo;
}

This content is released under the MIT license.

1## An HLSL implementation of OKLAB
2
3OKLAB is a perceptually uniform color space. That means that blending
4between colors in OKLAB space produces more perceptually uniform gradients,
5without weird transitional colors or changes in perceptual brightness or
6saturation.
7
8![HSV vs OKLCH gradient](hsv_vs_oklab_gradient.PNG)
9*Top: HSV gradient varying only hue; Bottom: OKLCH gradient varying only hue.*
10
11The [original OKLAB blog post](https://bottosson.github.io/posts/oklab/)
12explains its merits very well.
13
14OKLAB [should be supported in Unity
152022](https://twitter.com/bjornornorn/status/1512428218892095496?lang=en), but
16for us stuck on older versions, a library like this is necessary.
17
18This code is *not* optimized. If using in a performance
19critical setting, you should premultiply all matrices in your desired
20transformation.
21
22APIs provided:
23```
24float3 LRGBtoXYZ(float3 c);
25float3 XYZtoLRGB(float3 c);
26
27float3 XYZtoOKLAB(float3 c);
28float3 OKLABtoXYZ(float3 c);
29
30// Note: OKLCH hue is on the range [0, 2*PI], not [0, 1].
31float3 OKLABtoOKLCH(float3 c);
32float3 OKLCHtoOKLAB(float3 c);
33
34// Everything below this line is unoptimized syntactic sugar.
35float3 LRGBtoOKLAB(float3 c);
36float3 OKLABtoLRGB(float3 c);
37
38float3 LRGBtoOKLCH(float3 c);
39float3 OKLCHtoLRGB(float3 c);
40```
41
42The gradient above was generated with this fragment shader:
43```
44fixed4 frag(v2f i) : SV_Target
45{
46  float4 albedo = 1;
47
48  if (i.uv.y > 0.5) {
49    // HSV gradient
50    albedo.xyz = HSVtoRGB(float3(i.uv.x, 1.0, 1.0));
51  } else {
52    // OKLAB gradient
53    float3 c0 = LRGBtoOKLCH(float3(1, 0, 0));
54    c0.z += i.uv.x * 2 * 3.14159265;
55    albedo.xyz = OKLCHtoLRGB(c0);
56  }
57
58  return albedo;
59}
60```
61
62This content is released under the MIT license.