mirror of
https://github.com/3b1b/manim.git
synced 2025-09-01 00:48:45 +00:00
Change stroke shader to effectively project down to a flat plane before drawing, but to remember z information via gl_Position and lighting.
This commit is contained in:
parent
1a5fb207ae
commit
274ebe7a52
3 changed files with 51 additions and 62 deletions
|
@ -14,9 +14,9 @@ vec4 add_light(vec4 raw_color, vec3 point, vec3 unit_normal, vec3 light_coords,
|
|||
float dot_prod = dot(normalize(light_reflection), normalize(to_camera));
|
||||
float shine = gloss * exp(-3 * pow(1 - dot_prod, 2));
|
||||
float dp2 = dot(normalize(to_light), unit_normal);
|
||||
float mult = ((dp2 + 2.0) / 3.0);
|
||||
float shadow = ((dp2 + 2.0) / 3.0); // TODO, this should come from the mobject in some way
|
||||
return vec4(
|
||||
mult * mix(raw_color.rgb, vec3(1.0), shine),
|
||||
shadow * mix(raw_color.rgb, vec3(1.0), shine),
|
||||
raw_color.a
|
||||
);
|
||||
}
|
|
@ -3,14 +3,11 @@
|
|||
uniform mat4 to_screen_space;
|
||||
uniform vec3 light_source_position;
|
||||
|
||||
in vec3 xyz_coords;
|
||||
in vec3 global_unit_normal;
|
||||
in vec2 uv_coords;
|
||||
in vec2 uv_b2;
|
||||
|
||||
in float uv_stroke_width;
|
||||
in vec4 color;
|
||||
in float gloss;
|
||||
in float uv_anti_alias_width;
|
||||
|
||||
in float has_prev;
|
||||
|
@ -84,18 +81,15 @@ float modify_distance_for_endpoints(vec2 p, float dist, float t){
|
|||
// so to share functionality between this and others, the caller
|
||||
// replaces this line with the contents of named file
|
||||
#INSERT quadratic_bezier_distance.glsl
|
||||
#INSERT add_light.glsl
|
||||
|
||||
|
||||
void main() {
|
||||
if (uv_stroke_width == 0) discard;
|
||||
|
||||
// Add lighting if needed
|
||||
frag_color = add_light(color, xyz_coords, global_unit_normal, light_source_position, gloss);
|
||||
|
||||
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);
|
||||
|
||||
// frag_color.a += 0.3;
|
||||
|
|
|
@ -7,6 +7,7 @@ layout (triangle_strip, max_vertices = 5) out;
|
|||
uniform float aspect_ratio;
|
||||
uniform float focal_distance;
|
||||
uniform float anti_alias_width;
|
||||
uniform vec3 light_source_position;
|
||||
|
||||
in vec3 bp[3];
|
||||
in vec3 prev_bp[3];
|
||||
|
@ -20,7 +21,6 @@ in float v_gloss[3];
|
|||
|
||||
out vec4 color;
|
||||
out float uv_stroke_width;
|
||||
out float gloss;
|
||||
out float uv_anti_alias_width;
|
||||
|
||||
out float has_prev;
|
||||
|
@ -32,8 +32,6 @@ out float angle_to_next;
|
|||
|
||||
out float bezier_degree;
|
||||
|
||||
out vec3 xyz_coords;
|
||||
out vec3 global_unit_normal;
|
||||
out vec2 uv_coords;
|
||||
out vec2 uv_b2;
|
||||
|
||||
|
@ -50,10 +48,14 @@ const float MITER_JOINT = 3;
|
|||
#INSERT quadratic_bezier_geometry_functions.glsl
|
||||
#INSERT get_gl_Position.glsl
|
||||
#INSERT get_unit_normal.glsl
|
||||
#INSERT add_light.glsl
|
||||
|
||||
|
||||
float get_aaw_scalar(vec3 normal){
|
||||
return min(abs(normal.z), 5);
|
||||
void flatten_points(in vec3[3] points, out vec3[3] flat_points){
|
||||
for(int i = 0; i < 3; i++){
|
||||
flat_points[i] = points[i];
|
||||
flat_points[i].z = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -88,27 +90,6 @@ bool find_intersection(vec3 p0, vec3 v0, vec3 p1, vec3 v1, vec3 normal, out vec3
|
|||
}
|
||||
|
||||
|
||||
bool is_between(vec3 p, vec3 a, vec3 b){
|
||||
// Assumes three points fall on a line, returns whether
|
||||
// or not p sits between a and b.
|
||||
float d_pa = distance(p, a);
|
||||
float d_pb = distance(p, b);
|
||||
float d_ab = distance(a, b);
|
||||
return (d_ab >= d_pa && d_ab >= d_pb);
|
||||
}
|
||||
|
||||
|
||||
// Tries to detect if one of the corners defined by the buffer around
|
||||
// b0 and b2 should be modified to form a better convex hull
|
||||
bool should_motify_corner(vec3 c, vec3 from_c, vec3 o1, vec3 o2, vec3 from_o, vec3 normal, float buff){
|
||||
vec3 int1;
|
||||
vec3 int2;
|
||||
find_intersection(c, from_c, o1, from_o, normal, int1);
|
||||
find_intersection(c, from_c, o2, from_o, normal, int2);
|
||||
return !is_between(int2, c + 1 * from_c * buff, int1);
|
||||
}
|
||||
|
||||
|
||||
void create_joint(float angle, vec3 unit_tan, float buff, float should_bevel,
|
||||
vec3 static_c0, out vec3 changing_c0,
|
||||
vec3 static_c1, out vec3 changing_c1){
|
||||
|
@ -146,14 +127,13 @@ int get_corners(vec3 controls[3], vec3 normal, int degree, out vec3 corners[5]){
|
|||
vec3 v01 = -v10;
|
||||
vec3 v21 = -v12;
|
||||
|
||||
//
|
||||
vec3 p0_perp = cross(normal, v01); // Pointing to the left of the curve from p0
|
||||
vec3 p2_perp = cross(normal, v12); // Pointing to the left of the curve from p2
|
||||
|
||||
// aaw is the added width given around the polygon for antialiasing.
|
||||
// In case the normal is faced away from (0, 0, 1), the vector to the
|
||||
// camera, this is scaled up.
|
||||
float aaw = anti_alias_width / get_aaw_scalar(normal);
|
||||
float aaw = anti_alias_width;
|
||||
float buff0 = 0.5 * v_stroke_width[0] + aaw;
|
||||
float buff2 = 0.5 * v_stroke_width[2] + aaw;
|
||||
float aaw0 = (1 - has_prev) * aaw;
|
||||
|
@ -170,8 +150,7 @@ int get_corners(vec3 controls[3], vec3 normal, int degree, out vec3 corners[5]){
|
|||
|
||||
// Linear case is the simplest
|
||||
if(degree == 1){
|
||||
// Swap between 2 and 3 is deliberate, the order of corners
|
||||
// should be for a triangle_strip. Last entry is a dummy
|
||||
// The order of corners should be for a triangle_strip. Last entry is a dummy
|
||||
corners = vec3[5](c0, c1, c3, c2, vec3(0.0));
|
||||
return 4;
|
||||
}
|
||||
|
@ -207,26 +186,24 @@ void set_adjascent_info(vec3 c0, vec3 tangent,
|
|||
}
|
||||
|
||||
|
||||
void set_previous_and_next(vec3 controls[3], int degree, vec3 normal){
|
||||
float a_tol = 1e-8;
|
||||
void find_joint_info(vec3 controls[3], vec3 prev[3], vec3 next[3], int degree, vec3 normal){
|
||||
float tol = 1e-8;
|
||||
|
||||
// Made as floats not bools so they can be passed to the frag shader
|
||||
has_prev = float(distance(prev_bp[2], bp[0]) < a_tol);
|
||||
has_next = float(distance(next_bp[0], bp[2]) < a_tol);
|
||||
has_prev = float(distance(prev[2], controls[0]) < tol);
|
||||
has_next = float(distance(next[0], controls[2]) < tol);
|
||||
|
||||
if(has_prev > 0){
|
||||
if(bool(has_prev)){
|
||||
vec3 tangent = controls[1] - controls[0];
|
||||
set_adjascent_info(
|
||||
controls[0], tangent, degree, normal,
|
||||
vec3[3](prev_bp[0], prev_bp[1], prev_bp[2]),
|
||||
controls[0], tangent, degree, normal, prev,
|
||||
bevel_start, angle_from_prev
|
||||
);
|
||||
}
|
||||
if(has_next > 0){
|
||||
if(bool(has_next)){
|
||||
vec3 tangent = controls[1] - controls[2];
|
||||
set_adjascent_info(
|
||||
controls[2], tangent, degree, normal,
|
||||
vec3[3](next_bp[0], next_bp[1], next_bp[2]),
|
||||
controls[2], tangent, degree, normal, next,
|
||||
bevel_end, angle_to_next
|
||||
);
|
||||
angle_to_next *= -1;
|
||||
|
@ -236,38 +213,56 @@ void set_previous_and_next(vec3 controls[3], int degree, vec3 normal){
|
|||
|
||||
void main() {
|
||||
vec3 unit_normal = v_global_unit_normal[0];
|
||||
// anti_alias_width /= cos(0.5 * acos(abs(unit_normal.z)));
|
||||
|
||||
vec3 controls[3];
|
||||
bezier_degree = get_reduced_control_points(vec3[3](bp[0], bp[1], bp[2]), controls);
|
||||
int degree = int(bezier_degree);
|
||||
|
||||
// Stroke width should then scale based on z value
|
||||
|
||||
// Control points are projected to the xy plane before drawing, which in turn
|
||||
// gets tranlated to a uv plane. The z-coordinate information will be remembered
|
||||
// by what's sent out to gl_Position, and by how it affects the lighting and stroke width
|
||||
vec3 flat_controls[3];
|
||||
vec3 flat_prev[3];
|
||||
vec3 flat_next[3];
|
||||
flatten_points(controls, flat_controls);
|
||||
flatten_points(vec3[3](prev_bp[0], prev_bp[1], prev_bp[2]), flat_prev);
|
||||
flatten_points(vec3[3](next_bp[0], next_bp[1], next_bp[2]), flat_next);
|
||||
vec3 k_hat = vec3(0.0, 0.0, 1.0);
|
||||
|
||||
// Null curve
|
||||
if(degree == 0) return;
|
||||
|
||||
set_previous_and_next(controls, degree, unit_normal);
|
||||
find_joint_info(flat_controls, flat_prev, flat_next, degree, k_hat);
|
||||
|
||||
// Find uv conversion matrix
|
||||
mat4 xyz_to_uv = get_xyz_to_uv(controls[0], controls[1], unit_normal);
|
||||
float scale_factor = length(controls[1] - controls[0]);
|
||||
uv_anti_alias_width = anti_alias_width / scale_factor / get_aaw_scalar(unit_normal);
|
||||
uv_b2 = (xyz_to_uv * vec4(controls[2], 1.0)).xy;
|
||||
mat4 xyz_to_uv = get_xyz_to_uv(flat_controls[0], flat_controls[1], k_hat);
|
||||
float scale_factor = length(flat_controls[1] - flat_controls[0]);
|
||||
uv_anti_alias_width = anti_alias_width / scale_factor;
|
||||
uv_b2 = (xyz_to_uv * vec4(controls[2].xy, 0.0, 1.0)).xy;
|
||||
|
||||
// Corners of a bounding region around curve
|
||||
vec3 corners[5];
|
||||
int n_corners = get_corners(controls, unit_normal, degree, corners);
|
||||
int n_corners = get_corners(flat_controls, k_hat, degree, corners);
|
||||
|
||||
int index_map[5] = int[5](0, 0, 1, 2, 2);
|
||||
if(n_corners == 4) index_map[2] = 2;
|
||||
|
||||
// Emit each corner
|
||||
for(int i = 0; i < n_corners; i++){
|
||||
xyz_coords = corners[i];
|
||||
uv_coords = (xyz_to_uv * vec4(xyz_coords, 1.0)).xy;
|
||||
uv_coords = (xyz_to_uv * vec4(corners[i], 1.0)).xy;
|
||||
uv_stroke_width = v_stroke_width[index_map[i]] / scale_factor;
|
||||
color = v_color[index_map[i]];
|
||||
gloss = v_gloss[index_map[i]];
|
||||
global_unit_normal = v_global_unit_normal[index_map[i]];
|
||||
// TODO, scale stroke width by z coord somehow...
|
||||
// Apply some lighting to the color before sending out.
|
||||
vec3 xyz_coords = vec3(corners[i].xy, controls[index_map[i]].z);
|
||||
color = add_light(
|
||||
v_color[index_map[i]],
|
||||
xyz_coords,
|
||||
v_global_unit_normal[index_map[i]],
|
||||
light_source_position,
|
||||
v_gloss[index_map[i]]
|
||||
);
|
||||
gl_Position = get_gl_Position(xyz_coords);
|
||||
EmitVertex();
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue