Skip to content

Instantly share code, notes, and snippets.

@zesterer
Created September 1, 2019 12:36
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save zesterer/7dd75d7e8c9b601e82815f9003c21157 to your computer and use it in GitHub Desktop.
Save zesterer/7dd75d7e8c9b601e82815f9003c21157 to your computer and use it in GitHub Desktop.
fn linear_lerp(a: f32, b: f32, x: f32) -> f32 {
a + (b - a) * x
}
fn cosine_lerp(a: f32, b: f32, x: f32) -> f32 {
let x = 0.5 - (x.fract() as f32 * f32::consts::PI).cos() * 0.5;
a + (b - a) * x
}
fn perlin_ext(pos: Vec3<f32>, seed: u32, lerp: fn(f32, f32, f32) -> f32, octaves: usize, freq_factor: f32, scale_factor: f32) -> f32 {
let mut total = 0.0;
let mut scale = 1.0;
let mut freq = 1.0;
for i in 0..octaves {
total += perlin(pos * freq, seed + 1, lerp) * scale;
freq *= freq_factor;
scale *= scale_factor;
}
total
}
fn perlin(pos: Vec3<f32>, seed: u32, lerp: fn(f32, f32, f32) -> f32) -> f32 {
let apos = pos.map(|e| e.trunc() as u32);
let v000 = gradient(apos + Vec3::new(0, 0, 0), pos, seed);
let v100 = gradient(apos + Vec3::new(1, 0, 0), pos, seed);
let v010 = gradient(apos + Vec3::new(0, 1, 0), pos, seed);
let v110 = gradient(apos + Vec3::new(1, 1, 0), pos, seed);
let v001 = gradient(apos + Vec3::new(0, 0, 1), pos, seed);
let v101 = gradient(apos + Vec3::new(1, 0, 1), pos, seed);
let v011 = gradient(apos + Vec3::new(0, 1, 1), pos, seed);
let v111 = gradient(apos + Vec3::new(1, 1, 1), pos, seed);
let rpos = pos.map(|e| e.fract());
let h00 = lerp(v000, v100, rpos.x);
let h10 = lerp(v010, v110, rpos.x);
let h01 = lerp(v001, v101, rpos.x);
let h11 = lerp(v011, v111, rpos.x);
let d0 = lerp(h00, h10, rpos.y);
let d1 = lerp(h01, h11, rpos.y);
let v = lerp(d0, d1, rpos.z);
v
}
fn gradient(apos: Vec3<u32>, pos: Vec3<f32>, seed: u32) -> f32 {
pos
.map2(Vec3::iota() + seed, |e, i| (e, i))
.map2(apos, |(e, i), a| (e - a as f32) * noise(apos, i))
.sum()
}
fn noise(pos: Vec3<u32>, seed: u32) -> f32 {
floatify(permute(combine(pos), seed))
}
fn floatify(x: u32) -> f32 {
(x & 0xFFFF) as f32 / 32768.0 - 1.0
}
fn combine(pos: Vec3<u32>) -> u32 {
pos.iter().fold(0x3725EA13, |a, b| permute(*b ^ 0x55555555, a))
}
fn permute(x: u32, seed: u32) -> u32 {
let x = (x + seed.wrapping_mul(3471)).wrapping_add(0x3BE7172B).wrapping_mul(x).wrapping_add(0x172A3BE1);
x.wrapping_mul(x) ^ (x >> 17) ^ x.wrapping_mul(x) >> 15
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment