blob: 5dafa5a03b3373eb4b52caee44af302e81bbb51b [file] [log] [blame]
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
precision mediump float;
#include <impeller/color.glsl>
#include <impeller/types.glsl>
uniform FragInfo {
vec4 color;
vec2 center;
float radius;
float stroke_width;
float aa_pixels;
float stroked;
}
frag_info;
out vec4 frag_color;
highp in vec2 v_position;
float distanceFromCircle(float radius, vec2 center, vec2 point) {
return distance(point, center) - radius;
}
float distanceFromStrokedCircle(float radius,
float stroke_width,
vec2 center,
vec2 point) {
float half_stroke = stroke_width / 2.0;
float inner_radius = radius - half_stroke;
float outer_radius = radius + half_stroke;
float outer_distance = distanceFromCircle(outer_radius, center, point);
float inner_distance = -distanceFromCircle(inner_radius, center, point);
return max(inner_distance, outer_distance);
}
void main() {
float dist_filled =
distanceFromCircle(frag_info.radius, frag_info.center, v_position);
float dist_stroked = distanceFromStrokedCircle(
frag_info.radius, frag_info.stroke_width, frag_info.center, v_position);
float sdf_distance = mix(dist_filled, dist_stroked, frag_info.stroked);
float pixel_derivative_sdf = fwidth(sdf_distance);
// If the screen space derivative is less than the stroke width,
// only one pixel can be covered and shouldn't be faded.
if (frag_info.stroked > 0.0 &&
pixel_derivative_sdf * 2.0 >= frag_info.stroke_width) {
sdf_distance = -frag_info.radius;
}
float fade_width = pixel_derivative_sdf * frag_info.aa_pixels;
// The sdf_distance will be -pixel_derivative_sdf*N exactly at N pixels away
// from the edge of the circle
float alpha = 1.0 - smoothstep(-fade_width, 0.0, sdf_distance);
float finalAlpha = frag_info.color.w * alpha;
frag_color = vec4(frag_info.color.xyz, finalAlpha);
frag_color = IPPremultiply(frag_color);
}