1
0

completed perlin textures

This commit is contained in:
Ishan Jain 2021-03-05 20:54:25 +05:30
parent aa74b321b8
commit 7468ba1112
No known key found for this signature in database
GPG Key ID: F261A0E73038D89D
4 changed files with 67 additions and 40 deletions

View File

@ -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);

View File

@ -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);
} }
} }
} }

View File

@ -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())
} }
} }

View File

@ -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 {