From 4a29900914d87d887d8867b798cc5562a430ad6e Mon Sep 17 00:00:00 2001 From: Luc Fauvel Date: Mon, 5 Aug 2019 22:50:49 -0400 Subject: [PATCH 01/15] Copying terrain pipeline and shaders for fluids --- voxygen/shaders/fluid.frag | 30 +++++++++++ voxygen/shaders/fluid.vert | 49 +++++++++++++++++ voxygen/src/render/mod.rs | 1 + voxygen/src/render/pipelines/fluid.rs | 78 +++++++++++++++++++++++++++ voxygen/src/render/pipelines/mod.rs | 1 + voxygen/src/render/renderer.rs | 11 +++- 6 files changed, 169 insertions(+), 1 deletion(-) create mode 100644 voxygen/shaders/fluid.frag create mode 100644 voxygen/shaders/fluid.vert create mode 100644 voxygen/src/render/pipelines/fluid.rs diff --git a/voxygen/shaders/fluid.frag b/voxygen/shaders/fluid.frag new file mode 100644 index 0000000000..f037f5bcbe --- /dev/null +++ b/voxygen/shaders/fluid.frag @@ -0,0 +1,30 @@ +#version 330 core + +#include + +in vec3 f_pos; +flat in vec3 f_norm; +in vec3 f_col; +in float f_light; +in float f_opac; + +layout (std140) +uniform u_locals { + vec3 model_offs; +}; + +out vec4 tgt_color; + +#include +#include + +void main() { + vec3 light = get_sun_diffuse(f_norm, time_of_day.x) * f_light + light_at(f_pos, f_norm); + vec3 surf_color = f_col * light; + + float fog_level = fog(f_pos.xy, focus_pos.xy); + vec3 fog_color = get_sky_color(normalize(f_pos - cam_pos.xyz), time_of_day.x); + vec3 color = mix(surf_color, fog_color, fog_level); + + tgt_color = vec4(color, f_opac); +} diff --git a/voxygen/shaders/fluid.vert b/voxygen/shaders/fluid.vert new file mode 100644 index 0000000000..d62d9da725 --- /dev/null +++ b/voxygen/shaders/fluid.vert @@ -0,0 +1,49 @@ +#version 330 core + +#include + +in uint v_pos_norm; +in uint v_col_light; + +layout (std140) +uniform u_locals { + vec3 model_offs; +}; + +out vec3 f_pos; +flat out vec3 f_norm; +out vec3 f_col; +out float f_light; + +// First 3 normals are negative, next 3 are positive +vec3 normals[6] = vec3[]( vec3(-1,0,0), vec3(0,-1,0), vec3(0,0,-1), vec3(1,0,0), vec3(0,1,0), vec3(0,0,1) ); + +void main() { + f_pos = vec3( + float((v_pos_norm >> 0) & 0x00FFu), + float((v_pos_norm >> 8) & 0x00FFu), + float((v_pos_norm >> 16) & 0x1FFFu) + ) + model_offs; + + // TODO: last 3 bits in v_pos_norm should be a number between 0 and 5, rather than 0-2 and a direction. + uint norm_axis = (v_pos_norm >> 30) & 0x3u; + + // Increase array access by 3 to access positive values + uint norm_dir = ((v_pos_norm >> 29) & 0x1u) * 3u; + + // Use an array to avoid conditional branching + f_norm = normals[norm_axis + norm_dir]; + + f_col = vec3( + float((v_col_light >> 8) & 0xFFu), + float((v_col_light >> 16) & 0xFFu), + float((v_col_light >> 24) & 0xFFu) + ) / 200.0; + + f_light = float(v_col_light & 0xFFu) / 255.0; + + gl_Position = + proj_mat * + view_mat * + vec4(f_pos, 1); +} \ No newline at end of file diff --git a/voxygen/src/render/mod.rs b/voxygen/src/render/mod.rs index 8a5859c91c..4cd3e676b2 100644 --- a/voxygen/src/render/mod.rs +++ b/voxygen/src/render/mod.rs @@ -22,6 +22,7 @@ pub use self::{ create_quad as create_ui_quad, create_tri as create_ui_tri, Locals as UiLocals, Mode as UiMode, UiPipeline, }, + fluid::{Locals as FluidLocals, FluidPipeline}, Globals, Light, }, renderer::{Renderer, TgtColorFmt, TgtDepthFmt, WinColorFmt, WinDepthFmt}, diff --git a/voxygen/src/render/pipelines/fluid.rs b/voxygen/src/render/pipelines/fluid.rs new file mode 100644 index 0000000000..e91e143d64 --- /dev/null +++ b/voxygen/src/render/pipelines/fluid.rs @@ -0,0 +1,78 @@ +use super::{ + super::{Pipeline, TgtColorFmt, TgtDepthFmt}, + Globals, Light, +}; +use gfx::{ + self, + gfx_constant_struct_meta, + // Macros + gfx_defines, + gfx_impl_struct_meta, + gfx_pipeline, + gfx_pipeline_inner, + gfx_vertex_struct_meta, +}; +use std::ops::Mul; +use vek::*; + +gfx_defines! { + vertex Vertex { + pos_norm: u32 = "v_pos_norm", + col_light: u32 = "v_col_light", + } + + constant Locals { + model_offs: [f32; 3] = "model_offs", + } + + pipeline pipe { + vbuf: gfx::VertexBuffer = (), + + locals: gfx::ConstantBuffer = "u_locals", + globals: gfx::ConstantBuffer = "u_globals", + lights: gfx::ConstantBuffer = "u_lights", + + tgt_color: gfx::RenderTarget = "tgt_color", + tgt_depth: gfx::DepthTarget = gfx::preset::depth::LESS_EQUAL_WRITE, + } +} + +impl Vertex { + pub fn new(pos: Vec3, norm: Vec3, col: Rgb, light: f32, opac: f32) -> Self { + let (norm_axis, norm_dir) = norm + .as_slice() + .into_iter() + .enumerate() + .find(|(_i, e)| **e != 0.0) + .unwrap_or((0, &1.0)); + let norm_bits = (norm_axis << 1) | if *norm_dir > 0.0 { 1 } else { 0 }; + + Self { + pos_norm: 0 + | ((pos.x as u32) & 0x00FF) << 0 + | ((pos.y as u32) & 0x00FF) << 8 + | ((pos.z.max(0.0).min((1 << 13) as f32) as u32) & 0x1FFF) << 16 + | ((norm_bits as u32) & 0x7) << 29, + col_light: 0 + | ((col.r.mul(200.0) as u32) & 0xFF) << 8 + | ((col.g.mul(200.0) as u32) & 0xFF) << 16 + | ((col.b.mul(200.0) as u32) & 0xFF) << 24 + | ((light.mul(255.0) as u32) & 0xFF) << 0 + | ((opac.mul(0.4) as u32) & 0xFF) << 0, + } + } +} + +impl Locals { + pub fn default() -> Self { + Self { + model_offs: [0.0; 3], + } + } +} + +pub struct FluidPipeline; + +impl Pipeline for FluidPipeline { + type Vertex = Vertex; +} diff --git a/voxygen/src/render/pipelines/mod.rs b/voxygen/src/render/pipelines/mod.rs index c5ee05aaf5..6184e74a39 100644 --- a/voxygen/src/render/pipelines/mod.rs +++ b/voxygen/src/render/pipelines/mod.rs @@ -3,6 +3,7 @@ pub mod postprocess; pub mod skybox; pub mod terrain; pub mod ui; +pub mod fluid; use super::util::arr_to_mat; use gfx::{ diff --git a/voxygen/src/render/renderer.rs b/voxygen/src/render/renderer.rs index 6f4853d433..e659e9869d 100644 --- a/voxygen/src/render/renderer.rs +++ b/voxygen/src/render/renderer.rs @@ -3,7 +3,7 @@ use super::{ gfx_backend, mesh::Mesh, model::{DynamicModel, Model}, - pipelines::{figure, postprocess, skybox, terrain, ui, Globals, Light}, + pipelines::{figure, postprocess, skybox, terrain, ui, Globals, Light, fluid}, texture::Texture, Pipeline, RenderError, }; @@ -83,6 +83,15 @@ impl Renderer { let (skybox_pipeline, figure_pipeline, terrain_pipeline, ui_pipeline, postprocess_pipeline) = create_pipelines(&mut factory, &mut shader_reload_indicator)?; + // Construct a pipeline for rendering fluids + let fluid_pipeline = create_pipeline( + &mut factory, + fluid::pipe::new(), + include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/shaders/fluid.vert")), + include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/shaders/fluid.frag")), + &include_ctx, + )?; + let dims = win_color_view.get_dimensions(); let (tgt_color_view, tgt_depth_view, tgt_color_res) = Self::create_rt_views(&mut factory, (dims.0, dims.1))?; From 42237a84e47ccc5d815459535d158a8ce9894e44 Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Wed, 14 Aug 2019 22:28:37 +0100 Subject: [PATCH 02/15] Added translucent meshing pass, water reflections --- .../voxygen/shaders/fluid-frag.glsl | 8 +- .../voxygen/shaders/fluid-vert.glsl | 23 +++-- common/src/terrain/block.rs | 78 +++++++++++++--- common/src/terrain/mod.rs | 6 +- common/src/terrain/structure.rs | 4 +- voxygen/src/mesh/mod.rs | 7 +- voxygen/src/mesh/segment.rs | 11 ++- voxygen/src/mesh/terrain.rs | 91 ++++++++++--------- voxygen/src/mesh/vol.rs | 21 ++--- voxygen/src/render/mod.rs | 2 +- voxygen/src/render/pipelines/fluid.rs | 24 ++--- voxygen/src/render/pipelines/mod.rs | 2 +- voxygen/src/render/renderer.rs | 56 +++++++++--- voxygen/src/scene/figure.rs | 1 + voxygen/src/scene/mod.rs | 2 +- voxygen/src/scene/terrain.rs | 32 +++++-- voxygen/src/session.rs | 10 +- world/src/block/mod.rs | 49 ++++------ world/src/lib.rs | 6 +- 19 files changed, 270 insertions(+), 163 deletions(-) rename voxygen/shaders/fluid.frag => assets/voxygen/shaders/fluid-frag.glsl (60%) rename voxygen/shaders/fluid.vert => assets/voxygen/shaders/fluid-vert.glsl (73%) diff --git a/voxygen/shaders/fluid.frag b/assets/voxygen/shaders/fluid-frag.glsl similarity index 60% rename from voxygen/shaders/fluid.frag rename to assets/voxygen/shaders/fluid-frag.glsl index f037f5bcbe..5583c72df2 100644 --- a/voxygen/shaders/fluid.frag +++ b/assets/voxygen/shaders/fluid-frag.glsl @@ -22,9 +22,13 @@ void main() { vec3 light = get_sun_diffuse(f_norm, time_of_day.x) * f_light + light_at(f_pos, f_norm); vec3 surf_color = f_col * light; - float fog_level = fog(f_pos.xy, focus_pos.xy); + float fog_level = fog(f_pos.xy, focus_pos.xy); vec3 fog_color = get_sky_color(normalize(f_pos - cam_pos.xyz), time_of_day.x); - vec3 color = mix(surf_color, fog_color, fog_level); + + vec3 warped_norm = normalize(f_norm + (sin(f_pos.xyz + tick.x + 13.7) + sin(f_pos.zxy + tick.x + 19.3)) * 0.3); + vec3 reflect_color = get_sky_color(reflect(normalize(f_pos - cam_pos.xyz), warped_norm), time_of_day.x); + + vec3 color = mix(surf_color + reflect_color * 0.5, fog_color, fog_level); tgt_color = vec4(color, f_opac); } diff --git a/voxygen/shaders/fluid.vert b/assets/voxygen/shaders/fluid-vert.glsl similarity index 73% rename from voxygen/shaders/fluid.vert rename to assets/voxygen/shaders/fluid-vert.glsl index d62d9da725..71b14ea98e 100644 --- a/voxygen/shaders/fluid.vert +++ b/assets/voxygen/shaders/fluid-vert.glsl @@ -14,15 +14,16 @@ out vec3 f_pos; flat out vec3 f_norm; out vec3 f_col; out float f_light; +out float f_opac; // First 3 normals are negative, next 3 are positive vec3 normals[6] = vec3[]( vec3(-1,0,0), vec3(0,-1,0), vec3(0,0,-1), vec3(1,0,0), vec3(0,1,0), vec3(0,0,1) ); void main() { f_pos = vec3( - float((v_pos_norm >> 0) & 0x00FFu), - float((v_pos_norm >> 8) & 0x00FFu), - float((v_pos_norm >> 16) & 0x1FFFu) + float((v_pos_norm >> 0) & 0x00FFu), + float((v_pos_norm >> 8) & 0x00FFu), + float((v_pos_norm >> 16) & 0x1FFFu) ) + model_offs; // TODO: last 3 bits in v_pos_norm should be a number between 0 and 5, rather than 0-2 and a direction. @@ -35,15 +36,17 @@ void main() { f_norm = normals[norm_axis + norm_dir]; f_col = vec3( - float((v_col_light >> 8) & 0xFFu), - float((v_col_light >> 16) & 0xFFu), - float((v_col_light >> 24) & 0xFFu) + float((v_col_light >> 8) & 0xFFu), + float((v_col_light >> 16) & 0xFFu), + float((v_col_light >> 24) & 0xFFu) ) / 200.0; f_light = float(v_col_light & 0xFFu) / 255.0; + f_opac = 0.1; + gl_Position = - proj_mat * - view_mat * - vec4(f_pos, 1); -} \ No newline at end of file + proj_mat * + view_mat * + vec4(f_pos, 1); +} diff --git a/common/src/terrain/block.rs b/common/src/terrain/block.rs index f95f2cd9aa..812391f416 100644 --- a/common/src/terrain/block.rs +++ b/common/src/terrain/block.rs @@ -1,47 +1,97 @@ use crate::vol::Vox; use serde_derive::{Deserialize, Serialize}; +use std::ops::Deref; use vek::*; #[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)] +#[repr(u8)] +pub enum BlockKind { + Air, + Normal, + Dense, + Water, +} + +impl BlockKind { + pub fn is_air(&self) -> bool { + match self { + BlockKind::Air => true, + _ => false, + } + } + + pub fn is_fluid(&self) -> bool { + match self { + BlockKind::Water => true, + _ => false, + } + } + + pub fn is_opaque(&self) -> bool { + match self { + BlockKind::Air => false, + BlockKind::Water => false, + _ => true, + } + } +} + +#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)] +#[repr(packed)] pub struct Block { - kind: u8, + kind: BlockKind, color: [u8; 3], } impl Block { - pub fn new(kind: u8, color: Rgb) -> Self { + pub fn new(kind: BlockKind, color: Rgb) -> Self { Self { kind, color: color.into_array(), } } - pub fn get_color(self) -> Option> { - if self.is_empty() { - None - } else { + pub fn get_color(&self) -> Option> { + if !self.is_air() { Some(self.color.into()) + } else { + None } } - pub fn get_opacity(self) -> Option { - match self.kind { - 0 => None, - 1 => Some(0.85), - _ => Some(3.0), - } + pub fn kind(&self) -> BlockKind { + self.kind + } +} + +impl Deref for Block { + type Target = BlockKind; + + fn deref(&self) -> &Self::Target { + &self.kind } } impl Vox for Block { fn empty() -> Self { Self { - kind: 0, + kind: BlockKind::Air, color: [0; 3], } } fn is_empty(&self) -> bool { - self.kind == 0 + self.is_air() + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn block_size() { + assert_eq!(std::mem::size_of::(), 1); + assert_eq!(std::mem::size_of::(), 4); } } diff --git a/common/src/terrain/mod.rs b/common/src/terrain/mod.rs index 96f70ac059..a8d1391161 100644 --- a/common/src/terrain/mod.rs +++ b/common/src/terrain/mod.rs @@ -4,7 +4,11 @@ pub mod chonk; pub mod structure; // Reexports -pub use self::{biome::BiomeKind, block::Block, structure::Structure}; +pub use self::{ + biome::BiomeKind, + block::{Block, BlockKind}, + structure::Structure, +}; use crate::{vol::VolSize, volumes::vol_map_2d::VolMap2d}; use serde_derive::{Deserialize, Serialize}; diff --git a/common/src/terrain/structure.rs b/common/src/terrain/structure.rs index 7302160a05..d8b3d2455d 100644 --- a/common/src/terrain/structure.rs +++ b/common/src/terrain/structure.rs @@ -1,4 +1,4 @@ -use super::Block; +use super::{Block, BlockKind}; use crate::{ assets::{self, Asset}, vol::{BaseVol, ReadVol, SizedVol, Vox, WriteVol}, @@ -103,7 +103,7 @@ impl Asset for Structure { .get(index as usize) .copied() .unwrap_or_else(|| Rgb::broadcast(0)); - StructureBlock::Block(Block::new(1, color)) + StructureBlock::Block(Block::new(BlockKind::Normal, color)) } }; diff --git a/voxygen/src/mesh/mod.rs b/voxygen/src/mesh/mod.rs index 096536477e..c8b3b36308 100644 --- a/voxygen/src/mesh/mod.rs +++ b/voxygen/src/mesh/mod.rs @@ -6,7 +6,12 @@ use crate::render::{self, Mesh}; pub trait Meshable { type Pipeline: render::Pipeline; + type TranslucentPipeline: render::Pipeline; type Supplement; - fn generate_mesh(&self, supp: Self::Supplement) -> Mesh; + // Generate meshes - one opaque, one translucent + fn generate_mesh( + &self, + supp: Self::Supplement, + ) -> (Mesh, Mesh); } diff --git a/voxygen/src/mesh/segment.rs b/voxygen/src/mesh/segment.rs index ac1667688d..1aac195d16 100644 --- a/voxygen/src/mesh/segment.rs +++ b/voxygen/src/mesh/segment.rs @@ -5,7 +5,7 @@ use crate::{ use common::{ figure::Segment, util::{linear_to_srgb, srgb_to_linear}, - vol::{ReadVol, SizedVol}, + vol::{ReadVol, SizedVol, Vox}, }; use vek::*; @@ -13,9 +13,13 @@ type FigureVertex = ::Vertex; impl Meshable for Segment { type Pipeline = FigurePipeline; + type TranslucentPipeline = FigurePipeline; type Supplement = Vec3; - fn generate_mesh(&self, offs: Self::Supplement) -> Mesh { + fn generate_mesh( + &self, + offs: Self::Supplement, + ) -> (Mesh, Mesh) { let mut mesh = Mesh::new(); for pos in self.iter_positions() { @@ -38,10 +42,11 @@ impl Meshable for Segment { }, true, &[[[1.0; 3]; 3]; 3], + |vox| vox.is_empty(), ); } } - mesh + (mesh, Mesh::new()) } } diff --git a/voxygen/src/mesh/terrain.rs b/voxygen/src/mesh/terrain.rs index 49134f4dc0..588a7130f0 100644 --- a/voxygen/src/mesh/terrain.rs +++ b/voxygen/src/mesh/terrain.rs @@ -1,9 +1,9 @@ use crate::{ mesh::{vol, Meshable}, - render::{self, Mesh, TerrainPipeline}, + render::{self, FluidPipeline, Mesh, TerrainPipeline}, }; use common::{ - terrain::Block, + terrain::{Block, BlockKind}, vol::{BaseVol, ReadVol, VolSize}, volumes::vol_map_2d::VolMap2d, }; @@ -11,43 +11,28 @@ use std::fmt::Debug; use vek::*; type TerrainVertex = ::Vertex; +type FluidVertex = ::Vertex; -/* -impl Meshable for Dyna { - type Pipeline = TerrainPipeline; - type Supplement = (); - - fn generate_mesh(&self, _: Self::Supplement) -> Mesh { - let mut mesh = Mesh::new(); - - for pos in self - .iter_positions() - .filter(|pos| pos.map(|e| e >= 1).reduce_and()) - .filter(|pos| { - pos.map2(self.get_size(), |e, sz| e < sz as i32 - 1) - .reduce_and() - }) - { - let offs = pos.map(|e| e as f32 - 1.0); - - if let Some(col) = self.get(pos).ok().and_then(|vox| vox.get_color()) { - let col = col.map(|e| e as f32 / 255.0); - - vol::push_vox_verts(&mut mesh, self, pos, offs, col, TerrainVertex::new, true); - } - } - - mesh +fn block_shadow_density(kind: BlockKind) -> Option { + match kind { + BlockKind::Air => None, + BlockKind::Normal => Some(0.85), + BlockKind::Dense => Some(3.0), + BlockKind::Water => Some(0.01), } } -*/ impl + ReadVol + Debug, S: VolSize + Clone> Meshable for VolMap2d { type Pipeline = TerrainPipeline; + type TranslucentPipeline = FluidPipeline; type Supplement = Aabb; - fn generate_mesh(&self, range: Self::Supplement) -> Mesh { - let mut mesh = Mesh::new(); + fn generate_mesh( + &self, + range: Self::Supplement, + ) -> (Mesh, Mesh) { + let mut opaque_mesh = Mesh::new(); + let mut fluid_mesh = Mesh::new(); for x in range.min.x + 1..range.max.x - 1 { for y in range.min.y + 1..range.max.y - 1 { @@ -55,16 +40,19 @@ impl + ReadVol + Debug, S: VolSize + Clone> Meshable for for z in (range.min.z..range.max.z).rev() { let pos = Vec3::new(x, y, z); + let offs = (pos - (range.min + 1) * Vec3::new(1, 1, 0)).map(|e| e as f32); + + let block = self.get(pos).ok(); // Create mesh polygons - if let Some(col) = self.get(pos).ok().and_then(|vox| vox.get_color()) { + if let Some(col) = block + .filter(|vox| vox.is_opaque()) + .and_then(|vox| vox.get_color()) + { let col = col.map(|e| e as f32 / 255.0); - let offs = (pos - range.min * Vec3::new(1, 1, 0)).map(|e| e as f32) - - Vec3::new(1.0, 1.0, 0.0); - vol::push_vox_verts( - &mut mesh, + &mut opaque_mesh, self, pos, offs, @@ -74,6 +62,26 @@ impl + ReadVol + Debug, S: VolSize + Clone> Meshable for }, false, &neighbour_light, + |vox| !vox.is_opaque(), + ); + } else if let Some(col) = block + .filter(|vox| vox.is_fluid()) + .and_then(|vox| vox.get_color()) + { + let col = col.map(|e| e as f32 / 255.0); + + vol::push_vox_verts( + &mut fluid_mesh, + self, + pos, + offs, + col, + |pos, norm, col, ao, light| { + FluidVertex::new(pos, norm, col, light * ao, 0.3) + }, + false, + &neighbour_light, + |vox| vox.is_air(), ); } @@ -84,13 +92,13 @@ impl + ReadVol + Debug, S: VolSize + Clone> Meshable for // Accumulate shade under opaque blocks for i in 0..3 { for j in 0..3 { - neighbour_light[0][i][j] = if let Some(opacity) = self + neighbour_light[0][i][j] = if let Some(density) = self .get(pos + Vec3::new(i as i32 - 1, j as i32 - 1, -1)) .ok() - .and_then(|vox| vox.get_opacity()) + .and_then(|vox| block_shadow_density(vox.kind())) { - (neighbour_light[0][i][j] * (1.0 - opacity * 0.1)) - .max(1.0 - opacity) + (neighbour_light[0][i][j] * (1.0 - density * 0.1)) + .max(1.0 - density) } else { (neighbour_light[0][i][j] * 1.025).min(1.0) }; @@ -108,7 +116,8 @@ impl + ReadVol + Debug, S: VolSize + Clone> Meshable for } } } - mesh + + (opaque_mesh, fluid_mesh) } } diff --git a/voxygen/src/mesh/vol.rs b/voxygen/src/mesh/vol.rs index 0e98b84511..1d8a6d4d9e 100644 --- a/voxygen/src/mesh/vol.rs +++ b/voxygen/src/mesh/vol.rs @@ -88,26 +88,23 @@ fn create_quad, Vec3, Rgb, f32, f32) -> P } } -pub fn push_vox_verts< - V: ReadVol, - P: Pipeline, - F: Fn(Vec3, Vec3, Rgb, f32, f32) -> P::Vertex, ->( +pub fn push_vox_verts( mesh: &mut Mesh

