completed perlin textures
This commit is contained in:
parent
aa74b321b8
commit
7468ba1112
10
src/main.rs
10
src/main.rs
|
@ -23,11 +23,11 @@ use demos::Demo;
|
|||
|
||||
use std::time::Instant;
|
||||
|
||||
const NUM_SAMPLES: u8 = 25;
|
||||
const NUM_SAMPLES: u8 = 255;
|
||||
const VERTICAL_PARTITION: usize = 12;
|
||||
const HORIZONTAL_PARTITION: usize = 12;
|
||||
const WIDTH: usize = 1920;
|
||||
const HEIGHT: usize = 1080;
|
||||
const WIDTH: usize = 2560;
|
||||
const HEIGHT: usize = 1440;
|
||||
|
||||
fn main() -> Result<(), String> {
|
||||
run(WIDTH, HEIGHT)
|
||||
|
@ -134,9 +134,9 @@ fn run(mut width: usize, mut height: usize) -> Result<(), String> {
|
|||
|
||||
#[cfg(not(feature = "gui"))]
|
||||
fn run(width: usize, height: usize) -> Result<(), String> {
|
||||
// run_and_save_demo(demos::CheckeredMotionBlur {}, width, height);
|
||||
run_and_save_demo(demos::CheckeredMotionBlur {}, width, height);
|
||||
|
||||
//run_and_save_demo(demos::TwoSpheres {}, width, height);
|
||||
run_and_save_demo(demos::TwoSpheres {}, width, height);
|
||||
|
||||
run_and_save_demo(demos::PerlinNoiseBall {}, width, height);
|
||||
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
use crate::types::Vec3;
|
||||
use rand::{distributions::Uniform, Rng};
|
||||
use rand::Rng;
|
||||
|
||||
const POINT_COUNT: usize = 256;
|
||||
|
||||
pub struct Perlin {
|
||||
points: Vec<f64>,
|
||||
points: Vec<Vec3>,
|
||||
|
||||
permute_x: Vec<usize>,
|
||||
permute_y: Vec<usize>,
|
||||
|
@ -13,10 +13,9 @@ pub struct Perlin {
|
|||
|
||||
impl Perlin {
|
||||
pub fn new<R: Rng + ?Sized>(rng: &mut R) -> Self {
|
||||
let points = rng
|
||||
.sample_iter(Uniform::from(0.0..=1.0))
|
||||
.take(POINT_COUNT)
|
||||
.collect::<Vec<f64>>();
|
||||
let points = (0..POINT_COUNT)
|
||||
.map(|_| Vec3::random(rng).unit_vector())
|
||||
.collect::<Vec<Vec3>>();
|
||||
|
||||
let permute_x = Self::perlin_generate_permutation(rng);
|
||||
let permute_y = Self::perlin_generate_permutation(rng);
|
||||
|
@ -37,41 +36,57 @@ impl Perlin {
|
|||
}
|
||||
|
||||
pub fn noise(&self, p: Vec3) -> f64 {
|
||||
let mut smooth_grid = [[[Vec3::new(0.0, 0.0, 0.0); 2]; 2]; 2];
|
||||
|
||||
{
|
||||
let i = p.x().floor() as i32;
|
||||
let j = p.y().floor() as i32;
|
||||
let k = p.z().floor() as i32;
|
||||
|
||||
let mut smooth_grid = [[[0.0; 2]; 2]; 2];
|
||||
|
||||
for (di, a) in smooth_grid.iter_mut().enumerate() {
|
||||
let di = di as i32;
|
||||
for (dj, b) in a.iter_mut().enumerate() {
|
||||
let dj = dj as i32;
|
||||
for (dk, c) in b.iter_mut().enumerate() {
|
||||
let dk = dk as i32;
|
||||
|
||||
*c = self.points[self.permute_x[((i + di) & 255) as usize]
|
||||
^ self.permute_y[((j + dj) & 255) as usize]
|
||||
^ self.permute_z[((k + dk) & 255) as usize]]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let mut u = p.x() - p.x().floor();
|
||||
let mut v = p.y() - p.y().floor();
|
||||
let mut w = p.z() - p.z().floor();
|
||||
let u = p.x() - p.x().floor();
|
||||
let v = p.y() - p.y().floor();
|
||||
let w = p.z() - p.z().floor();
|
||||
|
||||
perlin_interpolate(smooth_grid, u, v, w)
|
||||
}
|
||||
|
||||
pub fn turbulence(&self, p: Vec3, depth: u32) -> f64 {
|
||||
let mut acc = 0.0f64;
|
||||
let mut weight = 1.0;
|
||||
let mut temp_p = p;
|
||||
|
||||
for _i in 0..depth {
|
||||
acc += weight * self.noise(temp_p);
|
||||
weight *= 0.5;
|
||||
temp_p *= 2.0;
|
||||
}
|
||||
|
||||
acc.abs()
|
||||
}
|
||||
}
|
||||
|
||||
fn perlin_interpolate(smooth_grid: [[[Vec3; 2]; 2]; 2], u: f64, v: f64, w: f64) -> f64 {
|
||||
// Hermitian smoothing so we don't see obvious grid features in the picture
|
||||
// Those features show up when we interpolate colors. Those features are
|
||||
// also called mach bands
|
||||
u = u * u * (3.0 - 2.0 * u);
|
||||
v = v * v * (3.0 - 2.0 * v);
|
||||
w = w * w * (3.0 - 2.0 * w);
|
||||
let uu = u * u * (3.0 - 2.0 * u);
|
||||
let vv = v * v * (3.0 - 2.0 * v);
|
||||
let ww = w * w * (3.0 - 2.0 * w);
|
||||
|
||||
return trilinear_interpolate(smooth_grid, u, v, w);
|
||||
}
|
||||
}
|
||||
|
||||
fn trilinear_interpolate(smooth_grid: [[[f64; 2]; 2]; 2], u: f64, v: f64, w: f64) -> f64 {
|
||||
let mut acc = 0.0;
|
||||
|
||||
for (di, a) in smooth_grid.iter().enumerate() {
|
||||
|
@ -80,10 +95,13 @@ fn trilinear_interpolate(smooth_grid: [[[f64; 2]; 2]; 2], u: f64, v: f64, w: f64
|
|||
let dj = dj as f64;
|
||||
for (dk, c) in b.iter().enumerate() {
|
||||
let dk = dk as f64;
|
||||
acc += (di * u + (1.0 - di) * (1.0 - u))
|
||||
* (dj * v + (1.0 - dj) * (1.0 - v))
|
||||
* (dk * w + (1.0 - dk) * (1.0 - w))
|
||||
* c;
|
||||
|
||||
let wt = Vec3::new(u - di, v - dj, w - dk);
|
||||
|
||||
acc += (di * uu + (1.0 - di) * (1.0 - uu))
|
||||
* (dj * vv + (1.0 - dj) * (1.0 - vv))
|
||||
* (dk * ww + (1.0 - dk) * (1.0 - ww))
|
||||
* c.dot(&wt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,6 +26,8 @@ impl PerlinNoise {
|
|||
|
||||
impl Texture for PerlinNoise {
|
||||
fn value(&self, _u: f64, _v: f64, p: Vec3) -> Vec3 {
|
||||
Vec3::new(1.0, 1.0, 1.0) * self.noise.noise(p * self.scale)
|
||||
Vec3::new(1.0, 1.0, 1.0)
|
||||
* 0.5
|
||||
* (1.0 + (self.scale * p.z() + 10.0 * self.noise.turbulence(p, 7)).sin())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,8 @@ use std::{
|
|||
ops::{Add, AddAssign, Div, DivAssign, Index, IndexMut, Mul, MulAssign, Neg, Sub, SubAssign},
|
||||
};
|
||||
|
||||
use rand::Rng;
|
||||
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct Vec3([f64; 3]);
|
||||
|
||||
|
@ -73,6 +75,11 @@ impl Vec3 {
|
|||
let length = self.length();
|
||||
Vec3([self[0] / length, self[1] / length, self[2] / length])
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn random<R: Rng + ?Sized>(rng: &mut R) -> Vec3 {
|
||||
Vec3([rng.gen(), rng.gen(), rng.gen()])
|
||||
}
|
||||
}
|
||||
|
||||
impl Add for Vec3 {
|
||||
|
|
Loading…
Reference in New Issue
Block a user