-
Notifications
You must be signed in to change notification settings - Fork 0
/
ColorSpace.cginc
138 lines (115 loc) · 3.05 KB
/
ColorSpace.cginc
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
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
//--------------------------------------------------------------------------------
// ColorSpace Conversion
// https://github.com/fuqunaga/ColorSpace
//
// Refs:
// https://en.wikipedia.org/wiki/SRGB
// https://en.wikipedia.org/wiki/CIELAB_color_space
// https://github.com/mattharrison/colorspace.py/blob/master/colorspace.py
//--------------------------------------------------------------------------------
//------------------------------------------------------------
// CIEXYZ
//------------------------------------------------------------
float3 RGBLinearToXYZ(float3 rgb)
{
float3x3 m = float3x3(
0.41239080, 0.35758434, 0.18048079,
0.21263901, 0.71516868, 0.07219232,
0.01933082, 0.11919478, 0.95053215
);
return mul(m, rgb);
}
float3 XYZToRGBLinear(float3 xyz)
{
float3x3 m = float3x3(
+3.24096994, -1.53738318, -0.49861076,
-0.96924364, +1.8759675, +0.04155506,
+0.05563008, -0.20397696, +1.05697151
);
return mul(m, xyz);
}
//------------------------------------------------------------
// CIELAB
// Note: the L* coordinate ranges from 0 to 100.
//------------------------------------------------------------
static const float LAB_Xn = 0.950489;
static const float LAB_Yn = 1.0;
static const float LAB_Zn = 1.088840;
float _LABFunc(float t)
{
const float T = 0.00885645168; //pow(6/29,3);
return t > T
? pow(t, 1.0/3.0)
: 7.78703704 * t + 4.0/29.0;
}
float _LABFuncInv(float t)
{
const float T = 6/29.0;
return t > T
? t*t*t
: 3*T*T*(t - 4/29.0);
}
float3 XYZToLAB(float3 xyz)
{
float fx = _LABFunc(xyz.x / LAB_Xn);
float fy = _LABFunc(xyz.y / LAB_Yn);
float fz = _LABFunc(xyz.z / LAB_Zn);
return float3(
116*fy - 16,
500*(fx-fy),
200*(fy-fz)
);
}
float3 LABToXYZ(float3 lab)
{
float ltmp = (lab.x + 16)/116;
return float3(
LAB_Xn * _LABFuncInv(ltmp + lab.y / 500),
LAB_Yn * _LABFuncInv(ltmp),
LAB_Zn * _LABFuncInv(ltmp - lab.z / 200)
);
}
//------------------------------------------------------------
// sRGB(D65)
//------------------------------------------------------------
float3 SRGBToRGBLinear(float3 rgb)
{
const float t = 0.04045;
float3 a = rgb / 12.92;
float3 b = pow((rgb+0.055)/1.055, 2.4);
return float3(
rgb.r<=t ? a.r : b.r,
rgb.g<=t ? a.g : b.g,
rgb.b<=t ? a.b : b.b
);
}
float3 RGBLinearToSRGB(float3 rgb)
{
const float t = 0.031308;
float3 a = rgb * 12.92;
float3 b = 1.055*pow(rgb, 1/2.4) - 0.055;
float3 srgb = float3(
rgb.r<=t ? a.r : b.r,
rgb.g<=t ? a.g : b.g,
rgb.b<=t ? a.b : b.b
);
return saturate(srgb);
}
float3 RGBToXYZ(float3 rgb)
{
return RGBLinearToXYZ(SRGBToRGBLinear(rgb));
}
float3 XYZToRGB(float3 xyz)
{
float3 rgbl = XYZToRGBLinear(xyz);
return RGBLinearToSRGB(rgbl);
}
// Note: the L* coordinate ranges from 0 to 100.
float3 RGBToLAB(float3 rgb)
{
return XYZToLAB(RGBToXYZ(rgb));
}
float3 LABToRGB(float3 lab)
{
return XYZToRGB(LABToXYZ(lab));
}