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;
|
use std::time::Instant;
|
||||||
|
|
||||||
const NUM_SAMPLES: u8 = 25;
|
const NUM_SAMPLES: u8 = 255;
|
||||||
const VERTICAL_PARTITION: usize = 12;
|
const VERTICAL_PARTITION: usize = 12;
|
||||||
const HORIZONTAL_PARTITION: usize = 12;
|
const HORIZONTAL_PARTITION: usize = 12;
|
||||||
const WIDTH: usize = 1920;
|
const WIDTH: usize = 2560;
|
||||||
const HEIGHT: usize = 1080;
|
const HEIGHT: usize = 1440;
|
||||||
|
|
||||||
fn main() -> Result<(), String> {
|
fn main() -> Result<(), String> {
|
||||||
run(WIDTH, HEIGHT)
|
run(WIDTH, HEIGHT)
|
||||||
|
@ -134,9 +134,9 @@ fn run(mut width: usize, mut height: usize) -> Result<(), String> {
|
||||||
|
|
||||||
#[cfg(not(feature = "gui"))]
|
#[cfg(not(feature = "gui"))]
|
||||||
fn run(width: usize, height: usize) -> Result<(), String> {
|
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);
|
run_and_save_demo(demos::PerlinNoiseBall {}, width, height);
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
use crate::types::Vec3;
|
use crate::types::Vec3;
|
||||||
use rand::{distributions::Uniform, Rng};
|
use rand::Rng;
|
||||||
|
|
||||||
const POINT_COUNT: usize = 256;
|
const POINT_COUNT: usize = 256;
|
||||||
|
|
||||||
pub struct Perlin {
|
pub struct Perlin {
|
||||||
points: Vec<f64>,
|
points: Vec<Vec3>,
|
||||||
|
|
||||||
permute_x: Vec<usize>,
|
permute_x: Vec<usize>,
|
||||||
permute_y: Vec<usize>,
|
permute_y: Vec<usize>,
|
||||||
|
@ -13,10 +13,9 @@ pub struct Perlin {
|
||||||
|
|
||||||
impl Perlin {
|
impl Perlin {
|
||||||
pub fn new<R: Rng + ?Sized>(rng: &mut R) -> Self {
|
pub fn new<R: Rng + ?Sized>(rng: &mut R) -> Self {
|
||||||
let points = rng
|
let points = (0..POINT_COUNT)
|
||||||
.sample_iter(Uniform::from(0.0..=1.0))
|
.map(|_| Vec3::random(rng).unit_vector())
|
||||||
.take(POINT_COUNT)
|
.collect::<Vec<Vec3>>();
|
||||||
.collect::<Vec<f64>>();
|
|
||||||
|
|
||||||
let permute_x = Self::perlin_generate_permutation(rng);
|
let permute_x = Self::perlin_generate_permutation(rng);
|
||||||
let permute_y = 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 {
|
pub fn noise(&self, p: Vec3) -> f64 {
|
||||||
let i = p.x().floor() as i32;
|
let mut smooth_grid = [[[Vec3::new(0.0, 0.0, 0.0); 2]; 2]; 2];
|
||||||
let j = p.y().floor() as i32;
|
|
||||||
let k = p.z().floor() as i32;
|
|
||||||
|
|
||||||
let mut smooth_grid = [[[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;
|
||||||
|
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;
|
||||||
|
|
||||||
for (di, a) in smooth_grid.iter_mut().enumerate() {
|
*c = self.points[self.permute_x[((i + di) & 255) as usize]
|
||||||
let di = di as i32;
|
^ self.permute_y[((j + dj) & 255) as usize]
|
||||||
for (dj, b) in a.iter_mut().enumerate() {
|
^ self.permute_z[((k + dk) & 255) as usize]]
|
||||||
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 u = p.x() - p.x().floor();
|
||||||
let mut v = p.y() - p.y().floor();
|
let v = p.y() - p.y().floor();
|
||||||
let mut w = p.z() - p.z().floor();
|
let w = p.z() - p.z().floor();
|
||||||
|
|
||||||
// Hermitian smoothing so we don't see obvious grid features in the picture
|
perlin_interpolate(smooth_grid, u, v, w)
|
||||||
// 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);
|
|
||||||
|
|
||||||
return trilinear_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 trilinear_interpolate(smooth_grid: [[[f64; 2]; 2]; 2], u: f64, v: f64, w: f64) -> f64 {
|
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
|
||||||
|
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);
|
||||||
|
|
||||||
let mut acc = 0.0;
|
let mut acc = 0.0;
|
||||||
|
|
||||||
for (di, a) in smooth_grid.iter().enumerate() {
|
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;
|
let dj = dj as f64;
|
||||||
for (dk, c) in b.iter().enumerate() {
|
for (dk, c) in b.iter().enumerate() {
|
||||||
let dk = dk as f64;
|
let dk = dk as f64;
|
||||||
acc += (di * u + (1.0 - di) * (1.0 - u))
|
|
||||||
* (dj * v + (1.0 - dj) * (1.0 - v))
|
let wt = Vec3::new(u - di, v - dj, w - dk);
|
||||||
* (dk * w + (1.0 - dk) * (1.0 - w))
|
|
||||||
* c;
|
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 {
|
impl Texture for PerlinNoise {
|
||||||
fn value(&self, _u: f64, _v: f64, p: Vec3) -> Vec3 {
|
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},
|
ops::{Add, AddAssign, Div, DivAssign, Index, IndexMut, Mul, MulAssign, Neg, Sub, SubAssign},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use rand::Rng;
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
pub struct Vec3([f64; 3]);
|
pub struct Vec3([f64; 3]);
|
||||||
|
|
||||||
|
@ -73,6 +75,11 @@ impl Vec3 {
|
||||||
let length = self.length();
|
let length = self.length();
|
||||||
Vec3([self[0] / length, self[1] / length, self[2] / 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 {
|
impl Add for Vec3 {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user