Skip to content

Commit 59502ed

Browse files
author
bors-servo
authored
Auto merge of #1791 - nical:corner, r=glennw
Use a better approximation for the border corner shader. Fixes #1750. <!-- Reviewable:start --> --- This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/webrender/1791) <!-- Reviewable:end -->
2 parents 17033a9 + 7a336bd commit 59502ed

File tree

7 files changed

+30
-16
lines changed

7 files changed

+30
-16
lines changed

webrender/res/ps_border_corner.glsl

+30-16
Original file line numberDiff line numberDiff line change
@@ -110,10 +110,10 @@ void write_color(vec4 color0, vec4 color1, int style, vec2 delta, int instance_k
110110
break;
111111
}
112112

113-
vColor00 = vec4(color0.rgb * modulate.x, color0.a);
114-
vColor01 = vec4(color0.rgb * modulate.y, color0.a);
115-
vColor10 = vec4(color1.rgb * modulate.z, color1.a);
116-
vColor11 = vec4(color1.rgb * modulate.w, color1.a);
113+
vColor00 = vec4(clamp(color0.rgb * modulate.x, vec3(0.0), vec3(1.0)), color0.a);
114+
vColor01 = vec4(clamp(color0.rgb * modulate.y, vec3(0.0), vec3(1.0)), color0.a);
115+
vColor10 = vec4(clamp(color1.rgb * modulate.z, vec3(0.0), vec3(1.0)), color1.a);
116+
vColor11 = vec4(clamp(color1.rgb * modulate.w, vec3(0.0), vec3(1.0)), color1.a);
117117
}
118118

119119
int select_style(int color_select, vec2 fstyle) {
@@ -325,8 +325,11 @@ void main(void) {
325325
alpha = min(alpha, do_clip());
326326

327327
// Find the appropriate distance to apply the AA smoothstep over.
328+
// Using 0.7 instead of 0.5 for the step compensates for the fact that smoothstep
329+
// is smooth at its endpoints and has a steeper maximum slope than a linear ramp.
328330
vec2 fw = fwidth(local_pos);
329-
float afwidth = length(fw);
331+
float aa_step = 0.7 * length(fw);
332+
330333
float distance_for_color;
331334
float color_mix_factor;
332335

@@ -336,28 +339,39 @@ void main(void) {
336339
if (all(lessThan(local_pos * vClipSign, vClipCenter * vClipSign))) {
337340
vec2 p = local_pos - vClipCenter;
338341

342+
// The coordinate system is snapped to pixel boundaries. To sample the distance,
343+
// however, we are interested in the center of the pixels which introduces an
344+
// error of half a pixel towards the exterior of the curve (See issue #1750).
345+
// This error is corrected by offsetting the distance by half a device pixel.
346+
// This not entirely correct: it leaves an error that varries between
347+
// 0 and (sqrt(2) - 1)/2 = 0.2 pixels but it is hardly noticeable and is better
348+
// than the constant sqrt(2)/2 px error without the correction.
349+
// To correct this exactly we would need to offset p by half a pixel in the
350+
// direction of the center of the ellipse (a different offset for each corner).
351+
352+
// A half device pixel in css pixels (using the average of width and height in case
353+
// there is any kind of transform applied).
354+
float half_px = 0.25 * (fw.x + fw.y);
339355
// Get signed distance from the inner/outer clips.
340-
float d0 = distance_to_ellipse(p, vRadii0.xy);
341-
float d1 = distance_to_ellipse(p, vRadii0.zw);
342-
float d2 = distance_to_ellipse(p, vRadii1.xy);
343-
float d3 = distance_to_ellipse(p, vRadii1.zw);
356+
float d0 = distance_to_ellipse(p, vRadii0.xy) + half_px;
357+
float d1 = distance_to_ellipse(p, vRadii0.zw) + half_px;
358+
float d2 = distance_to_ellipse(p, vRadii1.xy) + half_px;
359+
float d3 = distance_to_ellipse(p, vRadii1.zw) + half_px;
344360

345361
// SDF subtract main radii
346-
float d_main = max(d0, 0.5 * afwidth - d1);
362+
float d_main = max(d0, aa_step - d1);
347363

348364
// SDF subtract inner radii (double style borders)
349-
float d_inner = max(d2 - 0.5 * afwidth, -d3);
365+
float d_inner = max(d2 - aa_step, -d3);
350366

351367
// Select how to combine the SDF based on border style.
352368
float d = mix(max(d_main, -d_inner), d_main, vSDFSelect);
353369

354370
// Only apply AA to fragments outside the signed distance field.
355-
alpha = min(alpha, 1.0 - smoothstep(0.0, 0.5 * afwidth, d));
371+
alpha = min(alpha, 1.0 - smoothstep(0.0, aa_step, d));
356372

357373
// Get the groove/ridge mix factor.
358-
color_mix_factor = smoothstep(-0.5 * afwidth,
359-
0.5 * afwidth,
360-
-d2);
374+
color_mix_factor = smoothstep(-aa_step, aa_step, -d2);
361375
} else {
362376
// Handle the case where the fragment is outside the clip
363377
// region in a corner. This occurs when border width is
@@ -389,7 +403,7 @@ void main(void) {
389403
// Select color based on side of line. Get distance from the
390404
// reference line, and then apply AA along the edge.
391405
float ld = distance_to_line(vColorEdgeLine.xy, vColorEdgeLine.zw, local_pos);
392-
float m = smoothstep(-0.5 * afwidth, 0.5 * afwidth, ld);
406+
float m = smoothstep(-aa_step, aa_step, ld);
393407
vec4 color = mix(color0, color1, m);
394408

395409
oFragColor = color * vec4(1.0, 1.0, 1.0, alpha);
225 Bytes
Loading
11.8 KB
Loading
12.4 KB
Loading
25.6 KB
Loading
2.9 KB
Loading
227 Bytes
Loading

0 commit comments

Comments
 (0)