Skip to content
Snippets Groups Projects
Commit a0188542 authored by Finn Bear's avatar Finn Bear
Browse files

More tightly integrate fractal zoom into cartoon.

parent 4639aac7
No related branches found
No related tags found
No related merge requests found
mod circle;
mod dummy;
mod julia_gradient;
mod mandelbrot;
mod mandelbrot_gradient;
mod rectangle;
mod wgpu;
......@@ -17,9 +15,7 @@ use crate::governor::Governor;
use crate::slide::s4_automata::randomize_grid;
use crate::slide::s6_fractals::circle::circle;
use crate::slide::s6_fractals::dummy::is_black;
use crate::slide::s6_fractals::julia_gradient::julia as julia_gradient;
use crate::slide::s6_fractals::mandelbrot::mandelbrot;
use crate::slide::s6_fractals::mandelbrot_gradient::mandelbrot as mandelbrot_gradient;
use crate::slide::s6_fractals::rectangle::rectangle;
use crate::slide::s6_fractals::wgpu::Accelerator;
use crate::slide::Slide;
......@@ -79,17 +75,13 @@ enum FractalsState {
/// Whether fractal traversal mode is enabled.
traversal: bool,
},
MandelbrotGradient {
/// How many pixels of the grid we've filled in.
pixels: usize,
},
JuliaGradient {
/// How many pixels of the grid we've filled in.
pixels: usize,
},
MandelbrotZoom {
/// When we started fading in.
fade_start: f64,
/// When we started smoothing the gradient.
smooth_start: Option<f64>,
/// When we started zooming in.
zoom_start: Option<f64>,
/// Fractal zoom background image.
image: ColorImage,
/// GPU accelerator.
......@@ -169,21 +161,29 @@ impl Slide for Fractals {
} else if !*traversal {
*traversal = true;
} else {
self.state = FractalsState::MandelbrotGradient { pixels: 0 };
self.state = FractalsState::MandelbrotZoom {
fade_start: ctx.input().time,
smooth_start: None,
zoom_start: None,
image: ColorImage::new([1280, 720], Color32::RED),
accelerator: Accelerator::new(1280, 720),
zoom: 1.0,
}
}
}
FractalsState::MandelbrotGradient { .. } => {
self.state = FractalsState::JuliaGradient { pixels: 0 }
}
FractalsState::JuliaGradient { .. } => {
self.state = FractalsState::MandelbrotZoom {
fade_start: ctx.input().time,
image: ColorImage::new([1280, 720], Color32::RED),
accelerator: Accelerator::new(1280, 720),
zoom: 1.0,
FractalsState::MandelbrotZoom {
smooth_start,
zoom_start,
..
} => {
if smooth_start.is_none() {
*smooth_start = Some(ctx.input().time);
} else if zoom_start.is_none() {
*zoom_start = Some(ctx.input().time);
} else {
return true;
}
}
FractalsState::MandelbrotZoom { .. } => return true,
}
false
}
......@@ -237,6 +237,7 @@ impl Slide for Fractals {
}
// Again, don't necessarily need to understand what is going on here.
#[allow(unused)]
fn wrap_f32_algo<A: Fn(f32, f32) -> f32>(a: A) -> impl Fn(f32, f32) -> Color32 {
move |x: f32, y: f32| {
let c = (a(x, y) * 255.0) as u8;
......@@ -294,21 +295,10 @@ impl Slide for Fractals {
algo = Box::new(wrap_bool_algo(mandelbrot));
limit_pixels = Some(pixels);
}
FractalsState::MandelbrotGradient { pixels } => {
// Higher resolution grid.
self.grid.size_cells = 256;
self.code.code = pseudocode(include_str!("s6_fractals/mandelbrot_gradient.rs"));
algo = Box::new(wrap_f32_algo(mandelbrot_gradient));
limit_pixels = Some(pixels);
}
FractalsState::JuliaGradient { pixels } => {
self.code.code = pseudocode(include_str!("s6_fractals/julia_gradient.rs"));
algo = Box::new(wrap_f32_algo(julia_gradient));
limit_pixels = Some(pixels);
}
FractalsState::MandelbrotZoom {
fade_start,
smooth_start,
zoom_start,
image,
accelerator,
zoom,
......@@ -318,23 +308,30 @@ impl Slide for Fractals {
self.code.alpha = alpha;
});
/*
let ultimate = Pos2::new(
0.3602404434376143632361252444495 + 0.5 * 0.00006162543,
-(-0.6413130610648031748603750151 - 0.7 * 0.00006162543),
);
*/
let inverse_fade_time =
1.0 - ((ui.ctx().input().time - *fade_start) as f32 * 0.25).clamp(0.0, 1.0);
let ultimate = Pos2::new(-0.613287065, -0.44526086);
let smooth_time = smooth_start
.map(|s| (ui.ctx().input().time - s) as f32)
.unwrap_or(0.0);
let smoothing = (smooth_time * 0.75).min(1.0);
let time = (ui.ctx().input().time - *fade_start) as f32;
let fade_target = Pos2::new(-3.75, 0.0);
let zoom_target = Pos2::new(-0.613287065, -0.44526086);
let zoom_time = zoom_start
.map(|s| (ui.ctx().input().time - s) as f32)
.unwrap_or(0.0);
let screen = ui.ctx().input().screen_rect();
*zoom = 3.0 * 0.95f32.powf(time * 10.0).max(0.0001);
let lerp = (time * 1.0).sqrt().min(1.0);
let center = Pos2::new(ultimate.x * lerp, ultimate.y * lerp);
*zoom = (3.0 * 0.95f32.powf(zoom_time * 10.0).max(0.0001))
.max(inverse_fade_time * 10.0);
let lerp = (zoom_time * 0.4).sqrt().min(1.0);
let center = Pos2::new(
zoom_target.x * lerp + fade_target.x * inverse_fade_time,
zoom_target.y * lerp + fade_target.y * inverse_fade_time,
);
let cutoff = 270f32.min(32.0 + (18.0 / *zoom).sqrt());
accelerator.run(center, *zoom, cutoff, image);
//println!("zoom: {}", *zoom);
accelerator.run(center, *zoom, cutoff, smoothing, image);
egui::Image::new(&ui.ctx().load_texture("zoom", image.clone()), Vec2::ZERO)
.paint_at(ui, screen);
......
......@@ -5,12 +5,13 @@ struct ComputeParams {
center_y: f32;
zoom: f32;
cutoff: f32;
smoothing: f32;
};
[[group(0), binding(0)]] var<uniform> params: ComputeParams;
[[group(0), binding(1)]] var texture: [[stride(16)]] texture_storage_2d<rgba8unorm, write>;
fn mandelbrot(x: f32, y: f32, cutoff: f32) -> f32 {
fn mandelbrot(x: f32, y: f32, cutoff: f32, smoothing: f32) -> f32 {
var x1: f32 = 0.0;
var y1: f32 = 0.0;
var i: f32 = 0.0;
......@@ -27,7 +28,7 @@ fn mandelbrot(x: f32, y: f32, cutoff: f32) -> f32 {
}
var fract = 1.0 - log(log(sqrt(max(1.001, x1 * x1 + y1 * y1)))) / log(2.0);
return (i + fract) / cutoff;
return (i + fract * smoothing) / cutoff;
}
[[stage(compute), workgroup_size(8, 8)]]
......@@ -47,9 +48,8 @@ fn main([[builtin(global_invocation_id)]] global_id: vec3<u32>) {
let fx = params.center_x + nx * params.zoom * aspect;
let fy = params.center_y + ny * params.zoom;
let max_iter = params.cutoff;
let o = params.zoom * 0.2 / f32(W);
let iter = pow((mandelbrot(fx + o, fy + o, max_iter) + mandelbrot(fx + o, fy - o, max_iter) + mandelbrot(fx - o, fy + o, max_iter) + mandelbrot(fx - o, fy - o, max_iter)) * 0.25, 1.0);
let iter = pow((mandelbrot(fx + o, fy + o, params.cutoff, params.smoothing) + mandelbrot(fx + o, fy - o, params.cutoff, params.smoothing) + mandelbrot(fx - o, fy + o, params.cutoff, params.smoothing) + mandelbrot(fx - o, fy - o, params.cutoff, params.smoothing)) * 0.25, 1.0);
// https://flatuicolors.com/palette/defo
var amethyst = vec3<f32>(155.0/255.0, 89.0/255.0, 182.0/255.0);
......
#[rustfmt::skip]
pub fn julia(mut x: f32, mut y: f32) -> f32 {
let max = 128.0;
let mut i = 0.0;
while x * x + y * y
<= 4.0 && i < max {
let x_tmp = x * x
- y * y - 0.2278;
y = 2.0 * x * y - 0.65;
x = x_tmp;
i += 1.0;
}
return i / max;
}
#[rustfmt::skip]
pub fn mandelbrot(x: f32, y: f32) -> f32 {
let max = 80.0;
let mut x1 = 0.0;
let mut y1 = 0.0;
let mut i = 0.0;
while x1 * x1 + y1 * y1
<= 4.0 && i < max {
let x_tmp = x1 * x1
- y1 * y1 + x;
y1 = 2.0 * x1 * y1 + y;
x1 = x_tmp;
i += 1.0;
}
return i / max;
}
......@@ -130,7 +130,14 @@ impl Accelerator {
}
}
pub fn run(&mut self, center: Pos2, zoom: f32, cutoff: f32, output: &mut ColorImage) {
pub fn run(
&mut self,
center: Pos2,
zoom: f32,
cutoff: f32,
smoothing: f32,
output: &mut ColorImage,
) {
self.params.set(
&self.device,
Params {
......@@ -140,6 +147,7 @@ impl Accelerator {
center_y: center.y,
zoom,
cutoff,
smoothing,
},
);
......@@ -218,6 +226,7 @@ struct Params {
center_y: f32,
zoom: f32,
cutoff: f32,
smoothing: f32,
}
struct ComputeParams {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment