Added correctly generating world paths, sub-voxel shader noise

This commit is contained in:
Joshua Barretto 2020-04-20 20:18:51 +01:00
parent 431b2ae07b
commit 431e199731
8 changed files with 101 additions and 17 deletions

View File

@ -1,6 +1,7 @@
#version 330 core
#include <globals.glsl>
#include <random.glsl>
in vec3 f_pos;
flat in uint f_pos_norm;
@ -46,7 +47,9 @@ void main() {
ambient_light *= f_light * ao;
diffuse_light *= f_light * ao;
diffuse_light += point_light * ao;
vec3 surf_color = illuminate(srgb_to_linear(f_col), light, diffuse_light, ambient_light);
vec3 col = f_col + snoise(vec4(mod(floor(f_pos * 3.0), 100.0) * 10.0, 0)) * 0.02; // Small-scale noise
vec3 surf_color = illuminate(srgb_to_linear(col), light, diffuse_light, ambient_light);
float fog_level = fog(f_pos.xyz, focus_pos.xyz, medium.x);
vec4 clouds;

View File

@ -236,7 +236,7 @@ impl Scene {
};
self.camera.set_focus_pos(
player_pos + Vec3::unit_z() * (up + dist * 0.15 - tilt.min(0.0) * dist * 0.75),
player_pos + Vec3::unit_z() * (up + dist * 0.15 - tilt.min(0.0) * dist * 0.4),
);
// Tick camera for interpolation.

View File

@ -29,6 +29,7 @@ pub fn structure_gen<'a>(
|| st_sample.alt < st_sample.water_level
|| st_sample.spawn_rate < 0.5
|| st_sample.water_dist.map(|d| d < 8.0).unwrap_or(false)
|| st_sample.path.map(|(d, _)| d < 12.0).unwrap_or(false)
{
return None;
}

View File

@ -59,7 +59,7 @@ impl Civs {
}
}
for _ in 0..100 {
for _ in 0..32 {
attempt(5, || {
let loc = find_site_loc(&mut ctx, None)?;
this.establish_site(&mut ctx.reseed(), loc, |place| Site {
@ -498,7 +498,7 @@ fn walk_in_dir(sim: &WorldSim, a: Vec2<i32>, dir: Vec2<i32>) -> Option<f32> {
} else {
0.0
};
Some((b_alt - a_alt).abs() / 2.5)
Some(1.0 + ((b_alt - a_alt).abs() / 2.5).powf(2.0) + water_cost)
} else {
None
}

View File

@ -1118,18 +1118,7 @@ impl<'a> Sampler<'a> for ColumnGen<'a> {
5.0
};
const PATH_WIDTH: f32 = 5.0;
let path_dist_factor = sim
.get_nearest_path(wpos)
.map(|(dist, _)| dist / PATH_WIDTH)
.unwrap_or(1.0)
.min(1.0);
let ground = Lerp::lerp(
sub_surface_color,
ground,
(path_dist_factor.max(0.8) - 0.8) / 0.2,
);
let alt = alt - if path_dist_factor < 0.8 { 1.0 } else { 0.0 };
let path = sim.get_nearest_path(wpos);
Some(ColumnSample {
alt,
@ -1174,6 +1163,7 @@ impl<'a> Sampler<'a> for ColumnGen<'a> {
spawn_rate,
stone_col,
water_dist,
path,
chunk: sim_chunk,
})
@ -1207,6 +1197,7 @@ pub struct ColumnSample<'a> {
pub spawn_rate: f32,
pub stone_col: Rgb<u8>,
pub water_dist: Option<f32>,
pub path: Option<(f32, Vec2<i32>)>,
pub chunk: &'a SimChunk,
}

81
world/src/layer/mod.rs Normal file
View File

@ -0,0 +1,81 @@
use std::f32;
use vek::*;
use common::{
terrain::{Block, BlockKind},
vol::{BaseVol, ReadVol, RectSizedVol, RectVolSize, Vox, WriteVol},
};
use crate::{
column::ColumnSample,
util::{RandomField, Sampler},
};
pub fn apply_paths_to<'a>(
wpos2d: Vec2<i32>,
mut get_column: impl FnMut(Vec2<i32>) -> Option<&'a ColumnSample<'a>>,
vol: &mut (impl BaseVol<Vox = Block> + RectSizedVol + ReadVol + WriteVol),
) {
for y in 0..vol.size_xy().y as i32 {
for x in 0..vol.size_xy().x as i32 {
let offs = Vec2::new(x, y);
let wpos2d = wpos2d + offs;
// Sample terrain
let col_sample = if let Some(col_sample) = get_column(offs) {
col_sample
} else {
continue;
};
let surface_z = col_sample.riverless_alt.floor() as i32;
let noisy_color = |col: Rgb<u8>, factor: u32| {
let nz = RandomField::new(0).get(Vec3::new(wpos2d.x, wpos2d.y, surface_z));
col.map(|e| {
(e as u32 + nz % (factor * 2))
.saturating_sub(factor)
.min(255) as u8
})
};
if let Some((path_dist, path_nearest)) = col_sample.path.filter(|(dist, _)| *dist < 5.0) {
let inset = 0;
// Try to use the column at the centre of the path for sampling to make them
// flatter
let col = get_column(offs + path_nearest - wpos2d)
.unwrap_or(col_sample);
let (bridge_offset, depth) = if let Some(water_dist) = col.water_dist {
(
((water_dist.max(0.0) * 0.2).min(f32::consts::PI).cos() + 1.0) * 5.0,
((1.0 - ((water_dist + 2.0) * 0.3).min(0.0).cos().abs())
* (col.riverless_alt + 5.0 - col.alt).max(0.0)
* 1.75
+ 3.0) as i32,
)
} else {
(0.0, 3)
};
let surface_z = (col.riverless_alt + bridge_offset).floor() as i32;
for z in inset - depth..inset {
vol.set(
Vec3::new(offs.x, offs.y, surface_z + z),
if bridge_offset >= 2.0 && path_dist >= 3.0 || z < inset - 1 {
Block::new(BlockKind::Normal, noisy_color(Rgb::new(80, 80, 100), 8))
} else {
let path_color = col_sample.sub_surface_color.map(|e| (e * 255.0 * 0.7) as u8);
Block::new(BlockKind::Normal, noisy_color(path_color, 8))
},
);
}
let head_space = (8 - (path_dist * 0.25).powf(6.0).round() as i32).max(1);
for z in inset..inset + head_space {
let pos = Vec3::new(offs.x, offs.y, surface_z + z);
if vol.get(pos).unwrap().kind() != BlockKind::Water {
vol.set(pos, Block::empty());
}
}
}
}
}
}

View File

@ -9,6 +9,7 @@ mod column;
pub mod config;
pub mod sim;
pub mod site;
pub mod layer;
pub mod util;
// Reexports
@ -166,6 +167,9 @@ impl World {
.iter()
.for_each(|site| site.apply_to(chunk_wpos2d, sample_get, &mut chunk));
// Apply paths
layer::apply_paths_to(chunk_wpos2d, sample_get, &mut chunk);
let gen_entity_pos = || {
let lpos2d = TerrainChunkSize::RECT_SIZE
.map(|sz| rand::thread_rng().gen::<u32>().rem_euclid(sz) as i32);

View File

@ -149,7 +149,7 @@ impl Settlement {
this.place_farms(&mut ctx);
this.place_town(&mut ctx);
this.place_paths(ctx.rng);
//this.place_paths(ctx.rng);
this.place_buildings(&mut ctx);
this
@ -349,6 +349,10 @@ impl Settlement {
.tile_at(tile_pos)
.map(|t| t.contains(WayKind::Path))
.unwrap_or(true)
|| ctx.sim
.and_then(|sim| sim.get_nearest_path(self.origin + house_pos))
.map(|(dist, _)| dist < 28.0)
.unwrap_or(false)
{
continue;
}