Skip to content

Commit

Permalink
update: make DW noise more wacky
Browse files Browse the repository at this point in the history
  • Loading branch information
Velfi committed Jul 24, 2021
1 parent a70a121 commit 31f6d6c
Show file tree
Hide file tree
Showing 2 changed files with 120 additions and 15 deletions.
121 changes: 111 additions & 10 deletions src/noise/domain_warping_noise.rs
Original file line number Diff line number Diff line change
@@ -1,33 +1,134 @@
use log::trace;
use noise::{Fbm, NoiseFn};
use rand::{prelude::StdRng, Rng, SeedableRng};

pub struct DomainWarpingNoise {
fbm: Fbm,
params: DomainWarpingNoiseParams,
}

impl DomainWarpingNoise {
pub fn new() -> Self {
Self { fbm: Fbm::new() }
pub fn new(params: DomainWarpingNoiseParams) -> Self {
Self {
fbm: Fbm::new(),
params,
}
}

pub fn inigo() -> Self {
Self {
fbm: Fbm::new(),
params: DomainWarpingNoiseParams::inigo(),
}
}
}

impl Default for DomainWarpingNoise {
fn default() -> Self {
Self {
fbm: Fbm::new(),
params: Default::default(),
}
}
}

#[derive(Debug)]
pub struct DomainWarpingNoiseParams {
q: [f64; 9],
r: [f64; 9],
qn: f64,
rn: f64,
}

impl DomainWarpingNoiseParams {
pub fn new(q: [f64; 9], r: [f64; 9], qn: f64, rn: f64) -> Self {
Self { q, r, qn, rn }
}

pub fn random() -> Self {
// rng.gen handles arrays just fine but fills them with numbers between 0.0 and 1.0
// gen_range allows for numbers from a larger range but it can't handle arrays :(
let mut rng = StdRng::from_entropy();
let q_range = -100.0..100.0;
let q: [f64; 9] = [
rng.gen_range(q_range.clone()),
rng.gen_range(q_range.clone()),
rng.gen_range(q_range.clone()),
rng.gen_range(q_range.clone()),
rng.gen_range(q_range.clone()),
rng.gen_range(q_range.clone()),
rng.gen_range(q_range.clone()),
rng.gen_range(q_range.clone()),
rng.gen_range(q_range.clone()),
];

let r_range = -100.0..100.0;
let r: [f64; 9] = [
rng.gen_range(r_range.clone()),
rng.gen_range(r_range.clone()),
rng.gen_range(r_range.clone()),
rng.gen_range(r_range.clone()),
rng.gen_range(r_range.clone()),
rng.gen_range(r_range.clone()),
rng.gen_range(r_range.clone()),
rng.gen_range(r_range.clone()),
rng.gen_range(r_range.clone()),
];
let qn: f64 = rng.gen_range(0.001..5.0);
let rn: f64 = rng.gen_range(0.001..5.0);

let s = Self { q, r, qn, rn };

trace!(
"Creating random parameters for domain warping noise:\n{:?}",
s
);

s
}

// https://www.iquilezles.org/www/articles/warp/warp.htm
fn inigo() -> Self {
Self {
q: [0.0, 0.0, 0.0, 5.2, 1.3, 0.0, 0.0, 0.0, 0.0],
r: [1.7, 9.2, 0.0, 8.3, 2.8, 0.0, 0.0, 0.0, 0.0],
qn: 4.0,
rn: 4.0,
}
}
}

impl Default for DomainWarpingNoiseParams {
fn default() -> Self {
Self {
q: Default::default(),
r: Default::default(),
qn: 1.0,
rn: 1.0,
}
}
}

// Image for f(p) = fbm(p+fbm(p+fbm(p)))
impl NoiseFn<[f64; 3]> for DomainWarpingNoise {
fn get(&self, p: [f64; 3]) -> f64 {
let [q0, q1, q2, q3, q4, q5, q6, q7, q8] = self.params.q;
let q = vec3(
self.fbm.get(add(p, vec3(0.0, 0.0, 1.0))),
self.fbm.get(add(p, vec3(5.2, 1.3, 1.0))),
self.fbm.get(add(p, vec3(1.0, 1.0, 1.0))),
self.fbm.get(add(p, vec3(q0, q1, q2))),
self.fbm.get(add(p, vec3(q3, q4, q5))),
self.fbm.get(add(p, vec3(q6, q7, q8))),
);

let q = mul_n(q, 4.0);
let q = mul_n(q, self.params.qn);

let [r0, r1, r2, r3, r4, r5, r6, r7, r8] = self.params.r;
let r = vec3(
self.fbm.get(add(p, add(q, vec3(1.7, 9.2, 1.0)))),
self.fbm.get(add(p, add(q, vec3(8.3, 2.8, 1.0)))),
self.fbm.get(add(p, add(q, vec3(1.0, 1.0, 1.0)))),
self.fbm.get(add(p, add(q, vec3(r0, r1, r2)))),
self.fbm.get(add(p, add(q, vec3(r3, r4, r5)))),
self.fbm.get(add(p, add(q, vec3(r6, r7, r8)))),
);

let r = mul_n(r, 4.0);
let r = mul_n(r, self.params.rn);
self.fbm.get(add(p, r))
}
}
Expand Down
14 changes: 9 additions & 5 deletions src/noise/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,24 @@ mod domain_warping_noise;
use domain_warping_noise::DomainWarpingNoise;
use noise::NoiseFn;

use crate::noise::domain_warping_noise::DomainWarpingNoiseParams;

pub fn new_noise_fn_by_index(index: usize) -> Box<dyn NoiseFn<[f64; 3]>> {
match index {
0 => {
println!("now using Domain Warping Noise generator");
let dwn_params = DomainWarpingNoiseParams::random();
Box::new(DomainWarpingNoise::new(dwn_params))
}
1 => {
println!("now using Billowy Noise generator");
// TODO allow setting frequency, lacunarity, octaves, persistence
Box::new(noise::Billow::new())
}
1 => {
2 => {
println!("now using Heterogenous Multifractal Noise generator");
Box::new(noise::BasicMulti::new())
}
2 => {
println!("now using Domain Warping Noise generator");
Box::new(DomainWarpingNoise::new())
}
3 => {
println!("now using Fractal Brownian Motion Noise generator");
Box::new(noise::Fbm::new())
Expand Down

0 comments on commit 31f6d6c

Please sign in to comment.