@@ -230,6 +230,18 @@ fn gradient(
230230 let unit = normalize (v1 );
231231 let coord_offset = dot (unit , v2 ) / length (v1 );
232232
233+ let to_lms : mat3x4 <f32 > = mat3x4 <f32 >(
234+ vec4 <f32 >(0 .4121656120 , 0 .2118591070 , 0 .0883097947 , 0 .0 ),
235+ vec4 <f32 >(0 .5362752080 , 0 .6807189584 , 0 .2818474174 , 0 .0 ),
236+ vec4 <f32 >(0 .0514575653 , 0 .1074065790 , 0 .6302613616 , 0 .0 ),
237+ );
238+
239+ let to_rgb : mat3x4 <f32 > = mat3x4 <f32 >(
240+ vec4 <f32 >( 4 .0767245293 , - 3 .3072168827 , 0 .2307590544 , 0 .0 ),
241+ vec4 <f32 >(- 1 .2681437731 , 2 .6093323231 , - 0 .3411344290 , 0 .0 ),
242+ vec4 <f32 >(- 0 .0041119885 , - 0 .7034763098 , 1 .7068625689 , 0 .0 ),
243+ );
244+
233245 //need to store these as a var to use dynamic indexing in a loop
234246 //this is already added to wgsl spec but not in wgpu yet
235247 var colors_arr = colors ;
@@ -248,11 +260,15 @@ fn gradient(
248260 }
249261
250262 if (curr_offset <= coord_offset && coord_offset <= next_offset ) {
251- color = mix (colors_arr [i ], colors_arr [i + 1 ], smoothstep (
252- curr_offset ,
253- next_offset ,
254- coord_offset ,
255- ));
263+ // blend in OKLab
264+ let factor = smoothstep (curr_offset , next_offset , coord_offset );
265+ let lms_a = pow (colors_arr [i ] * to_lms , vec3 <f32 >(1 .0 / 3 .0 , 1 .0 / 3 .0 , 1 .0 / 3 .0 ));
266+ let lms_b = pow (colors_arr [i + 1 ] * to_lms , vec3 <f32 >(1 .0 / 3 .0 , 1 .0 / 3 .0 , 1 .0 / 3 .0 ));
267+ let mixed = mix (lms_a , lms_b , factor );
268+
269+ // back to sRGB
270+ color = to_rgb * (mixed * mixed * mixed );
271+ color . a = mix (colors_arr [i ]. a , colors_arr [i + 1 ]. a , factor );
256272 }
257273
258274 if (coord_offset >= offsets_arr [last_index ]) {
0 commit comments