blob: 77cecb9ea58ec6f9788c69d2f5a487e2d38b86e5 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
|
## 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.

*Top: HSV gradient varying only hue; Bottom: OKLCH gradient varying only hue.*
The [original OKLAB blog post](https://bottosson.github.io/posts/oklab/)
explains its merits very well.
OKLAB [should be supported in Unity
2022](https://twitter.com/bjornornorn/status/1512428218892095496?lang=en), 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.
|