mirror of
https://github.com/zed-industries/zed.git
synced 2024-11-09 00:50:04 +03:00
Fix border rendering
After implementing it a while ago, our previous interpolation scheme didn't really make sense to me and was causing borders to be rendered incorrectly. We don't really draw backgrounds and borders as part of the same draw call anymore, but it seemed reasonable to have a correct implementation in the shader anyway. This commit uses Porter-Duff compositing (i.e., `over`) to produce a color that is the result of superimposing the border on top of the background. Then, we linearly interpolate towards the background color as we slide out of the border and into the background.
This commit is contained in:
parent
b78497bf54
commit
3ab2062614
@ -16,6 +16,7 @@ float gaussian(float x, float sigma);
|
||||
float2 erf(float2 x);
|
||||
float blur_along_x(float x, float y, float sigma, float corner,
|
||||
float2 half_size);
|
||||
float4 over(float4 below, float4 above);
|
||||
|
||||
struct QuadVertexOutput {
|
||||
float4 position [[position]];
|
||||
@ -108,21 +109,11 @@ fragment float4 quad_fragment(QuadFragmentInput input [[stage_in]],
|
||||
color = input.background_color;
|
||||
} else {
|
||||
float inset_distance = distance + border_width;
|
||||
|
||||
// Decrease border's opacity as we move inside the background.
|
||||
input.border_color.a *= 1. - saturate(0.5 - inset_distance);
|
||||
|
||||
// Alpha-blend the border and the background.
|
||||
float output_alpha = input.border_color.a +
|
||||
input.background_color.a * (1. - input.border_color.a);
|
||||
float3 premultiplied_border_rgb =
|
||||
input.border_color.rgb * input.border_color.a;
|
||||
float3 premultiplied_background_rgb =
|
||||
input.background_color.rgb * input.background_color.a;
|
||||
float3 premultiplied_output_rgb =
|
||||
premultiplied_border_rgb +
|
||||
premultiplied_background_rgb * (1. - input.border_color.a);
|
||||
color = float4(premultiplied_output_rgb, output_alpha);
|
||||
// Blend the border on top of the background and then linearly interpolate
|
||||
// between the two as we slide inside the background.
|
||||
float4 blended_border = over(input.background_color, input.border_color);
|
||||
color = mix(blended_border, input.background_color,
|
||||
saturate(0.5 - inset_distance));
|
||||
}
|
||||
|
||||
return color * float4(1., 1., 1., saturate(0.5 - distance));
|
||||
@ -653,3 +644,12 @@ float4 distance_from_clip_rect(float2 unit_vertex, Bounds_ScaledPixels bounds,
|
||||
position.y - clip_bounds.origin.y,
|
||||
clip_bounds.origin.y + clip_bounds.size.height - position.y);
|
||||
}
|
||||
|
||||
float4 over(float4 below, float4 above) {
|
||||
float4 result;
|
||||
float alpha = above.a + below.a * (1.0 - above.a);
|
||||
result.rgb =
|
||||
(above.rgb * above.a + below.rgb * below.a * (1.0 - above.a)) / alpha;
|
||||
result.a = alpha;
|
||||
return result;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user