From fe6cf0396f5f0f663f46a516c610789d7a78d87b Mon Sep 17 00:00:00 2001 From: Imbris Date: Mon, 7 Dec 2020 01:18:19 -0500 Subject: [PATCH] Draw water --- voxygen/src/render/mod.rs | 2 +- voxygen/src/render/pipelines/fluid.rs | 26 ++++++++++++- voxygen/src/render/pipelines/mod.rs | 3 +- voxygen/src/render/renderer/binding.rs | 8 +++- voxygen/src/render/renderer/drawer.rs | 51 ++++++++++++++----------- voxygen/src/scene/mod.rs | 10 ++--- voxygen/src/scene/terrain.rs | 53 ++++++++++++-------------- 7 files changed, 91 insertions(+), 62 deletions(-) diff --git a/voxygen/src/render/mod.rs b/voxygen/src/render/mod.rs index 7a8440d44d..1a8e6df8d5 100644 --- a/voxygen/src/render/mod.rs +++ b/voxygen/src/render/mod.rs @@ -24,7 +24,7 @@ pub use self::{ BoneData as FigureBoneData, BoneMeshes, FigureLayout, FigureModel, Locals as FigureLocals, }, - fluid::Vertex as FluidVertex, + fluid::{BindGroup as FluidWaves, Vertex as FluidVertex}, lod_terrain::{LodData, Vertex as LodTerrainVertex}, particle::{Instance as ParticleInstance, Vertex as ParticleVertex}, postprocess::Locals as PostProcessLocals, diff --git a/voxygen/src/render/pipelines/fluid.rs b/voxygen/src/render/pipelines/fluid.rs index a1cb89fd92..0444737eaa 100644 --- a/voxygen/src/render/pipelines/fluid.rs +++ b/voxygen/src/render/pipelines/fluid.rs @@ -1,4 +1,4 @@ -use super::super::{AaMode, GlobalsLayouts, TerrainLayout}; +use super::super::{AaMode, GlobalsLayouts, TerrainLayout, Texture}; use bytemuck::{Pod, Zeroable}; use vek::*; @@ -43,6 +43,11 @@ impl Vertex { } } +pub struct BindGroup { + pub(in super::super) bind_group: wgpu::BindGroup, + waves: Texture, +} + pub struct FluidLayout { pub waves: wgpu::BindGroupLayout, } @@ -76,6 +81,25 @@ impl FluidLayout { }), } } + + pub fn bind(&self, device: &wgpu::Device, waves: Texture) -> BindGroup { + let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor { + label: None, + layout: &self.waves, + entries: &[ + wgpu::BindGroupEntry { + binding: 0, + resource: wgpu::BindingResource::TextureView(&waves.view), + }, + wgpu::BindGroupEntry { + binding: 1, + resource: wgpu::BindingResource::Sampler(&waves.sampler), + }, + ], + }); + + BindGroup { bind_group, waves } + } } pub struct FluidPipeline { diff --git a/voxygen/src/render/pipelines/mod.rs b/voxygen/src/render/pipelines/mod.rs index 05f07c80f8..5fcc628103 100644 --- a/voxygen/src/render/pipelines/mod.rs +++ b/voxygen/src/render/pipelines/mod.rs @@ -15,7 +15,6 @@ use crate::scene::camera::CameraMode; use bytemuck::{Pod, Zeroable}; use common::terrain::BlockKind; use vek::*; -use wgpu::BindGroup; pub const MAX_POINT_LIGHT_COUNT: usize = 31; pub const MAX_FIGURE_SHADOW_COUNT: usize = 24; @@ -243,7 +242,7 @@ pub struct GlobalsLayouts { } pub struct ColLights { - pub bind_group: BindGroup, + pub bind_group: wgpu::BindGroup, pub texture: Texture, phantom: std::marker::PhantomData, } diff --git a/voxygen/src/render/renderer/binding.rs b/voxygen/src/render/renderer/binding.rs index 9469e4c78b..0f1c70a426 100644 --- a/voxygen/src/render/renderer/binding.rs +++ b/voxygen/src/render/renderer/binding.rs @@ -1,7 +1,9 @@ use super::{ super::{ consts::Consts, - pipelines::{figure, lod_terrain, terrain, ui, ColLights, GlobalModel, GlobalsBindGroup}, + pipelines::{ + figure, fluid, lod_terrain, terrain, ui, ColLights, GlobalModel, GlobalsBindGroup, + }, texture::Texture, }, Renderer, @@ -64,4 +66,8 @@ impl Renderer { pub fn terrain_bind_col_light(&self, col_light: Texture) -> ColLights { self.layouts.global.bind_col_light(&self.device, col_light) } + + pub fn fluid_bind_waves(&self, texture: Texture) -> fluid::BindGroup { + self.layouts.fluid.bind(&self.device, texture) + } } diff --git a/voxygen/src/render/renderer/drawer.rs b/voxygen/src/render/renderer/drawer.rs index c30edb025b..ca7a09888b 100644 --- a/voxygen/src/render/renderer/drawer.rs +++ b/voxygen/src/render/renderer/drawer.rs @@ -181,28 +181,16 @@ impl<'a> FirstPassDrawer<'a> { self.render_pass.draw(0..model.len() as u32, 0..1) } - /*pub fn draw_fluid<'b: 'a>( - &mut self, - model: &'b Model, - locals: &'b Consts, - waves: &'b Consts, - globals: &'b Consts, - lights: &'b Consts, - shadows: &'b Consts, - verts: Range, - ) { + pub fn draw_particles(&mut self) -> ParticleDrawer<'_, 'a> { self.render_pass - .set_pipeline(&self.renderer.fluid_pipeline.pipeline); - self.render_pass.set_bind_group(0, &globals.bind_group, &[]); - self.render_pass.set_bind_group(1, &lights.bind_group, &[]); - self.render_pass.set_bind_group(2, &shadows.bind_group, &[]); - self.render_pass.set_bind_group(3, &locals.bind_group, &[]); - self.render_pass.set_bind_group(4, &waves.bind_group, &[]); - self.render_pass.set_vertex_buffer(0, &model.vbuf, 0, 0); - self.render_pass.draw(verts, 0..1); + .set_pipeline(&self.renderer.particle_pipeline.pipeline); + + ParticleDrawer { + render_pass: &mut self.render_pass, + } } - pub fn draw_sprite<'b: 'a>( + /*pub fn draw_sprite<'b: 'a>( &mut self, model: &'b Model, instances: &'a Instances, @@ -221,11 +209,12 @@ impl<'a> FirstPassDrawer<'a> { self.render_pass.draw(verts, 0..instances.count() as u32); }*/ - pub fn draw_particles<'c>(&'c mut self) -> ParticleDrawer<'c, 'a> { + pub fn draw_fluid<'b: 'a>(&mut self, waves: &'b fluid::BindGroup) -> FluidDrawer<'_, 'a> { self.render_pass - .set_pipeline(&self.renderer.particle_pipeline.pipeline); + .set_pipeline(&self.renderer.fluid_pipeline.pipeline); + self.render_pass.set_bind_group(1, &waves.bind_group, &[]); - ParticleDrawer { + FluidDrawer { render_pass: &mut self.render_pass, } } @@ -236,7 +225,7 @@ pub struct ParticleDrawer<'pass_ref, 'pass: 'pass_ref> { } impl<'pass_ref, 'pass: 'pass_ref> ParticleDrawer<'pass_ref, 'pass> { - // Note: if we ever need to draw less than the whole model, this api can be + // Note: if we ever need to draw less than the whole model, these APIs can be // changed pub fn draw<'data: 'pass>( &mut self, @@ -252,6 +241,22 @@ impl<'pass_ref, 'pass: 'pass_ref> ParticleDrawer<'pass_ref, 'pass> { } } +pub struct FluidDrawer<'pass_ref, 'pass: 'pass_ref> { + render_pass: &'pass_ref mut wgpu::RenderPass<'pass>, +} + +impl<'pass_ref, 'pass: 'pass_ref> FluidDrawer<'pass_ref, 'pass> { + pub fn draw<'data: 'pass>( + &mut self, + model: &'data Model, + locals: &'data terrain::BoundLocals, + ) { + self.render_pass.set_vertex_buffer(0, model.buf().slice(..)); + self.render_pass.set_bind_group(2, &locals.bind_group, &[]); + self.render_pass.draw(0..model.len() as u32, 0..1); + } +} + pub struct SecondPassDrawer<'a> { pub(super) render_pass: wgpu::RenderPass<'a>, pub renderer: &'a Renderer, diff --git a/voxygen/src/scene/mod.rs b/voxygen/src/scene/mod.rs index 960bb2b1e7..839f8aba44 100644 --- a/voxygen/src/scene/mod.rs +++ b/voxygen/src/scene/mod.rs @@ -1020,7 +1020,7 @@ impl Scene { self.figure_mgr .render_player(drawer, state, player_entity, tick, global, lod, camera_data); - self.terrain.render(drawer, global, lod, focus_pos); + self.terrain.render(drawer, focus_pos); /* self.figure_mgr.render( renderer, @@ -1037,14 +1037,12 @@ impl Scene { // Render the skybox. drawer.draw_skybox(&self.skybox.model); - /*self.terrain.render_translucent( - renderer, - global, - lod, + self.terrain.render_translucent( + drawer, focus_pos, cam_pos, scene_data.sprite_render_distance, - );*/ + ); // Render particle effects. self.particle_mgr diff --git a/voxygen/src/scene/terrain.rs b/voxygen/src/scene/terrain.rs index 464bebe223..8d34f2f4ad 100644 --- a/voxygen/src/scene/terrain.rs +++ b/voxygen/src/scene/terrain.rs @@ -9,9 +9,9 @@ use crate::{ }, render::{ pipelines::{self, ColLights}, - ColLightInfo, Consts, FirstPassDrawer, FluidVertex, GlobalModel, Instances, LodData, Mesh, - Model, RenderError, Renderer, SpriteInstance, SpriteLocals, SpriteVertex, TerrainLocals, - TerrainVertex, Texture, + ColLightInfo, Consts, FirstPassDrawer, FluidVertex, FluidWaves, GlobalModel, Instances, + LodData, Mesh, Model, RenderError, Renderer, SpriteInstance, SpriteLocals, SpriteVertex, + TerrainLocals, TerrainVertex, Texture, }, }; @@ -332,7 +332,7 @@ pub struct Terrain { /// for any particular chunk; look at the `texture` field in /// `TerrainChunkData` for that. col_lights: ColLights, - waves: Texture, + waves: FluidWaves, phantom: PhantomData, } @@ -564,13 +564,17 @@ impl Terrain { mesh_recv_overflow: 0.0, sprite_data: sprite_render_context.sprite_data, sprite_col_lights: sprite_render_context.sprite_col_lights, - waves: renderer - .create_texture( - &assets::Image::load_expect("voxygen.texture.waves").read().0, - Some(wgpu::FilterMode::Linear), - Some(wgpu::AddressMode::Repeat), - ) - .expect("Failed to create wave texture"), + waves: { + let waves_tex = renderer + .create_texture( + &assets::Image::load_expect("voxygen.texture.waves").read().0, + Some(wgpu::FilterMode::Linear), + Some(wgpu::AddressMode::Repeat), + ) + .expect("Failed to create wave texture"); + + renderer.fluid_bind_waves(waves_tex) + }, col_lights, phantom: PhantomData, } @@ -1454,13 +1458,7 @@ impl Terrain { }); } - pub fn render<'a>( - &'a self, - drawer: &mut FirstPassDrawer<'a>, - global: &GlobalModel, - lod: &LodData, - focus_pos: Vec3, - ) { + pub fn render<'a>(&'a self, drawer: &mut FirstPassDrawer<'a>, focus_pos: Vec3) { span!(_guard, "render", "Terrain::render"); let focus_chunk = Vec2::from(focus_pos).map2(TerrainChunk::RECT_SIZE, |e: f32, sz| { (e as i32).div_euclid(sz as i32) @@ -1480,11 +1478,9 @@ impl Terrain { } } - pub fn render_translucent( - &self, - renderer: &mut Renderer, - global: &GlobalModel, - lod: &LodData, + pub fn render_translucent<'a>( + &'a self, + drawer: &mut FirstPassDrawer<'a>, focus_pos: Vec3, cam_pos: Vec3, sprite_render_distance: f32, @@ -1566,6 +1562,8 @@ impl Terrain { drop(guard); // Translucent + span!(guard, "Fluid chunks"); + let mut fluid_drawer = drawer.draw_fluid(&self.waves); chunk_iter .clone() .filter(|(_, chunk)| chunk.visible.is_visible()) @@ -1579,13 +1577,12 @@ impl Terrain { .into_iter() .rev() // Render back-to-front .for_each(|(model, locals)| { - /*renderer.render_fluid_chunk( + fluid_drawer.draw( model, - global, locals, - lod, - &self.waves, - )*/ + ) }); + drop(fluid_drawer); + drop(guard); } }