Skip to content

Commit e865f8f

Browse files
committed
Better AA
1 parent 5194e06 commit e865f8f

File tree

1 file changed

+43
-56
lines changed

1 file changed

+43
-56
lines changed

shaders/src/shaders/loading_repeating_circles.rs

Lines changed: 43 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -32,18 +32,16 @@ pub struct Inputs {
3232

3333
/// Epsilon used for floating-point comparisons.
3434
const EPSILON: f32 = 1.0e-6;
35-
/// Anti-aliasing width for edges.
36-
const AA_WIDTH: f32 = 0.005;
3735
/// A small constant gap between stacked progress bars.
3836
const PROGRESS_BAR_GAP: f32 = 0.01;
3937

4038
/// An SDF value that can be negative (inside the shape) or positive (outside the shape).
4139
#[derive(Copy, Clone, PartialEq, PartialOrd)]
4240
pub struct SDFValue(f32);
4341
impl SDFValue {
44-
const FAR_OUTSIDE: SDFValue = SDFValue(f32::MAX);
45-
const FAR_INSIDE: SDFValue = SDFValue(f32::MIN);
46-
const SURFACE: SDFValue = SDFValue(0.0);
42+
pub const FAR_OUTSIDE: SDFValue = SDFValue(f32::MAX);
43+
pub const FAR_INSIDE: SDFValue = SDFValue(f32::MIN);
44+
pub const SURFACE: SDFValue = SDFValue(0.0);
4745

4846
/// Creates a new SDFValue.
4947
#[must_use]
@@ -71,10 +69,14 @@ impl SDFValue {
7169

7270
/// Converts the SDF value to an alpha value for anti-aliasing.
7371
/// Alpha is 1.0 deep inside, 0.0 deep outside, and smooth in between.
74-
/// The transition happens from `AA_WIDTH` (alpha 0) to `-AA_WIDTH` (alpha 1).
72+
/// The transition happens from `aa_width` (alpha 0) to `-aa_width` (alpha 1).
7573
#[must_use]
76-
pub fn to_alpha(self) -> f32 {
77-
return smoothstep(AA_WIDTH, -AA_WIDTH, self.0);
74+
pub fn to_alpha(self, aa_width: f32) -> f32 {
75+
if aa_width <= EPSILON {
76+
return self.is_inside() as i32 as f32;
77+
}
78+
79+
return smoothstep(aa_width, -aa_width, self.0);
7880
}
7981

8082
/// Insets the shape by a given thickness.
@@ -486,7 +488,7 @@ fn sdf_circle_filled(uv: Vec2, radius: f32) -> SDFValue {
486488
/// * `t` should be in `0..1`.
487489
/// * `c` is usually in `-2..2`.
488490
#[must_use]
489-
fn exp_time(t: f32, c: f32) -> f32 {
491+
pub fn exp_time(t: f32, c: f32) -> f32 {
490492
let c = c * 10.0;
491493

492494
if c.abs() < EPSILON {
@@ -500,7 +502,7 @@ fn exp_time(t: f32, c: f32) -> f32 {
500502

501503
/// Returns the derivative of the exponential function.
502504
#[must_use]
503-
fn exp_time_derivative(t: f32, c: f32) -> f32 {
505+
pub fn exp_time_derivative(t: f32, c: f32) -> f32 {
504506
let c = c * 10.0;
505507

506508
if c.abs() < EPSILON {
@@ -513,20 +515,20 @@ fn exp_time_derivative(t: f32, c: f32) -> f32 {
513515
}
514516

515517
#[must_use]
516-
fn offset_loop_time(t: f32, offset: f32) -> f32 {
518+
pub fn offset_loop_time(t: f32, offset: f32) -> f32 {
517519
// Apply offset
518520
let offset_t = t + offset;
519521
// Wrap around to [0, 1]
520522
return offset_t.rem_euclid(1.0);
521523
}
522524

523-
struct RotatingCircleResult {
525+
pub struct RotatingCircleResult {
524526
position: Vec2,
525527
angle: f32,
526528
}
527529

528530
#[must_use]
529-
fn rotating_discrete_circle(
531+
pub fn rotating_discrete_circle(
530532
center: Vec2,
531533
radius: f32,
532534
start_angle: f32,
@@ -556,7 +558,7 @@ fn rotating_discrete_circle(
556558
///
557559
/// Returns: `0` before `start_time`, `1` after `end_time`, and a `0..1` ramp between them.
558560
#[must_use]
559-
fn remap_time(parent_t: f32, start_time: f32, end_time: f32) -> f32 {
561+
pub fn remap_time(parent_t: f32, start_time: f32, end_time: f32) -> f32 {
560562
if start_time >= end_time {
561563
// If start and end are the same, or invalid order we do an instant step.
562564
return if parent_t >= start_time { 1.0 } else { 0.0 };
@@ -694,7 +696,7 @@ fn draw_time_bar_discrete(
694696
let bar_full_potential_width = aspect.x * 2.0;
695697
let step_width = bar_full_potential_width / steps_f;
696698
let segment_left_bound = -aspect.x + step_width * fade_start_step;
697-
let segment_right_bound = -aspect.x + step_width * fade_end_step + AA_WIDTH;
699+
let segment_right_bound = -aspect.x + step_width * fade_end_step;
698700
if uv.x < segment_left_bound {
699701
fade_in_percentage = 1.0;
700702
}
@@ -740,10 +742,10 @@ impl Inputs {
740742
// Determine the shorter dimension of the screen.
741743
let shorter_dim = screen_xy.min_element();
742744

743-
let mut DEBUG = false;
745+
let mut debug = false;
744746
// if mouse is pressed, enable debug mode
745747
if self.mouse.z > 0.0 {
746-
DEBUG = true;
748+
debug = true;
747749
}
748750

749751
let debug_zoom = 10.0;
@@ -752,7 +754,7 @@ impl Inputs {
752754
let mut debug_zoom = 5.0;
753755
let mut debug_translate = vec2(0.0, 4.5);
754756

755-
if !DEBUG {
757+
if !debug {
756758
debug_zoom = 1.0;
757759
debug_translate = vec2(0.0, 0.0);
758760
}
@@ -773,13 +775,7 @@ impl Inputs {
773775

774776
let outline_stroke = 0.05; // Width of the outline stroke.
775777
let m_viewport_rect = sdf_box_filled(uv, aspect).to_outline(outline_stroke);
776-
debug_red_alpha = debug_red_alpha.max(m_viewport_rect.to_alpha());
777-
778-
let center = Vec2::ZERO;
779-
let bottom_middle = vec2(0.0, -aspect.y);
780-
let top_middle = vec2(0.0, aspect.y);
781-
let left_middle = vec2(-aspect.x, 0.0);
782-
let right_middle = vec2(aspect.x, 0.0);
778+
debug_red_alpha = debug_red_alpha.max(m_viewport_rect.to_alpha(aa_width));
783779

784780
let target_radius = 0.2;
785781
let target_stroke = 0.05;
@@ -803,26 +799,26 @@ impl Inputs {
803799
// rotating circles
804800
let num_circles = 12;
805801
let angle_between_circles = 2.0 * PI / num_circles as f32;
806-
let mut H = 0.0;
802+
let mut distance_for_main_circle = 0.0;
807803
for i in 0..num_circles {
808804
let circle_angle = angle_between_circles * i as f32;
809-
let H_candidate = calculate_initial_distance_for_main_circle_center(
805+
let distance_candidate = calculate_initial_distance_for_main_circle_center(
810806
aspect,
811807
target_radius + target_stroke / 2.0,
812808
circle_angle,
813809
);
814-
if let Some(H_candidate) = H_candidate {
815-
H = H_candidate.max(H);
810+
if let Some(distance_candidate) = distance_candidate {
811+
distance_for_main_circle = distance_candidate.max(distance_for_main_circle);
816812
}
817813
}
818814
// move from bottom_middle to center
819-
let middle_circle_start_radius = H;
815+
let middle_circle_start_radius = distance_for_main_circle;
820816
let middle_circle_radius =
821817
mix(middle_circle_start_radius, 0.0, t_master * t_master).max(target_radius);
822-
let middle_circle_start_position = Vec2::new(0.0, -H);
818+
let middle_circle_start_position = Vec2::new(0.0, -distance_for_main_circle);
823819

824-
let mut middle_circle_position = mix(middle_circle_start_position, center, t_master);
825-
let mut middle_circle_position = rotating_discrete_circle(
820+
let middle_circle_position = mix(middle_circle_start_position, Vec2::ZERO, t_master);
821+
let middle_circle_position = rotating_discrete_circle(
826822
middle_circle_start_position / 2.0, // maybe without /2.0
827823
middle_circle_start_radius / 2.0,
828824
-t_master * PI, // we only want half the rotation
@@ -837,7 +833,7 @@ impl Inputs {
837833
middle_circle_start_radius / 2.0,
838834
)
839835
.to_outline(target_stroke / 2.0);
840-
debug_blue_alpha = debug_blue_alpha.max(m_middle_circle_position_path.to_alpha());
836+
debug_blue_alpha = debug_blue_alpha.max(m_middle_circle_position_path.to_alpha(aa_width));
841837

842838
let middle_circle_moved_distance =
843839
(middle_circle_start_position - middle_circle_position).length();
@@ -852,18 +848,18 @@ impl Inputs {
852848
// (middle_circle_position.y + middle_circle_radius) * (1.0 - t_master);
853849

854850
let m_start_circle = sdf_circle_filled(uv, target_radius).to_outline(target_stroke);
855-
debug_red_alpha = debug_red_alpha.max(m_start_circle.to_alpha());
851+
debug_red_alpha = debug_red_alpha.max(m_start_circle.to_alpha(aa_width));
856852
let m_middle_circle_path = sdf_circle_filled(
857853
uv - middle_circle_start_position,
858854
middle_circle_start_radius,
859855
)
860856
.to_outline(target_stroke / 2.0);
861-
debug_red_alpha = debug_red_alpha.max(m_middle_circle_path.to_alpha());
857+
debug_red_alpha = debug_red_alpha.max(m_middle_circle_path.to_alpha(aa_width));
862858

863859
let m_middle_circle_outline =
864860
sdf_circle_filled(uv - middle_circle_position, middle_circle_radius)
865861
.to_outline(target_stroke / 2.0);
866-
debug_blue_alpha = debug_blue_alpha.max(m_middle_circle_outline.to_alpha());
862+
debug_blue_alpha = debug_blue_alpha.max(m_middle_circle_outline.to_alpha(aa_width));
867863

868864
for i in 0..num_circles {
869865
// Compute the position of the circle based on the angle and radius.
@@ -887,31 +883,22 @@ impl Inputs {
887883
outer_discrete_circle.angle,
888884
outer_circle_fade,
889885
);
890-
black_alpha = black_alpha.max(m.0.to_alpha() * (m.1 + t_assist_circle).min(1.0));
886+
black_alpha = black_alpha.max(m.0.to_alpha(aa_width) * (m.1 + t_assist_circle).min(1.0));
891887
// * (m.y + 6.0 / 256.0));
892888

893889
let m = sdf_circle_filled(uv - middle_circle_position, middle_circle_radius)
894890
.to_outline(outer_circle_outer_radius);
895-
black_alpha = black_alpha.max(m.to_alpha() * t_assist_circle);
891+
black_alpha = black_alpha.max(m.to_alpha(aa_width) * t_assist_circle);
896892
}
897893

898-
if DEBUG {
899-
let sdf_arc_test = sdf_arc_outline(
900-
uv - center,
901-
-PI / 4.0,
902-
PI / 4.0,
903-
1.0,
904-
0.0,
905-
0.5,
906-
-PI / 4.0,
907-
1.0,
908-
);
894+
if debug && false {
895+
let sdf_arc_test = sdf_arc_outline(uv, -PI / 4.0, PI / 4.0, 1.0, 0.0, 0.5, -PI / 4.0, 1.0);
909896
debug_green_alpha =
910-
debug_green_alpha.max(sdf_arc_test.0.offset(0.05).to_alpha() * sdf_arc_test.1);
911-
debug_red_alpha = debug_red_alpha.max(sdf_arc_test.0.to_alpha() * sdf_arc_test.1);
897+
debug_green_alpha.max(sdf_arc_test.0.offset(0.05).to_alpha(aa_width) * sdf_arc_test.1);
898+
debug_red_alpha = debug_red_alpha.max(sdf_arc_test.0.to_alpha(aa_width) * sdf_arc_test.1);
912899
}
913900

914-
if !DEBUG {
901+
if !debug {
915902
debug_blue_alpha = 0.0;
916903
debug_red_alpha = 0.0;
917904
debug_green_alpha = 0.0;
@@ -925,7 +912,7 @@ impl Inputs {
925912
t_master,
926913
0, // index
927914
);
928-
debug_green_alpha = debug_green_alpha.max(m_master_time_bar.to_alpha());
915+
debug_green_alpha = debug_green_alpha.max(m_master_time_bar.to_alpha(aa_width));
929916
let m_master_time_bar = draw_time_bar_discrete(
930917
uv,
931918
aspect,
@@ -935,7 +922,7 @@ impl Inputs {
935922
10,
936923
);
937924
debug_green_alpha =
938-
debug_green_alpha.max(m_master_time_bar.0.to_alpha() * m_master_time_bar.1);
925+
debug_green_alpha.max(m_master_time_bar.0.to_alpha(aa_width) * m_master_time_bar.1);
939926

940927
let m_master_time_offset_bar = sdf_progress_bar(
941928
uv,
@@ -944,7 +931,7 @@ impl Inputs {
944931
t_master_offset,
945932
2, // index
946933
);
947-
debug_red_alpha = debug_red_alpha.max(m_master_time_offset_bar.to_alpha());
934+
debug_red_alpha = debug_red_alpha.max(m_master_time_offset_bar.to_alpha(aa_width));
948935
}
949936

950937
let color_background = Vec4::ONE;

0 commit comments

Comments
 (0)