@@ -11,6 +11,7 @@ struct VertexOutput {
1111 @location (4 ) border_color : vec4 <f32 >,
1212 @location (5 ) border_width : f32 ,
1313 @location (6 ) radius : f32 ,
14+ @location (7 ) pos : vec2 <f32 >,
1415 @builtin (position ) position : vec4 <f32 >,
1516
1617};
@@ -60,13 +61,48 @@ fn vertex(
6061 // clamp radius between (0.0) and (shortest side / 2.0)
6162 out . radius = clamp (out . radius , 0 .0 , min (out . size . x , out . size . y ) / 2 .0 );
6263
63-
64+ out . pos = vertex_position . xy ;
6465 out . uv = vertex_uv ;
6566 out . position = view . view_proj * vec4 <f32 >(vertex_position , 1 .0 );
6667 out . color = unpack_color_from_u32 (node . color );
6768 return out ;
6869}
6970
71+
72+ fn distance_alg (
73+ frag_coord : vec2 <f32 >,
74+ position : vec2 <f32 >,
75+ size : vec2 <f32 >,
76+ radius : f32
77+ ) -> f32 {
78+ var inner_size : vec2 <f32 > = size - vec2 <f32 >(radius , radius ) * 2 .0 ;
79+ var top_left : vec2 <f32 > = position + vec2 <f32 >(radius , radius );
80+ var bottom_right : vec2 <f32 > = top_left + inner_size ;
81+
82+ var top_left_distance : vec2 <f32 > = top_left - frag_coord ;
83+ var bottom_right_distance : vec2 <f32 > = frag_coord - bottom_right ;
84+
85+ var dist : vec2 <f32 > = vec2 <f32 >(
86+ max (max (top_left_distance . x , bottom_right_distance . x ), 0 .0 ),
87+ max (max (top_left_distance . y , bottom_right_distance . y ), 0 .0 )
88+ );
89+
90+ return sqrt (dist . x * dist . x + dist . y * dist . y );
91+ }
92+
93+ // Based on the fragement position and the center of the quad, select one of the 4 radi.
94+ // Order matches CSS border radius attribute:
95+ // radi.x = top-left, radi.y = top-right, radi.z = bottom-right, radi.w = bottom-left
96+ fn select_border_radius (radi : vec4 <f32 >, position : vec2 <f32 >, center : vec2 <f32 >) -> f32 {
97+ var rx = radi . x ;
98+ var ry = radi . y ;
99+ rx = select (radi . x , radi . y , position . x > center . x );
100+ ry = select (radi . w , radi . z , position . x > center . x );
101+ rx = select (rx , ry , position . y > center . y );
102+ return rx ;
103+ }
104+
105+
70106@group (1 ) @binding (0 )
71107var sprite_texture : texture_2d <f32 >;
72108@group (1 ) @binding (1 )
@@ -80,15 +116,43 @@ fn distance_round_border(point: vec2<f32>, size: vec2<f32>, radius: f32) -> f32
80116fn fragment (in : VertexOutput ) -> @location (0 ) vec4 <f32 > {
81117 var color = textureSample (sprite_texture , sprite_sampler , in . uv );
82118 color = in . color * color ;
119+
120+
83121
84- if ( in . radius > 0 .0 || in . border_width > 0 .0 ) {
85- var distance = distance_round_border ( in . point , in . size * 0 .5 , in . radius );
122+ var border_radius = in . radius ;
123+ var scale = vec2 ( 1 .0 , 1 .0 );
86124
87- var inner_alpha = 1 .0 - smoothstep (0 .0 , 0 .0 , distance );
88- var border_alpha = 1 .0 - smoothstep (in . border_width , in . border_width , abs (distance ));
89- color = mix (vec4 <f32 >(0 .0 ), mix (color , in . border_color , border_alpha ), inner_alpha );
125+ if (in . border_width > 0 .0 ) {
126+ var internal_border : f32 = max (border_radius - in . border_width , 0 .0 );
127+
128+ var internal_distance : f32 = distance_alg (
129+ in . position . xy ,
130+ in . pos + vec2 <f32 >(in . border_width , in . border_width ),
131+ scale - vec2 <f32 >(in . border_width * 2 .0 , in . border_width * 2 .0 ),
132+ internal_border
133+ );
134+
135+ var border_mix : f32 = smoothstep (
136+ max (internal_border - 0 .5 , 0 .0 ),
137+ internal_border + 0 .5 ,
138+ internal_distance
139+ );
140+
141+ color = mix (in . color , in . border_color , vec4 <f32 >(border_mix , border_mix , border_mix , border_mix ));
90142 }
91143
144+ var dist : f32 = distance_alg (
145+ vec2 <f32 >(in . position . x , in . position . y ),
146+ in . pos ,
147+ scale ,
148+ border_radius
149+ );
150+
151+ var radius_alpha : f32 = 1 .0 - smoothstep (
152+ max (border_radius - 0 .5 , 0 .0 ),
153+ border_radius + 0 .5 ,
154+ dist
155+ );
92156
93- return color ;
157+ return vec4 < f32 >( color . x , color . y , color . z , color . w * radius_alpha ) ;
94158}
0 commit comments