From eb8a896865a6f3dbb5e3680c43ae408e29176ae4 Mon Sep 17 00:00:00 2001 From: lamp Date: Fri, 29 Dec 2023 23:32:34 +0000 Subject: initial dsw_mixin stuff --- src/main.rs | 79 +++++++++++++++++++++++++++++++---------------------------- src/perlin.rs | 65 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 107 insertions(+), 37 deletions(-) (limited to 'src') diff --git a/src/main.rs b/src/main.rs index 5acfbd1..0f8a07e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -4,6 +4,8 @@ mod image; use std::{println, format}; +use perlin::MixInImage; + use crate::perlin::Perlin; use crate::vec3::{Vec3,Point3, Color}; use crate::image::Image; @@ -85,55 +87,58 @@ fn sample(h: f64, l: f64) -> Color { }.hsl_to_rgb() } +fn main() { + // params + let height = 512; + let width = 512; + let scale = 1.0; + let turb_depth = 15; + let dsw_factor = 1.5; + let mixin_factor = 0.015; + let mixin_strength = 0.3; + let mixin_image = MixInImage::from_bmp(&include_bytes!("../mixin.bmp").to_vec()); + //let palette = GradientPalette{start: hex_color("0000ff"), end: hex_color("ff0000")}; + //let palette = IdenPalette{}; + let palette = FirePalette{}; + + let hue_perlin = Perlin::new(); + //let light_perlin = Perlin::new(); + let mut image = Image::new(width, height); + for x in 0..width { + for y in 0..height { + let hue_noise = hue_perlin.turb_dsw_mixin(&Point3{x: (x as f64 / width as f64) * scale, y: (y as f64 / height as f64) * scale, z: 0.0}, turb_depth, dsw_factor, &mixin_image, mixin_factor, mixin_strength); + //let light_noise = light_perlin.turb_dsw(&Point3{x: (x as f64 / width as f64) * scale, y: (y as f64 / height as f64) * scale, z: 0.0}, 7); + //image.set(x, y, &sample(hue_noise, light_noise)).unwrap(); + //image.set(x, y, &Color{x: hue_noise, y: hue_noise, z: hue_noise}).unwrap(); + image.set(x, y, &palette.sample(hue_noise)).unwrap(); + } + } + image.write(&mut std::io::stdout()); +} + // fn main() { // // params // let height = 512; // let width = 512; +// let frames = 600; // let scale = 1.0; // let turb_depth = 20; // let dsw_factor = 1.5; -// //let palette = GradientPalette{start: hex_color("0000ff"), end: hex_color("ff0000")}; -// //let palette = IdenPalette{}; // let palette = FirePalette{}; // let hue_perlin = Perlin::new(); -// //let light_perlin = Perlin::new(); // let mut image = Image::new(width, height); -// for x in 0..width { -// for y in 0..height { -// let hue_noise = hue_perlin.turb_dsw(&Point3{x: (x as f64 / width as f64) * scale, y: (y as f64 / height as f64) * scale, z: 0.0}, turb_depth, dsw_factor); -// //let light_noise = light_perlin.turb_dsw(&Point3{x: (x as f64 / width as f64) * scale, y: (y as f64 / height as f64) * scale, z: 0.0}, 7); -// //image.set(x, y, &sample(hue_noise, light_noise)).unwrap(); -// //image.set(x, y, &Color{x: hue_noise, y: hue_noise, z: hue_noise}).unwrap(); -// image.set(x, y, &palette.sample(hue_noise)).unwrap(); +// for f in 0..frames { +// for x in 0..width { +// for y in 0..height { +// let hue_noise = hue_perlin.turb_dsw(&Point3{x: (x as f64 / width as f64) * scale, y: (y as f64 / height as f64) * scale, z: (f as f64 / frames as f64) * scale}, turb_depth, dsw_factor); +// image.set(x, y, &palette.sample(hue_noise)).unwrap(); +// } // } +// let path = format!("./anim/{}.ppm", f); +// image.write(&mut std::fs::File::create(path).unwrap()); + +// println!("Finished frame {} of {}!", f, frames); // } -// image.write(&mut std::io::stdout()); // } -fn main() { - // params - let height = 512; - let width = 512; - let frames = 600; - let scale = 1.0; - let turb_depth = 20; - let dsw_factor = 1.5; - let palette = FirePalette{}; - - let hue_perlin = Perlin::new(); - let mut image = Image::new(width, height); - for f in 0..frames { - for x in 0..width { - for y in 0..height { - let hue_noise = hue_perlin.turb_dsw(&Point3{x: (x as f64 / width as f64) * scale, y: (y as f64 / height as f64) * scale, z: (f as f64 / frames as f64) * scale}, turb_depth, dsw_factor); - image.set(x, y, &palette.sample(hue_noise)).unwrap(); - } - } - let path = format!("./anim/{}.ppm", f); - image.write(&mut std::fs::File::create(path).unwrap()); - - println!("Finished frame {} of {}!", f, frames); - } -} - diff --git a/src/perlin.rs b/src/perlin.rs index 393582b..0b29f48 100644 --- a/src/perlin.rs +++ b/src/perlin.rs @@ -1,7 +1,53 @@ +use std::eprintln; + use crate::vec3::{Vec3, Point3}; const POINT_COUNT: usize = 256; +// Mix-in images are necessarily monochrome, so each data entry is a pixel. +pub struct MixInImage { + width: usize, + height: usize, + data: Vec, +} + +impl MixInImage { + pub fn from_bmp(bmp_data: &Vec) -> Self { + let data_position = u32::from_le_bytes([ + bmp_data[0x0A], + bmp_data[0x0B], + bmp_data[0x0C], + bmp_data[0x0D], + ]); + // assuming windows BITMAPINFOHEADER, these are i32 + let width = i32::from_le_bytes([ + bmp_data[0x12], + bmp_data[0x13], + bmp_data[0x14], + bmp_data[0x15], + ]) as usize; + let height = i32::from_le_bytes([ + bmp_data[0x16], + bmp_data[0x17], + bmp_data[0x18], + bmp_data[0x19], + ]) as usize; + // assuming 3 channels, all of which are equal + let data = bmp_data[(data_position as usize)..bmp_data.len()].iter().skip(2).step_by(3).map(|x| *x as f64 / 255.0).collect(); + Self { + width, + height, + data, + } + } + + pub fn get(&self, point: &Point3) -> &f64 { + let disc_x = ((point.x * self.width as f64) % self.width as f64) as usize; + let disc_y = ((point.y * self.height as f64) % self.height as f64) as usize; + self.data.get((disc_y * self.width) + disc_x).unwrap() + } +} + pub struct Perlin { ranvec: Vec, perm_x: Vec, @@ -50,6 +96,25 @@ impl Perlin { accum.abs() } + + pub fn turb_dsw_mixin(&self, point: &Point3, depth: u32, factor: f64, mixin: &MixInImage, mixin_factor: f64, mixin_strength: f64) -> f64 { + let mut accum = 0.0; + let mut temp_point = point.clone(); + let mut mixin_point = point.clone(); + let mut weight = 1.0; + + for _ in 0..depth { + accum += weight * (1.0 - mixin_strength) * self.noise(&temp_point); + temp_point *= 2.0; + let diff = temp_point.xy_diff(&|p: &Vec3| -> f64 {weight * self.noise(p)}); + temp_point += &diff * factor; + mixin_point += &diff * mixin_factor; + accum += weight * mixin_strength * mixin.get(&mixin_point); + weight *= 0.5; + } + accum.abs() + } + pub fn noise(&self, point: &Point3) -> f64 { let u = point.x - point.x.floor(); let v = point.y - point.y.floor(); -- cgit v1.2.3