mirror of
https://github.com/3b1b/manim.git
synced 2025-08-02 19:46:21 +08:00
First pass at a winding-based fill approach
This commit is contained in:
@ -2,29 +2,20 @@
|
||||
|
||||
in vec4 color;
|
||||
in float fill_all; // Either 0 or 1
|
||||
in float uv_anti_alias_width;
|
||||
|
||||
in float orientation;
|
||||
in vec2 uv_coords;
|
||||
in float is_linear;
|
||||
|
||||
out vec4 frag_color;
|
||||
|
||||
float sdf(){
|
||||
float x0 = uv_coords.x;
|
||||
float y0 = uv_coords.y;
|
||||
if(bool(is_linear)) return abs(y0);
|
||||
|
||||
float Fxy = y0 - x0 * x0;
|
||||
if(orientation * Fxy >= 0) return 0.0;
|
||||
|
||||
return abs(Fxy) / sqrt(1 + 4 * x0 * x0);
|
||||
}
|
||||
|
||||
|
||||
void main() {
|
||||
if (color.a == 0) discard;
|
||||
frag_color = color;
|
||||
if (bool(fill_all)) return;
|
||||
frag_color.a *= smoothstep(1, 0, sdf() / uv_anti_alias_width);
|
||||
if (orientation == 0) return;
|
||||
|
||||
float x0 = uv_coords.x;
|
||||
float y0 = uv_coords.y;
|
||||
float Fxy = y0 - x0 * x0;
|
||||
if(orientation * Fxy < 0) discard;
|
||||
|
||||
}
|
||||
|
@ -1,129 +1,68 @@
|
||||
#version 330
|
||||
|
||||
layout (triangles) in;
|
||||
layout (triangle_strip, max_vertices = 5) out;
|
||||
layout (triangle_strip, max_vertices = 7) out;
|
||||
|
||||
uniform float anti_alias_width;
|
||||
uniform float pixel_size;
|
||||
uniform vec3 corner;
|
||||
|
||||
in vec3 verts[3];
|
||||
in float v_orientation[3];
|
||||
in vec4 v_color[3];
|
||||
in vec3 v_base_point[3];
|
||||
in float v_vert_index[3];
|
||||
|
||||
|
||||
out vec4 color;
|
||||
out float fill_all;
|
||||
out float uv_anti_alias_width;
|
||||
|
||||
out float orientation;
|
||||
// uv space is where the curve coincides with y = x^2
|
||||
out vec2 uv_coords;
|
||||
out float is_linear;
|
||||
|
||||
const float ANGLE_THRESHOLD = 1e-3;
|
||||
|
||||
|
||||
// Analog of import for manim only
|
||||
#INSERT get_gl_Position.glsl
|
||||
#INSERT get_xyz_to_uv.glsl
|
||||
#INSERT get_unit_normal.glsl
|
||||
#INSERT finalize_color.glsl
|
||||
|
||||
|
||||
void emit_vertex_wrapper(vec3 point, int index, vec3 unit_normal){
|
||||
color = finalize_color(v_color[index], point, unit_normal);
|
||||
void emit_vertex_wrapper(vec3 point, vec4 v_color, vec3 unit_normal){
|
||||
color = finalize_color(v_color, point, unit_normal);
|
||||
gl_Position = get_gl_Position(point);
|
||||
EmitVertex();
|
||||
}
|
||||
|
||||
|
||||
void emit_simple_triangle(vec3 unit_normal){
|
||||
for(int i = 0; i < 3; i++){
|
||||
emit_vertex_wrapper(verts[i], i, unit_normal);
|
||||
}
|
||||
EndPrimitive();
|
||||
}
|
||||
|
||||
|
||||
void emit_pentagon(
|
||||
// Triangle vertices
|
||||
vec3 p0,
|
||||
vec3 p1,
|
||||
vec3 p2,
|
||||
// Unit tangent vector
|
||||
vec3 t01,
|
||||
vec3 t12,
|
||||
vec3 unit_normal
|
||||
){
|
||||
// Vectors perpendicular to the curve in the plane of the curve
|
||||
// pointing outside the curve
|
||||
vec3 p0_perp = cross(t01, unit_normal);
|
||||
vec3 p2_perp = cross(t12, unit_normal);
|
||||
|
||||
float angle = acos(clamp(dot(t01, t12), -1, 1));
|
||||
is_linear = float(angle < ANGLE_THRESHOLD);
|
||||
|
||||
if(bool(is_linear)){
|
||||
// Cross with unit z vector
|
||||
p0_perp = normalize(vec3(-t01.y, t01.x, 0));
|
||||
p2_perp = p0_perp;
|
||||
}
|
||||
|
||||
bool fill_inside = orientation > 0.0;
|
||||
float aaw = anti_alias_width * pixel_size;
|
||||
vec3 corners[5] = vec3[5](p0, p0, p1, p2, p2);
|
||||
|
||||
if(fill_inside || bool(is_linear)){
|
||||
// Add buffer outside the curve
|
||||
corners[0] += aaw * p0_perp;
|
||||
corners[2] += 0.5 * aaw * (p0_perp + p2_perp);
|
||||
corners[4] += aaw * p2_perp;
|
||||
} else{
|
||||
// Add buffer inside the curve
|
||||
corners[1] -= aaw * p0_perp;
|
||||
corners[3] -= aaw * p2_perp;
|
||||
}
|
||||
|
||||
// Compute xy_to_uv matrix, and potentially re-evaluate bezier degree
|
||||
bool too_steep;
|
||||
mat4 xyz_to_uv = get_xyz_to_uv(p0, p1, p2, 10.0, too_steep);
|
||||
if(too_steep) is_linear = 1.0;
|
||||
uv_anti_alias_width = aaw * length(xyz_to_uv[0].xyz);
|
||||
|
||||
for(int i = 0; i < 5; i++){
|
||||
int j = int[5](0, 0, 1, 2, 2)[i];
|
||||
vec3 corner = corners[i];
|
||||
uv_coords = (xyz_to_uv * vec4(corner, 1.0)).xy;
|
||||
emit_vertex_wrapper(corner, j, unit_normal);
|
||||
}
|
||||
EndPrimitive();
|
||||
}
|
||||
|
||||
|
||||
void main(){
|
||||
// If vert indices are sequential, don't fill all
|
||||
fill_all = float(
|
||||
(v_vert_index[1] - v_vert_index[0]) != 1.0 ||
|
||||
(v_vert_index[2] - v_vert_index[1]) != 1.0
|
||||
);
|
||||
// We use the triangle strip primative, but
|
||||
// actually only need every other strip element
|
||||
if (int(v_vert_index[0]) % 2 == 1) return;
|
||||
|
||||
vec3 p0 = verts[0];
|
||||
vec3 p1 = verts[1];
|
||||
vec3 p2 = verts[2];
|
||||
vec3 t01 = p1 - p0;
|
||||
vec3 t12 = p2 - p1;
|
||||
vec3 unit_normal = normalize(cross(t01, t12));
|
||||
// Curves are marked as eneded when the handle after
|
||||
// the first anchor is set equal to that anchor
|
||||
if (verts[0] == verts[1]) return;
|
||||
|
||||
if(bool(fill_all)){
|
||||
emit_simple_triangle(unit_normal);
|
||||
return;
|
||||
}
|
||||
orientation = v_orientation[1];
|
||||
vec3 unit_normal = get_unit_normal(verts[0], verts[1], verts[2]);
|
||||
|
||||
emit_pentagon(
|
||||
p0, p1, p2,
|
||||
normalize(t01),
|
||||
normalize(t12),
|
||||
unit_normal
|
||||
);
|
||||
// Emit main triangle
|
||||
orientation = 0.0;
|
||||
uv_coords = vec2(0.0);
|
||||
emit_vertex_wrapper(verts[2], v_color[2], unit_normal);
|
||||
emit_vertex_wrapper(v_base_point[0], v_color[1], unit_normal);
|
||||
emit_vertex_wrapper(verts[0], v_color[0], unit_normal);
|
||||
|
||||
// Emit edge triangle
|
||||
orientation = 1.0;
|
||||
uv_coords = vec2(0, 0);
|
||||
// Two dummies
|
||||
emit_vertex_wrapper(verts[0], v_color[0], unit_normal);
|
||||
emit_vertex_wrapper(verts[0], v_color[0], unit_normal);
|
||||
// Inner corner
|
||||
uv_coords = vec2(0.5, 0);
|
||||
emit_vertex_wrapper(verts[1], v_color[1], unit_normal);
|
||||
// Last corner
|
||||
uv_coords = vec2(1.0, 1.0);
|
||||
emit_vertex_wrapper(verts[2], v_color[2], unit_normal);
|
||||
EndPrimitive();
|
||||
}
|
||||
|
||||
|
@ -2,17 +2,17 @@
|
||||
|
||||
in vec3 point;
|
||||
in vec4 fill_rgba;
|
||||
in float orientation;
|
||||
in float vert_index;
|
||||
in vec3 base_point;
|
||||
|
||||
out vec3 verts; // Bezier control point
|
||||
out float v_orientation;
|
||||
out vec4 v_joint_product;
|
||||
out vec4 v_color;
|
||||
out vec3 v_base_point;
|
||||
out float v_vert_index;
|
||||
|
||||
void main(){
|
||||
verts = point;
|
||||
v_orientation = orientation;
|
||||
v_color = fill_rgba;
|
||||
v_vert_index = vert_index;
|
||||
v_base_point = base_point;
|
||||
v_vert_index = gl_VertexID;
|
||||
}
|
Reference in New Issue
Block a user