, vol: &V, pos: Vec3, offs: Vec3, col: Rgb, - vcons: F, + vcons: impl Fn(Vec3, Vec3, Rgb, f32, f32) -> P::Vertex, error_makes_face: bool, darknesses: &[[[f32; 3]; 3]; 3], + should_add: impl Fn(&V::Vox) -> bool, ) { let (x, y, z) = (Vec3::unit_x(), Vec3::unit_y(), Vec3::unit_z()); // -x if vol .get(pos - Vec3::unit_x()) - .map(|v| v.is_empty()) + .map(|v| should_add(v)) .unwrap_or(error_makes_face) { mesh.push_quad(create_quad( @@ -123,7 +120,7 @@ pub fn push_vox_verts< // +x if vol .get(pos + Vec3::unit_x()) - .map(|v| v.is_empty()) + .map(|v| should_add(v)) .unwrap_or(error_makes_face) { mesh.push_quad(create_quad( @@ -139,7 +136,7 @@ pub fn push_vox_verts< // -y if vol .get(pos - Vec3::unit_y()) - .map(|v| v.is_empty()) + .map(|v| should_add(v)) .unwrap_or(error_makes_face) { mesh.push_quad(create_quad( @@ -155,7 +152,7 @@ pub fn push_vox_verts< // +y if vol .get(pos + Vec3::unit_y()) - .map(|v| v.is_empty()) + .map(|v| should_add(v)) .unwrap_or(error_makes_face) { mesh.push_quad(create_quad( @@ -171,7 +168,7 @@ pub fn push_vox_verts< // -z if vol .get(pos - Vec3::unit_z()) - .map(|v| v.is_empty()) + .map(|v| should_add(v)) .unwrap_or(error_makes_face) { mesh.push_quad(create_quad( @@ -187,7 +184,7 @@ pub fn push_vox_verts< // +z if vol .get(pos + Vec3::unit_z()) - .map(|v| v.is_empty()) + .map(|v| should_add(v)) .unwrap_or(error_makes_face) { mesh.push_quad(create_quad( diff --git a/voxygen/src/render/mod.rs b/voxygen/src/render/mod.rs index 4cd3e676b2..369142cd90 100644 --- a/voxygen/src/render/mod.rs +++ b/voxygen/src/render/mod.rs @@ -13,6 +13,7 @@ pub use self::{ model::{DynamicModel, Model}, pipelines::{ figure::{BoneData as FigureBoneData, FigurePipeline, Locals as FigureLocals}, + fluid::FluidPipeline, postprocess::{ create_mesh as create_pp_mesh, Locals as PostProcessLocals, PostProcessPipeline, }, @@ -22,7 +23,6 @@ pub use self::{ create_quad as create_ui_quad, create_tri as create_ui_tri, Locals as UiLocals, Mode as UiMode, UiPipeline, }, - fluid::{Locals as FluidLocals, FluidPipeline}, Globals, Light, }, renderer::{Renderer, TgtColorFmt, TgtDepthFmt, WinColorFmt, WinDepthFmt}, diff --git a/voxygen/src/render/pipelines/fluid.rs b/voxygen/src/render/pipelines/fluid.rs index e91e143d64..c88dc6f454 100644 --- a/voxygen/src/render/pipelines/fluid.rs +++ b/voxygen/src/render/pipelines/fluid.rs @@ -1,16 +1,16 @@ use super::{ - super::{Pipeline, TgtColorFmt, TgtDepthFmt}, + super::{Pipeline, TerrainLocals, TgtColorFmt, TgtDepthFmt}, Globals, Light, }; use gfx::{ self, - gfx_constant_struct_meta, // Macros gfx_defines, gfx_impl_struct_meta, gfx_pipeline, gfx_pipeline_inner, gfx_vertex_struct_meta, + state::ColorMask, }; use std::ops::Mul; use vek::*; @@ -21,18 +21,14 @@ gfx_defines! { col_light: u32 = "v_col_light", } - constant Locals { - model_offs: [f32; 3] = "model_offs", - } - pipeline pipe { vbuf: gfx::VertexBuffer = (), - locals: gfx::ConstantBuffer = "u_locals", + locals: gfx::ConstantBuffer = "u_locals", globals: gfx::ConstantBuffer = "u_globals", lights: gfx::ConstantBuffer = "u_lights", - tgt_color: gfx::RenderTarget = "tgt_color", + tgt_color: gfx::BlendTarget = ("tgt_color", ColorMask::all(), gfx::preset::blend::ALPHA), tgt_depth: gfx::DepthTarget = gfx::preset::depth::LESS_EQUAL_WRITE, } } @@ -57,16 +53,8 @@ impl Vertex { | ((col.r.mul(200.0) as u32) & 0xFF) << 8 | ((col.g.mul(200.0) as u32) & 0xFF) << 16 | ((col.b.mul(200.0) as u32) & 0xFF) << 24 - | ((light.mul(255.0) as u32) & 0xFF) << 0 - | ((opac.mul(0.4) as u32) & 0xFF) << 0, - } - } -} - -impl Locals { - pub fn default() -> Self { - Self { - model_offs: [0.0; 3], + | ((light.mul(255.0) as u32) & 0xFF) << 0, + //| ((opac.mul(0.4) as u32) & 0xFF) << 0, } } } diff --git a/voxygen/src/render/pipelines/mod.rs b/voxygen/src/render/pipelines/mod.rs index 6184e74a39..801e3b9a74 100644 --- a/voxygen/src/render/pipelines/mod.rs +++ b/voxygen/src/render/pipelines/mod.rs @@ -1,9 +1,9 @@ pub mod figure; +pub mod fluid; pub mod postprocess; pub mod skybox; pub mod terrain; pub mod ui; -pub mod fluid; use super::util::arr_to_mat; use gfx::{ diff --git a/voxygen/src/render/renderer.rs b/voxygen/src/render/renderer.rs index e659e9869d..91e76032f5 100644 --- a/voxygen/src/render/renderer.rs +++ b/voxygen/src/render/renderer.rs @@ -3,7 +3,7 @@ use super::{ gfx_backend, mesh::Mesh, model::{DynamicModel, Model}, - pipelines::{figure, postprocess, skybox, terrain, ui, Globals, Light, fluid}, + pipelines::{figure, fluid, postprocess, skybox, terrain, ui, Globals, Light}, texture::Texture, Pipeline, RenderError, }; @@ -64,6 +64,7 @@ pub struct Renderer { skybox_pipeline: GfxPipeline>, figure_pipeline: GfxPipeline>, terrain_pipeline: GfxPipeline>, + fluid_pipeline: GfxPipeline>, ui_pipeline: GfxPipeline>, postprocess_pipeline: GfxPipeline>, @@ -80,18 +81,9 @@ impl Renderer { ) -> Result { let mut shader_reload_indicator = ReloadIndicator::new(); - let (skybox_pipeline, figure_pipeline, terrain_pipeline, ui_pipeline, postprocess_pipeline) = + let (skybox_pipeline, figure_pipeline, terrain_pipeline, fluid_pipeline, ui_pipeline, postprocess_pipeline) = create_pipelines(&mut factory, &mut shader_reload_indicator)?; - // Construct a pipeline for rendering fluids - let fluid_pipeline = create_pipeline( - &mut factory, - fluid::pipe::new(), - include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/shaders/fluid.vert")), - include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/shaders/fluid.frag")), - &include_ctx, - )?; - let dims = win_color_view.get_dimensions(); let (tgt_color_view, tgt_depth_view, tgt_color_res) = Self::create_rt_views(&mut factory, (dims.0, dims.1))?; @@ -115,6 +107,7 @@ impl Renderer { skybox_pipeline, figure_pipeline, terrain_pipeline, + fluid_pipeline, ui_pipeline, postprocess_pipeline, @@ -200,13 +193,15 @@ impl Renderer { Ok(( skybox_pipeline, figure_pipeline, - terrain_pipline, + terrain_pipeline, + fluid_pipeline, ui_pipeline, postprocess_pipeline, )) => { self.skybox_pipeline = skybox_pipeline; self.figure_pipeline = figure_pipeline; - self.terrain_pipeline = terrain_pipline; + self.terrain_pipeline = terrain_pipeline; + self.fluid_pipeline = fluid_pipeline; self.ui_pipeline = ui_pipeline; self.postprocess_pipeline = postprocess_pipeline; } @@ -407,6 +402,28 @@ impl Renderer { ); } + /// Queue the rendering of the provided terrain chunk model in the upcoming frame. + pub fn render_fluid_chunk( + &mut self, + model: &Model, + globals: &Consts, + locals: &Consts, + lights: &Consts, + ) { + self.encoder.draw( + &model.slice, + &self.fluid_pipeline.pso, + &fluid::pipe::Data { + vbuf: model.vbuf.clone(), + locals: locals.buf.clone(), + globals: globals.buf.clone(), + lights: lights.buf.clone(), + tgt_color: self.tgt_color_view.clone(), + tgt_depth: self.tgt_depth_view.clone(), + }, + ); + } + /// Queue the rendering of the provided UI element in the upcoming frame. pub fn render_ui_element( &mut self, @@ -471,6 +488,7 @@ fn create_pipelines( GfxPipeline>, GfxPipeline>, GfxPipeline>, + GfxPipeline>, GfxPipeline>, GfxPipeline>, ), @@ -528,6 +546,17 @@ fn create_pipelines( &include_ctx, )?; + // Construct a pipeline for rendering fluids + let fluid_pipeline = create_pipeline( + factory, + fluid::pipe::new(), + &assets::load_watched::("voxygen.shaders.fluid-vert", shader_reload_indicator) + .unwrap(), + &assets::load_watched::("voxygen.shaders.fluid-frag", shader_reload_indicator) + .unwrap(), + &include_ctx, + )?; + // Construct a pipeline for rendering UI elements let ui_pipeline = create_pipeline( factory, @@ -560,6 +589,7 @@ fn create_pipelines( skybox_pipeline, figure_pipeline, terrain_pipeline, + fluid_pipeline, ui_pipeline, postprocess_pipeline, )) diff --git a/voxygen/src/scene/figure.rs b/voxygen/src/scene/figure.rs index 94275944a9..dea1155706 100644 --- a/voxygen/src/scene/figure.rs +++ b/voxygen/src/scene/figure.rs @@ -165,6 +165,7 @@ impl FigureModelCache { let full_specifier: String = ["voxygen.voxel.", mesh_name].concat(); Segment::from(assets::load_expect::(full_specifier.as_str()).as_ref()) .generate_mesh(position) + .0 } fn load_head(race: humanoid::Race, body_type: humanoid::BodyType) -> Mesh { diff --git a/voxygen/src/scene/mod.rs b/voxygen/src/scene/mod.rs index 50acb1a533..a043709fc8 100644 --- a/voxygen/src/scene/mod.rs +++ b/voxygen/src/scene/mod.rs @@ -221,9 +221,9 @@ impl Scene { renderer.render_skybox(&self.skybox.model, &self.globals, &self.skybox.locals); // Render terrain and figures. - self.terrain.render(renderer, &self.globals, &self.lights); self.figure_mgr .render(renderer, client, &self.globals, &self.lights, &self.camera); + self.terrain.render(renderer, &self.globals, &self.lights); renderer.render_post_process( &self.postprocess.model, diff --git a/voxygen/src/scene/terrain.rs b/voxygen/src/scene/terrain.rs index 637f76ea24..deed0a9fcb 100644 --- a/voxygen/src/scene/terrain.rs +++ b/voxygen/src/scene/terrain.rs @@ -1,6 +1,9 @@ use crate::{ mesh::Meshable, - render::{Consts, Globals, Light, Mesh, Model, Renderer, TerrainLocals, TerrainPipeline}, + render::{ + Consts, FluidPipeline, Globals, Light, Mesh, Model, Renderer, TerrainLocals, + TerrainPipeline, + }, }; use client::Client; use common::{ @@ -16,7 +19,8 @@ use vek::*; struct TerrainChunk { // GPU data - model: Model, + opaque_model: Model, + fluid_model: Model, locals: Consts, visible: bool, z_bounds: (f32, f32), @@ -32,7 +36,8 @@ struct ChunkMeshState { struct MeshWorkerResponse { pos: Vec2, z_bounds: (f32, f32), - mesh: Mesh, + opaque_mesh: Mesh, + fluid_mesh: Mesh, started_tick: u64, } @@ -44,10 +49,12 @@ fn mesh_worker( volume: >>::Sample, range: Aabb, ) -> MeshWorkerResponse { + let (opaque_mesh, fluid_mesh) = volume.generate_mesh(range); MeshWorkerResponse { pos, z_bounds, - mesh: volume.generate_mesh(range), + opaque_mesh, + fluid_mesh, started_tick, } } @@ -262,8 +269,11 @@ impl Terrain { self.chunks.insert( response.pos, TerrainChunk { - model: renderer - .create_model(&response.mesh) + opaque_model: renderer + .create_model(&response.opaque_mesh) + .expect("Failed to upload chunk mesh to the GPU!"), + fluid_model: renderer + .create_model(&response.fluid_mesh) .expect("Failed to upload chunk mesh to the GPU!"), locals: renderer .create_consts(&[TerrainLocals { @@ -334,9 +344,17 @@ impl Terrain { globals: &Consts, lights: &Consts, ) { + // Opaque for (_pos, chunk) in &self.chunks { if chunk.visible { - renderer.render_terrain_chunk(&chunk.model, globals, &chunk.locals, lights); + renderer.render_terrain_chunk(&chunk.opaque_model, globals, &chunk.locals, lights); + } + } + + // Translucent + for (_pos, chunk) in &self.chunks { + if chunk.visible { + renderer.render_fluid_chunk(&chunk.fluid_model, globals, &chunk.locals, lights); } } } diff --git a/voxygen/src/session.rs b/voxygen/src/session.rs index 36cd3d995f..99e84bd260 100644 --- a/voxygen/src/session.rs +++ b/voxygen/src/session.rs @@ -8,7 +8,13 @@ use crate::{ }; use client::{self, Client}; use common::{ - clock::Clock, comp, comp::Pos, comp::Vel, msg::ClientState, terrain::Block, vol::ReadVol, + clock::Clock, + comp, + comp::Pos, + comp::Vel, + msg::ClientState, + terrain::{Block, BlockKind}, + vol::ReadVol, }; use log::error; use specs::Join; @@ -39,7 +45,7 @@ impl SessionState { key_state: KeyState::new(), controller: comp::Controller::default(), hud: Hud::new(global_state), - selected_block: Block::new(1, Rgb::broadcast(255)), + selected_block: Block::new(BlockKind::Normal, Rgb::broadcast(255)), } } } diff --git a/world/src/block/mod.rs b/world/src/block/mod.rs index fc4e7123f2..2396b9fdeb 100644 --- a/world/src/block/mod.rs +++ b/world/src/block/mod.rs @@ -6,7 +6,7 @@ use crate::{ World, CONFIG, }; use common::{ - terrain::{structure::StructureBlock, Block, Structure}, + terrain::{structure::StructureBlock, Block, BlockKind, Structure}, util::saturate_srgb, vol::{ReadVol, Vox}, }; @@ -221,8 +221,7 @@ impl<'a> BlockGen<'a> { // let sand = Block::new(1, Rgb::new(180, 150, 50)); // let warm_stone = Block::new(1, Rgb::new(165, 165, 130)); - //let water = Block::new(1, Rgb::new(100, 150, 255)); - let water = Block::new(1, Rgb::new(0, 24, 255)); + let water = Block::new(BlockKind::Water, Rgb::new(0, 24, 255)); let grass_depth = 1.5 + 2.0 * chaos; let block = if (wposf.z as f32) < height - grass_depth { @@ -234,9 +233,9 @@ impl<'a> BlockGen<'a> { // Underground if (wposf.z as f32) > alt - 32.0 * chaos { - Some(Block::new(1, col)) + Some(Block::new(BlockKind::Normal, col)) } else { - Some(Block::new(2, col)) + Some(Block::new(BlockKind::Dense, col)) } } else if (wposf.z as f32) < height { let col = Lerp::lerp( @@ -248,7 +247,7 @@ impl<'a> BlockGen<'a> { ); // Surface Some(Block::new( - 1, + BlockKind::Normal, saturate_srgb(col, 0.45).map(|e| (e * 255.0) as u8), )) } else if (wposf.z as f32) < water_height { @@ -284,7 +283,7 @@ impl<'a> BlockGen<'a> { let field2 = RandomField::new(world.sim().seed + 2); Some(Block::new( - 1, + BlockKind::Normal, stone_col - Rgb::new( field0.get(wpos) as u8 % 16, @@ -415,7 +414,7 @@ impl StructureInfo { .map(|e: i32| (e.abs() / 2) * 2) .reduce_max() { - Some(Block::new(2, Rgb::new(203, 170, 146))) + Some(Block::new(BlockKind::Dense, Rgb::new(203, 170, 146))) } else { None } @@ -452,39 +451,27 @@ fn block_from_structure( match sblock { StructureBlock::TemperateLeaves => Some(Block::new( - 1, - Lerp::lerp( - Rgb::new(0.0, 132.0, 94.0), - Rgb::new(142.0, 181.0, 0.0), - lerp, - ) - .map(|e| e as u8), + BlockKind::Normal, + Lerp::lerp(Rgb::new(0.0, 132.0, 94.0), Rgb::new(142.0, 181.0, 0.0), lerp) + .map(|e| e as u8), )), StructureBlock::PineLeaves => Some(Block::new( - 1, - Lerp::lerp( - Rgb::new(0.0, 108.0, 113.0), - Rgb::new(30.0, 156.0, 10.0), - lerp, - ) - .map(|e| e as u8), + BlockKind::Normal, + Lerp::lerp(Rgb::new(0.0, 60.0, 50.0), Rgb::new(30.0, 100.0, 10.0), lerp) + .map(|e| e as u8), )), StructureBlock::PalmLeaves => Some(Block::new( - 1, - Lerp::lerp( - Rgb::new(15.0, 156.0, 70.0), - Rgb::new(40.0, 222.0, 0.0), - lerp, - ) - .map(|e| e as u8), + BlockKind::Normal, + Lerp::lerp(Rgb::new(0.0, 108.0, 113.0), Rgb::new(30.0, 156.0, 10.0), lerp) + .map(|e| e as u8), )), StructureBlock::Acacia => Some(Block::new( - 1, + BlockKind::Normal, Lerp::lerp(Rgb::new(35.0, 156.0, 0.0), Rgb::new(62.0, 208.0, 0.0), lerp) .map(|e| e as u8), )), StructureBlock::Fruit => Some(Block::new( - 1, + BlockKind::Normal, Lerp::lerp(Rgb::new(237.0, 0.0, 0.0), Rgb::new(200.0, 237.0, 0.0), lerp) .map(|e| e as u8), )), diff --git a/world/src/lib.rs b/world/src/lib.rs index b93b4bdcca..d84c128f7f 100644 --- a/world/src/lib.rs +++ b/world/src/lib.rs @@ -16,7 +16,7 @@ use crate::{ util::{Sampler, SamplerMut}, }; use common::{ - terrain::{Block, TerrainChunk, TerrainChunkMeta, TerrainChunkSize}, + terrain::{Block, BlockKind, TerrainChunk, TerrainChunkMeta, TerrainChunkSize}, vol::{ReadVol, VolSize, Vox, WriteVol}, }; use rand::Rng; @@ -59,8 +59,8 @@ impl World { pub fn generate_chunk(&self, chunk_pos: Vec2) -> (TerrainChunk, ChunkSupplement) { let air = Block::empty(); - let stone = Block::new(2, Rgb::new(200, 220, 255)); - let water = Block::new(5, Rgb::new(100, 150, 255)); + let stone = Block::new(BlockKind::Dense, Rgb::new(200, 220, 255)); + let water = Block::new(BlockKind::Water, Rgb::new(100, 150, 255)); let chunk_size2d = Vec2::from(TerrainChunkSize::SIZE); let (base_z, sim_chunk) = match self From fa6825f13bb340873e2318b8e4518d65d4e866de Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Thu, 15 Aug 2019 02:35:56 +0100 Subject: [PATCH 03/15] Better fluid meshing, disabled fluid backface culling and depth buffer writing --- assets/voxygen/shaders/fluid-frag.glsl | 3 +- assets/voxygen/shaders/fluid-vert.glsl | 2 +- assets/voxygen/shaders/include/random.glsl | 13 +++++ assets/voxygen/shaders/include/sky.glsl | 8 +-- voxygen/src/mesh/segment.rs | 1 + voxygen/src/mesh/terrain.rs | 4 +- voxygen/src/mesh/vol.rs | 64 ++++++++++++++++++---- voxygen/src/render/pipelines/fluid.rs | 4 +- voxygen/src/render/renderer.rs | 13 ++++- world/src/column/mod.rs | 4 +- 10 files changed, 94 insertions(+), 22 deletions(-) create mode 100644 assets/voxygen/shaders/include/random.glsl diff --git a/assets/voxygen/shaders/fluid-frag.glsl b/assets/voxygen/shaders/fluid-frag.glsl index 5583c72df2..b354cb0e58 100644 --- a/assets/voxygen/shaders/fluid-frag.glsl +++ b/assets/voxygen/shaders/fluid-frag.glsl @@ -1,6 +1,7 @@ #version 330 core #include +#include in vec3 f_pos; flat in vec3 f_norm; @@ -25,7 +26,7 @@ void main() { float fog_level = fog(f_pos.xy, focus_pos.xy); vec3 fog_color = get_sky_color(normalize(f_pos - cam_pos.xyz), time_of_day.x); - vec3 warped_norm = normalize(f_norm + (sin(f_pos.xyz + tick.x + 13.7) + sin(f_pos.zxy + tick.x + 19.3)) * 0.3); + vec3 warped_norm = normalize(f_norm + smooth_rand(floor(f_pos), tick.x) * 0.5); vec3 reflect_color = get_sky_color(reflect(normalize(f_pos - cam_pos.xyz), warped_norm), time_of_day.x); vec3 color = mix(surf_color + reflect_color * 0.5, fog_color, fog_level); diff --git a/assets/voxygen/shaders/fluid-vert.glsl b/assets/voxygen/shaders/fluid-vert.glsl index 71b14ea98e..43da1243c8 100644 --- a/assets/voxygen/shaders/fluid-vert.glsl +++ b/assets/voxygen/shaders/fluid-vert.glsl @@ -43,7 +43,7 @@ void main() { f_light = float(v_col_light & 0xFFu) / 255.0; - f_opac = 0.1; + f_opac = 0.3; gl_Position = proj_mat * diff --git a/assets/voxygen/shaders/include/random.glsl b/assets/voxygen/shaders/include/random.glsl new file mode 100644 index 0000000000..6c606a9677 --- /dev/null +++ b/assets/voxygen/shaders/include/random.glsl @@ -0,0 +1,13 @@ +vec3 rand_perm_3(vec3 pos) { + return sin(pos * vec3(1473.7 * pos.z + 472.3, 8891.1 * pos.x + 723.1, 3813.3 * pos.y + 982.5)); +} + +vec4 rand_perm_4(vec4 pos) { + return sin(473.3 * pos * vec4(317.3 * pos.w + 917.7, 1473.7 * pos.z + 472.3, 8891.1 * pos.x + 723.1, 3813.3 * pos.y + 982.5) / pos.yxwz); +} + +vec3 smooth_rand(vec3 pos, float lerp_axis) { + vec3 r0 = rand_perm_3(vec3(pos.x, pos.y, pos.z) + floor(lerp_axis)); + vec3 r1 = rand_perm_3(vec3(pos.x, pos.y, pos.z) + floor(lerp_axis + 1.0)); + return r0 + (r1 - r0) * fract(lerp_axis); +} diff --git a/assets/voxygen/shaders/include/sky.glsl b/assets/voxygen/shaders/include/sky.glsl index ef47282f16..25c1fba993 100644 --- a/assets/voxygen/shaders/include/sky.glsl +++ b/assets/voxygen/shaders/include/sky.glsl @@ -1,3 +1,5 @@ +#include + const float PI = 3.141592; const vec3 SKY_DAY_TOP = vec3(0.1, 0.2, 0.9); @@ -54,10 +56,6 @@ vec3 get_sun_diffuse(vec3 norm, float time_of_day) { return diffuse_light; } -vec3 rand_offs(vec3 pos) { - return sin(pos * vec3(1473.7 * pos.z + 472.3, 8891.1 * pos.x + 723.1, 3813.3 * pos.y + 982.5)); -} - // This has been extracted into a function to allow quick exit when detecting a star. float is_star_at(vec3 dir) { float star_scale = 30.0; @@ -69,7 +67,7 @@ float is_star_at(vec3 dir) { vec3 pos = (floor(dir * star_scale) + vec3(i, j, k) - vec3(0.5)) / star_scale; // Noisy offsets - pos += (3.0 / star_scale) * rand_offs(pos); + pos += (3.0 / star_scale) * rand_perm_3(pos); // Find distance to fragment float dist = length(normalize(pos) - dir); diff --git a/voxygen/src/mesh/segment.rs b/voxygen/src/mesh/segment.rs index 1aac195d16..e0b77ac31e 100644 --- a/voxygen/src/mesh/segment.rs +++ b/voxygen/src/mesh/segment.rs @@ -43,6 +43,7 @@ impl Meshable for Segment { true, &[[[1.0; 3]; 3]; 3], |vox| vox.is_empty(), + |vox| !vox.is_empty(), ); } } diff --git a/voxygen/src/mesh/terrain.rs b/voxygen/src/mesh/terrain.rs index 588a7130f0..f8c30ea446 100644 --- a/voxygen/src/mesh/terrain.rs +++ b/voxygen/src/mesh/terrain.rs @@ -18,7 +18,7 @@ fn block_shadow_density(kind: BlockKind) -> Option { BlockKind::Air => None, BlockKind::Normal => Some(0.85), BlockKind::Dense => Some(3.0), - BlockKind::Water => Some(0.01), + BlockKind::Water => Some(0.8), } } @@ -63,6 +63,7 @@ impl + ReadVol + Debug, S: VolSize + Clone> Meshable for false, &neighbour_light, |vox| !vox.is_opaque(), + |vox| vox.is_opaque(), ); } else if let Some(col) = block .filter(|vox| vox.is_fluid()) @@ -82,6 +83,7 @@ impl + ReadVol + Debug, S: VolSize + Clone> Meshable for false, &neighbour_light, |vox| vox.is_air(), + |vox| vox.is_opaque(), ); } diff --git a/voxygen/src/mesh/vol.rs b/voxygen/src/mesh/vol.rs index 1d8a6d4d9e..cf683be658 100644 --- a/voxygen/src/mesh/vol.rs +++ b/voxygen/src/mesh/vol.rs @@ -1,6 +1,6 @@ use vek::*; -use common::vol::{ReadVol, Vox}; +use common::vol::ReadVol; use crate::render::{ mesh::{Mesh, Quad}, @@ -16,15 +16,16 @@ fn get_ao_quad( shift: Vec3, dirs: &[Vec3], darknesses: &[[[f32; 3]; 3]; 3], + is_opaque: impl Fn(&V::Vox) -> bool, ) -> Vec4<(f32, f32)> { dirs.windows(2) .map(|offs| { let (s1, s2) = ( vol.get(pos + shift + offs[0]) - .map(|v| !v.is_empty()) + .map(&is_opaque) .unwrap_or(false), vol.get(pos + shift + offs[1]) - .map(|v| !v.is_empty()) + .map(&is_opaque) .unwrap_or(false), ); @@ -42,7 +43,7 @@ fn get_ao_quad( } else { let corner = vol .get(pos + shift + offs[0] + offs[1]) - .map(|v| !v.is_empty()) + .map(&is_opaque) .unwrap_or(false); // Map both 1 and 2 neighbors to 0.5 occlusion. if s1 || s2 || corner { @@ -98,6 +99,7 @@ pub fn push_vox_verts( error_makes_face: bool, darknesses: &[[[f32; 3]; 3]; 3], should_add: impl Fn(&V::Vox) -> bool, + is_opaque: impl Fn(&V::Vox) -> bool, ) { let (x, y, z) = (Vec3::unit_x(), Vec3::unit_y(), Vec3::unit_z()); @@ -113,7 +115,14 @@ pub fn push_vox_verts( Vec3::unit_y(), -Vec3::unit_x(), col, - get_ao_quad(vol, pos, -Vec3::unit_x(), &[-z, -y, z, y, -z], darknesses), + get_ao_quad( + vol, + pos, + -Vec3::unit_x(), + &[-z, -y, z, y, -z], + darknesses, + &is_opaque, + ), &vcons, )); } @@ -129,7 +138,14 @@ pub fn push_vox_verts( Vec3::unit_z(), Vec3::unit_x(), col, - get_ao_quad(vol, pos, Vec3::unit_x(), &[-y, -z, y, z, -y], darknesses), + get_ao_quad( + vol, + pos, + Vec3::unit_x(), + &[-y, -z, y, z, -y], + darknesses, + &is_opaque, + ), &vcons, )); } @@ -145,7 +161,14 @@ pub fn push_vox_verts( Vec3::unit_z(), -Vec3::unit_y(), col, - get_ao_quad(vol, pos, -Vec3::unit_y(), &[-x, -z, x, z, -x], darknesses), + get_ao_quad( + vol, + pos, + -Vec3::unit_y(), + &[-x, -z, x, z, -x], + darknesses, + &is_opaque, + ), &vcons, )); } @@ -161,7 +184,14 @@ pub fn push_vox_verts( Vec3::unit_x(), Vec3::unit_y(), col, - get_ao_quad(vol, pos, Vec3::unit_y(), &[-z, -x, z, x, -z], darknesses), + get_ao_quad( + vol, + pos, + Vec3::unit_y(), + &[-z, -x, z, x, -z], + darknesses, + &is_opaque, + ), &vcons, )); } @@ -177,7 +207,14 @@ pub fn push_vox_verts( Vec3::unit_x(), -Vec3::unit_z(), col, - get_ao_quad(vol, pos, -Vec3::unit_z(), &[-y, -x, y, x, -y], darknesses), + get_ao_quad( + vol, + pos, + -Vec3::unit_z(), + &[-y, -x, y, x, -y], + darknesses, + &is_opaque, + ), &vcons, )); } @@ -193,7 +230,14 @@ pub fn push_vox_verts( Vec3::unit_y(), Vec3::unit_z(), col, - get_ao_quad(vol, pos, Vec3::unit_z(), &[-x, -y, x, y, -x], darknesses), + get_ao_quad( + vol, + pos, + Vec3::unit_z(), + &[-x, -y, x, y, -x], + darknesses, + &is_opaque, + ), &vcons, )); } diff --git a/voxygen/src/render/pipelines/fluid.rs b/voxygen/src/render/pipelines/fluid.rs index c88dc6f454..e4c040c644 100644 --- a/voxygen/src/render/pipelines/fluid.rs +++ b/voxygen/src/render/pipelines/fluid.rs @@ -29,12 +29,12 @@ gfx_defines! { lights: gfx::ConstantBuffer = "u_lights", tgt_color: gfx::BlendTarget = ("tgt_color", ColorMask::all(), gfx::preset::blend::ALPHA), - tgt_depth: gfx::DepthTarget = gfx::preset::depth::LESS_EQUAL_WRITE, + tgt_depth: gfx::DepthTarget = gfx::preset::depth::LESS_EQUAL_TEST, } } impl Vertex { - pub fn new(pos: Vec3, norm: Vec3, col: Rgb, light: f32, opac: f32) -> Self { + pub fn new(pos: Vec3, norm: Vec3, col: Rgb, light: f32, _opac: f32) -> Self { let (norm_axis, norm_dir) = norm .as_slice() .into_iter() diff --git a/voxygen/src/render/renderer.rs b/voxygen/src/render/renderer.rs index 91e76032f5..a445dea895 100644 --- a/voxygen/src/render/renderer.rs +++ b/voxygen/src/render/renderer.rs @@ -506,12 +506,16 @@ fn create_pipelines( let srgb = assets::load_watched::("voxygen.shaders.include.srgb", shader_reload_indicator) .unwrap(); + let random = + assets::load_watched::("voxygen.shaders.include.random", shader_reload_indicator) + .unwrap(); let mut include_ctx = IncludeContext::new(); include_ctx.include("globals.glsl", &globals); include_ctx.include("sky.glsl", &sky); include_ctx.include("light.glsl", &light); include_ctx.include("srgb.glsl", &srgb); + include_ctx.include("random.glsl", &random); // Construct a pipeline for rendering skyboxes let skybox_pipeline = create_pipeline( @@ -522,6 +526,7 @@ fn create_pipelines( &assets::load_watched::("voxygen.shaders.skybox-frag", shader_reload_indicator) .unwrap(), &include_ctx, + gfx::state::CullFace::Back, )?; // Construct a pipeline for rendering figures @@ -533,6 +538,7 @@ fn create_pipelines( &assets::load_watched::("voxygen.shaders.figure-frag", shader_reload_indicator) .unwrap(), &include_ctx, + gfx::state::CullFace::Back, )?; // Construct a pipeline for rendering terrain @@ -544,6 +550,7 @@ fn create_pipelines( &assets::load_watched::("voxygen.shaders.terrain-frag", shader_reload_indicator) .unwrap(), &include_ctx, + gfx::state::CullFace::Back, )?; // Construct a pipeline for rendering fluids @@ -555,6 +562,7 @@ fn create_pipelines( &assets::load_watched::("voxygen.shaders.fluid-frag", shader_reload_indicator) .unwrap(), &include_ctx, + gfx::state::CullFace::Nothing, )?; // Construct a pipeline for rendering UI elements @@ -566,6 +574,7 @@ fn create_pipelines( &assets::load_watched::("voxygen.shaders.ui-frag", shader_reload_indicator) .unwrap(), &include_ctx, + gfx::state::CullFace::Back, )?; // Construct a pipeline for rendering our post-processing @@ -583,6 +592,7 @@ fn create_pipelines( ) .unwrap(), &include_ctx, + gfx::state::CullFace::Back, )?; Ok(( @@ -602,6 +612,7 @@ fn create_pipeline<'a, P: gfx::pso::PipelineInit>( vs: &str, fs: &str, ctx: &IncludeContext, + cull_face: gfx::state::CullFace, ) -> Result, RenderError> { let vs = ctx.expand(vs).map_err(RenderError::IncludeError)?; let fs = ctx.expand(fs).map_err(RenderError::IncludeError)?; @@ -617,7 +628,7 @@ fn create_pipeline<'a, P: gfx::pso::PipelineInit>( gfx::Primitive::TriangleList, gfx::state::Rasterizer { front_face: gfx::state::FrontFace::CounterClockwise, - cull_face: gfx::state::CullFace::Back, + cull_face, method: gfx::state::RasterMethod::Fill, offset: None, samples: Some(gfx::state::MultiSample), diff --git a/world/src/column/mod.rs b/world/src/column/mod.rs index 3408f146f1..0958e810ab 100644 --- a/world/src/column/mod.rs +++ b/world/src/column/mod.rs @@ -335,7 +335,9 @@ impl<'a> Sampler for ColumnGen<'a> { / 100.0, ), // Beach - ((alt - CONFIG.sea_level - 1.0) / 2.0).min(1.0 - river * 2.0), + ((alt - CONFIG.sea_level - 1.0) / 2.0) + .min(1.0 - river * 2.0) + .max(0.0), ), sub_surface_color: dirt, tree_density, From d65bacbea1886e69c00cf00c4828e30dc8711291 Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Thu, 15 Aug 2019 03:24:06 +0100 Subject: [PATCH 04/15] Better waves --- assets/voxygen/shaders/fluid-frag.glsl | 2 +- assets/voxygen/shaders/include/random.glsl | 95 ++++++++++++++++++++++ 2 files changed, 96 insertions(+), 1 deletion(-) diff --git a/assets/voxygen/shaders/fluid-frag.glsl b/assets/voxygen/shaders/fluid-frag.glsl index b354cb0e58..b3bdd52292 100644 --- a/assets/voxygen/shaders/fluid-frag.glsl +++ b/assets/voxygen/shaders/fluid-frag.glsl @@ -26,7 +26,7 @@ void main() { float fog_level = fog(f_pos.xy, focus_pos.xy); vec3 fog_color = get_sky_color(normalize(f_pos - cam_pos.xyz), time_of_day.x); - vec3 warped_norm = normalize(f_norm + smooth_rand(floor(f_pos), tick.x) * 0.5); + vec3 warped_norm = normalize(f_norm + smooth_rand(f_pos * 0.6, tick.x) * 0.75); vec3 reflect_color = get_sky_color(reflect(normalize(f_pos - cam_pos.xyz), warped_norm), time_of_day.x); vec3 color = mix(surf_color + reflect_color * 0.5, fog_color, fog_level); diff --git a/assets/voxygen/shaders/include/random.glsl b/assets/voxygen/shaders/include/random.glsl index 6c606a9677..1b97d1c3dc 100644 --- a/assets/voxygen/shaders/include/random.glsl +++ b/assets/voxygen/shaders/include/random.glsl @@ -1,3 +1,97 @@ +// Simplex 4D Noise +// by Ian McEwan, Ashima Arts +// +vec4 permute(vec4 x){return mod(((x*34.0)+1.0)*x, 289.0);} +float permute(float x){return floor(mod(((x*34.0)+1.0)*x, 289.0));} +vec4 taylorInvSqrt(vec4 r){return 1.79284291400159 - 0.85373472095314 * r;} +float taylorInvSqrt(float r){return 1.79284291400159 - 0.85373472095314 * r;} + +vec4 grad4(float j, vec4 ip){ + const vec4 ones = vec4(1.0, 1.0, 1.0, -1.0); + vec4 p,s; + + p.xyz = floor( fract (vec3(j) * ip.xyz) * 7.0) * ip.z - 1.0; + p.w = 1.5 - dot(abs(p.xyz), ones.xyz); + s = vec4(lessThan(p, vec4(0.0))); + p.xyz = p.xyz + (s.xyz*2.0 - 1.0) * s.www; + + return p; +} + +float snoise(vec4 v){ + const vec2 C = vec2( 0.138196601125010504, // (5 - sqrt(5))/20 G4 + 0.309016994374947451); // (sqrt(5) - 1)/4 F4 +// First corner + vec4 i = floor(v + dot(v, C.yyyy) ); + vec4 x0 = v - i + dot(i, C.xxxx); + +// Other corners + +// Rank sorting originally contributed by Bill Licea-Kane, AMD (formerly ATI) + vec4 i0; + + vec3 isX = step( x0.yzw, x0.xxx ); + vec3 isYZ = step( x0.zww, x0.yyz ); +// i0.x = dot( isX, vec3( 1.0 ) ); + i0.x = isX.x + isX.y + isX.z; + i0.yzw = 1.0 - isX; + +// i0.y += dot( isYZ.xy, vec2( 1.0 ) ); + i0.y += isYZ.x + isYZ.y; + i0.zw += 1.0 - isYZ.xy; + + i0.z += isYZ.z; + i0.w += 1.0 - isYZ.z; + + // i0 now contains the unique values 0,1,2,3 in each channel + vec4 i3 = clamp( i0, 0.0, 1.0 ); + vec4 i2 = clamp( i0-1.0, 0.0, 1.0 ); + vec4 i1 = clamp( i0-2.0, 0.0, 1.0 ); + + // x0 = x0 - 0.0 + 0.0 * C + vec4 x1 = x0 - i1 + 1.0 * C.xxxx; + vec4 x2 = x0 - i2 + 2.0 * C.xxxx; + vec4 x3 = x0 - i3 + 3.0 * C.xxxx; + vec4 x4 = x0 - 1.0 + 4.0 * C.xxxx; + +// Permutations + i = mod(i, 289.0); + float j0 = permute( permute( permute( permute(i.w) + i.z) + i.y) + i.x); + vec4 j1 = permute( permute( permute( permute ( + i.w + vec4(i1.w, i2.w, i3.w, 1.0 )) + + i.z + vec4(i1.z, i2.z, i3.z, 1.0 )) + + i.y + vec4(i1.y, i2.y, i3.y, 1.0 )) + + i.x + vec4(i1.x, i2.x, i3.x, 1.0 )); +// Gradients +// ( 7*7*6 points uniformly over a cube, mapped onto a 4-octahedron.) +// 7*7*6 = 294, which is close to the ring size 17*17 = 289. + + vec4 ip = vec4(1.0/294.0, 1.0/49.0, 1.0/7.0, 0.0) ; + + vec4 p0 = grad4(j0, ip); + vec4 p1 = grad4(j1.x, ip); + vec4 p2 = grad4(j1.y, ip); + vec4 p3 = grad4(j1.z, ip); + vec4 p4 = grad4(j1.w, ip); + +// Normalise gradients + vec4 norm = taylorInvSqrt(vec4(dot(p0,p0), dot(p1,p1), dot(p2, p2), dot(p3,p3))); + p0 *= norm.x; + p1 *= norm.y; + p2 *= norm.z; + p3 *= norm.w; + p4 *= taylorInvSqrt(dot(p4,p4)); + +// Mix contributions from the five corners + vec3 m0 = max(0.6 - vec3(dot(x0,x0), dot(x1,x1), dot(x2,x2)), 0.0); + vec2 m1 = max(0.6 - vec2(dot(x3,x3), dot(x4,x4) ), 0.0); + m0 = m0 * m0; + m1 = m1 * m1; + return 49.0 * ( dot(m0*m0, vec3( dot( p0, x0 ), dot( p1, x1 ), dot( p2, x2 ))) + + dot(m1*m1, vec2( dot( p3, x3 ), dot( p4, x4 ) ) ) ) ; + +} + vec3 rand_perm_3(vec3 pos) { return sin(pos * vec3(1473.7 * pos.z + 472.3, 8891.1 * pos.x + 723.1, 3813.3 * pos.y + 982.5)); } @@ -7,6 +101,7 @@ vec4 rand_perm_4(vec4 pos) { } vec3 smooth_rand(vec3 pos, float lerp_axis) { + return vec3(snoise(vec4(pos, lerp_axis)), snoise(vec4(pos + 400.0, lerp_axis)), snoise(vec4(pos + 1000.0, lerp_axis))); vec3 r0 = rand_perm_3(vec3(pos.x, pos.y, pos.z) + floor(lerp_axis)); vec3 r1 = rand_perm_3(vec3(pos.x, pos.y, pos.z) + floor(lerp_axis + 1.0)); return r0 + (r1 - r0) * fract(lerp_axis); From 944067fd43cddb6eeb090b9ed572ab7b5582a600 Mon Sep 17 00:00:00 2001 From: Vechro Date: Thu, 15 Aug 2019 16:50:46 +0300 Subject: [PATCH 05/15] Add water special index --- common/src/terrain/structure.rs | 2 ++ world/src/block/mod.rs | 1 + 2 files changed, 3 insertions(+) diff --git a/common/src/terrain/structure.rs b/common/src/terrain/structure.rs index d8b3d2455d..0154b01aad 100644 --- a/common/src/terrain/structure.rs +++ b/common/src/terrain/structure.rs @@ -15,6 +15,7 @@ pub enum StructureBlock { PineLeaves, Acacia, PalmLeaves, + Water, Fruit, Hollow, Block(Block), @@ -95,6 +96,7 @@ impl Asset for Structure { 0 => StructureBlock::TemperateLeaves, 1 => StructureBlock::PineLeaves, 2 => StructureBlock::PalmLeaves, + 3 => StructureBlock::Water, 4 => StructureBlock::Acacia, 7 => StructureBlock::Fruit, 15 => StructureBlock::Hollow, diff --git a/world/src/block/mod.rs b/world/src/block/mod.rs index 2396b9fdeb..bf6f2b33ec 100644 --- a/world/src/block/mod.rs +++ b/world/src/block/mod.rs @@ -465,6 +465,7 @@ fn block_from_structure( Lerp::lerp(Rgb::new(0.0, 108.0, 113.0), Rgb::new(30.0, 156.0, 10.0), lerp) .map(|e| e as u8), )), + StructureBlock::Water => Some(Block::new(BlockKind::Water, Rgb::new(100, 150, 255))), StructureBlock::Acacia => Some(Block::new( BlockKind::Normal, Lerp::lerp(Rgb::new(35.0, 156.0, 0.0), Rgb::new(62.0, 208.0, 0.0), lerp) From b5b3b980fe46601620bfb0580c424ef746a31a47 Mon Sep 17 00:00:00 2001 From: Vechro Date: Thu, 15 Aug 2019 17:23:14 +0300 Subject: [PATCH 06/15] Add green sludge special index --- common/src/terrain/structure.rs | 2 ++ world/src/block/mod.rs | 1 + 2 files changed, 3 insertions(+) diff --git a/common/src/terrain/structure.rs b/common/src/terrain/structure.rs index 0154b01aad..0f70b37fbe 100644 --- a/common/src/terrain/structure.rs +++ b/common/src/terrain/structure.rs @@ -16,6 +16,7 @@ pub enum StructureBlock { Acacia, PalmLeaves, Water, + GreenSludge, Fruit, Hollow, Block(Block), @@ -98,6 +99,7 @@ impl Asset for Structure { 2 => StructureBlock::PalmLeaves, 3 => StructureBlock::Water, 4 => StructureBlock::Acacia, + 6 => StructureBlock::GreenSludge, 7 => StructureBlock::Fruit, 15 => StructureBlock::Hollow, index => { diff --git a/world/src/block/mod.rs b/world/src/block/mod.rs index bf6f2b33ec..7b1dcd6123 100644 --- a/world/src/block/mod.rs +++ b/world/src/block/mod.rs @@ -466,6 +466,7 @@ fn block_from_structure( .map(|e| e as u8), )), StructureBlock::Water => Some(Block::new(BlockKind::Water, Rgb::new(100, 150, 255))), + StructureBlock::GreenSludge => Some(Block::new(BlockKind::Water, Rgb::new(30, 126, 23))), StructureBlock::Acacia => Some(Block::new( BlockKind::Normal, Lerp::lerp(Rgb::new(35.0, 156.0, 0.0), Rgb::new(62.0, 208.0, 0.0), lerp) From 5d4079b165513fe411bfe940f496dab61ab2c5ca Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Fri, 16 Aug 2019 11:31:51 +0100 Subject: [PATCH 07/15] Better reflection calculations --- assets/voxygen/shaders/fluid-frag.glsl | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/assets/voxygen/shaders/fluid-frag.glsl b/assets/voxygen/shaders/fluid-frag.glsl index b3bdd52292..fab8149bc6 100644 --- a/assets/voxygen/shaders/fluid-frag.glsl +++ b/assets/voxygen/shaders/fluid-frag.glsl @@ -26,10 +26,12 @@ void main() { float fog_level = fog(f_pos.xy, focus_pos.xy); vec3 fog_color = get_sky_color(normalize(f_pos - cam_pos.xyz), time_of_day.x); - vec3 warped_norm = normalize(f_norm + smooth_rand(f_pos * 0.6, tick.x) * 0.75); - vec3 reflect_color = get_sky_color(reflect(normalize(f_pos - cam_pos.xyz), warped_norm), time_of_day.x); + vec3 cam_to_frag = normalize(f_pos - cam_pos.xyz); + vec3 warped_norm = normalize(f_norm + smooth_rand(f_pos * 0.35, tick.x) * 0.2); + vec3 reflect_color = get_sky_color(reflect(cam_to_frag, warped_norm), time_of_day.x); + float passthrough = max(dot(f_norm, -cam_to_frag), 0.0); - vec3 color = mix(surf_color + reflect_color * 0.5, fog_color, fog_level); + vec4 color = mix(vec4(reflect_color, 1.0), vec4(surf_color, f_opac), passthrough); - tgt_color = vec4(color, f_opac); + tgt_color = mix(color, vec4(fog_color, 1.0), fog_level); } From 825d8bb632a608d02ef49b3f9708af0f8d3e373d Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Fri, 16 Aug 2019 12:38:59 +0100 Subject: [PATCH 08/15] Fixed water in caves, made water reflection vary with lighting --- assets/voxygen/shaders/fluid-frag.glsl | 6 +++--- common/src/sys/phys.rs | 4 ++-- common/src/terrain/block.rs | 8 ++++++++ voxygen/src/mesh/terrain.rs | 24 +++++++++++------------- world/src/block/mod.rs | 21 ++++++++++++++++----- 5 files changed, 40 insertions(+), 23 deletions(-) diff --git a/assets/voxygen/shaders/fluid-frag.glsl b/assets/voxygen/shaders/fluid-frag.glsl index fab8149bc6..ffba9efc6e 100644 --- a/assets/voxygen/shaders/fluid-frag.glsl +++ b/assets/voxygen/shaders/fluid-frag.glsl @@ -21,15 +21,15 @@ out vec4 tgt_color; void main() { vec3 light = get_sun_diffuse(f_norm, time_of_day.x) * f_light + light_at(f_pos, f_norm); - vec3 surf_color = f_col * light; + vec3 surf_color = f_col * light; float fog_level = fog(f_pos.xy, focus_pos.xy); vec3 fog_color = get_sky_color(normalize(f_pos - cam_pos.xyz), time_of_day.x); vec3 cam_to_frag = normalize(f_pos - cam_pos.xyz); vec3 warped_norm = normalize(f_norm + smooth_rand(f_pos * 0.35, tick.x) * 0.2); - vec3 reflect_color = get_sky_color(reflect(cam_to_frag, warped_norm), time_of_day.x); - float passthrough = max(dot(f_norm, -cam_to_frag), 0.0); + vec3 reflect_color = get_sky_color(reflect(cam_to_frag, warped_norm), time_of_day.x) * light; + float passthrough = dot(faceforward(f_norm, f_norm, cam_to_frag), -cam_to_frag); vec4 color = mix(vec4(reflect_color, 1.0), vec4(surf_color, f_opac), passthrough); diff --git a/common/src/sys/phys.rs b/common/src/sys/phys.rs index dadc527fd7..89cfceecdd 100644 --- a/common/src/sys/phys.rs +++ b/common/src/sys/phys.rs @@ -108,7 +108,7 @@ impl<'a> System<'a> for Sys { if terrain .get(block_pos) - .map(|vox| !vox.is_empty()) + .map(|vox| vox.is_solid()) .unwrap_or(false) { let player_aabb = Aabb { @@ -183,7 +183,7 @@ impl<'a> System<'a> for Sys { .filter(|(block_pos, _)| { terrain .get(*block_pos) - .map(|vox| !vox.is_empty()) + .map(|vox| vox.is_solid()) .unwrap_or(false) }) // Find the maximum of the minimum collision axes (this bit is weird, trust me that it works) diff --git a/common/src/terrain/block.rs b/common/src/terrain/block.rs index 812391f416..e6650576ad 100644 --- a/common/src/terrain/block.rs +++ b/common/src/terrain/block.rs @@ -34,6 +34,14 @@ impl BlockKind { _ => true, } } + + pub fn is_solid(&self) -> bool { + match self { + BlockKind::Air => false, + BlockKind::Water => false, + _ => true, + } + } } #[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)] diff --git a/voxygen/src/mesh/terrain.rs b/voxygen/src/mesh/terrain.rs index f8c30ea446..ded6a4415b 100644 --- a/voxygen/src/mesh/terrain.rs +++ b/voxygen/src/mesh/terrain.rs @@ -13,12 +13,12 @@ use vek::*; type TerrainVertex = ::Vertex; type FluidVertex = ::Vertex; -fn block_shadow_density(kind: BlockKind) -> Option { +fn block_shadow_density(kind: BlockKind) -> (f32, f32) { match kind { - BlockKind::Air => None, - BlockKind::Normal => Some(0.85), - BlockKind::Dense => Some(3.0), - BlockKind::Water => Some(0.8), + BlockKind::Air => (0.0, 0.0), + BlockKind::Normal => (0.085, 0.3), + BlockKind::Dense => (0.3, 0.0), + BlockKind::Water => (0.08, 0.0), } } @@ -94,16 +94,14 @@ impl + ReadVol + Debug, S: VolSize + Clone> Meshable for // Accumulate shade under opaque blocks for i in 0..3 { for j in 0..3 { - neighbour_light[0][i][j] = if let Some(density) = self + let (density, cap) = self .get(pos + Vec3::new(i as i32 - 1, j as i32 - 1, -1)) .ok() - .and_then(|vox| block_shadow_density(vox.kind())) - { - (neighbour_light[0][i][j] * (1.0 - density * 0.1)) - .max(1.0 - density) - } else { - (neighbour_light[0][i][j] * 1.025).min(1.0) - }; + .map(|vox| block_shadow_density(vox.kind())) + .unwrap_or((0.0, 0.0)); + + neighbour_light[0][i][j] = + (neighbour_light[0][i][j] * (1.0 - density)).max(cap); } } diff --git a/world/src/block/mod.rs b/world/src/block/mod.rs index 7b1dcd6123..0e70764ac5 100644 --- a/world/src/block/mod.rs +++ b/world/src/block/mod.rs @@ -163,7 +163,7 @@ impl<'a> BlockGen<'a> { let (definitely_underground, height, water_height) = if (wposf.z as f32) < alt - 64.0 * chaos { // Shortcut warping - (true, alt, water_level) + (true, alt, CONFIG.sea_level /*water_level*/) } else { // Apply warping let warp = (world @@ -204,7 +204,11 @@ impl<'a> BlockGen<'a> { (alt + warp).max(cliff_height) }; - (false, height, (water_level + warp).max(CONFIG.sea_level)) + ( + false, + height, + /*(water_level + warp).max(*/ CONFIG.sea_level, /*)*/ + ) }; // Sample blocks @@ -250,9 +254,6 @@ impl<'a> BlockGen<'a> { BlockKind::Normal, saturate_srgb(col, 0.45).map(|e| (e * 255.0) as u8), )) - } else if (wposf.z as f32) < water_height { - // Ocean - Some(water) } else { None }; @@ -296,6 +297,16 @@ impl<'a> BlockGen<'a> { } }); + // Water + let block = block.or_else(|| { + if (wposf.z as f32) < water_height { + // Ocean + Some(water) + } else { + None + } + }); + let block = structures .iter() .find_map(|st| { From f0e52e60029e06d14c5e816b491cd0b8d2682f36 Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Fri, 16 Aug 2019 15:58:14 +0100 Subject: [PATCH 09/15] Better reflections and water fog --- assets/voxygen/shaders/figure-frag.glsl | 2 +- assets/voxygen/shaders/fluid-frag.glsl | 16 ++++++++-------- assets/voxygen/shaders/fluid-vert.glsl | 3 --- assets/voxygen/shaders/include/globals.glsl | 1 + assets/voxygen/shaders/include/sky.glsl | 21 +++++++++++++++------ assets/voxygen/shaders/terrain-frag.glsl | 2 +- voxygen/src/menu/char_selection/scene.rs | 2 ++ voxygen/src/mesh/terrain.rs | 2 +- voxygen/src/render/pipelines/mod.rs | 5 +++++ voxygen/src/scene/mod.rs | 8 +++++++- world/src/block/mod.rs | 2 +- world/src/lib.rs | 2 +- 12 files changed, 43 insertions(+), 23 deletions(-) diff --git a/assets/voxygen/shaders/figure-frag.glsl b/assets/voxygen/shaders/figure-frag.glsl index 11c0fd4a51..7803dadb3f 100644 --- a/assets/voxygen/shaders/figure-frag.glsl +++ b/assets/voxygen/shaders/figure-frag.glsl @@ -31,7 +31,7 @@ void main() { vec3 light = get_sun_diffuse(f_norm, time_of_day.x) + light_at(f_pos, f_norm); vec3 surf_color = srgb_to_linear(model_col.rgb * f_col) * 4.0 * light; - float fog_level = fog(f_pos.xy, focus_pos.xy); + float fog_level = fog(f_pos.xyz, focus_pos.xyz, medium.x); vec3 fog_color = get_sky_color(normalize(f_pos - cam_pos.xyz), time_of_day.x); vec3 color = mix(surf_color, fog_color, fog_level); diff --git a/assets/voxygen/shaders/fluid-frag.glsl b/assets/voxygen/shaders/fluid-frag.glsl index ffba9efc6e..25b7c83e78 100644 --- a/assets/voxygen/shaders/fluid-frag.glsl +++ b/assets/voxygen/shaders/fluid-frag.glsl @@ -7,7 +7,6 @@ in vec3 f_pos; flat in vec3 f_norm; in vec3 f_col; in float f_light; -in float f_opac; layout (std140) uniform u_locals { @@ -20,18 +19,19 @@ out vec4 tgt_color; #include void main() { - vec3 light = get_sun_diffuse(f_norm, time_of_day.x) * f_light + light_at(f_pos, f_norm); + vec3 warped_norm = normalize(f_norm + smooth_rand(f_pos * 0.35, tick.x) * 0.2); + + vec3 light = get_sun_diffuse(warped_norm, time_of_day.x) * f_light + light_at(f_pos, warped_norm); vec3 surf_color = f_col * light; - float fog_level = fog(f_pos.xy, focus_pos.xy); + float fog_level = fog(f_pos.xyz, focus_pos.xyz, medium.x); vec3 fog_color = get_sky_color(normalize(f_pos - cam_pos.xyz), time_of_day.x); vec3 cam_to_frag = normalize(f_pos - cam_pos.xyz); - vec3 warped_norm = normalize(f_norm + smooth_rand(f_pos * 0.35, tick.x) * 0.2); - vec3 reflect_color = get_sky_color(reflect(cam_to_frag, warped_norm), time_of_day.x) * light; - float passthrough = dot(faceforward(f_norm, f_norm, cam_to_frag), -cam_to_frag); + vec3 reflect_color = get_sky_color(reflect(cam_to_frag, warped_norm), time_of_day.x) * f_light; + float passthrough = dot(faceforward(warped_norm, warped_norm, cam_to_frag), -cam_to_frag); - vec4 color = mix(vec4(reflect_color, 1.0), vec4(surf_color, f_opac), passthrough); + vec4 color = mix(vec4(reflect_color, 1.0), vec4(surf_color, 0.8 / (1.0 + light * 2.0)), passthrough); - tgt_color = mix(color, vec4(fog_color, 1.0), fog_level); + tgt_color = mix(color, vec4(fog_color, 0.0), fog_level); } diff --git a/assets/voxygen/shaders/fluid-vert.glsl b/assets/voxygen/shaders/fluid-vert.glsl index 43da1243c8..d09305e9e7 100644 --- a/assets/voxygen/shaders/fluid-vert.glsl +++ b/assets/voxygen/shaders/fluid-vert.glsl @@ -14,7 +14,6 @@ out vec3 f_pos; flat out vec3 f_norm; out vec3 f_col; out float f_light; -out float f_opac; // First 3 normals are negative, next 3 are positive vec3 normals[6] = vec3[]( vec3(-1,0,0), vec3(0,-1,0), vec3(0,0,-1), vec3(1,0,0), vec3(0,1,0), vec3(0,0,1) ); @@ -43,8 +42,6 @@ void main() { f_light = float(v_col_light & 0xFFu) / 255.0; - f_opac = 0.3; - gl_Position = proj_mat * view_mat * diff --git a/assets/voxygen/shaders/include/globals.glsl b/assets/voxygen/shaders/include/globals.glsl index cbd7e2e739..7235e43695 100644 --- a/assets/voxygen/shaders/include/globals.glsl +++ b/assets/voxygen/shaders/include/globals.glsl @@ -9,4 +9,5 @@ uniform u_globals { vec4 tick; vec4 screen_res; uvec4 light_count; + uvec4 medium; }; diff --git a/assets/voxygen/shaders/include/sky.glsl b/assets/voxygen/shaders/include/sky.glsl index 25c1fba993..aa38b4a337 100644 --- a/assets/voxygen/shaders/include/sky.glsl +++ b/assets/voxygen/shaders/include/sky.glsl @@ -144,11 +144,20 @@ vec3 get_sky_color(vec3 dir, float time_of_day) { return sky_color + sun_light; } -float fog(vec2 f_pos, vec2 focus_pos) { - float dist = distance(f_pos, focus_pos) / view_distance.x; - const float min_fog = 0.5; - const float max_fog = 1.0; - const float diff_fog = 0.5; // max - min +float fog(vec3 f_pos, vec3 focus_pos, uint medium) { + float fog_radius = view_distance.x; + float mist_radius = 10000000.0; - return pow(clamp((dist - min_fog) / (diff_fog), 0.0, 1.0), 1.7); + float min_fog = 0.5; + float max_fog = 1.0; + + if (medium == 1u) { + mist_radius = 32.0; + min_fog = 0.0; + } + + float fog = distance(f_pos.xy, focus_pos.xy) / fog_radius; + float mist = distance(f_pos, focus_pos) / mist_radius; + + return pow(clamp((max(fog, mist) - min_fog) / (max_fog - min_fog), 0.0, 1.0), 1.7); } diff --git a/assets/voxygen/shaders/terrain-frag.glsl b/assets/voxygen/shaders/terrain-frag.glsl index cb0f75cf71..55a7018dd7 100644 --- a/assets/voxygen/shaders/terrain-frag.glsl +++ b/assets/voxygen/shaders/terrain-frag.glsl @@ -21,7 +21,7 @@ void main() { vec3 light = get_sun_diffuse(f_norm, time_of_day.x) * f_light + light_at(f_pos, f_norm); vec3 surf_color = f_col * light; - float fog_level = fog(f_pos.xy, focus_pos.xy); + float fog_level = fog(f_pos.xyz, focus_pos.xyz, medium.x); vec3 fog_color = get_sky_color(normalize(f_pos - cam_pos.xyz), time_of_day.x); vec3 color = mix(surf_color, fog_color, fog_level); diff --git a/voxygen/src/menu/char_selection/scene.rs b/voxygen/src/menu/char_selection/scene.rs index 488a2b1640..d01df92018 100644 --- a/voxygen/src/menu/char_selection/scene.rs +++ b/voxygen/src/menu/char_selection/scene.rs @@ -17,6 +17,7 @@ use client::Client; use common::{ comp::{humanoid, Body}, state::DeltaTime, + terrain::BlockKind, }; use log::error; use vek::*; @@ -102,6 +103,7 @@ impl Scene { client.state().get_time(), renderer.get_resolution(), 0, + BlockKind::Air, )], ) { error!("Renderer failed to update: {:?}", err); diff --git a/voxygen/src/mesh/terrain.rs b/voxygen/src/mesh/terrain.rs index ded6a4415b..90bdab211c 100644 --- a/voxygen/src/mesh/terrain.rs +++ b/voxygen/src/mesh/terrain.rs @@ -18,7 +18,7 @@ fn block_shadow_density(kind: BlockKind) -> (f32, f32) { BlockKind::Air => (0.0, 0.0), BlockKind::Normal => (0.085, 0.3), BlockKind::Dense => (0.3, 0.0), - BlockKind::Water => (0.08, 0.0), + BlockKind::Water => (0.15, 0.0), } } diff --git a/voxygen/src/render/pipelines/mod.rs b/voxygen/src/render/pipelines/mod.rs index 801e3b9a74..08713bfc6b 100644 --- a/voxygen/src/render/pipelines/mod.rs +++ b/voxygen/src/render/pipelines/mod.rs @@ -6,6 +6,7 @@ pub mod terrain; pub mod ui; use super::util::arr_to_mat; +use common::terrain::BlockKind; use gfx::{ self, gfx_constant_struct_meta, @@ -27,6 +28,7 @@ gfx_defines! { tick: [f32; 4] = "tick", screen_res: [f32; 4] = "screen_res", light_count: [u32; 4] = "light_count", + medium: [u32; 4] = "medium", } constant Light { @@ -47,6 +49,7 @@ impl Globals { tick: f64, screen_res: Vec2, light_count: usize, + medium: BlockKind, ) -> Self { Self { view_mat: arr_to_mat(view_mat.into_col_array()), @@ -58,6 +61,7 @@ impl Globals { tick: [tick as f32; 4], screen_res: Vec4::from(screen_res.map(|e| e as f32)).into_array(), light_count: [light_count as u32; 4], + medium: [if medium.is_fluid() { 1 } else { 0 }; 4], } } } @@ -74,6 +78,7 @@ impl Default for Globals { 0.0, Vec2::new(800, 500), 0, + BlockKind::Air, ) } } diff --git a/voxygen/src/scene/mod.rs b/voxygen/src/scene/mod.rs index a043709fc8..c6da07713f 100644 --- a/voxygen/src/scene/mod.rs +++ b/voxygen/src/scene/mod.rs @@ -15,7 +15,7 @@ use crate::{ window::Event, }; use client::Client; -use common::comp; +use common::{comp, terrain::BlockKind, vol::ReadVol}; use specs::Join; use vek::*; @@ -194,6 +194,12 @@ impl Scene { client.state().get_time(), renderer.get_resolution(), lights.len(), + client + .state() + .terrain() + .get(cam_pos.map(|e| e.floor() as i32)) + .map(|b| b.kind()) + .unwrap_or(BlockKind::Air), )], ) .expect("Failed to update global constants"); diff --git a/world/src/block/mod.rs b/world/src/block/mod.rs index 0e70764ac5..c927a5194f 100644 --- a/world/src/block/mod.rs +++ b/world/src/block/mod.rs @@ -225,7 +225,7 @@ impl<'a> BlockGen<'a> { // let sand = Block::new(1, Rgb::new(180, 150, 50)); // let warm_stone = Block::new(1, Rgb::new(165, 165, 130)); - let water = Block::new(BlockKind::Water, Rgb::new(0, 24, 255)); + let water = Block::new(BlockKind::Water, Rgb::new(60, 90, 190)); let grass_depth = 1.5 + 2.0 * chaos; let block = if (wposf.z as f32) < height - grass_depth { diff --git a/world/src/lib.rs b/world/src/lib.rs index d84c128f7f..e9273d34e1 100644 --- a/world/src/lib.rs +++ b/world/src/lib.rs @@ -60,7 +60,7 @@ impl World { pub fn generate_chunk(&self, chunk_pos: Vec2) -> (TerrainChunk, ChunkSupplement) { let air = Block::empty(); let stone = Block::new(BlockKind::Dense, Rgb::new(200, 220, 255)); - let water = Block::new(BlockKind::Water, Rgb::new(100, 150, 255)); + let water = Block::new(BlockKind::Water, Rgb::new(60, 90, 190)); let chunk_size2d = Vec2::from(TerrainChunkSize::SIZE); let (base_z, sim_chunk) = match self From 6cf5b998572f48277a877f5d3d96e8d67ecf7b84 Mon Sep 17 00:00:00 2001 From: Vechro Date: Fri, 16 Aug 2019 19:13:06 +0300 Subject: [PATCH 10/15] Add water-based dungeons --- assets/world/structure/dungeon/meso_sewer_temple.vox | 3 +++ assets/world/structure/dungeon/ruins_maze.vox | 3 +++ world/src/column/mod.rs | 8 ++++++++ 3 files changed, 14 insertions(+) create mode 100644 assets/world/structure/dungeon/meso_sewer_temple.vox create mode 100644 assets/world/structure/dungeon/ruins_maze.vox diff --git a/assets/world/structure/dungeon/meso_sewer_temple.vox b/assets/world/structure/dungeon/meso_sewer_temple.vox new file mode 100644 index 0000000000..0dc46e18d8 --- /dev/null +++ b/assets/world/structure/dungeon/meso_sewer_temple.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e360e6fbff3254e779ec209a9c0592d9e3c64d52bac04d7f0bace06d05254d7d +size 1328948 diff --git a/assets/world/structure/dungeon/ruins_maze.vox b/assets/world/structure/dungeon/ruins_maze.vox new file mode 100644 index 0000000000..fe7a9203ac --- /dev/null +++ b/assets/world/structure/dungeon/ruins_maze.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:31c169a0c575f086de75dc357a4126ea3cf710a8f02a3655905826125a05e187 +size 1548480 diff --git a/world/src/column/mod.rs b/world/src/column/mod.rs index 0958e810ab..bfe9500244 100644 --- a/world/src/column/mod.rs +++ b/world/src/column/mod.rs @@ -37,6 +37,14 @@ lazy_static! { assets::load_map("world.structure.dungeon.ruins_3", |s: Structure| s .with_center(Vec3::new(58, 45, 72))) .unwrap(), + assets::load_map( + "world.structure.dungeon.meso_sewer_temple", + |s: Structure| s.with_center(Vec3::new(66, 56, 60)) + ) + .unwrap(), + assets::load_map("world.structure.dungeon.ruins_maze", |s: Structure| s + .with_center(Vec3::new(56, 62, 116))) + .unwrap(), ]; } From e535537106ef692d289c6087aa96f95ef7cd253a Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Fri, 16 Aug 2019 18:23:58 +0100 Subject: [PATCH 11/15] Added default block kind to structure loading --- common/src/terrain/structure.rs | 19 ++++++++++++++++--- world/src/block/mod.rs | 15 +++++++++++++-- world/src/column/mod.rs | 18 ++++++++++++------ 3 files changed, 41 insertions(+), 11 deletions(-) diff --git a/common/src/terrain/structure.rs b/common/src/terrain/structure.rs index 0f70b37fbe..338ab6e6d7 100644 --- a/common/src/terrain/structure.rs +++ b/common/src/terrain/structure.rs @@ -11,6 +11,7 @@ use vek::*; #[derive(Copy, Clone)] pub enum StructureBlock { + None, TemperateLeaves, PineLeaves, Acacia, @@ -19,12 +20,12 @@ pub enum StructureBlock { GreenSludge, Fruit, Hollow, - Block(Block), + Block(Rgb), } impl Vox for StructureBlock { fn empty() -> Self { - StructureBlock::Block(Block::empty()) + StructureBlock::None } fn is_empty(&self) -> bool { @@ -43,6 +44,7 @@ pub struct Structure { center: Vec3, vol: Dyna, empty: StructureBlock, + default_kind: BlockKind, } impl Structure { @@ -51,12 +53,21 @@ impl Structure { self } + pub fn with_default_kind(mut self, kind: BlockKind) -> Self { + self.default_kind = kind; + self + } + pub fn get_bounds(&self) -> Aabb { Aabb { min: -self.center, max: self.vol.get_size().map(|e| e as i32) - self.center, } } + + pub fn default_kind(&self) -> BlockKind { + self.default_kind + } } impl BaseVol for Structure { @@ -107,7 +118,7 @@ impl Asset for Structure { .get(index as usize) .copied() .unwrap_or_else(|| Rgb::broadcast(0)); - StructureBlock::Block(Block::new(BlockKind::Normal, color)) + StructureBlock::Block(color) } }; @@ -121,12 +132,14 @@ impl Asset for Structure { center: Vec3::zero(), vol, empty: StructureBlock::empty(), + default_kind: BlockKind::Normal, }) } else { Ok(Self { center: Vec3::zero(), vol: Dyna::filled(Vec3::zero(), StructureBlock::empty(), ()), empty: StructureBlock::empty(), + default_kind: BlockKind::Normal, }) } } diff --git a/world/src/block/mod.rs b/world/src/block/mod.rs index c927a5194f..a8251bfb93 100644 --- a/world/src/block/mod.rs +++ b/world/src/block/mod.rs @@ -440,7 +440,14 @@ impl StructureInfo { .get((block_pos * 128) / 128) // Scaling .ok() .and_then(|b| { - block_from_structure(*b, block_pos, self.pos.into(), self.seed, sample) + block_from_structure( + *b, + volume.default_kind(), + block_pos, + self.pos.into(), + self.seed, + sample, + ) }) } } @@ -449,6 +456,7 @@ impl StructureInfo { fn block_from_structure( sblock: StructureBlock, + default_kind: BlockKind, pos: Vec3, structure_pos: Vec2, structure_seed: u32, @@ -461,6 +469,7 @@ fn block_from_structure( + ((field.get(Vec3::from(pos)) % 256) as f32 / 256.0 - 0.5) * 0.15; match sblock { + StructureBlock::None => None, StructureBlock::TemperateLeaves => Some(Block::new( BlockKind::Normal, Lerp::lerp(Rgb::new(0.0, 132.0, 94.0), Rgb::new(142.0, 181.0, 0.0), lerp) @@ -489,6 +498,8 @@ fn block_from_structure( .map(|e| e as u8), )), StructureBlock::Hollow => Some(Block::empty()), - StructureBlock::Block(block) => Some(block).filter(|block| !block.is_empty()), + StructureBlock::Block(color) => { + Some(Block::new(default_kind, color)).filter(|block| !block.is_empty()) + } } } diff --git a/world/src/column/mod.rs b/world/src/column/mod.rs index bfe9500244..021a422d87 100644 --- a/world/src/column/mod.rs +++ b/world/src/column/mod.rs @@ -7,7 +7,7 @@ use crate::{ }; use common::{ assets, - terrain::{Structure, TerrainChunkSize}, + terrain::{BlockKind, Structure, TerrainChunkSize}, vol::VolSize, }; use lazy_static::lazy_static; @@ -29,21 +29,27 @@ static DUNGEON_RAND: RandomPerm = RandomPerm::new(0x42782335); lazy_static! { pub static ref DUNGEONS: Vec> = vec![ assets::load_map("world.structure.dungeon.ruins", |s: Structure| s - .with_center(Vec3::new(57, 58, 61))) + .with_center(Vec3::new(57, 58, 61)) + .with_default_kind(BlockKind::Dense)) .unwrap(), assets::load_map("world.structure.dungeon.ruins_2", |s: Structure| s - .with_center(Vec3::new(53, 57, 60))) + .with_center(Vec3::new(53, 57, 60)) + .with_default_kind(BlockKind::Dense)) .unwrap(), assets::load_map("world.structure.dungeon.ruins_3", |s: Structure| s - .with_center(Vec3::new(58, 45, 72))) + .with_center(Vec3::new(58, 45, 72)) + .with_default_kind(BlockKind::Dense)) .unwrap(), assets::load_map( "world.structure.dungeon.meso_sewer_temple", - |s: Structure| s.with_center(Vec3::new(66, 56, 60)) + |s: Structure| s + .with_center(Vec3::new(66, 56, 60)) + .with_default_kind(BlockKind::Dense) ) .unwrap(), assets::load_map("world.structure.dungeon.ruins_maze", |s: Structure| s - .with_center(Vec3::new(56, 62, 116))) + .with_center(Vec3::new(56, 62, 116)) + .with_default_kind(BlockKind::Dense)) .unwrap(), ]; } From 71710fb09192b643f54437f92ccc69ced4240f31 Mon Sep 17 00:00:00 2001 From: Vechro Date: Sat, 17 Aug 2019 09:28:34 +0300 Subject: [PATCH 12/15] Dungeon fixes --- assets/world/structure/dungeon/ruins_maze.vox | 4 ++-- world/src/column/mod.rs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/assets/world/structure/dungeon/ruins_maze.vox b/assets/world/structure/dungeon/ruins_maze.vox index fe7a9203ac..8d217b8b37 100644 --- a/assets/world/structure/dungeon/ruins_maze.vox +++ b/assets/world/structure/dungeon/ruins_maze.vox @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:31c169a0c575f086de75dc357a4126ea3cf710a8f02a3655905826125a05e187 -size 1548480 +oid sha256:6b36a0b173af8711f60fcbcba05bee1acf49973e4139f818d36486a50675b60f +size 1571100 diff --git a/world/src/column/mod.rs b/world/src/column/mod.rs index 021a422d87..36b9416d92 100644 --- a/world/src/column/mod.rs +++ b/world/src/column/mod.rs @@ -43,12 +43,12 @@ lazy_static! { assets::load_map( "world.structure.dungeon.meso_sewer_temple", |s: Structure| s - .with_center(Vec3::new(66, 56, 60)) + .with_center(Vec3::new(63, 62, 60)) .with_default_kind(BlockKind::Dense) ) .unwrap(), assets::load_map("world.structure.dungeon.ruins_maze", |s: Structure| s - .with_center(Vec3::new(56, 62, 116)) + .with_center(Vec3::new(60, 60, 116)) .with_default_kind(BlockKind::Dense)) .unwrap(), ]; From 75dbebbd05eb72ac63c1f1b4d393f5055ee18658 Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Sat, 17 Aug 2019 18:07:25 +0100 Subject: [PATCH 13/15] More interesting waves --- assets/voxygen/shaders/fluid-frag.glsl | 21 +++- assets/voxygen/shaders/include/random.glsl | 120 ++++++--------------- voxygen/src/render/renderer.rs | 10 +- world/src/block/mod.rs | 24 +++-- 4 files changed, 73 insertions(+), 102 deletions(-) diff --git a/assets/voxygen/shaders/fluid-frag.glsl b/assets/voxygen/shaders/fluid-frag.glsl index 25b7c83e78..f4cbade5fa 100644 --- a/assets/voxygen/shaders/fluid-frag.glsl +++ b/assets/voxygen/shaders/fluid-frag.glsl @@ -19,7 +19,18 @@ out vec4 tgt_color; #include void main() { - vec3 warped_norm = normalize(f_norm + smooth_rand(f_pos * 0.35, tick.x) * 0.2); + /* + vec3 hex_pos = f_pos * 2.0; + hex_pos = hex_pos + vec3(hex_pos.y * 1.4 / 3.0, hex_pos.y * 0.1, 0); + if (fract(hex_pos.x) > fract(hex_pos.y)) { + hex_pos += vec3(1.0, 1.0, 0); + } + hex_pos = f_pos;//floor(hex_pos); + */ + + vec3 warped_norm = normalize(f_norm + + smooth_rand(f_pos * 1.0, tick.x * 1.0) * 0.05 + + smooth_rand(f_pos * 0.25, tick.x * 0.25) * 0.1); vec3 light = get_sun_diffuse(warped_norm, time_of_day.x) * f_light + light_at(f_pos, warped_norm); vec3 surf_color = f_col * light; @@ -28,10 +39,12 @@ void main() { vec3 fog_color = get_sky_color(normalize(f_pos - cam_pos.xyz), time_of_day.x); vec3 cam_to_frag = normalize(f_pos - cam_pos.xyz); - vec3 reflect_color = get_sky_color(reflect(cam_to_frag, warped_norm), time_of_day.x) * f_light; - float passthrough = dot(faceforward(warped_norm, warped_norm, cam_to_frag), -cam_to_frag); + vec3 reflect_ray_dir = reflect(cam_to_frag, warped_norm); + reflect_ray_dir.z = max(reflect_ray_dir.z, 0.05); + vec3 reflect_color = get_sky_color(reflect_ray_dir, time_of_day.x) * f_light; + float passthrough = pow(dot(faceforward(warped_norm, warped_norm, cam_to_frag), -cam_to_frag), 1.0); - vec4 color = mix(vec4(reflect_color, 1.0), vec4(surf_color, 0.8 / (1.0 + light * 2.0)), passthrough); + vec4 color = mix(vec4(reflect_color, 1.0), vec4(surf_color, 0.5 / (1.0 + light * 2.0)), passthrough); tgt_color = mix(color, vec4(fog_color, 0.0), fog_level); } diff --git a/assets/voxygen/shaders/include/random.glsl b/assets/voxygen/shaders/include/random.glsl index 1b97d1c3dc..b1f0e18a21 100644 --- a/assets/voxygen/shaders/include/random.glsl +++ b/assets/voxygen/shaders/include/random.glsl @@ -1,95 +1,35 @@ -// Simplex 4D Noise -// by Ian McEwan, Ashima Arts -// -vec4 permute(vec4 x){return mod(((x*34.0)+1.0)*x, 289.0);} -float permute(float x){return floor(mod(((x*34.0)+1.0)*x, 289.0));} -vec4 taylorInvSqrt(vec4 r){return 1.79284291400159 - 0.85373472095314 * r;} -float taylorInvSqrt(float r){return 1.79284291400159 - 0.85373472095314 * r;} - -vec4 grad4(float j, vec4 ip){ - const vec4 ones = vec4(1.0, 1.0, 1.0, -1.0); - vec4 p,s; - - p.xyz = floor( fract (vec3(j) * ip.xyz) * 7.0) * ip.z - 1.0; - p.w = 1.5 - dot(abs(p.xyz), ones.xyz); - s = vec4(lessThan(p, vec4(0.0))); - p.xyz = p.xyz + (s.xyz*2.0 - 1.0) * s.www; - - return p; +float hash(vec4 p) { + p = fract( p*0.3183099+.1); + p *= 17.0; + return (fract(p.x*p.y*p.z*p.w*(p.x+p.y+p.z+p.w)) - 0.5) * 2.0; } -float snoise(vec4 v){ - const vec2 C = vec2( 0.138196601125010504, // (5 - sqrt(5))/20 G4 - 0.309016994374947451); // (sqrt(5) - 1)/4 F4 -// First corner - vec4 i = floor(v + dot(v, C.yyyy) ); - vec4 x0 = v - i + dot(i, C.xxxx); - -// Other corners - -// Rank sorting originally contributed by Bill Licea-Kane, AMD (formerly ATI) - vec4 i0; - - vec3 isX = step( x0.yzw, x0.xxx ); - vec3 isYZ = step( x0.zww, x0.yyz ); -// i0.x = dot( isX, vec3( 1.0 ) ); - i0.x = isX.x + isX.y + isX.z; - i0.yzw = 1.0 - isX; - -// i0.y += dot( isYZ.xy, vec2( 1.0 ) ); - i0.y += isYZ.x + isYZ.y; - i0.zw += 1.0 - isYZ.xy; - - i0.z += isYZ.z; - i0.w += 1.0 - isYZ.z; - - // i0 now contains the unique values 0,1,2,3 in each channel - vec4 i3 = clamp( i0, 0.0, 1.0 ); - vec4 i2 = clamp( i0-1.0, 0.0, 1.0 ); - vec4 i1 = clamp( i0-2.0, 0.0, 1.0 ); - - // x0 = x0 - 0.0 + 0.0 * C - vec4 x1 = x0 - i1 + 1.0 * C.xxxx; - vec4 x2 = x0 - i2 + 2.0 * C.xxxx; - vec4 x3 = x0 - i3 + 3.0 * C.xxxx; - vec4 x4 = x0 - 1.0 + 4.0 * C.xxxx; - -// Permutations - i = mod(i, 289.0); - float j0 = permute( permute( permute( permute(i.w) + i.z) + i.y) + i.x); - vec4 j1 = permute( permute( permute( permute ( - i.w + vec4(i1.w, i2.w, i3.w, 1.0 )) - + i.z + vec4(i1.z, i2.z, i3.z, 1.0 )) - + i.y + vec4(i1.y, i2.y, i3.y, 1.0 )) - + i.x + vec4(i1.x, i2.x, i3.x, 1.0 )); -// Gradients -// ( 7*7*6 points uniformly over a cube, mapped onto a 4-octahedron.) -// 7*7*6 = 294, which is close to the ring size 17*17 = 289. - - vec4 ip = vec4(1.0/294.0, 1.0/49.0, 1.0/7.0, 0.0) ; - - vec4 p0 = grad4(j0, ip); - vec4 p1 = grad4(j1.x, ip); - vec4 p2 = grad4(j1.y, ip); - vec4 p3 = grad4(j1.z, ip); - vec4 p4 = grad4(j1.w, ip); - -// Normalise gradients - vec4 norm = taylorInvSqrt(vec4(dot(p0,p0), dot(p1,p1), dot(p2, p2), dot(p3,p3))); - p0 *= norm.x; - p1 *= norm.y; - p2 *= norm.z; - p3 *= norm.w; - p4 *= taylorInvSqrt(dot(p4,p4)); - -// Mix contributions from the five corners - vec3 m0 = max(0.6 - vec3(dot(x0,x0), dot(x1,x1), dot(x2,x2)), 0.0); - vec2 m1 = max(0.6 - vec2(dot(x3,x3), dot(x4,x4) ), 0.0); - m0 = m0 * m0; - m1 = m1 * m1; - return 49.0 * ( dot(m0*m0, vec3( dot( p0, x0 ), dot( p1, x1 ), dot( p2, x2 ))) - + dot(m1*m1, vec2( dot( p3, x3 ), dot( p4, x4 ) ) ) ) ; - +float snoise(in vec4 x) { + vec4 p = floor(x); + vec4 f = fract(x); + f = f * f * (3.0 - 2.0 * f); + return mix( + mix( + mix( + mix(hash(p + vec4(0,0,0,0)), hash(p + vec4(1,0,0,0)), f.x), + mix(hash(p + vec4(0,1,0,0)), hash(p + vec4(1,1,0,0)), f.x), + f.y), + mix( + mix(hash(p + vec4(0,0,1,0)), hash(p + vec4(1,0,1,0)), f.x), + mix(hash(p + vec4(0,1,1,0)), hash(p + vec4(1,1,1,0)), f.x), + f.y), + f.z), + mix( + mix( + mix(hash(p + vec4(0,0,0,1)), hash(p + vec4(1,0,0,1)), f.x), + mix(hash(p + vec4(0,1,0,1)), hash(p + vec4(1,1,0,1)), f.x), + f.y), + mix( + mix(hash(p + vec4(0,0,1,1)), hash(p + vec4(1,0,1,1)), f.x), + mix(hash(p + vec4(0,1,1,1)), hash(p + vec4(1,1,1,1)), f.x), + f.y), + f.z), + f.w); } vec3 rand_perm_3(vec3 pos) { diff --git a/voxygen/src/render/renderer.rs b/voxygen/src/render/renderer.rs index a445dea895..e862da5a29 100644 --- a/voxygen/src/render/renderer.rs +++ b/voxygen/src/render/renderer.rs @@ -81,8 +81,14 @@ impl Renderer { ) -> Result { let mut shader_reload_indicator = ReloadIndicator::new(); - let (skybox_pipeline, figure_pipeline, terrain_pipeline, fluid_pipeline, ui_pipeline, postprocess_pipeline) = - create_pipelines(&mut factory, &mut shader_reload_indicator)?; + let ( + skybox_pipeline, + figure_pipeline, + terrain_pipeline, + fluid_pipeline, + ui_pipeline, + postprocess_pipeline, + ) = create_pipelines(&mut factory, &mut shader_reload_indicator)?; let dims = win_color_view.get_dimensions(); let (tgt_color_view, tgt_depth_view, tgt_color_res) = diff --git a/world/src/block/mod.rs b/world/src/block/mod.rs index a8251bfb93..af8b907f9a 100644 --- a/world/src/block/mod.rs +++ b/world/src/block/mod.rs @@ -472,8 +472,12 @@ fn block_from_structure( StructureBlock::None => None, StructureBlock::TemperateLeaves => Some(Block::new( BlockKind::Normal, - Lerp::lerp(Rgb::new(0.0, 132.0, 94.0), Rgb::new(142.0, 181.0, 0.0), lerp) - .map(|e| e as u8), + Lerp::lerp( + Rgb::new(0.0, 132.0, 94.0), + Rgb::new(142.0, 181.0, 0.0), + lerp, + ) + .map(|e| e as u8), )), StructureBlock::PineLeaves => Some(Block::new( BlockKind::Normal, @@ -482,15 +486,23 @@ fn block_from_structure( )), StructureBlock::PalmLeaves => Some(Block::new( BlockKind::Normal, - Lerp::lerp(Rgb::new(0.0, 108.0, 113.0), Rgb::new(30.0, 156.0, 10.0), lerp) - .map(|e| e as u8), + Lerp::lerp( + Rgb::new(0.0, 108.0, 113.0), + Rgb::new(30.0, 156.0, 10.0), + lerp, + ) + .map(|e| e as u8), )), StructureBlock::Water => Some(Block::new(BlockKind::Water, Rgb::new(100, 150, 255))), StructureBlock::GreenSludge => Some(Block::new(BlockKind::Water, Rgb::new(30, 126, 23))), StructureBlock::Acacia => Some(Block::new( BlockKind::Normal, - Lerp::lerp(Rgb::new(35.0, 156.0, 0.0), Rgb::new(62.0, 208.0, 0.0), lerp) - .map(|e| e as u8), + Lerp::lerp( + Rgb::new(15.0, 126.0, 50.0), + Rgb::new(30.0, 180.0, 10.0), + lerp, + ) + .map(|e| e as u8), )), StructureBlock::Fruit => Some(Block::new( BlockKind::Normal, From 749ec15bf9b237284bdb6f924fc880fb6e6c3b6d Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Sat, 17 Aug 2019 23:20:07 +0100 Subject: [PATCH 14/15] Cleanup, comments --- assets/voxygen/shaders/fluid-frag.glsl | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/assets/voxygen/shaders/fluid-frag.glsl b/assets/voxygen/shaders/fluid-frag.glsl index f4cbade5fa..8d060ca3da 100644 --- a/assets/voxygen/shaders/fluid-frag.glsl +++ b/assets/voxygen/shaders/fluid-frag.glsl @@ -18,31 +18,39 @@ out vec4 tgt_color; #include #include +vec3 warp_normal(vec3 norm, vec3 pos, float time) { + return normalize(norm + + smooth_rand(pos * 1.0, time * 1.0) * 0.05 + + smooth_rand(pos * 0.25, time * 0.25) * 0.1); +} + void main() { /* + // Round the position to the nearest triangular grid cell vec3 hex_pos = f_pos * 2.0; hex_pos = hex_pos + vec3(hex_pos.y * 1.4 / 3.0, hex_pos.y * 0.1, 0); if (fract(hex_pos.x) > fract(hex_pos.y)) { hex_pos += vec3(1.0, 1.0, 0); } - hex_pos = f_pos;//floor(hex_pos); + hex_pos = floor(hex_pos); */ - vec3 warped_norm = normalize(f_norm - + smooth_rand(f_pos * 1.0, tick.x * 1.0) * 0.05 - + smooth_rand(f_pos * 0.25, tick.x * 0.25) * 0.1); + vec3 norm = warp_normal(f_norm, f_pos, tick.x); - vec3 light = get_sun_diffuse(warped_norm, time_of_day.x) * f_light + light_at(f_pos, warped_norm); + vec3 light = get_sun_diffuse(norm, time_of_day.x) * f_light + light_at(f_pos, norm); vec3 surf_color = f_col * light; float fog_level = fog(f_pos.xyz, focus_pos.xyz, medium.x); vec3 fog_color = get_sky_color(normalize(f_pos - cam_pos.xyz), time_of_day.x); vec3 cam_to_frag = normalize(f_pos - cam_pos.xyz); - vec3 reflect_ray_dir = reflect(cam_to_frag, warped_norm); + vec3 reflect_ray_dir = reflect(cam_to_frag, norm); + // Hack to prevent the reflection ray dipping below the horizon and creating weird blue spots in the water reflect_ray_dir.z = max(reflect_ray_dir.z, 0.05); + vec3 reflect_color = get_sky_color(reflect_ray_dir, time_of_day.x) * f_light; - float passthrough = pow(dot(faceforward(warped_norm, warped_norm, cam_to_frag), -cam_to_frag), 1.0); + // 0 = 100% reflection, 1 = translucent water + float passthrough = pow(dot(faceforward(norm, norm, cam_to_frag), -cam_to_frag), 1.0); vec4 color = mix(vec4(reflect_color, 1.0), vec4(surf_color, 0.5 / (1.0 + light * 2.0)), passthrough); From 49426565dc5942f820615b3c9702bebb76f8f4db Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Sun, 18 Aug 2019 15:33:16 +0100 Subject: [PATCH 15/15] Renamed normal StructureBlock variant --- common/src/terrain/structure.rs | 6 +++--- world/src/block/mod.rs | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/common/src/terrain/structure.rs b/common/src/terrain/structure.rs index 338ab6e6d7..9225df4b16 100644 --- a/common/src/terrain/structure.rs +++ b/common/src/terrain/structure.rs @@ -20,7 +20,7 @@ pub enum StructureBlock { GreenSludge, Fruit, Hollow, - Block(Rgb), + Normal(Rgb), } impl Vox for StructureBlock { @@ -30,7 +30,7 @@ impl Vox for StructureBlock { fn is_empty(&self) -> bool { match self { - StructureBlock::Block(block) => block.is_empty(), + StructureBlock::None => true, _ => false, } } @@ -118,7 +118,7 @@ impl Asset for Structure { .get(index as usize) .copied() .unwrap_or_else(|| Rgb::broadcast(0)); - StructureBlock::Block(color) + StructureBlock::Normal(color) } }; diff --git a/world/src/block/mod.rs b/world/src/block/mod.rs index af8b907f9a..ea166d4e93 100644 --- a/world/src/block/mod.rs +++ b/world/src/block/mod.rs @@ -510,7 +510,7 @@ fn block_from_structure( .map(|e| e as u8), )), StructureBlock::Hollow => Some(Block::empty()), - StructureBlock::Block(color) => { + StructureBlock::Normal(color) => { Some(Block::new(default_kind, color)).filter(|block| !block.is_empty()) } }