// https://www.scratchapixel.com/lessons/procedural-generation-virtual-worlds/procedural-patterns-noise-part-1/simple-pattern-examples.html use rand::RngCore; use crate::ppm::{Pixel, Ppm}; use crate::value_noise::ValueNoise; use crate::vec2::Vec2; pub fn generate_turbulence( width: usize, height: usize, rng: impl RngCore, ) -> Ppm { let mut noise_map = vec![0.0; width * height]; let noise = ValueNoise::new(rng); let frequency = 0.02; let frequency_mult = 1.8; let amplitude_mult = 0.35; let num_layers = 5; let mut max_noise_val = 0.0f64; for j in 0..height { for i in 0..width { let mut noise_point = Vec2::new(i as f64, j as f64) * frequency; let mut amplitude = 1.0; for _ in 0..num_layers { noise_map[j * width + i] = (2.0 * noise.eval(noise_point) - 1.0).abs() * amplitude; noise_point = noise_point * frequency_mult; amplitude *= amplitude_mult; } max_noise_val = max_noise_val.max(noise_map[j * width + i]); } } let data = noise_map .into_iter() .map(|f| { let v = (f / max_noise_val * 192.0 + 32.0).floor() as u8; Pixel(v, v, v) }) .collect(); Ppm { width, height, data, } }