3b1b-manim/manimlib/shaders/quadratic_bezier_stroke/frag.glsl

93 lines
No EOL
2.6 KiB
GLSL

#version 330
#INSERT camera_uniform_declarations.glsl
in vec2 uv_coords;
in vec2 uv_b2;
in float uv_stroke_width;
in vec4 color;
in float uv_anti_alias_width;
in float has_prev;
in float has_next;
in float bevel_start;
in float bevel_end;
in float angle_from_prev;
in float angle_to_next;
in float bezier_degree;
out vec4 frag_color;
float cross2d(vec2 v, vec2 w){
return v.x * w.y - w.x * v.y;
}
float modify_distance_for_endpoints(vec2 p, float dist, float t){
float buff = 0.5 * uv_stroke_width - uv_anti_alias_width;
// Check the beginning of the curve
if(t == 0){
// Clip the start
if(has_prev == 0) return max(dist, -p.x + buff);
// Bevel start
if(bevel_start == 1){
float a = angle_from_prev;
mat2 rot = mat2(
cos(a), sin(a),
-sin(a), cos(a)
);
// Dist for intersection of two lines
float bevel_d = max(abs(p.y), abs((rot * p).y));
// Dist for union of this intersection with the real curve
// intersected with radius 2 away from curve to smooth out
// really sharp corners
return max(min(dist, bevel_d), dist / 2);
}
// Otherwise, start will be rounded off
}else if(t == 1){
// Check the end of the curve
// TODO, too much code repetition
vec2 v21 = (bezier_degree == 2) ? vec2(1, 0) - uv_b2 : vec2(-1, 0);
float len_v21 = length(v21);
if(len_v21 == 0){
v21 = -uv_b2;
len_v21 = length(v21);
}
float perp_dist = dot(p - uv_b2, v21) / len_v21;
if(has_next == 0) return max(dist, -perp_dist + buff);
// Bevel end
if(bevel_end == 1){
float a = -angle_to_next;
mat2 rot = mat2(
cos(a), sin(a),
-sin(a), cos(a)
);
vec2 v21_unit = v21 / length(v21);
float bevel_d = max(
abs(cross2d(p - uv_b2, v21_unit)),
abs(cross2d((rot * (p - uv_b2)), v21_unit))
);
return max(min(dist, bevel_d), dist / 2);
}
// Otherwise, end will be rounded off
}
return dist;
}
#INSERT quadratic_bezier_distance.glsl
void main() {
if (uv_stroke_width == 0) discard;
float dist_to_curve = min_dist_to_curve(uv_coords, uv_b2, bezier_degree);
// An sdf for the region around the curve we wish to color.
float signed_dist = abs(dist_to_curve) - 0.5 * uv_stroke_width;
frag_color = color;
frag_color.a *= smoothstep(0.5, -0.5, signed_dist / uv_anti_alias_width);
}