Simple coral

This commit is contained in:
Joshua Barretto 2021-01-06 20:57:33 +00:00
parent a548769c6f
commit fdf3ab6a78
5 changed files with 153 additions and 3 deletions

View File

@ -193,6 +193,16 @@ impl Block {
}
}
#[inline]
pub fn get_max_sunlight(&self) -> Option<u8> {
match self.kind() {
BlockKind::Water => Some(2),
BlockKind::Leaves => Some(4),
_ if self.is_opaque() => Some(0),
_ => None,
}
}
#[inline]
pub fn is_solid(&self) -> bool {
self.get_sprite()

View File

@ -6,7 +6,7 @@ pub use self::{scatter::apply_scatter_to, tree::apply_trees_to};
use crate::{
column::ColumnSample,
util::{RandomField, Sampler},
util::{FastNoise, FastNoise2d, RandomField, Sampler},
Canvas, IndexRef,
};
use common::{
@ -22,7 +22,7 @@ use rand::prelude::*;
use serde::Deserialize;
use std::{
f32,
ops::{Mul, Sub},
ops::{Mul, Range, Sub},
};
use vek::*;
@ -302,3 +302,77 @@ pub fn apply_caves_supplement<'a>(
}
}
}
pub fn apply_coral_to(canvas: &mut Canvas) {
let info = canvas.info();
if !info.chunk.river.near_water() {
return; // Don't bother with coral for a chunk nowhere near water
}
canvas.foreach_col(|canvas, wpos2d, col| {
const CORAL_DEPTH: Range<f32> = 14.0..32.0;
const CORAL_HEIGHT: f32 = 14.0;
const CORAL_DEPTH_FADEOUT: f32 = 5.0;
const CORAL_SCALE: f32 = 10.0;
let water_depth = col.water_level - col.alt;
if !CORAL_DEPTH.contains(&water_depth) {
return; // Avoid coral entirely for this column if we're outside coral depths
}
for z in col.alt.floor() as i32..(col.alt + CORAL_HEIGHT) as i32 {
let wpos = Vec3::new(wpos2d.x, wpos2d.y, z);
let coral_factor = Lerp::lerp(
1.0,
0.0,
// Fade coral out due to incorrect depth
((water_depth.clamped(CORAL_DEPTH.start, CORAL_DEPTH.end) - water_depth).abs()
/ CORAL_DEPTH_FADEOUT)
.min(1.0),
) * Lerp::lerp(
1.0,
0.0,
// Fade coral out due to incorrect altitude above the seabed
((z as f32 - col.alt) / CORAL_HEIGHT).powi(2),
) * FastNoise::new(info.index.seed + 7)
.get(wpos.map(|e| e as f64) / 32.0)
.sub(0.2)
.mul(100.0)
.clamped(0.0, 1.0);
let nz = Vec3::iota().map(|e: u32| FastNoise::new(info.index.seed + e * 177));
let wpos_warped = wpos.map(|e| e as f32)
+ nz.map(|nz| {
nz.get(wpos.map(|e| e as f64) / CORAL_SCALE as f64) * CORAL_SCALE * 0.3
});
// let is_coral = FastNoise2d::new(info.index.seed + 17)
// .get(wpos_warped.xy().map(|e| e as f64) / CORAL_SCALE)
// .sub(1.0 - coral_factor)
// .max(0.0)
// .div(coral_factor) > 0.5;
let is_coral = [
FastNoise::new(info.index.seed),
FastNoise::new(info.index.seed + 177),
]
.iter()
.all(|nz| {
nz.get(wpos_warped.map(|e| e as f64) / CORAL_SCALE as f64)
.abs()
< coral_factor * 0.3
});
if is_coral {
let _ = canvas.set(
wpos,
Block::new(BlockKind::WeakRock, Rgb::new(170, 220, 210)),
);
}
}
});
}

View File

@ -290,6 +290,7 @@ impl World {
layer::apply_scatter_to(&mut canvas, &mut dynamic_rng);
layer::apply_caves_to(&mut canvas, &mut dynamic_rng);
layer::apply_paths_to(&mut canvas);
layer::apply_coral_to(&mut canvas);
// Apply site generation
sim_chunk.sites.iter().for_each(|site| {

View File

@ -24,6 +24,30 @@ impl Sampler<'static> for FastNoise {
type Sample = f32;
fn get(&self, pos: Self::Index) -> Self::Sample {
// let align_pos = pos.map(|e| e.floor());
// let near_pos = align_pos.map(|e| e as i32);
// let v000 = self.noise_at(near_pos + Vec3::new(0, 0, 0));
// let v100 = self.noise_at(near_pos + Vec3::new(1, 0, 0));
// let v010 = self.noise_at(near_pos + Vec3::new(0, 1, 0));
// let v110 = self.noise_at(near_pos + Vec3::new(1, 1, 0));
// let v001 = self.noise_at(near_pos + Vec3::new(0, 0, 1));
// let v101 = self.noise_at(near_pos + Vec3::new(1, 0, 1));
// let v011 = self.noise_at(near_pos + Vec3::new(0, 1, 1));
// let v111 = self.noise_at(near_pos + Vec3::new(1, 1, 1));
// let factor = (pos - align_pos).map(|e| e as f32);
// let v00 = v000 + factor.z * (v001 - v000);
// let v10 = v010 + factor.z * (v011 - v010);
// let v01 = v100 + factor.z * (v101 - v100);
// let v11 = v110 + factor.z * (v111 - v110);
// let v0 = v00 + factor.y * (v01 - v00);
// let v1 = v10 + factor.y * (v11 - v10);
// (v0 + factor.x * (v1 - v0)) * 2.0 - 1.0
let near_pos = pos.map(|e| e.floor() as i32);
let v000 = self.noise_at(near_pos + Vec3::new(0, 0, 0));
@ -51,3 +75,44 @@ impl Sampler<'static> for FastNoise {
(y0 + factor.z * (y1 - y0)) * 2.0 - 1.0
}
}
pub struct FastNoise2d {
noise: RandomField,
}
impl FastNoise2d {
pub const fn new(seed: u32) -> Self {
Self {
noise: RandomField::new(seed),
}
}
#[allow(clippy::excessive_precision)] // TODO: Pending review in #587
fn noise_at(&self, pos: Vec2<i32>) -> f32 {
(self.noise.get(Vec3::new(pos.x, pos.y, 0)) & 4095) as f32 * 0.000244140625
}
}
impl Sampler<'static> for FastNoise2d {
type Index = Vec2<f64>;
type Sample = f32;
fn get(&self, pos: Self::Index) -> Self::Sample {
let near_pos = pos.map(|e| e.floor() as i32);
let v00 = self.noise_at(near_pos + Vec2::new(0, 0));
let v10 = self.noise_at(near_pos + Vec2::new(1, 0));
let v01 = self.noise_at(near_pos + Vec2::new(0, 1));
let v11 = self.noise_at(near_pos + Vec2::new(1, 1));
let factor = pos.map(|e| {
let f = e.fract().add(1.0).fract() as f32;
f.powi(2) * (3.0 - 2.0 * f)
});
let v0 = v00 + factor.y * (v10 - v00);
let v1 = v01 + factor.y * (v11 - v01);
(v0 + factor.x * (v1 - v0)) * 2.0 - 1.0
}
}

View File

@ -9,7 +9,7 @@ pub mod unit_chooser;
// Reexports
pub use self::{
fast_noise::FastNoise,
fast_noise::{FastNoise, FastNoise2d},
map_vec::MapVec,
random::{RandomField, RandomPerm},
sampler::{Sampler, SamplerMut},