chore: refactor the texture size constants

This commit is contained in:
Rekai Nyangadzayi Musuka 2021-03-29 21:06:32 -05:00
parent 3d0f2acea3
commit 0c6dae0d04
3 changed files with 40 additions and 46 deletions

View File

@ -1,3 +1,7 @@
pub use crate::mandelbrot::Bounds;
pub use crate::mandelbrot::Mandelbrot;
pub const TEXTURE_WIDTH: usize = 1280;
pub const TEXTURE_HEIGHT: usize = 720;
mod mandelbrot;

View File

@ -1,5 +1,5 @@
use bevy::{prelude::*, render::texture::TextureFormat};
use mandelbrot::{Bounds, Mandelbrot};
use mandelbrot::{Bounds, Mandelbrot, TEXTURE_HEIGHT, TEXTURE_WIDTH};
use std::time::Instant;
fn main() {
@ -110,12 +110,12 @@ fn startup(
mut textures: ResMut<Assets<Texture>>,
mut materials: ResMut<Assets<ColorMaterial>>,
) {
let img_size = Vec2::new(Mandelbrot::width() as f32, Mandelbrot::height() as f32);
let img_buf = Mandelbrot::new().image().to_vec();
let texture_size = Vec2::new(TEXTURE_WIDTH as f32, TEXTURE_HEIGHT as f32);
let texture_data = Mandelbrot::new().image().to_vec();
let texture_handle = textures.add(Texture::new(
img_size,
img_buf,
texture_size,
texture_data,
TextureFormat::Rgba8UnormSrgb,
));

View File

@ -1,6 +1,10 @@
use crate::{TEXTURE_HEIGHT, TEXTURE_WIDTH};
use num_complex::Complex;
use rayon::prelude::*;
const DEFAULT_ITERATION_LIMIT: u32 = 64;
const DEFAULT_BOUNDS: Bounds = Bounds::new((-2.5, 1.0), (-1.0, 1.0));
pub struct Coordinate(usize, usize);
impl Coordinate {
@ -36,73 +40,59 @@ impl Bounds {
}
}
const DEFAULT_MAX_ITERATIONS: u32 = 64;
const DEFAULT_BOUNDS: Bounds = Bounds::new((-2.5, 1.0), (-1.0, 1.0));
#[derive(Debug, Clone)]
pub struct Mandelbrot {
texture_buffer: Vec<u8>,
frame_buffer: Box<[u8; (TEXTURE_WIDTH * TEXTURE_HEIGHT) * 4]>,
}
impl Mandelbrot {
const IMG_WIDTH: usize = 1280;
const IMG_HEIGHT: usize = 720;
pub fn new() -> Self {
Mandelbrot {
texture_buffer: vec![0; (Self::IMG_WIDTH * Self::IMG_HEIGHT) * 4],
frame_buffer: Box::new([0; (TEXTURE_WIDTH * TEXTURE_HEIGHT) * 4]),
}
}
pub fn width() -> usize {
Self::IMG_WIDTH
}
pub fn height() -> usize {
Self::IMG_HEIGHT
}
pub fn image(&mut self) -> &[u8] {
let max_iters = DEFAULT_MAX_ITERATIONS as f64;
let limit_f64 = DEFAULT_ITERATION_LIMIT as f64;
self.texture_buffer
self.frame_buffer
.par_chunks_mut(4)
.enumerate()
.for_each(|(i, buf)| {
let iters = Self::escape_time(i, DEFAULT_BOUNDS, DEFAULT_MAX_ITERATIONS);
let normalized_iters = iters / max_iters;
let iterations = Self::escape_time(i, DEFAULT_BOUNDS, DEFAULT_ITERATION_LIMIT);
let normalized_iters = iterations / limit_f64;
let h = normalized_iters * 350.0;
let v = if iters == max_iters { 0.0 } else { 1.0 };
let v = if iterations == limit_f64 { 0.0 } else { 1.0 };
buf.copy_from_slice(&Self::hsv_to_rgb(h, 1.0, v));
});
&self.texture_buffer
self.frame_buffer.as_ref()
}
pub fn scaled_image(&mut self, bounds: Bounds, max_iterations: u32) -> &[u8] {
self.texture_buffer
pub fn scaled_image(&mut self, bounds: Bounds, limit: u32) -> &[u8] {
self.frame_buffer
.par_chunks_mut(4)
.enumerate()
.for_each(|(i, buf)| {
let max_iters = max_iterations as f64;
let limit_f64 = limit as f64;
let iters = Self::escape_time(i, bounds, max_iterations);
let normalized_iters = iters / max_iters;
let iterations = Self::escape_time(i, bounds, limit);
let normalized_iters = iterations / limit_f64;
let h = normalized_iters * 350.0;
let v = if iters == max_iters { 0.0 } else { 1.0 };
let v = if iterations == limit_f64 { 0.0 } else { 1.0 };
buf.copy_from_slice(&Self::hsv_to_rgb(h, 1.0, v))
});
&self.texture_buffer
self.frame_buffer.as_ref()
}
fn escape_time(i: usize, bounds: Bounds, max_iterations: u32) -> f64 {
let point = Coordinate::new(i % Self::IMG_WIDTH, i / Self::IMG_WIDTH);
fn escape_time(i: usize, bounds: Bounds, iteration_limit: u32) -> f64 {
let point = Coordinate::new(i % TEXTURE_WIDTH, i / TEXTURE_WIDTH);
let c = Self::coords_to_complex(point, bounds);
Self::count_iterations(c, max_iterations)
Self::count_iterations(c, iteration_limit)
}
#[inline]
@ -137,27 +127,27 @@ impl Mandelbrot {
[r, g, b, a]
}
fn count_iterations(c: Complex<f64>, max_iterations: u32) -> f64 {
fn count_iterations(c: Complex<f64>, maximum: u32) -> f64 {
let mut z: Complex<f64> = Complex::new(0.0, 0.0);
let mut num_iters: u32 = 0;
let mut count: u32 = 0;
loop {
if z.norm_sqr() > 4.0 {
break;
}
if num_iters >= max_iterations {
if count >= maximum {
break;
}
z = (z * z) + c;
num_iters += 1;
count += 1;
}
if num_iters < max_iterations {
(num_iters as f64 + 1.0) - z.norm().ln().ln() / 2f64.ln()
if count < maximum {
(count as f64 + 1.0) - z.norm().ln().ln() / 2f64.ln()
} else {
num_iters as f64
count as f64
}
}
@ -173,7 +163,7 @@ impl Mandelbrot {
// const X_MIN: f64 = -2.5;
// const X_MAX: f64 = 1.0;
bounds.0 + ((bounds.1 - bounds.0) * (x as f64 - 0.0)) / Self::IMG_WIDTH as f64 - 0.0
bounds.0 + ((bounds.1 - bounds.0) * (x as f64 - 0.0)) / TEXTURE_WIDTH as f64 - 0.0
}
#[inline]
@ -181,6 +171,6 @@ impl Mandelbrot {
// const Y_MIN: f64 = -1.0;
// const Y_MAX: f64 = 1.0;
bounds.0 + ((bounds.1 - bounds.0) * (y as f64 - 0.0)) / Self::IMG_HEIGHT as f64 - 0.0
bounds.0 + ((bounds.1 - bounds.0) * (y as f64 - 0.0)) / TEXTURE_HEIGHT as f64 - 0.0
}
}