@@ -31,7 +31,7 @@ struct GradientVertexOutput {
31
31
@location (0 ) uv : vec2 <f32 >,
32
32
@location (1 ) @interpolate (flat ) size : vec2 <f32 >,
33
33
@location (2 ) @interpolate (flat ) flags : u32 ,
34
- @location (3 ) @interpolate (flat ) radius : vec4 <f32 >,
34
+ @location (3 ) @interpolate (flat ) radius : vec4 <f32 >,
35
35
@location (4 ) @interpolate (flat ) border : vec4 <f32 >,
36
36
37
37
// Position relative to the center of the rectangle.
@@ -114,27 +114,27 @@ fn fragment(in: GradientVertexOutput) -> @location(0) vec4<f32> {
114
114
}
115
115
}
116
116
117
- // This function converts two linear rgb colors to srgb space, mixes them, and then converts the result back to linear rgb space.
118
- fn mix_linear_rgb_in_srgb_space (a : vec4 <f32 >, b : vec4 <f32 >, t : f32 ) -> vec4 <f32 > {
117
+ // This function converts two linear rgba colors to srgba space, mixes them, and then converts the result back to linear rgb space.
118
+ fn mix_linear_rgba_in_srgba_space (a : vec4 <f32 >, b : vec4 <f32 >, t : f32 ) -> vec4 <f32 > {
119
119
let a_srgb = pow (a . rgb, vec3 (1 . / 2.2 ));
120
120
let b_srgb = pow (b . rgb, vec3 (1 . / 2.2 ));
121
121
let mixed_srgb = mix (a_srgb , b_srgb , t );
122
122
return vec4 (pow (mixed_srgb , vec3 (2.2 )), mix (a . a, b . a, t ));
123
123
}
124
124
125
- fn linear_rgb_to_oklab (c : vec4 <f32 >) -> vec4 <f32 > {
125
+ fn linear_rgba_to_oklaba (c : vec4 <f32 >) -> vec4 <f32 > {
126
126
let l = pow (0.41222146 * c . x + 0.53633255 * c . y + 0.051445995 * c . z, 1 . / 3 . );
127
127
let m = pow (0.2119035 * c . x + 0.6806995 * c . y + 0.10739696 * c . z, 1 . / 3 . );
128
128
let s = pow (0.08830246 * c . x + 0.28171885 * c . y + 0.6299787 * c . z, 1 . / 3 . );
129
129
return vec4 (
130
130
0.21045426 * l + 0.7936178 * m - 0.004072047 * s ,
131
131
1.9779985 * l - 2.4285922 * m + 0.4505937 * s ,
132
- 0.025904037 * l + 0.78277177 * m - 0.80867577 * s ,
133
- c . w
132
+ 0.025904037 * l + 0.78277177 * m - 0.80867577 * s ,
133
+ c . a
134
134
);
135
135
}
136
136
137
- fn oklab_to_linear_rgba (c : vec4 <f32 >) -> vec4 <f32 > {
137
+ fn oklaba_to_linear_rgba (c : vec4 <f32 >) -> vec4 <f32 > {
138
138
let l_ = c . x + 0.39633778 * c . y + 0.21580376 * c . z;
139
139
let m_ = c . x - 0.105561346 * c . y - 0.06385417 * c . z;
140
140
let s_ = c . x - 0.08948418 * c . y - 1.2914855 * c . z;
@@ -145,26 +145,127 @@ fn oklab_to_linear_rgba(c: vec4<f32>) -> vec4<f32> {
145
145
4.0767417 * l - 3.3077116 * m + 0.23096994 * s ,
146
146
- 1.268438 * l + 2.6097574 * m - 0.34131938 * s ,
147
147
- 0.0041960863 * l - 0.7034186 * m + 1.7076147 * s ,
148
- c . w
148
+ c . a
149
149
);
150
150
}
151
151
152
- fn mix_linear_rgb_in_oklab_space (a : vec4 <f32 >, b : vec4 <f32 >, t : f32 ) -> vec4 <f32 > {
153
- return oklab_to_linear_rgba (mix (linear_rgb_to_oklab (a ), linear_rgb_to_oklab (b ), t ));
152
+ fn mix_linear_rgba_in_oklaba_space (a : vec4 <f32 >, b : vec4 <f32 >, t : f32 ) -> vec4 <f32 > {
153
+ return oklaba_to_linear_rgba (mix (linear_rgba_to_oklaba (a ), linear_rgba_to_oklaba (b ), t ));
154
+ }
155
+
156
+ fn linear_rgba_to_hsla (c : vec4 <f32 >) -> vec4 <f32 > {
157
+ let maxc = max (max (c . r, c . g), c . b);
158
+ let minc = min (min (c . r, c . g), c . b);
159
+ let delta = maxc - minc ;
160
+ let l = (maxc + minc ) * 0.5 ;
161
+ var h : f32 = 0.0 ;
162
+ var s : f32 = 0.0 ;
163
+ if delta != 0.0 {
164
+ s = delta / (1.0 - abs (2.0 * l - 1.0 ));
165
+ if maxc == c . r {
166
+ h = ((c . g - c . b) / delta ) % 6.0 ;
167
+ } else if maxc == c . g {
168
+ h = ((c . b - c . r) / delta ) + 2.0 ;
169
+ } else {
170
+ h = ((c . r - c . g) / delta ) + 4.0 ;
171
+ }
172
+ h = h / 6.0 ;
173
+ if h < 0.0 {
174
+ h = h + 1.0 ;
175
+ }
176
+ }
177
+ return vec4 <f32 >(h , s , l , c . a);
178
+ }
179
+
180
+ fn hsla_to_linear_rgba (hsl : vec4 <f32 >) -> vec4 <f32 > {
181
+ let h = hsl . x;
182
+ let s = hsl . y;
183
+ let l = hsl . z;
184
+ let c = (1.0 - abs (2.0 * l - 1.0 )) * s ;
185
+ let hp = h * 6.0 ;
186
+ let x = c * (1.0 - abs (hp % 2.0 - 1.0 ));
187
+ var r : f32 = 0.0 ;
188
+ var g : f32 = 0.0 ;
189
+ var b : f32 = 0.0 ;
190
+ if 0.0 <= hp && hp < 1.0 {
191
+ r = c ; g = x ; b = 0.0 ;
192
+ } else if 1.0 <= hp && hp < 2.0 {
193
+ r = x ; g = c ; b = 0.0 ;
194
+ } else if 2.0 <= hp && hp < 3.0 {
195
+ r = 0.0 ; g = c ; b = x ;
196
+ } else if 3.0 <= hp && hp < 4.0 {
197
+ r = 0.0 ; g = x ; b = c ;
198
+ } else if 4.0 <= hp && hp < 5.0 {
199
+ r = x ; g = 0.0 ; b = c ;
200
+ } else if 5.0 <= hp && hp < 6.0 {
201
+ r = c ; g = 0.0 ; b = x ;
202
+ }
203
+ let m = l - 0.5 * c ;
204
+ return vec4 <f32 >(r + m , g + m , b + m , hsl . a);
205
+ }
206
+
207
+ fn linear_rgba_to_hsva (c : vec4 <f32 >) -> vec4 <f32 > {
208
+ let maxc = max (max (c . r, c . g), c . b);
209
+ let minc = min (min (c . r, c . g), c . b);
210
+ let delta = maxc - minc ;
211
+ var h : f32 = 0.0 ;
212
+ var s : f32 = 0.0 ;
213
+ let v : f32 = maxc ;
214
+ if delta != 0.0 {
215
+ s = delta / maxc ;
216
+ if maxc == c . r {
217
+ h = ((c . g - c . b) / delta ) % 6.0 ;
218
+ } else if maxc == c . g {
219
+ h = ((c . b - c . r) / delta ) + 2.0 ;
220
+ } else {
221
+ h = ((c . r - c . g) / delta ) + 4.0 ;
222
+ }
223
+ h = h / 6.0 ;
224
+ if h < 0.0 {
225
+ h = h + 1.0 ;
226
+ }
227
+ }
228
+ return vec4 <f32 >(h , s , v , c . a);
229
+ }
230
+
231
+ fn hsva_to_linear_rgba (hsva : vec4 <f32 >) -> vec4 <f32 > {
232
+ let h = hsva . x * 6.0 ;
233
+ let s = hsva . y;
234
+ let v = hsva . z;
235
+ let c = v * s ;
236
+ let x = c * (1.0 - abs (h % 2.0 - 1.0 ));
237
+ let m = v - c ;
238
+ var r : f32 = 0.0 ;
239
+ var g : f32 = 0.0 ;
240
+ var b : f32 = 0.0 ;
241
+ if 0.0 <= h && h < 1.0 {
242
+ r = c ; g = x ; b = 0.0 ;
243
+ } else if 1.0 <= h && h < 2.0 {
244
+ r = x ; g = c ; b = 0.0 ;
245
+ } else if 2.0 <= h && h < 3.0 {
246
+ r = 0.0 ; g = c ; b = x ;
247
+ } else if 3.0 <= h && h < 4.0 {
248
+ r = 0.0 ; g = x ; b = c ;
249
+ } else if 4.0 <= h && h < 5.0 {
250
+ r = x ; g = 0.0 ; b = c ;
251
+ } else if 5.0 <= h && h < 6.0 {
252
+ r = c ; g = 0.0 ; b = x ;
253
+ }
254
+ return vec4 <f32 >(r + m , g + m , b + m , hsva . a);
154
255
}
155
256
156
257
/// hue is left in radians and not converted to degrees
157
- fn linear_rgb_to_oklch (c : vec4 <f32 >) -> vec4 <f32 > {
158
- let o = linear_rgb_to_oklab (c );
258
+ fn linear_rgba_to_oklcha (c : vec4 <f32 >) -> vec4 <f32 > {
259
+ let o = linear_rgba_to_oklaba (c );
159
260
let chroma = sqrt (o . y * o . y + o . z * o . z);
160
261
let hue = atan2 (o . z, o . y);
161
- return vec4 (o . x, chroma , select (hue + TAU , hue , hue < 0.0 ), o . w );
262
+ return vec4 (o . x, chroma , select (hue + TAU , hue , hue < 0.0 ), o . a );
162
263
}
163
264
164
- fn oklch_to_linear_rgb (c : vec4 <f32 >) -> vec4 <f32 > {
265
+ fn oklcha_to_linear_rgba (c : vec4 <f32 >) -> vec4 <f32 > {
165
266
let a = c . y * cos (c . z);
166
267
let b = c . y * sin (c . z);
167
- return oklab_to_linear_rgba (vec4 (c . x, a , b , c . w ));
268
+ return oklaba_to_linear_rgba (vec4 (c . x, a , b , c . a ));
168
269
}
169
270
170
271
fn rem_euclid (a : f32 , b : f32 ) -> f32 {
@@ -181,28 +282,75 @@ fn lerp_hue_long(a: f32, b: f32, t: f32) -> f32 {
181
282
return rem_euclid (a + select (diff - TAU , diff + TAU , 0 . < diff ) * t , TAU );
182
283
}
183
284
184
- fn mix_oklch (a : vec4 <f32 >, b : vec4 <f32 >, t : f32 ) -> vec4 <f32 > {
285
+ fn mix_oklcha (a : vec4 <f32 >, b : vec4 <f32 >, t : f32 ) -> vec4 <f32 > {
185
286
return vec4 (
186
287
mix (a . xy, b . xy, t ),
187
288
lerp_hue (a . z, b . z, t ),
188
- mix (a . w , b . w , t )
289
+ mix (a . a , b . a , t )
189
290
);
190
291
}
191
292
192
- fn mix_oklch_long (a : vec4 <f32 >, b : vec4 <f32 >, t : f32 ) -> vec4 <f32 > {
293
+ fn mix_oklcha_long (a : vec4 <f32 >, b : vec4 <f32 >, t : f32 ) -> vec4 <f32 > {
193
294
return vec4 (
194
295
mix (a . xy, b . xy, t ),
195
296
lerp_hue_long (a . z, b . z, t ),
196
- mix (a . w , b . w , t )
297
+ mix (a . a , b . a , t )
197
298
);
198
299
}
199
300
200
- fn mix_linear_rgb_in_oklch_space (a : vec4 <f32 >, b : vec4 <f32 >, t : f32 ) -> vec4 <f32 > {
201
- return oklch_to_linear_rgb (mix_oklch (linear_rgb_to_oklch (a ), linear_rgb_to_oklch (b ), t ));
301
+ fn mix_linear_rgba_in_oklcha_space (a : vec4 <f32 >, b : vec4 <f32 >, t : f32 ) -> vec4 <f32 > {
302
+ return oklcha_to_linear_rgba (mix_oklcha (linear_rgba_to_oklcha (a ), linear_rgba_to_oklcha (b ), t ));
303
+ }
304
+
305
+ fn mix_linear_rgba_in_oklcha_space_long (a : vec4 <f32 >, b : vec4 <f32 >, t : f32 ) -> vec4 <f32 > {
306
+ return oklcha_to_linear_rgba (mix_oklcha_long (linear_rgba_to_oklcha (a ), linear_rgba_to_oklcha (b ), t ));
307
+ }
308
+
309
+ fn mix_linear_rgba_in_hsva_space (a : vec4 <f32 >, b : vec4 <f32 >, t : f32 ) -> vec4 <f32 > {
310
+ let ha = linear_rgba_to_hsva (a );
311
+ let hb = linear_rgba_to_hsva (b );
312
+ var h : f32 ;
313
+ if ha . y == 0 . {
314
+ h = hb . x;
315
+ } else if hb . y == 0 . {
316
+ h = ha . x;
317
+ } else {
318
+ h = lerp_hue (ha . x * TAU , hb . x * TAU , t ) / TAU ;
319
+ }
320
+ let s = mix (ha . y, hb . y, t );
321
+ let v = mix (ha . z, hb . z, t );
322
+ let a_alpha = mix (ha . a, hb . a, t );
323
+ return hsva_to_linear_rgba (vec4 <f32 >(h , s , v , a_alpha ));
324
+ }
325
+
326
+ fn mix_linear_rgba_in_hsva_space_long (a : vec4 <f32 >, b : vec4 <f32 >, t : f32 ) -> vec4 <f32 > {
327
+ let ha = linear_rgba_to_hsva (a );
328
+ let hb = linear_rgba_to_hsva (b );
329
+ let h = lerp_hue_long (ha . x * TAU , hb . x * TAU , t ) / TAU ;
330
+ let s = mix (ha . y, hb . y, t );
331
+ let v = mix (ha . z, hb . z, t );
332
+ let a_alpha = mix (ha . a, hb . a, t );
333
+ return hsva_to_linear_rgba (vec4 <f32 >(h , s , v , a_alpha ));
334
+ }
335
+
336
+ fn mix_linear_rgba_in_hsla_space (a : vec4 <f32 >, b : vec4 <f32 >, t : f32 ) -> vec4 <f32 > {
337
+ let ha = linear_rgba_to_hsla (a );
338
+ let hb = linear_rgba_to_hsla (b );
339
+ let h = lerp_hue (ha . x * TAU , hb . x * TAU , t ) / TAU ;
340
+ let s = mix (ha . y, hb . y, t );
341
+ let l = mix (ha . z, hb . z, t );
342
+ let a_alpha = mix (ha . a, hb . a, t );
343
+ return hsla_to_linear_rgba (vec4 <f32 >(h , s , l , a_alpha ));
202
344
}
203
345
204
- fn mix_linear_rgb_in_oklch_space_long (a : vec4 <f32 >, b : vec4 <f32 >, t : f32 ) -> vec4 <f32 > {
205
- return oklch_to_linear_rgb (mix_oklch_long (linear_rgb_to_oklch (a ), linear_rgb_to_oklch (b ), t ));
346
+ fn mix_linear_rgba_in_hsla_space_long (a : vec4 <f32 >, b : vec4 <f32 >, t : f32 ) -> vec4 <f32 > {
347
+ let ha = linear_rgba_to_hsla (a );
348
+ let hb = linear_rgba_to_hsla (b );
349
+ let h = lerp_hue_long (ha . x * TAU , hb . x * TAU , t ) / TAU ;
350
+ let s = mix (ha . y, hb . y, t );
351
+ let l = mix (ha . z, hb . z, t );
352
+ let a_alpha = mix (ha . a, hb . a, t );
353
+ return hsla_to_linear_rgba (vec4 <f32 >(h , s , l , a_alpha ));
206
354
}
207
355
208
356
// These functions are used to calculate the distance in gradient space from the start of the gradient to the point.
@@ -277,13 +425,21 @@ fn interpolate_gradient(
277
425
}
278
426
279
427
#ifdef IN_SRGB
280
- return mix_linear_rgb_in_srgb_space (start_color , end_color , t );
428
+ return mix_linear_rgba_in_srgba_space (start_color , end_color , t );
281
429
#else ifdef IN_OKLAB
282
- return mix_linear_rgb_in_oklab_space (start_color , end_color , t );
430
+ return mix_linear_rgba_in_oklaba_space (start_color , end_color , t );
283
431
#else ifdef IN_OKLCH
284
- return mix_linear_rgb_in_oklch_space (start_color , end_color , t );
432
+ return mix_linear_rgba_in_oklcha_space (start_color , end_color , t );
285
433
#else ifdef IN_OKLCH_LONG
286
- return mix_linear_rgb_in_oklch_space_long (start_color , end_color , t );
434
+ return mix_linear_rgba_in_oklcha_space_long (start_color , end_color , t );
435
+ #else ifdef IN_HSV
436
+ return mix_linear_rgba_in_hsva_space (start_color , end_color , t );
437
+ #else ifdef IN_HSV_LONG
438
+ return mix_linear_rgba_in_hsva_space_long (start_color , end_color , t );
439
+ #else ifdef IN_HSL
440
+ return mix_linear_rgba_in_hsla_space (start_color , end_color , t );
441
+ #else ifdef IN_HSL_LONG
442
+ return mix_linear_rgba_in_hsla_space_long (start_color , end_color , t );
287
443
#else
288
444
return mix (start_color , end_color , t );
289
445
#endif
0 commit comments