summaryrefslogtreecommitdiff
path: root/source
diff options
context:
space:
mode:
Diffstat (limited to 'source')
-rw-r--r--source/benoit/benoit.rs8
-rw-r--r--source/benoit/benoit/application.rs2
-rw-r--r--source/benoit/benoit/application/animate.rs10
-rw-r--r--source/benoit/benoit/application/colour.rs29
-rw-r--r--source/benoit/benoit/application/draw.rs5
-rw-r--r--source/benoit/benoit/application/get_iterator_function.rs2
-rw-r--r--source/benoit/benoit/application/handle_keys.rs17
-rw-r--r--source/benoit/benoit/application/loop.rs33
-rw-r--r--source/benoit/benoit/application/render.rs6
-rw-r--r--source/benoit/benoit/application/render_row.rs30
-rw-r--r--source/benoit/benoit/application/run.rs9
-rw-r--r--source/benoit/benoit/configuration.rs2
-rw-r--r--source/benoit/benoit/configuration/default.rs5
-rw-r--r--source/benoit/benoit/configuration/load.rs3
-rw-r--r--source/benoit/benoit/fractal.rs31
-rw-r--r--source/benoit/benoit/fractal/get_name.rs34
-rw-r--r--source/benoit/benoit/render_data.rs5
-rw-r--r--source/benoit/benoit/render_data/new.rs8
-rw-r--r--source/benoit/benoit/render_data/slice.rs7
19 files changed, 168 insertions, 78 deletions
diff --git a/source/benoit/benoit.rs b/source/benoit/benoit.rs
index dfb4856..b301f36 100644
--- a/source/benoit/benoit.rs
+++ b/source/benoit/benoit.rs
@@ -23,15 +23,9 @@
pub mod application;
pub mod configuration;
+pub mod fractal;
pub mod iteration;
pub mod render_data;
pub mod video;
pub const PRECISION: u32 = 0x80;
-
-#[derive(Clone, Copy)]
-pub enum Fractal {
- BurningShip,
- Mandelbrot,
- Tricorn,
-}
diff --git a/source/benoit/benoit/application.rs b/source/benoit/benoit/application.rs
index 07f3815..be3d0fb 100644
--- a/source/benoit/benoit/application.rs
+++ b/source/benoit/benoit/application.rs
@@ -21,7 +21,7 @@
If not, see <https://www.gnu.org/licenses/>.
*/
-use crate::benoit::Fractal;
+use crate::benoit::fractal::Fractal;
use crate::benoit::iteration::IteratorFunction;
use crate::benoit::video::Video;
diff --git a/source/benoit/benoit/application/animate.rs b/source/benoit/benoit/application/animate.rs
index 65b4aeb..48677f3 100644
--- a/source/benoit/benoit/application/animate.rs
+++ b/source/benoit/benoit/application/animate.rs
@@ -34,7 +34,7 @@ use std::ops::MulAssign;
impl Application {
pub fn animate(&self) -> i32 {
// zoom_start:
- let mut zoom = Float::with_val(PRECISION, 1.0 / 2.0);
+ let mut zoom = Float::with_val(PRECISION, 1.0 / 4.0);
let zoom_stop = Float::with_val(PRECISION, &self.zoom);
@@ -70,13 +70,15 @@ impl Application {
let canvas_size = self.canvas_height as usize * self.canvas_width as usize;
- let mut data: Vec::<u32> = vec![0x0; canvas_size];
+ let mut iteration_count_buffer: Vec::<u32> = vec![0x0; canvas_size];
+ let mut square_distance_buffer: Vec::<f32> = vec![0.0; canvas_size];
+
let mut image: Vec::<u8> = vec![0x0; canvas_size * 0x3];
for frame in 0x0..self.frame_count {
eprint!("{frame:010}: ");
- self.render(&mut data[..], &self.center_real, &self.center_imaginary, &zoom, self.maximum_iteration_count);
- self.colour(&mut image[..], &data[..]);
+ self.render(&mut iteration_count_buffer[..], &mut square_distance_buffer[..], &self.center_real, &self.center_imaginary, &zoom, self.maximum_iteration_count);
+ self.colour(&mut image[..], &mut iteration_count_buffer[..], &mut square_distance_buffer[..]);
self.dump(format!("{}/frame{frame:010}.webp", self.dump_path), &image, self.canvas_width, self.canvas_height);
diff --git a/source/benoit/benoit/application/colour.rs b/source/benoit/benoit/application/colour.rs
index c9cf507..701d49f 100644
--- a/source/benoit/benoit/application/colour.rs
+++ b/source/benoit/benoit/application/colour.rs
@@ -24,30 +24,33 @@
use crate::benoit::application::Application;
impl Application {
- pub fn colour(&self, buffer: &mut [u8], data: &[u32]) {
+ pub fn colour(&self, buffer: &mut [u8], iteration_count_buffer: &[u32], square_distance_buffer: &[f32]) {
let canvas_size = self.canvas_height * self.canvas_width;
+
for pixel in 0x0..canvas_size {
- let iteration_count = data[pixel as usize];
+ let iteration_count = iteration_count_buffer[pixel as usize];
+
+ let (red, green, blue) = if iteration_count != self.maximum_iteration_count {
+ let distance = square_distance_buffer[pixel as usize].sqrt();
- let factor = {
- let factor = iteration_count as f32 / 64.0 % 1.0;
+ let mut factor = (iteration_count as f32 + 1.0 - distance.log2().log2()) / 16.0 % 1.0;
- (if factor >= 1.0 / 2.0 {
+ factor %= 1.0;
+
+ factor = (if factor >= 1.0 / 2.0 {
1.0 - factor
} else {
factor
- }) * 2.0
- };
+ }) * 2.0;
- let value: u8 = if iteration_count != self.maximum_iteration_count {
- (factor * 255.0).round() as u8
+ (factor * factor, factor * factor, factor)
} else {
- 0x0
+ (0.0, 0.0, 0.0)
};
- let red = value;
- let green = value;
- let blue = value;
+ let red = (red * 255.0).round() as u8;
+ let green = (green * 255.0).round() as u8;
+ let blue = (blue * 255.0).round() as u8;
buffer[pixel as usize * 0x3] = red;
buffer[pixel as usize * 0x3 + 0x1] = green;
diff --git a/source/benoit/benoit/application/draw.rs b/source/benoit/benoit/application/draw.rs
index 715b3da..6b1300b 100644
--- a/source/benoit/benoit/application/draw.rs
+++ b/source/benoit/benoit/application/draw.rs
@@ -29,12 +29,9 @@ use sdl2::pixels::Color;
use sdl2::rect::Rect;
impl Application {
- pub fn draw(&mut self, data: &mut [u32], image: &mut [u8]) {
+ pub fn draw(&mut self, image: &[u8]) {
let canvas_size = self.canvas_height * self.canvas_width;
- self.render(&mut data[..], &self.center_real, &self.center_imaginary, &self.zoom, self.maximum_iteration_count);
- self.colour(&mut image[..], &data[..]);
-
for pixel in 0x0..canvas_size {
let y = pixel as u32 / self.canvas_width;
let x = pixel as u32 - y * self.canvas_width;
diff --git a/source/benoit/benoit/application/get_iterator_function.rs b/source/benoit/benoit/application/get_iterator_function.rs
index b2375a0..1ca2cb7 100644
--- a/source/benoit/benoit/application/get_iterator_function.rs
+++ b/source/benoit/benoit/application/get_iterator_function.rs
@@ -21,7 +21,7 @@
If not, see <https://www.gnu.org/licenses/>.
*/
-use crate::benoit::Fractal;
+use crate::benoit::fractal::Fractal;
use crate::benoit::application::Application;
use crate::benoit::iteration::*;
diff --git a/source/benoit/benoit/application/handle_keys.rs b/source/benoit/benoit/application/handle_keys.rs
index 67e32cd..659a584 100644
--- a/source/benoit/benoit/application/handle_keys.rs
+++ b/source/benoit/benoit/application/handle_keys.rs
@@ -23,6 +23,8 @@
use crate::benoit::PRECISION;
use crate::benoit::application::Application;
+use crate::benoit::fractal::Fractal;
+use crate::benoit::iteration::IteratorFunction;
extern crate rug;
extern crate sdl2;
@@ -30,11 +32,26 @@ extern crate sdl2;
use rug::Float;
use sdl2::keyboard::Scancode;
+fn cycle_fractal(fractal: Fractal) -> (Fractal, IteratorFunction) {
+ let fractal = match fractal {
+ Fractal::BurningShip => Fractal::Mandelbrot,
+ Fractal::Mandelbrot => Fractal::Tricorn,
+ Fractal::Tricorn => Fractal::BurningShip,
+ };
+
+ let iterator_function = Application::get_iterator_function(fractal);
+
+ eprintln!("rendering the {}", fractal.get_name());
+
+ return (fractal, iterator_function);
+}
+
impl Application {
pub fn handle_keys(&mut self, scan_code: Scancode) -> bool {
match scan_code {
Scancode::Escape => return true,
Scancode::C => self.do_draw = true,
+ Scancode::Tab => (self.fractal, self.iterator_function) = cycle_fractal(self.fractal),
Scancode::X => self.do_dump = true,
Scancode::Z => eprintln!("c = {}{:+}i -- {}x @ {} iter.", &self.center_real, &self.center_imaginary, &self.zoom, self.maximum_iteration_count),
_ => {},
diff --git a/source/benoit/benoit/application/loop.rs b/source/benoit/benoit/application/loop.rs
index 8261970..f6747e7 100644
--- a/source/benoit/benoit/application/loop.rs
+++ b/source/benoit/benoit/application/loop.rs
@@ -29,34 +29,41 @@ impl Application {
pub fn r#loop(&mut self) -> i32 {
eprintln!();
eprintln!("Controls:");
- eprintln!("- W Translate up");
- eprintln!("- A Translate left");
- eprintln!("- S Translate down");
- eprintln!("- D Translate right");
+ eprintln!("- W Translate up");
+ eprintln!("- A Translate left");
+ eprintln!("- S Translate down");
+ eprintln!("- D Translate right");
eprintln!();
- eprintln!("- Q Zoom out");
- eprintln!("- E Zoom in");
+ eprintln!("- Q Zoom out");
+ eprintln!("- E Zoom in");
eprintln!();
- eprintln!("- R Decrease max. iteration count");
- eprintln!("- F Increase max. iteration count");
+ eprintln!("- R Decrease max. iteration count");
+ eprintln!("- F Increase max. iteration count");
eprintln!();
- eprintln!("- Z Print centre value (c)");
- eprintln!("- X Dump frame");
- eprintln!("- C Render frame");
+ eprintln!("- Tab Cycle between fractals");
+ eprintln!();
+ eprintln!("- Z Print centre value (c)");
+ eprintln!("- X Dump frame");
+ eprintln!("- C Render frame");
eprintln!();
let mut event_pump = self.video.as_mut().unwrap().sdl.event_pump().expect("unable to get event pump");
let canvas_size = self.canvas_height as usize * self.canvas_width as usize;
- let mut data: Vec::<u32> = vec![0x0; canvas_size];
+ let mut iteration_count_buffer: Vec::<u32> = vec![0x0; canvas_size];
+ let mut square_distance_buffer: Vec::<f32> = vec![0.0; canvas_size];
+
let mut image: Vec::<u8> = vec![0x0; canvas_size * 0x3];
loop {
if self.poll_events(&mut event_pump) { break }
if self.do_draw {
- self.draw(data.as_mut_slice(), image.as_mut_slice());
+ self.render(&mut iteration_count_buffer[..], &mut square_distance_buffer[..], &self.center_real, &self.center_imaginary, &self.zoom, self.maximum_iteration_count);
+ self.colour(&mut image[..], &iteration_count_buffer[..], &square_distance_buffer[..]);
+
+ self.draw(&image[..]);
self.do_draw = false;
}
diff --git a/source/benoit/benoit/application/render.rs b/source/benoit/benoit/application/render.rs
index e06b168..17ccc88 100644
--- a/source/benoit/benoit/application/render.rs
+++ b/source/benoit/benoit/application/render.rs
@@ -33,16 +33,16 @@ use std::sync::Arc;
use std::time::Instant;
impl Application {
- pub fn render(&self, buffer: &mut [u32], center_real: &Float, center_imaginary: &Float, zoom: &Float, maximum_iteration_count: u32) {
+ pub fn render(&self, iteration_count_buffer: &mut [u32], square_distance_buffer: &mut [f32], center_real: &Float, center_imaginary: &Float, zoom: &Float, maximum_iteration_count: u32) {
eprint!("rendering...");
let time_start = Instant::now();
let iterator = self.iterator_function;
- let data = Arc::new(RenderData::new(buffer, self.canvas_width, self.canvas_height, center_real.clone(), center_imaginary.clone(), zoom.clone(), maximum_iteration_count));
+ let data = Arc::new(RenderData::new(iteration_count_buffer, square_distance_buffer, self.canvas_width, self.canvas_height, center_real.clone(), center_imaginary.clone(), zoom.clone(), maximum_iteration_count));
- (0x0..self.canvas_height).into_par_iter().for_each_with(data, |data, row| {
+ (0x0..self.canvas_height).into_par_iter().for_each(|row| {
Application::render_row(data.clone(), row, iterator);
});
diff --git a/source/benoit/benoit/application/render_row.rs b/source/benoit/benoit/application/render_row.rs
index 20fabdb..23946ec 100644
--- a/source/benoit/benoit/application/render_row.rs
+++ b/source/benoit/benoit/application/render_row.rs
@@ -32,12 +32,12 @@ use rug::Float;
use std::sync::Arc;
impl Application {
- pub fn render_row(task: Arc<RenderData>, y: u32, iterator: IteratorFunction) {
- let buffer = unsafe { task.slice(y) };
+ pub fn render_row(data: Arc<RenderData>, y: u32, iterator: IteratorFunction) {
+ let (iteration_count_buffer, square_distance_buffer) = unsafe { data.slice(y) };
- for x in 0x0..task.canvas_width {
- let canvas_width = Float::with_val(PRECISION, task.canvas_width);
- let canvas_height = Float::with_val(PRECISION, task.canvas_height);
+ for x in 0x0..data.canvas_width {
+ let canvas_width = Float::with_val(PRECISION, data.canvas_width);
+ let canvas_height = Float::with_val(PRECISION, data.canvas_height);
let x_float = Float::with_val(PRECISION, x);
let y_float = Float::with_val(PRECISION, y);
@@ -48,8 +48,8 @@ impl Application {
let mut ca = Float::with_val(PRECISION, &x_float - &tmp0);
ca *= 4.0;
ca /= &canvas_width;
- ca /= &task.zoom;
- ca += &task.real;
+ ca /= &data.zoom;
+ ca += &data.real;
ca
};
@@ -60,8 +60,8 @@ impl Application {
let mut cb = Float::with_val(PRECISION, &y_float - &tmp0);
cb *= 4.0;
cb /= &canvas_height;
- cb /= &task.zoom;
- cb += &task.imaginary;
+ cb /= &data.zoom;
+ cb += &data.imaginary;
cb
};
@@ -70,16 +70,22 @@ impl Application {
let mut zb = Float::with_val(PRECISION, &cb);
let mut iteration_count: u32 = 0x0;
+ let mut square_distance;
while {
- let square_distance = Float::with_val(PRECISION, &za * &za + &zb * &zb);
- square_distance <= 4.0 && iteration_count < task.maximum_iteration_count
+ square_distance = Float::with_val(PRECISION, &za * &za + &zb * &zb).to_f32();
+ // Having a larger escape radius gives better
+ // results with regard to smoothing.
+ square_distance <= 256.0 && iteration_count < data.maximum_iteration_count
} {
iterator(&mut za, &mut zb, &ca, &cb);
iteration_count += 0x1;
}
- unsafe { *buffer.get_unchecked_mut(x as usize) = iteration_count }
+ unsafe {
+ *iteration_count_buffer.get_unchecked_mut(x as usize) = iteration_count;
+ *square_distance_buffer.get_unchecked_mut(x as usize) = square_distance;
+ }
}
}
}
diff --git a/source/benoit/benoit/application/run.rs b/source/benoit/benoit/application/run.rs
index 7b91c22..e8ee4e3 100644
--- a/source/benoit/benoit/application/run.rs
+++ b/source/benoit/benoit/application/run.rs
@@ -21,20 +21,13 @@
If not, see <https://www.gnu.org/licenses/>.
*/
-use crate::benoit::Fractal;
use crate::benoit::application::Application;
extern crate sdl2;
impl Application {
pub fn run(&mut self) -> i32 {
- let fractal_name = match self.fractal {
- Fractal::BurningShip => "burning ship",
- Fractal::Mandelbrot => "mandelbrot set",
- Fractal::Tricorn => "tricorn",
- };
-
- eprintln!("rendering the {fractal_name}");
+ eprintln!("rendering the {}", self.fractal.get_name());
return match self.interactive {
true => self.r#loop(),
diff --git a/source/benoit/benoit/configuration.rs b/source/benoit/benoit/configuration.rs
index b330089..455107f 100644
--- a/source/benoit/benoit/configuration.rs
+++ b/source/benoit/benoit/configuration.rs
@@ -21,7 +21,7 @@
If not, see <https://www.gnu.org/licenses/>.
*/
-use crate::benoit::Fractal;
+use crate::benoit::fractal::Fractal;
extern crate rug;
diff --git a/source/benoit/benoit/configuration/default.rs b/source/benoit/benoit/configuration/default.rs
index 19fc5fb..5442a99 100644
--- a/source/benoit/benoit/configuration/default.rs
+++ b/source/benoit/benoit/configuration/default.rs
@@ -21,8 +21,9 @@
If not, see <https://www.gnu.org/licenses/>.
*/
-use crate::benoit::{Fractal, PRECISION};
+use crate::benoit::PRECISION;
use crate::benoit::configuration::Configuration;
+use crate::benoit::fractal::Fractal;
extern crate rug;
@@ -42,7 +43,7 @@ impl Configuration {
center_real: Float::with_val(PRECISION, 0.0),
center_imaginary: Float::with_val(PRECISION, 0.0),
- zoom: Float::with_val(PRECISION, 1.0),
+ zoom: Float::with_val(PRECISION, 1.0 / 4.0),
maximum_iteration_count: 0x100,
dump_path: "./render/".to_string(),
diff --git a/source/benoit/benoit/configuration/load.rs b/source/benoit/benoit/configuration/load.rs
index 6d39c13..4f5f557 100644
--- a/source/benoit/benoit/configuration/load.rs
+++ b/source/benoit/benoit/configuration/load.rs
@@ -21,8 +21,9 @@
If not, see <https://www.gnu.org/licenses/>.
*/
-use crate::benoit::{Fractal, PRECISION};
+use crate::benoit::PRECISION;
use crate::benoit::configuration::Configuration;
+use crate::benoit::fractal::Fractal;
extern crate rug;
extern crate toml;
diff --git a/source/benoit/benoit/fractal.rs b/source/benoit/benoit/fractal.rs
new file mode 100644
index 0000000..1c7c08d
--- /dev/null
+++ b/source/benoit/benoit/fractal.rs
@@ -0,0 +1,31 @@
+/*
+ Copyright 2021, 2023 Gabriel Bjørnager Jensen.
+
+ This file is part of Benoit.
+
+ Benoit is free software: you can redistribute it
+ and/or modify it under the terms of the GNU
+ Affero General Public License as published by
+ the Free Software Foundation, either version 3
+ of the License, or (at your option) any later
+ version.
+
+ Benoit is distributed in the hope that it will
+ be useful, but WITHOUT ANY WARRANTY; without
+ even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Affero General Public License for more details.
+
+ You should have received a copy of the GNU
+ Affero General Public License along with Benoit.
+ If not, see <https://www.gnu.org/licenses/>.
+*/
+
+pub mod get_name;
+
+#[derive(Clone, Copy)]
+pub enum Fractal {
+ BurningShip,
+ Mandelbrot,
+ Tricorn,
+}
diff --git a/source/benoit/benoit/fractal/get_name.rs b/source/benoit/benoit/fractal/get_name.rs
new file mode 100644
index 0000000..cdbadb1
--- /dev/null
+++ b/source/benoit/benoit/fractal/get_name.rs
@@ -0,0 +1,34 @@
+/*
+ Copyright 2021, 2023 Gabriel Bjørnager Jensen.
+
+ This file is part of Benoit.
+
+ Benoit is free software: you can redistribute it
+ and/or modify it under the terms of the GNU
+ Affero General Public License as published by
+ the Free Software Foundation, either version 3
+ of the License, or (at your option) any later
+ version.
+
+ Benoit is distributed in the hope that it will
+ be useful, but WITHOUT ANY WARRANTY; without
+ even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Affero General Public License for more details.
+
+ You should have received a copy of the GNU
+ Affero General Public License along with Benoit.
+ If not, see <https://www.gnu.org/licenses/>.
+*/
+
+use crate::benoit::fractal::Fractal;
+
+impl Fractal {
+ pub fn get_name(self) -> &'static str {
+ return match self {
+ Fractal::BurningShip => "burning ship",
+ Fractal::Mandelbrot => "mandelbrot set",
+ Fractal::Tricorn => "tricorn",
+ };
+ }
+}
diff --git a/source/benoit/benoit/render_data.rs b/source/benoit/benoit/render_data.rs
index 602521e..a849cfd 100644
--- a/source/benoit/benoit/render_data.rs
+++ b/source/benoit/benoit/render_data.rs
@@ -26,8 +26,8 @@ extern crate rug;
use rug::Float;
pub mod new;
-pub mod slice;
pub mod send;
+pub mod slice;
pub mod sync;
pub struct RenderData {
@@ -40,5 +40,6 @@ pub struct RenderData {
pub maximum_iteration_count: u32,
- buffer: *mut u32,
+ iteration_count_buffer: *mut u32,
+ square_distance_buffer: *mut f32,
}
diff --git a/source/benoit/benoit/render_data/new.rs b/source/benoit/benoit/render_data/new.rs
index fb45390..6e801a0 100644
--- a/source/benoit/benoit/render_data/new.rs
+++ b/source/benoit/benoit/render_data/new.rs
@@ -28,8 +28,9 @@ extern crate rug;
use rug::Float;
impl RenderData {
- pub fn new(buffer: &mut [u32], canvas_width: u32, canvas_height: u32, real: Float, imaginary: Float, zoom: Float, maximum_iteration_count: u32) -> RenderData {
- let buffer_pointer = buffer.as_mut_ptr();
+ pub fn new(iteration_count_buffer: &mut [u32], square_distance_buffer: &mut [f32], canvas_width: u32, canvas_height: u32, real: Float, imaginary: Float, zoom: Float, maximum_iteration_count: u32) -> RenderData {
+ let iteration_count_buffer_pointer = iteration_count_buffer.as_mut_ptr();
+ let square_distance_buffer_pointer = square_distance_buffer.as_mut_ptr();
return RenderData {
canvas_width: canvas_width,
@@ -41,7 +42,8 @@ impl RenderData {
maximum_iteration_count: maximum_iteration_count,
- buffer: buffer_pointer,
+ iteration_count_buffer: iteration_count_buffer_pointer,
+ square_distance_buffer: square_distance_buffer_pointer,
};
}
}
diff --git a/source/benoit/benoit/render_data/slice.rs b/source/benoit/benoit/render_data/slice.rs
index 6783aae..4f6b486 100644
--- a/source/benoit/benoit/render_data/slice.rs
+++ b/source/benoit/benoit/render_data/slice.rs
@@ -26,10 +26,11 @@ use crate::benoit::render_data::RenderData;
use std::slice::from_raw_parts_mut;
impl RenderData {
- pub unsafe fn slice(&self, row: u32) -> &mut [u32] {
+ pub unsafe fn slice(&self, row: u32) -> (&mut [u32], &mut [f32]) {
let offset = row as isize * self.canvas_width as isize;
- let slice = from_raw_parts_mut(self.buffer.offset(offset), self.canvas_width as usize);
+ let iteration_count = from_raw_parts_mut(self.iteration_count_buffer.offset(offset), self.canvas_width as usize);
+ let distance = from_raw_parts_mut(self.square_distance_buffer.offset(offset), self.canvas_width as usize);
- return slice;
+ return (iteration_count, distance);
}
}