From faa3664559bc7fd4ff843d814e28f0b166f1d86f Mon Sep 17 00:00:00 2001 From: Luc Fauvel Date: Mon, 5 Aug 2019 22:50:49 -0400 Subject: [PATCH] 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))?;