From d6062dc8548c5841c2fc49b7b7a6cf384887fa6b Mon Sep 17 00:00:00 2001 From: Capucho Date: Sun, 6 Dec 2020 17:04:46 +0000 Subject: [PATCH] Reenable terrain rendering Refractor col lights --- assets/voxygen/shaders/terrain-frag.glsl | 4 +- voxygen/src/menu/char_selection/mod.rs | 8 ++- voxygen/src/render/model.rs | 5 +- voxygen/src/render/pipelines/figure.rs | 57 +++------------------ voxygen/src/render/pipelines/fluid.rs | 5 +- voxygen/src/render/pipelines/mod.rs | 63 +++++++++++++++++++++++- voxygen/src/render/pipelines/terrain.rs | 42 ++++++++-------- voxygen/src/render/renderer/binding.rs | 18 +++++-- voxygen/src/render/renderer/drawer.rs | 20 ++++---- voxygen/src/scene/figure/mod.rs | 13 ++--- voxygen/src/scene/mod.rs | 16 ++---- voxygen/src/scene/terrain.rs | 34 ++++++------- 12 files changed, 157 insertions(+), 128 deletions(-) diff --git a/assets/voxygen/shaders/terrain-frag.glsl b/assets/voxygen/shaders/terrain-frag.glsl index aaf7d5cacb..69a549cc88 100644 --- a/assets/voxygen/shaders/terrain-frag.glsl +++ b/assets/voxygen/shaders/terrain-frag.glsl @@ -45,9 +45,9 @@ in vec4 sun_pos; const vec4 sun_pos = vec4(0.0); #endif */ -layout(set = 1, binding = 1) +layout(set = 2, binding = 0) uniform texture2D t_col_light; -layout(set = 1, binding = 2) +layout(set = 2, binding = 1) uniform sampler s_col_light; layout (std140, set = 1, binding = 0) diff --git a/voxygen/src/menu/char_selection/mod.rs b/voxygen/src/menu/char_selection/mod.rs index f2c87987b1..4f8ee4cc95 100644 --- a/voxygen/src/menu/char_selection/mod.rs +++ b/voxygen/src/menu/char_selection/mod.rs @@ -237,8 +237,12 @@ impl PlayState for CharSelectionState { let (humanoid_body, loadout) = Self::get_humanoid_body_inventory(&self.char_selection_ui, &client); - self.scene - .render(&mut drawer.first_pass(), client.get_tick(), humanoid_body, loadout); + self.scene.render( + &mut drawer.first_pass(), + client.get_tick(), + humanoid_body, + loadout, + ); // Clouds drawer.second_pass().draw_clouds(); diff --git a/voxygen/src/render/model.rs b/voxygen/src/render/model.rs index 8540c8c361..8f800f6df6 100644 --- a/voxygen/src/render/model.rs +++ b/voxygen/src/render/model.rs @@ -13,7 +13,10 @@ pub struct SubModel<'a, V: Vertex> { } impl<'a, V: Vertex> SubModel<'a, V> { - pub(super) fn buf(&self) -> wgpu::BufferSlice<'a> { self.buf.slice(map_range(&self.vertex_range)) } + pub(super) fn buf(&self) -> wgpu::BufferSlice<'a> { + self.buf.slice(map_range(&self.vertex_range)) + } + pub fn len(&self) -> u32 { self.vertex_range.end - self.vertex_range.start } } diff --git a/voxygen/src/render/pipelines/figure.rs b/voxygen/src/render/pipelines/figure.rs index e8f26c6fe6..e5b2db70d5 100644 --- a/voxygen/src/render/pipelines/figure.rs +++ b/voxygen/src/render/pipelines/figure.rs @@ -1,5 +1,5 @@ use super::{ - super::{AaMode, Bound, Consts, GlobalsLayouts, Mesh, Model, Texture}, + super::{AaMode, Bound, Consts, GlobalsLayouts, Mesh, Model}, terrain::Vertex, }; use crate::mesh::greedy::GreedyMesh; @@ -26,7 +26,6 @@ pub struct BoneData { } pub type BoundLocals = Bound<(Consts, Consts)>; -pub type ColLights = Bound; impl Locals { pub fn new( @@ -102,7 +101,6 @@ pub type BoneMeshes = (Mesh, anim::vek::Aabb); pub struct FigureLayout { pub locals: wgpu::BindGroupLayout, - pub col_light: wgpu::BindGroupLayout, } impl FigureLayout { @@ -135,31 +133,6 @@ impl FigureLayout { }, ], }), - col_light: device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { - label: None, - entries: &[ - // col lights - wgpu::BindGroupLayoutEntry { - binding: 0, - visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, - ty: wgpu::BindingType::Texture { - sample_type: wgpu::TextureSampleType::Float { filterable: true }, - view_dimension: wgpu::TextureViewDimension::D2, - multisampled: false, - }, - count: None, - }, - wgpu::BindGroupLayoutEntry { - binding: 1, - visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, - ty: wgpu::BindingType::Sampler { - filtering: true, - comparison: false, - }, - count: None, - }, - ], - }), } } @@ -189,28 +162,6 @@ impl FigureLayout { with: (locals, bone_data), } } - - pub fn bind_texture(&self, device: &wgpu::Device, col_light: Texture) -> ColLights { - let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor { - label: None, - layout: &self.col_light, - entries: &[ - wgpu::BindGroupEntry { - binding: 0, - resource: wgpu::BindingResource::TextureView(&col_light.view), - }, - wgpu::BindGroupEntry { - binding: 1, - resource: wgpu::BindingResource::Sampler(&col_light.sampler), - }, - ], - }); - - ColLights { - bind_group, - with: col_light, - } - } } pub struct FigurePipeline { @@ -232,7 +183,11 @@ impl FigurePipeline { device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { label: Some("Figure pipeline layout"), push_constant_ranges: &[], - bind_group_layouts: &[&global_layout.globals, &layout.locals, &layout.col_light], + bind_group_layouts: &[ + &global_layout.globals, + &layout.locals, + &global_layout.col_light, + ], }); let samples = match aa_mode { diff --git a/voxygen/src/render/pipelines/fluid.rs b/voxygen/src/render/pipelines/fluid.rs index e5d2df4376..a1cb89fd92 100644 --- a/voxygen/src/render/pipelines/fluid.rs +++ b/voxygen/src/render/pipelines/fluid.rs @@ -66,7 +66,10 @@ impl FluidLayout { wgpu::BindGroupLayoutEntry { binding: 1, visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, - ty: wgpu::BindingType::Sampler { filtering: true, comparison: false }, + ty: wgpu::BindingType::Sampler { + filtering: true, + comparison: false, + }, count: None, }, ], diff --git a/voxygen/src/render/pipelines/mod.rs b/voxygen/src/render/pipelines/mod.rs index 2d6f12bac0..1c3a49a6e2 100644 --- a/voxygen/src/render/pipelines/mod.rs +++ b/voxygen/src/render/pipelines/mod.rs @@ -15,6 +15,7 @@ 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; @@ -231,6 +232,13 @@ pub struct GlobalsBindGroup { pub struct GlobalsLayouts { pub globals: wgpu::BindGroupLayout, + pub col_light: wgpu::BindGroupLayout, +} + +pub struct ColLights { + pub bind_group: BindGroup, + pub texture: Texture, + phantom: std::marker::PhantomData, } impl GlobalsLayouts { @@ -406,7 +414,33 @@ impl GlobalsLayouts { ], }); - Self { globals } + let col_light = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { + label: None, + entries: &[ + // col lights + wgpu::BindGroupLayoutEntry { + binding: 0, + visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, + ty: wgpu::BindingType::Texture { + sample_type: wgpu::TextureSampleType::Float { filterable: true }, + view_dimension: wgpu::TextureViewDimension::D2, + multisampled: false, + }, + count: None, + }, + wgpu::BindGroupLayoutEntry { + binding: 1, + visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, + ty: wgpu::BindingType::Sampler { + filtering: true, + comparison: false, + }, + count: None, + }, + ], + }); + + Self { globals, col_light } } pub fn bind( @@ -500,4 +534,31 @@ impl GlobalsLayouts { GlobalsBindGroup { bind_group } } + + pub fn bind_col_light( + &self, + device: &wgpu::Device, + col_light: Texture, + ) -> ColLights { + let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor { + label: None, + layout: &self.col_light, + entries: &[ + wgpu::BindGroupEntry { + binding: 0, + resource: wgpu::BindingResource::TextureView(&col_light.view), + }, + wgpu::BindGroupEntry { + binding: 1, + resource: wgpu::BindingResource::Sampler(&col_light.sampler), + }, + ], + }); + + ColLights { + texture: col_light, + bind_group, + phantom: std::marker::PhantomData, + } + } } diff --git a/voxygen/src/render/pipelines/terrain.rs b/voxygen/src/render/pipelines/terrain.rs index 7f5ae1ab6d..a293a84486 100644 --- a/voxygen/src/render/pipelines/terrain.rs +++ b/voxygen/src/render/pipelines/terrain.rs @@ -172,30 +172,26 @@ impl TerrainLayout { }, count: None, }, - // col lights - wgpu::BindGroupLayoutEntry { - binding: 1, - visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, - ty: wgpu::BindingType::Texture { - sample_type: wgpu::TextureSampleType::Float { filterable: true }, - view_dimension: wgpu::TextureViewDimension::D2, - multisampled: false, - }, - count: None, - }, - wgpu::BindGroupLayoutEntry { - binding: 2, - visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, - ty: wgpu::BindingType::Sampler { - filtering: true, - comparison: false, - }, - count: None, - }, ], }), } } + + pub fn bind_locals(&self, device: &wgpu::Device, locals: Consts) -> BoundLocals { + let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor { + label: None, + layout: &self.locals, + entries: &[wgpu::BindGroupEntry { + binding: 0, + resource: locals.buf().as_entire_binding(), + }], + }); + + BoundLocals { + bind_group, + with: locals, + } + } } pub struct TerrainPipeline { @@ -217,7 +213,11 @@ impl TerrainPipeline { device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { label: Some("Terrain pipeline layout"), push_constant_ranges: &[], - bind_group_layouts: &[&global_layout.globals, &layout.locals], + bind_group_layouts: &[ + &global_layout.globals, + &layout.locals, + &global_layout.col_light, + ], }); let samples = match aa_mode { diff --git a/voxygen/src/render/renderer/binding.rs b/voxygen/src/render/renderer/binding.rs index 58e3526d5d..4825b4a058 100644 --- a/voxygen/src/render/renderer/binding.rs +++ b/voxygen/src/render/renderer/binding.rs @@ -1,7 +1,7 @@ use super::{ super::{ consts::Consts, - pipelines::{figure, lod_terrain, ui, GlobalModel, GlobalsBindGroup}, + pipelines::{figure, lod_terrain, terrain, ui, ColLights, GlobalModel, GlobalsBindGroup}, texture::Texture, }, Renderer, @@ -49,7 +49,19 @@ impl Renderer { .bind_locals(&self.device, locals, bone_data) } - pub fn figure_bind_texture(&self, col_light: Texture) -> figure::ColLights { - self.layouts.figure.bind_texture(&self.device, col_light) + pub fn create_terrain_bound_locals( + &mut self, + locals: &[terrain::Locals], + ) -> terrain::BoundLocals { + let locals = self.create_consts(locals); + self.layouts.terrain.bind_locals(&self.device, locals) + } + + pub fn figure_bind_col_light(&self, col_light: Texture) -> ColLights { + self.layouts.global.bind_col_light(&self.device, col_light) + } + + pub fn terrain_bind_col_light(&self, col_light: Texture) -> ColLights { + self.layouts.global.bind_col_light(&self.device, col_light) } } diff --git a/voxygen/src/render/renderer/drawer.rs b/voxygen/src/render/renderer/drawer.rs index 2a4f81395b..0bdc3086b1 100644 --- a/voxygen/src/render/renderer/drawer.rs +++ b/voxygen/src/render/renderer/drawer.rs @@ -3,10 +3,10 @@ use super::{ buffer::Buffer, consts::Consts, instances::Instances, - model::{DynamicModel, SubModel,Model}, + model::{DynamicModel, Model, SubModel}, pipelines::{ - clouds, figure, fluid, particle, postprocess, sprite, terrain, ui, GlobalsBindGroup, - Light, Shadow, + clouds, figure, fluid, particle, postprocess, sprite, terrain, ui, ColLights, + GlobalsBindGroup, Light, Shadow, }, }, Renderer, @@ -154,28 +154,30 @@ impl<'a> FirstPassDrawer<'a> { &mut self, model: SubModel<'b, terrain::Vertex>, locals: &'b figure::BoundLocals, - col_lights: &'b figure::ColLights + col_lights: &'b ColLights, ) { self.render_pass .set_pipeline(&self.renderer.figure_pipeline.pipeline); self.render_pass.set_bind_group(1, &locals.bind_group, &[]); - self.render_pass.set_bind_group(2, &col_lights.bind_group, &[]); self.render_pass - .set_vertex_buffer(0, model.buf()); + .set_bind_group(2, &col_lights.bind_group, &[]); + self.render_pass.set_vertex_buffer(0, model.buf()); self.render_pass.draw(0..model.len(), 0..1); } pub fn draw_terrain<'b: 'a>( &mut self, - model: &'b SubModel, + model: &'b Model, locals: &'b terrain::BoundLocals, + col_lights: &'b ColLights, ) { self.render_pass .set_pipeline(&self.renderer.terrain_pipeline.pipeline); self.render_pass.set_bind_group(1, &locals.bind_group, &[]); self.render_pass - .set_vertex_buffer(0, model.buf()); - self.render_pass.draw(0..model.len(), 0..1) + .set_bind_group(2, &col_lights.bind_group, &[]); + self.render_pass.set_vertex_buffer(0, model.buf().slice(..)); + self.render_pass.draw(0..model.len() as u32, 0..1) } /*pub fn draw_fluid<'b: 'a>( diff --git a/voxygen/src/scene/figure/mod.rs b/voxygen/src/scene/figure/mod.rs index 2de7335d99..da369e501d 100644 --- a/voxygen/src/scene/figure/mod.rs +++ b/voxygen/src/scene/figure/mod.rs @@ -7,8 +7,9 @@ pub use load::load_mesh; // TODO: Don't make this public. use crate::{ ecs::comp::Interpolated, render::{ - pipelines, ColLightInfo, FigureBoneData, FigureLocals, FigureModel, FirstPassDrawer, - GlobalModel, LodData, Mesh, RenderError, Renderer, SubModel, TerrainVertex, + pipelines::{self, ColLights}, + ColLightInfo, FigureBoneData, FigureLocals, FigureModel, FirstPassDrawer, GlobalModel, + LodData, Mesh, RenderError, Renderer, SubModel, TerrainVertex, }, scene::{ camera::{Camera, CameraMode, Dependents}, @@ -63,7 +64,7 @@ pub type CameraData<'a> = (&'a Camera, f32); pub type FigureModelRef<'a> = ( &'a pipelines::figure::BoundLocals, SubModel<'a, TerrainVertex>, - &'a pipelines::figure::ColLights, /* */ + &'a ColLights, ); /// An entry holding enough information to draw or destroy a figure in a @@ -79,7 +80,7 @@ pub struct FigureModelEntry { /// Texture used to store color/light information for this figure entry. /* TODO: Consider using mipmaps instead of storing multiple texture atlases for different * LOD levels. */ - col_lights: pipelines::figure::ColLights, + col_lights: ColLights, /// Vertex ranges stored in this figure entry; there may be several for one /// figure, because of LOD models. lod_vertex_ranges: [Range; N], @@ -5207,7 +5208,7 @@ impl FigureColLights { pub fn texture<'a, const N: usize>( &'a self, model: &'a FigureModelEntry, - ) -> &'a pipelines::figure::ColLights { + ) -> &'a ColLights { /* &self.col_lights */ &model.col_lights } @@ -5231,7 +5232,7 @@ impl FigureColLights { .allocate(guillotiere::Size::new(tex_size.x as i32, tex_size.y as i32)) .expect("Not yet implemented: allocate new atlas on allocation failure."); let col_lights = pipelines::shadow::create_col_lights(renderer, &(tex, tex_size)); - let col_lights = renderer.figure_bind_texture(col_lights); + let col_lights = renderer.figure_bind_col_light(col_lights); let model_len = u32::try_from(opaque.vertices().len()) .expect("The model size for this figure does not fit in a u32!"); let model = renderer.create_model(&opaque)?; diff --git a/voxygen/src/scene/mod.rs b/voxygen/src/scene/mod.rs index a4a3218f4c..553f79a3be 100644 --- a/voxygen/src/scene/mod.rs +++ b/voxygen/src/scene/mod.rs @@ -1017,20 +1017,12 @@ impl Scene { }*/ let lod = self.lod.get_data(); - self.figure_mgr.render_player( - drawer, - state, - player_entity, - tick, - global, - lod, - camera_data, - ); + self.figure_mgr + .render_player(drawer, state, player_entity, tick, global, lod, camera_data); - // Render terrain and figures. - /*self.terrain.render(renderer, global, lod, focus_pos); + self.terrain.render(drawer, global, lod, focus_pos); - self.figure_mgr.render( + /* self.figure_mgr.render( renderer, state, player_entity, diff --git a/voxygen/src/scene/terrain.rs b/voxygen/src/scene/terrain.rs index c3d2136df3..06a5a6fd7d 100644 --- a/voxygen/src/scene/terrain.rs +++ b/voxygen/src/scene/terrain.rs @@ -8,8 +8,9 @@ use crate::{ terrain::{generate_mesh, SUNLIGHT}, }, render::{ - pipelines, ColLightInfo, Consts, FluidVertex, GlobalModel, Instances, LodData, Mesh, Model, - RenderError, Renderer, SpriteInstance, SpriteLocals, SpriteVertex, TerrainLocals, + pipelines::{self, ColLights}, + ColLightInfo, Consts, FirstPassDrawer, FluidVertex, GlobalModel, Instances, LodData, Mesh, + Model, RenderError, Renderer, SpriteInstance, SpriteLocals, SpriteVertex, TerrainLocals, TerrainVertex, Texture, }, }; @@ -75,11 +76,11 @@ pub struct TerrainChunkData { /// shadow chunks will still keep it alive; we could deal with this by /// making this an `Option`, but it probably isn't worth it since they /// shouldn't be that much more nonlocal than regular chunks). - texture: Arc, // TODO: make this actually work with a bind group + col_lights: Arc>, light_map: LightMapFn, glow_map: LightMapFn, sprite_instances: HashMap<(SpriteKind, usize), Instances>, - locals: Consts, + locals: pipelines::terrain::BoundLocals, pub blocks_of_interest: BlocksOfInterest, visible: Visibility, @@ -330,7 +331,7 @@ pub struct Terrain { /// we allocate. Code cannot assume that this is the assigned texture /// for any particular chunk; look at the `texture` field in /// `TerrainChunkData` for that. - col_lights: Texture, /* */ + col_lights: ColLights, waves: Texture, phantom: PhantomData, @@ -577,7 +578,7 @@ impl Terrain { fn make_atlas( renderer: &mut Renderer, - ) -> Result<(AtlasAllocator, Texture /* */), RenderError> { + ) -> Result<(AtlasAllocator, ColLights), RenderError> { span!(_guard, "make_atlas", "Terrain::make_atlas"); let max_texture_size = renderer.max_texture_size(); let atlas_size = guillotiere::Size::new(max_texture_size as i32, max_texture_size as i32); @@ -622,7 +623,8 @@ impl Terrain { ..Default::default() }, ); - Ok((atlas, texture)) + let col_light = renderer.terrain_bind_col_light(texture); + Ok((atlas, col_light)) } fn remove_chunk_meta(&mut self, _pos: Vec2, chunk: &TerrainChunkData) { @@ -1134,7 +1136,7 @@ impl Terrain { allocation.rectangle.min.y as u32, ); renderer.update_texture( - col_lights, + &col_lights, atlas_offs.into_array(), tex_size.into_array(), &tex, @@ -1159,7 +1161,7 @@ impl Terrain { light_map: mesh.light_map, glow_map: mesh.glow_map, sprite_instances, - locals: renderer.create_consts(&[TerrainLocals { + locals: renderer.create_terrain_bound_locals(&[TerrainLocals { model_offs: Vec3::from( response.pos.map2(VolGrid2d::::chunk_size(), |e, sz| { e as f32 * sz as f32 @@ -1452,9 +1454,9 @@ impl Terrain { }); } - pub fn render( - &self, - renderer: &mut Renderer, + pub fn render<'a>( + &'a self, + drawer: &mut FirstPassDrawer<'a>, global: &GlobalModel, lod: &LodData, focus_pos: Vec3, @@ -1473,13 +1475,7 @@ impl Terrain { for (_, chunk) in chunk_iter { if chunk.visible.is_visible() { - /* renderer.render_terrain_chunk( - &chunk.opaque_model, - &chunk.texture, - global, - &chunk.locals, - lod, - );*/ + drawer.draw_terrain(&chunk.opaque_model, &chunk.locals, &self.col_lights) } } }