Search across packages, versions, files, declarations, and comments. Use multiple terms to narrow results (AND), and add @vertex, @fragment, or @compute to filter by shader stage.
1#define_import_path bevy_ui_render::color_space
2#import bevy_render::maths::PI
4const TAU: f32 = 2. * PI;
5const HUE_GUARD: f32 = 0.0001;
7// https://en.wikipedia.org/wiki/SRGB
8fn gamma(value: f32) -> f32 {
9 if value <= 0.0 {
10 return value;
11 }
12 if value <= 0.04045 {
13 return value / 12.92; // linear falloff in dark values
14 } else {
15 return pow((value + 0.055) / 1.055, 2.4); // gamma curve in other area
16 }
19// https://en.wikipedia.org/wiki/SRGB
20fn inverse_gamma(value: f32) -> f32 {
21 if value <= 0.0 {
22 return value;
23 }
25 if value <= 0.0031308 {
26 return value * 12.92; // linear falloff in dark values
27 } else {
28 return 1.055 * pow(value, 1.0 / 2.4) - 0.055; // gamma curve in other area
29 }
32fn srgb_to_linear_rgb(color: vec3<f32>) -> vec3<f32> {
33 return vec3(
34 gamma(color.x),
35 gamma(color.y),
36 gamma(color.z)
37 );
40fn linear_rgb_to_srgb(color: vec3<f32>) -> vec3<f32> {
41 return vec3(
42 inverse_gamma(color.x),
43 inverse_gamma(color.y),
44 inverse_gamma(color.z)
45 );
48fn oklab_to_linear_rgb(c: vec3<f32>) -> vec3<f32> {
49 let l_ = c.x + 0.39633778 * c.y + 0.21580376 * c.z;
50 let m_ = c.x - 0.105561346 * c.y - 0.06385417 * c.z;
51 let s_ = c.x - 0.08948418 * c.y - 1.2914855 * c.z;
52 let l = l_ * l_ * l_;
53 let m = m_ * m_ * m_;
54 let s = s_ * s_ * s_;
55 return vec3(
56 4.0767417 * l - 3.3077116 * m + 0.23096994 * s,
57 -1.268438 * l + 2.6097574 * m - 0.34131938 * s,
58 -0.0041960863 * l - 0.7034186 * m + 1.7076147 * s,
59 );
62fn hsl_to_linear_rgb(hsl: vec3<f32>) -> vec3<f32> {
63 let h = hsl.x;
64 let s = hsl.y;
65 let l = hsl.z;
66 let c = (1.0 - abs(2.0 * l - 1.0)) * s;
67 let hp = h * 6.0;
68 let x = c * (1.0 - abs(hp % 2.0 - 1.0));
69 var r: f32 = 0.0;
70 var g: f32 = 0.0;
71 var b: f32 = 0.0;
72 if 0.0 <= hp && hp < 1.0 {
73 r = c; g = x; b = 0.0;
74 } else if 1.0 <= hp && hp < 2.0 {
75 r = x; g = c; b = 0.0;
76 } else if 2.0 <= hp && hp < 3.0 {
77 r = 0.0; g = c; b = x;
78 } else if 3.0 <= hp && hp < 4.0 {
79 r = 0.0; g = x; b = c;
80 } else if 4.0 <= hp && hp < 5.0 {
81 r = x; g = 0.0; b = c;
82 } else if 5.0 <= hp && hp < 6.0 {
83 r = c; g = 0.0; b = x;
84 }
85 let m = l - 0.5 * c;
86 return srgb_to_linear_rgb(vec3(r + m, g + m, b + m));
89fn hsv_to_linear_rgb(hsva: vec3<f32>) -> vec3<f32> {
90 let h = hsva.x * 6.0;
91 let s = hsva.y;
92 let v = hsva.z;
93 let c = v * s;
94 let x = c * (1.0 - abs(h % 2.0 - 1.0));
95 let m = v - c;
96 var r: f32 = 0.0;
97 var g: f32 = 0.0;
98 var b: f32 = 0.0;
99 if 0.0 <= h && h < 1.0 {
100 r = c; g = x; b = 0.0;
101 } else if 1.0 <= h && h < 2.0 {
102 r = x; g = c; b = 0.0;
103 } else if 2.0 <= h && h < 3.0 {
104 r = 0.0; g = c; b = x;
105 } else if 3.0 <= h && h < 4.0 {
106 r = 0.0; g = x; b = c;
107 } else if 4.0 <= h && h < 5.0 {
108 r = x; g = 0.0; b = c;
109 } else if 5.0 <= h && h < 6.0 {
110 r = c; g = 0.0; b = x;
111 }
112 return srgb_to_linear_rgb(vec3(r + m, g + m, b + m));
115fn oklch_to_linear_rgb(c: vec3<f32>) -> vec3<f32> {
116 let hue = c.z * TAU;
117 return oklab_to_linear_rgb(vec3(c.x, c.y * cos(hue), c.y * sin(hue)));
120fn mix_oklch(a: vec3<f32>, b: vec3<f32>, t: f32) -> vec3<f32> {
121 // If the chroma is close to zero for one of the endpoints, don't interpolate
122 // the hue and instead use the hue of the other endpoint. This allows gradients that smoothly
123 // transition from black or white to a target color without passing through unrelated hues.
124 var h = a.z;
125 var g = b.z;
126 if a.y < HUE_GUARD {
127 h = g;
128 } else if b.y < HUE_GUARD {
129 g = h;
130 }
132 let hue_diff = g - h;
133 if abs(hue_diff) > 0.5 {
134 if hue_diff > 0.0 {
135 h += (hue_diff - 1.) * t;
136 } else {
137 h += (hue_diff + 1.) * t;
138 }
139 } else {
140 h += hue_diff * t;
141 }
142 return vec3(
143 mix(a.x, b.x, t),
144 mix(a.y, b.y, t),
145 fract(h),
146 );
149fn mix_oklch_long(a: vec3<f32>, b: vec3<f32>, t: f32) -> vec3<f32> {
150 var h = a.z;
151 var g = b.z;
152 if a.y < HUE_GUARD {
153 h = g;
154 } else if b.y < HUE_GUARD {
155 g = h;
156 }
158 let hue_diff = g - h;
159 if abs(hue_diff) < 0.5 {
160 if hue_diff >= 0.0 {
161 h += (hue_diff - 1.) * t;
162 } else {
163 h += (hue_diff + 1.) * t;
164 }
165 } else {
166 h += hue_diff * t;
167 }
168 return vec3(
169 mix(a.x, b.x, t),
170 mix(a.y, b.y, t),
171 fract(h),
172 );
175fn mix_hsl(a: vec3<f32>, b: vec3<f32>, t: f32) -> vec3<f32> {
176 // If the saturation is close to zero for one of the endpoints, don't interpolate
177 // the hue and instead use the hue of the other endpoint. This allows gradients that smoothly
178 // transition from black or white to a target color without passing through unrelated hues.
179 var h = a.x;
180 var g = b.x;
181 if a.y < HUE_GUARD {
182 h = g;
183 } else if b.y < HUE_GUARD {
184 g = h;
185 }
187 return vec3(
188 fract(h + (fract(g - h + 0.5) - 0.5) * t),
189 mix(a.y, b.y, t),
190 mix(a.z, b.z, t),
191 );
194fn mix_hsl_long(a: vec3<f32>, b: vec3<f32>, t: f32) -> vec3<f32> {
195 var h = a.x;
196 var g = b.x;
197 if a.y < HUE_GUARD {
198 h = g;
199 } else if b.y < HUE_GUARD {
200 g = h;
201 }
203 let d = fract(g - h + 0.5) - 0.5;
204 return vec3(
205 fract(h + (d + select(1., -1., 0. < d)) * t),
206 mix(a.y, b.y, t),
207 mix(a.z, b.z, t),
208 );
211fn mix_hsv(a: vec3<f32>, b: vec3<f32>, t: f32) -> vec3<f32> {
212 // If the saturation is close to zero for one of the endpoints, don't interpolate
213 // the hue and instead use the hue of the other endpoint. This allows gradients that smoothly
214 // transition from black or white to a target color without passing through unrelated hues.
215 var h = a.x;
216 var g = b.x;
217 if a.y < HUE_GUARD {
218 h = g;
219 } else if b.y < HUE_GUARD {
220 g = h;
221 }
223 let hue_diff = g - h;
224 if abs(hue_diff) > 0.5 {
225 if hue_diff > 0.0 {
226 h += (hue_diff - 1.0) * t;
227 } else {
228 h += (hue_diff + 1.0) * t;
229 }
230 } else {
231 h += hue_diff * t;
232 }
233 return vec3(
234 fract(h),
235 mix(a.y, b.y, t),
236 mix(a.z, b.z, t),
237 );
240fn mix_hsv_long(a: vec3<f32>, b: vec3<f32>, t: f32) -> vec3<f32> {
241 var h = a.x;
242 var g = b.x;
243 if a.y < HUE_GUARD {
244 h = g;
245 } else if b.y < HUE_GUARD {
246 g = h;
247 }
249 let hue_diff = g - h;
250 if abs(hue_diff) < 0.5 {
251 if hue_diff >= 0.0 {
252 h += (hue_diff - 1.0) * t;
253 } else {
254 h += (hue_diff + 1.0) * t;
255 }
256 } else {
257 h += hue_diff * t;
258 }
259 return vec3(
260 fract(h),
261 mix(a.y, b.y, t),
262 mix(a.z, b.z, t),
263 );
Contents