@@ -84,20 +84,23 @@ const char masking_glsl[] = GLSL(330,
8484 layout (location = UNIFORM_MASK_INVERTED_LOC )
8585 uniform bool mask_inverted ;
8686 in vec2 texcoord ;
87- float mask_rectangle_sdf (vec2 point , vec2 half_size ) {
88- vec2 d = abs (point ) - half_size ;
89- return length (max (d , 0.0 ));
87+ vec2 mask_rectangle_sdf (vec2 point , vec2 half_size ) {
88+ vec2 d = max (abs (point ) - half_size , 0.0 );
89+ float l = length (d );
90+ // Add a small number to avoid 0/0.
91+ return vec2 (l , l / (max (d .x , d .y ) + 1e-8 ));
9092 }
9193 float mask_factor () {
9294 vec2 mask_size = textureSize (mask_tex , 0 );
9395 vec2 maskcoord = texcoord - mask_offset ;
9496 vec4 mask = texture2D (mask_tex , maskcoord / mask_size );
9597 if (mask_corner_radius != 0 ) {
9698 vec2 inner_size = mask_size - vec2 (mask_corner_radius ) * 2.0f ;
97- float dist = mask_rectangle_sdf (maskcoord - mask_size / 2.0f ,
98- inner_size / 2.0f ) - mask_corner_radius + 1.0f ;
99+ vec2 sdf = mask_rectangle_sdf (maskcoord - mask_size / 2.0f ,
100+ inner_size / 2.0f );
101+ float dist = sdf .x - mask_corner_radius + sdf .y / 2.0f ;
99102 if (dist > 0.0f ) {
100- mask .r *= (1.0f - clamp (dist , 0.0f , 1.0f ));
103+ mask .r *= (1.0f - clamp (dist , 0.0f , sdf . y ) / ( sdf . y + 1e-8 ));
101104 }
102105 }
103106 if (mask_inverted ) {
@@ -130,9 +133,13 @@ const char blit_shader_glsl[] = GLSL(330,
130133 uniform float time ;
131134 // Signed distance field for rectangle center at (0, 0), with size of
132135 // half_size * 2
133- float rectangle_sdf (vec2 point , vec2 half_size ) {
134- vec2 d = abs (point ) - half_size ;
135- return length (max (d , 0.0 ));
136+ // Returns 2 number: the distance, and the approximate chord length inside
137+ // the pixel around `point`.
138+ vec2 rectangle_sdf (vec2 point , vec2 half_size ) {
139+ vec2 d = max (abs (point ) - half_size , 0.0 );
140+ float l = length (d );
141+ // Add a small number to avoid 0/0.
142+ return vec2 (l , l / (max (d .x , d .y ) + 1e-8 ));
136143 }
137144
138145 vec4 default_post_processing (vec4 c ) {
@@ -162,16 +169,20 @@ const char blit_shader_glsl[] = GLSL(330,
162169
163170 vec2 outer_size = effective_size ;
164171 vec2 inner_size = outer_size - vec2 (corner_radius ) * 2.0f ;
165- // +1.0 so the last 1-pixel ring of the rounded rectangle will transition
166- // smoothly from 1 to 0 for anti-aliasing. If we don't do this, everything
167- // inside the corner radius will be solid, and we will have an extra 1-pixel
168- // feathering outside the corner radius, which makes it look bad.
169- float rect_distance = rectangle_sdf (texcoord - outer_size / 2.0f ,
170- inner_size / 2.0f ) - corner_radius + 1.0f ;
172+ vec2 sdf = rectangle_sdf (texcoord - outer_size / 2.0f ,
173+ inner_size / 2.0f );
174+ // For anti-aliasing, we estimate how much of the pixel is covered by the rounded
175+ // rectangle. This differs depends on at what angle the circle sweeps through the
176+ // pixel. e.g. if it goes from corner to corner, then the coverage goes from 0 to
177+ // 1 when the distance goes from -sqrt(2)/2 to +sqrt(2)/2; if it goes from egde to
178+ // edge, then the coverage goes from 0 to 1 when the distance goes from -0.5 to 0.5.
179+ // The chord length returned by `rectangle_sdf` is an approximation of this.
180+ float rect_distance = sdf .x - corner_radius + sdf .y / 2.0f ;
181+ // Add a small number to sdf.y to avoid 0/0
171182 if (rect_distance > 0.0f ) {
172- c = (1.0f - clamp (rect_distance , 0.0f , 1.0f )) * rim_color ;
183+ c = (1.0f - clamp (rect_distance , 0.0f , sdf . y ) / ( sdf . y + 1e-8 )) * rim_color ;
173184 } else {
174- float factor = clamp (rect_distance + border_width , 0.0f , 1.0f );
185+ float factor = clamp (rect_distance + border_width , 0.0f , sdf . y ) / ( sdf . y + 1e-8 );
175186 c = (1.0f - factor ) * c + factor * border_color ;
176187 }
177188 }
0 commit comments