Replace "bezier_degree" with "is_linear"

This commit is contained in:
Grant Sanderson 2023-01-10 08:54:02 -08:00
parent 2b90f0b244
commit 05796654f4
5 changed files with 32 additions and 43 deletions

View file

@ -59,26 +59,27 @@ mat3 map_point_pairs(vec2 src0, vec2 src1, vec2 dest0, vec2 dest1){
}
mat3 get_xy_to_uv(vec2 controls[3], float bezier_degree, out float new_bezier_degree){
mat3 get_xy_to_uv(vec2 controls[3], float temp_is_linear, out float is_linear){
vec2[2] dest;
new_bezier_degree = bezier_degree;
if (bezier_degree == 1.0){
dest[0] = vec2(0, 0);
dest[1] = vec2(1, 0);
}else{
is_linear = temp_is_linear;
if (!bool(is_linear)){
vec2 xs = xs_on_clean_parabola(controls);
float x0 = xs.x;
float x2 = xs.y;
float thresh = 2.0;
if((x0 > thresh && x2 > thresh) || (x0 < -thresh && x2 < -thresh)){
dest[0] = vec2(0, 0);
dest[1] = vec2(1, 0);
new_bezier_degree = 1.0;
is_linear = 1.0;
}else{
dest[0] = vec2(x0, x0 * x0);
dest[1] = vec2(x2, x2 * x2);
}
}
// Check if is_linear status changed above
if (bool(is_linear)){
dest[0] = vec2(0, 0);
dest[1] = vec2(1, 0);
}
return map_point_pairs(
controls[0], controls[2], dest[0], dest[1]
);

View file

@ -8,22 +8,16 @@ in float uv_anti_alias_width;
in float orientation;
in vec2 uv_coords;
in float bezier_degree;
in float is_linear;
out vec4 frag_color;
float sdf(){
float x0 = uv_coords.x;
float y0 = uv_coords.y;
if(bezier_degree == 1.0){
return abs(y0);
}
float sdf(float x0, float y0){
if(bool(is_linear)) return abs(y0);
float Fxy = y0 - x0 * x0;
if(orientation * Fxy >= 0){
return 0.0;
}
if(orientation * Fxy >= 0) return 0.0;
return abs(Fxy) / sqrt(1 + 4 * x0 * x0);
}
@ -32,5 +26,6 @@ void main() {
if (color.a == 0) discard;
frag_color = color;
if (fill_all == 1.0) return;
frag_color.a *= smoothstep(1, 0, sdf() / uv_anti_alias_width);
float dist = sdf(uv_coords.x, uv_coords.y);
frag_color.a *= smoothstep(1, 0, dist / uv_anti_alias_width);
}

View file

@ -29,7 +29,7 @@ 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 bezier_degree;
out float is_linear;
vec3 unit_normal;
@ -80,7 +80,7 @@ void emit_pentagon(vec3[3] points, vec3 normal){
bool fill_inside = orientation > 0.0;
float aaw = anti_alias_width * frame_shape.y / pixel_shape.y;
vec3 corners[5];
if(bezier_degree == 1.0){
if(bool(is_linear)){
// For straight lines, buff out in both directions
corners = vec3[5](
p0 + aaw * p0_perp,
@ -109,13 +109,10 @@ void emit_pentagon(vec3[3] points, vec3 normal){
}
// Compute xy_to_uv matrix, and potentially re-evaluate bezier degree
float new_bezier_degree;
mat3 xy_to_uv = get_xy_to_uv(
vec2[3](p0.xy, p1.xy, p2.xy),
bezier_degree,
new_bezier_degree
is_linear, is_linear
);
bezier_degree = new_bezier_degree;
uv_anti_alias_width = aaw * length(xy_to_uv[0].xy);
for(int i = 0; i < 5; i++){
@ -143,7 +140,7 @@ void main(){
vec3 v01 = normalize(bp[1] - bp[0]);
vec3 v12 = normalize(bp[2] - bp[1]);
float angle = acos(clamp(dot(v01, v12), -1, 1));
bezier_degree = (angle < 1e-3) ? 1.0 : 2.0;
is_linear = float(angle < 1e-3);
vec3[3] new_bp = vec3[3](bp[0], bp[1], bp[2]);
unit_normal = get_unit_normal(new_bp);
orientation = v_orientation[0];

View file

@ -8,7 +8,7 @@ in float uv_stroke_width;
in float uv_anti_alias_width;
in vec4 color;
in float bezier_degree;
in float is_linear;
out vec4 frag_color;
@ -16,11 +16,10 @@ const float QUICK_DIST_WIDTH = 0.2;
// Distance from (x0, y0) to the curve y = x^2
float dist_to_curve(float x0, float y0){
if(bezier_degree == 1.0){
// In this case, the curve will actually have
// been set to equal the x axis
return y0;
}
// In the linear case, the curve will have
// been set to equal the x axis
if(bool(is_linear)) return y0;
if(uv_stroke_width < QUICK_DIST_WIDTH){
// This is a quick approximation for computing
// the distance to the curve.

View file

@ -31,7 +31,7 @@ out vec4 color;
out float uv_stroke_width;
out float uv_anti_alias_width;
out float bezier_degree;
out float is_linear;
out vec2 uv_coords;
@ -75,7 +75,6 @@ void create_joint(float angle, vec2 unit_tan, float buff,
// emitted as a triangle fan
int get_corners(
vec2 controls[3],
int degree,
float stroke_widths[3],
float angle_from_prev,
float angle_to_next,
@ -111,7 +110,7 @@ int get_corners(
create_joint(angle_to_next, v21, buff2, c3, c3, c2, c2);
// Linear case is the simplest
if(degree == 1){
if(bool(is_linear)){
// The order of corners should be for a triangle_strip. Last entry is a dummy
corners = vec2[5](c0, c1, c3, c2, vec2(0.0));
return 4;
@ -164,24 +163,22 @@ void main() {
// coincides with y = x^2, between some values x0 and x2. Or, in
// the case of a linear curve (bezier degree 1), just put it on
// the segment from (0, 0) to (1, 0)
bezier_degree = (abs(v_joint_angle[1]) < ANGLE_THRESHOLD) ? 1.0 : 2.0;
is_linear = float(abs(v_joint_angle[1]) < ANGLE_THRESHOLD);
float new_bezier_degree;
mat3 xy_to_uv = get_xy_to_uv(flat_controls, bezier_degree, new_bezier_degree);
bezier_degree = new_bezier_degree;
mat3 xy_to_uv = get_xy_to_uv(flat_controls, is_linear, is_linear);
float scale_factor = length(xy_to_uv[0].xy);
uv_anti_alias_width = scale_factor * anti_alias_width * (frame_shape.y / pixel_shape.y);
// If the curve is flat, put the middle control in the midpoint
if (bezier_degree == 1.0){
if (bool(is_linear)){
flat_controls[1] = 0.5 * (flat_controls[0] + flat_controls[2]);
}
// Corners of a bounding region around curve
vec2 corners[5];
int n_corners = get_corners(
flat_controls, int(bezier_degree), scaled_strokes,
flat_controls, scaled_strokes,
angle_from_prev, angle_to_next,
corners
);