chore: refactor the texture size constants
This commit is contained in:
parent
3d0f2acea3
commit
0c6dae0d04
|
@ -1,3 +1,7 @@
|
||||||
pub use crate::mandelbrot::Bounds;
|
pub use crate::mandelbrot::Bounds;
|
||||||
pub use crate::mandelbrot::Mandelbrot;
|
pub use crate::mandelbrot::Mandelbrot;
|
||||||
|
|
||||||
|
pub const TEXTURE_WIDTH: usize = 1280;
|
||||||
|
pub const TEXTURE_HEIGHT: usize = 720;
|
||||||
|
|
||||||
mod mandelbrot;
|
mod mandelbrot;
|
||||||
|
|
10
src/main.rs
10
src/main.rs
|
@ -1,5 +1,5 @@
|
||||||
use bevy::{prelude::*, render::texture::TextureFormat};
|
use bevy::{prelude::*, render::texture::TextureFormat};
|
||||||
use mandelbrot::{Bounds, Mandelbrot};
|
use mandelbrot::{Bounds, Mandelbrot, TEXTURE_HEIGHT, TEXTURE_WIDTH};
|
||||||
use std::time::Instant;
|
use std::time::Instant;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
@ -110,12 +110,12 @@ fn startup(
|
||||||
mut textures: ResMut<Assets<Texture>>,
|
mut textures: ResMut<Assets<Texture>>,
|
||||||
mut materials: ResMut<Assets<ColorMaterial>>,
|
mut materials: ResMut<Assets<ColorMaterial>>,
|
||||||
) {
|
) {
|
||||||
let img_size = Vec2::new(Mandelbrot::width() as f32, Mandelbrot::height() as f32);
|
let texture_size = Vec2::new(TEXTURE_WIDTH as f32, TEXTURE_HEIGHT as f32);
|
||||||
let img_buf = Mandelbrot::new().image().to_vec();
|
let texture_data = Mandelbrot::new().image().to_vec();
|
||||||
|
|
||||||
let texture_handle = textures.add(Texture::new(
|
let texture_handle = textures.add(Texture::new(
|
||||||
img_size,
|
texture_size,
|
||||||
img_buf,
|
texture_data,
|
||||||
TextureFormat::Rgba8UnormSrgb,
|
TextureFormat::Rgba8UnormSrgb,
|
||||||
));
|
));
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,10 @@
|
||||||
|
use crate::{TEXTURE_HEIGHT, TEXTURE_WIDTH};
|
||||||
use num_complex::Complex;
|
use num_complex::Complex;
|
||||||
use rayon::prelude::*;
|
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);
|
pub struct Coordinate(usize, usize);
|
||||||
|
|
||||||
impl Coordinate {
|
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)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct Mandelbrot {
|
pub struct Mandelbrot {
|
||||||
texture_buffer: Vec<u8>,
|
frame_buffer: Box<[u8; (TEXTURE_WIDTH * TEXTURE_HEIGHT) * 4]>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Mandelbrot {
|
impl Mandelbrot {
|
||||||
const IMG_WIDTH: usize = 1280;
|
|
||||||
const IMG_HEIGHT: usize = 720;
|
|
||||||
|
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Mandelbrot {
|
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] {
|
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)
|
.par_chunks_mut(4)
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.for_each(|(i, buf)| {
|
.for_each(|(i, buf)| {
|
||||||
let iters = Self::escape_time(i, DEFAULT_BOUNDS, DEFAULT_MAX_ITERATIONS);
|
let iterations = Self::escape_time(i, DEFAULT_BOUNDS, DEFAULT_ITERATION_LIMIT);
|
||||||
let normalized_iters = iters / max_iters;
|
let normalized_iters = iterations / limit_f64;
|
||||||
|
|
||||||
let h = normalized_iters * 350.0;
|
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));
|
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] {
|
pub fn scaled_image(&mut self, bounds: Bounds, limit: u32) -> &[u8] {
|
||||||
self.texture_buffer
|
self.frame_buffer
|
||||||
.par_chunks_mut(4)
|
.par_chunks_mut(4)
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.for_each(|(i, buf)| {
|
.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 iterations = Self::escape_time(i, bounds, limit);
|
||||||
let normalized_iters = iters / max_iters;
|
let normalized_iters = iterations / limit_f64;
|
||||||
|
|
||||||
let h = normalized_iters * 350.0;
|
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))
|
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 {
|
fn escape_time(i: usize, bounds: Bounds, iteration_limit: u32) -> f64 {
|
||||||
let point = Coordinate::new(i % Self::IMG_WIDTH, i / Self::IMG_WIDTH);
|
let point = Coordinate::new(i % TEXTURE_WIDTH, i / TEXTURE_WIDTH);
|
||||||
let c = Self::coords_to_complex(point, bounds);
|
let c = Self::coords_to_complex(point, bounds);
|
||||||
|
|
||||||
Self::count_iterations(c, max_iterations)
|
Self::count_iterations(c, iteration_limit)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -137,27 +127,27 @@ impl Mandelbrot {
|
||||||
[r, g, b, a]
|
[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 z: Complex<f64> = Complex::new(0.0, 0.0);
|
||||||
let mut num_iters: u32 = 0;
|
let mut count: u32 = 0;
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
if z.norm_sqr() > 4.0 {
|
if z.norm_sqr() > 4.0 {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if num_iters >= max_iterations {
|
if count >= maximum {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
z = (z * z) + c;
|
z = (z * z) + c;
|
||||||
num_iters += 1;
|
count += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if num_iters < max_iterations {
|
if count < maximum {
|
||||||
(num_iters as f64 + 1.0) - z.norm().ln().ln() / 2f64.ln()
|
(count as f64 + 1.0) - z.norm().ln().ln() / 2f64.ln()
|
||||||
} else {
|
} else {
|
||||||
num_iters as f64
|
count as f64
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -173,7 +163,7 @@ impl Mandelbrot {
|
||||||
// const X_MIN: f64 = -2.5;
|
// const X_MIN: f64 = -2.5;
|
||||||
// const X_MAX: f64 = 1.0;
|
// 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]
|
#[inline]
|
||||||
|
@ -181,6 +171,6 @@ impl Mandelbrot {
|
||||||
// const Y_MIN: f64 = -1.0;
|
// const Y_MIN: f64 = -1.0;
|
||||||
// const Y_MAX: 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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue