diff --git a/voxygen/src/render/mod.rs b/voxygen/src/render/mod.rs index 32b42581eb..7a8440d44d 100644 --- a/voxygen/src/render/mod.rs +++ b/voxygen/src/render/mod.rs @@ -40,7 +40,13 @@ pub use self::{ }, GlobalModel, Globals, GlobalsBindGroup, GlobalsLayouts, Light, Shadow, }, - renderer::{ColLightInfo, Drawer, Renderer, UiDrawer}, + renderer::{ + drawer::{ + Drawer, FirstPassDrawer, ParticleDrawer, PreparedUiDrawer, SecondPassDrawer, + ThirdPassDrawer, UiDrawer, + }, + ColLightInfo, Renderer, + }, texture::Texture, }; pub use wgpu::{AddressMode, FilterMode}; diff --git a/voxygen/src/render/pipelines/clouds.rs b/voxygen/src/render/pipelines/clouds.rs index 19905731d3..1fb3b6d90d 100644 --- a/voxygen/src/render/pipelines/clouds.rs +++ b/voxygen/src/render/pipelines/clouds.rs @@ -25,45 +25,6 @@ impl Locals { } } -/*#[repr(C)] -#[derive(Copy, Clone, Debug, Zeroable, Pod)] -pub struct Vertex { - pos: [f32; 2], -} - -impl Vertex { - fn desc<'a>() -> wgpu::VertexBufferDescriptor<'a> { - use std::mem; - const ATTRIBUTES: [wgpu::VertexAttributeDescriptor; 1] = - wgpu::vertex_attr_array![0 => Float2]; - wgpu::VertexBufferDescriptor { - stride: mem::size_of::() as wgpu::BufferAddress, - step_mode: wgpu::InputStepMode::Vertex, - attributes: &ATTRIBUTES, - } - } -} - -pub fn create_mesh() -> Mesh { - let mut mesh = Mesh::new(); - - #[rustfmt::skip] - mesh.push_tri(Tri::new( - Vertex { pos: [ 1.0, -1.0] }, - Vertex { pos: [-1.0, 1.0] }, - Vertex { pos: [-1.0, -1.0] }, - )); - - #[rustfmt::skip] - mesh.push_tri(Tri::new( - Vertex { pos: [1.0, -1.0] }, - Vertex { pos: [1.0, 1.0] }, - Vertex { pos: [-1.0, 1.0] }, - )); - - mesh -}*/ - pub struct BindGroup { pub(in super::super) bind_group: wgpu::BindGroup, } @@ -92,7 +53,10 @@ impl CloudsLayout { 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, }, // Depth source @@ -109,7 +73,10 @@ impl CloudsLayout { wgpu::BindGroupLayoutEntry { binding: 3, 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, }, // Locals diff --git a/voxygen/src/render/pipelines/mod.rs b/voxygen/src/render/pipelines/mod.rs index a0f571b675..2d6f12bac0 100644 --- a/voxygen/src/render/pipelines/mod.rs +++ b/voxygen/src/render/pipelines/mod.rs @@ -349,7 +349,7 @@ impl GlobalsLayouts { visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, ty: wgpu::BindingType::Texture { sample_type: wgpu::TextureSampleType::Float { filterable: true }, - view_dimension: wgpu::TextureViewDimension::D2, + view_dimension: wgpu::TextureViewDimension::Cube, multisampled: false, }, count: None, diff --git a/voxygen/src/render/pipelines/particle.rs b/voxygen/src/render/pipelines/particle.rs index 1da2a71ba6..2e62c748f0 100644 --- a/voxygen/src/render/pipelines/particle.rs +++ b/voxygen/src/render/pipelines/particle.rs @@ -174,7 +174,6 @@ impl ParticlePipeline { device: &wgpu::Device, vs_module: &wgpu::ShaderModule, fs_module: &wgpu::ShaderModule, - sc_desc: &wgpu::SwapChainDescriptor, global_layout: &GlobalsLayouts, aa_mode: AaMode, ) -> Self { @@ -216,7 +215,8 @@ impl ParticlePipeline { }), primitive_topology: wgpu::PrimitiveTopology::TriangleList, color_states: &[wgpu::ColorStateDescriptor { - format: sc_desc.format, + // TODO pass this format in or make it a const + format: wgpu::TextureFormat::Rgba8UnormSrgb, color_blend: wgpu::BlendDescriptor { src_factor: wgpu::BlendFactor::SrcAlpha, dst_factor: wgpu::BlendFactor::OneMinusSrcAlpha, diff --git a/voxygen/src/render/pipelines/postprocess.rs b/voxygen/src/render/pipelines/postprocess.rs index 16d8e6f7de..101517497a 100644 --- a/voxygen/src/render/pipelines/postprocess.rs +++ b/voxygen/src/render/pipelines/postprocess.rs @@ -22,45 +22,6 @@ impl Locals { } } -/*#[repr(C)] -#[derive(Copy, Clone, Debug, Zeroable, Pod)] -pub struct Vertex { - pub pos: [f32; 2], -} - -impl Vertex { - fn desc<'a>() -> wgpu::VertexBufferDescriptor<'a> { - use std::mem; - const ATTRIBUTES: [wgpu::VertexAttributeDescriptor; 1] = - wgpu::vertex_attr_array![0 => Float2]; - wgpu::VertexBufferDescriptor { - stride: mem::size_of::() as wgpu::BufferAddress, - step_mode: wgpu::InputStepMode::Vertex, - attributes: &ATTRIBUTES, - } - } -} - -pub fn create_mesh() -> Mesh { - let mut mesh = Mesh::new(); - - #[rustfmt::skip] - mesh.push_tri(Tri::new( - Vertex { pos: [ 1.0, -1.0] }, - Vertex { pos: [-1.0, 1.0] }, - Vertex { pos: [-1.0, -1.0] }, - )); - - #[rustfmt::skip] - mesh.push_tri(Tri::new( - Vertex { pos: [1.0, -1.0] }, - Vertex { pos: [1.0, 1.0] }, - Vertex { pos: [-1.0, 1.0] }, - )); - - mesh -}*/ - pub struct BindGroup { pub(in super::super) bind_group: wgpu::BindGroup, } @@ -89,7 +50,10 @@ impl PostProcessLayout { 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, }, // Locals diff --git a/voxygen/src/render/renderer.rs b/voxygen/src/render/renderer.rs index d3b6f8954b..9458758626 100644 --- a/voxygen/src/render/renderer.rs +++ b/voxygen/src/render/renderer.rs @@ -1,7 +1,5 @@ mod binding; -mod drawer; - -pub use drawer::{Drawer, UiDrawer}; +pub(super) mod drawer; use super::{ consts::Consts, @@ -172,12 +170,10 @@ impl Locals { sampler, &clouds_locals, ); - let postprocess_bind = layouts.postprocess.bind( - device, - tgt_color_pp_view, - sampler, - &postprocess_locals, - ); + let postprocess_bind = + layouts + .postprocess + .bind(device, tgt_color_pp_view, sampler, &postprocess_locals); Self { clouds: clouds_locals, @@ -203,12 +199,10 @@ impl Locals { sampler, &self.clouds, ); - self.postprocess_bind = layouts.postprocess.bind( - device, - tgt_color_pp_view, - sampler, - &self.postprocess, - ); + self.postprocess_bind = + layouts + .postprocess + .bind(device, tgt_color_pp_view, sampler, &self.postprocess); } } @@ -920,7 +914,7 @@ impl Renderer { pub fn start_recording_frame<'a>( &'a mut self, globals: &'a GlobalsBindGroup, - ) -> Result>, RenderError> { + ) -> Result>, RenderError> { span!( _guard, "start_recording_frame", @@ -958,7 +952,7 @@ impl Renderer { label: Some("A render encoder"), }); - Ok(Some(Drawer::new(encoder, self, tex, globals))) + Ok(Some(drawer::Drawer::new(encoder, self, tex, globals))) } /// Recreate the pipelines @@ -2134,7 +2128,6 @@ fn create_pipelines( device, &create_shader("particle-vert", ShaderKind::Vertex)?, &create_shader("particle-frag", ShaderKind::Fragment)?, - sc_desc, &layouts.global, mode.aa, ); diff --git a/voxygen/src/render/renderer/drawer.rs b/voxygen/src/render/renderer/drawer.rs index 0847f28f26..4812aaa4dd 100644 --- a/voxygen/src/render/renderer/drawer.rs +++ b/voxygen/src/render/renderer/drawer.rs @@ -5,8 +5,8 @@ use super::{ instances::Instances, model::{DynamicModel, Model}, pipelines::{ - clouds, figure, fluid, postprocess, sprite, terrain, ui, GlobalsBindGroup, Light, - Shadow, + clouds, figure, fluid, particle, postprocess, sprite, terrain, ui, GlobalsBindGroup, + Light, Shadow, }, }, Renderer, @@ -19,7 +19,6 @@ pub struct Drawer<'a> { renderer: &'a mut Renderer, tex: wgpu::SwapChainTexture, globals: &'a GlobalsBindGroup, - //pub(super) postprocess_locals: wgpu::BindGroup, } impl<'a> Drawer<'a> { @@ -111,7 +110,7 @@ impl<'a> Drawer<'a> { }, }], // TODO: do we need this? - depth_stencil_attachment: None + depth_stencil_attachment: None, }); render_pass.set_bind_group(0, &self.globals.bind_group, &[]); @@ -231,6 +230,36 @@ impl<'a> FirstPassDrawer<'a> { self.render_pass.set_vertex_buffer(1, &instances.ibuf, 0, 0); self.render_pass.draw(verts, 0..instances.count() as u32); }*/ + + pub fn draw_particles<'c>(&'c mut self) -> ParticleDrawer<'c, 'a> { + self.render_pass + .set_pipeline(&self.renderer.particle_pipeline.pipeline); + + ParticleDrawer { + render_pass: &mut self.render_pass, + } + } +} + +pub struct ParticleDrawer<'pass_ref, 'pass: 'pass_ref> { + render_pass: &'pass_ref mut wgpu::RenderPass<'pass>, +} + +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 + // changed + pub fn draw<'data: 'pass>( + &mut self, + model: &'data Model, + instances: &'data Instances, + ) { + self.render_pass.set_vertex_buffer(0, model.buf().slice(..)); + self.render_pass + .set_vertex_buffer(1, instances.buf().slice(..)); + self.render_pass + // TODO: since we cast to u32 maybe this should returned by the len/count functions? + .draw(0..model.len() as u32, 0..instances.count() as u32); + } } pub struct SecondPassDrawer<'a> { @@ -262,7 +291,7 @@ impl<'a> ThirdPassDrawer<'a> { self.render_pass.draw(0..3, 0..1); } - pub fn draw_ui<'c>(&'c mut self) -> UiDrawer<'c, 'a> { + pub fn draw_ui(&mut self) -> UiDrawer<'_, 'a> { self.render_pass .set_pipeline(&self.renderer.ui_pipeline.pipeline); diff --git a/voxygen/src/scene/camera.rs b/voxygen/src/scene/camera.rs index fc34f8c93b..196ca31e02 100644 --- a/voxygen/src/scene/camera.rs +++ b/voxygen/src/scene/camera.rs @@ -136,7 +136,7 @@ impl Camera { self.dependents.view_mat_inv = self.dependents.view_mat.inverted(); self.dependents.proj_mat = - Mat4::perspective_rh_no(self.fov, self.aspect, NEAR_PLANE, FAR_PLANE); + Mat4::perspective_rh_zo(self.fov, self.aspect, NEAR_PLANE, FAR_PLANE); self.dependents.proj_mat_inv = self.dependents.proj_mat.inverted(); // TODO: Make this more efficient. diff --git a/voxygen/src/scene/mod.rs b/voxygen/src/scene/mod.rs index dce0ab2f9d..a5930db6ff 100644 --- a/voxygen/src/scene/mod.rs +++ b/voxygen/src/scene/mod.rs @@ -16,8 +16,9 @@ pub use self::{ use crate::{ audio::{ambient::AmbientMgr, music::MusicMgr, sfx::SfxMgr, AudioFrontend}, render::{ - create_skybox_mesh, CloudsLocals, Consts, GlobalModel, Globals, GlobalsBindGroup, Light, - Model, PostProcessLocals, Renderer, Shadow, ShadowLocals, SkyboxVertex, + create_skybox_mesh, CloudsLocals, Consts, FirstPassDrawer, GlobalModel, Globals, + GlobalsBindGroup, Light, Model, PostProcessLocals, Renderer, Shadow, ShadowLocals, + SkyboxVertex, }, settings::Settings, window::{AnalogGameInput, Event}, @@ -976,9 +977,9 @@ impl Scene { pub fn global_bind_group(&self) -> &GlobalsBindGroup { &self.globals_bind_group } /// Render the scene using the provided `Renderer`. - pub fn render( - &mut self, - renderer: &mut Renderer, + pub fn render<'a>( + &'a self, + drawer: &mut FirstPassDrawer<'a>, state: &State, player_entity: EcsEntity, tick: u64, @@ -995,7 +996,7 @@ impl Scene { let camera_data = (&self.camera, scene_data.figure_lod_render_distance); // would instead have this as an extension. - if renderer.render_mode().shadow.is_map() && (is_daylight || !light_data.1.is_empty()) { + /*if renderer.render_mode().shadow.is_map() && (is_daylight || !light_data.1.is_empty()) { // if is_daylight { // // Set up shadow mapping. // renderer.start_shadows(); @@ -1013,10 +1014,10 @@ impl Scene { // // Flush shadows. // renderer.flush_shadows(); // } - } + }*/ let lod = self.lod.get_data(); - self.figure_mgr.render_player( + /*self.figure_mgr.render_player( renderer, state, player_entity, @@ -1024,10 +1025,10 @@ impl Scene { global, lod, camera_data, - ); + );*/ // Render terrain and figures. - self.terrain.render(renderer, global, lod, focus_pos); + /*self.terrain.render(renderer, global, lod, focus_pos); self.figure_mgr.render( renderer, @@ -1038,21 +1039,22 @@ impl Scene { lod, camera_data, ); - self.lod.render(renderer, global); + self.lod.render(renderer, global);*/ // Render the skybox. // TODO: renderer.render_skybox(&self.skybox.model, global, lod); - self.terrain.render_translucent( + /*self.terrain.render_translucent( renderer, global, lod, focus_pos, cam_pos, scene_data.sprite_render_distance, - ); + );*/ // Render particle effects. - self.particle_mgr.render(renderer, scene_data, global, lod); + self.particle_mgr + .render(&mut drawer.draw_particles(), scene_data); } } diff --git a/voxygen/src/scene/particle.rs b/voxygen/src/scene/particle.rs index 6fda87dbfb..ce46cecde2 100644 --- a/voxygen/src/scene/particle.rs +++ b/voxygen/src/scene/particle.rs @@ -3,7 +3,7 @@ use crate::{ mesh::{greedy::GreedyMesh, segment::generate_mesh_base_vol_particle}, render::{ pipelines::particle::ParticleMode, GlobalModel, Instances, Light, LodData, Model, - ParticleInstance, ParticleVertex, Renderer, + ParticleDrawer, ParticleInstance, ParticleVertex, Renderer, }, }; use common::{ @@ -1178,13 +1178,7 @@ impl ParticleMgr { self.instances = gpu_instances; } - pub fn render( - &self, - renderer: &mut Renderer, - scene_data: &SceneData, - global: &GlobalModel, - lod: &LodData, - ) { + pub fn render<'a>(&'a self, drawer: &mut ParticleDrawer<'_, 'a>, scene_data: &SceneData) { span!(_guard, "render", "ParticleMgr::render"); if scene_data.particles_enabled { let model = &self @@ -1192,8 +1186,7 @@ impl ParticleMgr { .get(DEFAULT_MODEL_KEY) .expect("Expected particle model in cache"); - /* renderer.render_particles(model, global, &self.instances, - * lod); */ + drawer.draw(model, &self.instances); } } diff --git a/voxygen/src/session/mod.rs b/voxygen/src/session/mod.rs index 539995bd02..b3dcdd5a0a 100644 --- a/voxygen/src/session/mod.rs +++ b/voxygen/src/session/mod.rs @@ -1387,7 +1387,16 @@ impl PlayState for SessionState { /// This method should be called once per frame. fn render(&mut self, renderer: &mut Renderer, settings: &Settings) { span!(_guard, "render", "::render"); - // Render the screen using the global renderer + let mut drawer = match renderer + .start_recording_frame(self.scene.global_bind_group()) + .unwrap() + { + Some(d) => d, + // Couldn't get swap chain texture this frame + None => return, + }; + + // Render world { let client = self.client.borrow(); @@ -1410,7 +1419,7 @@ impl PlayState for SessionState { is_aiming: self.is_aiming, }; self.scene.render( - renderer, + &mut drawer.first_pass(), client.state(), client.entity(), client.get_tick(), @@ -1418,18 +1427,6 @@ impl PlayState for SessionState { ); } - let mut drawer = match renderer - .start_recording_frame(self.scene.global_bind_group()) - .unwrap() - { - Some(d) => d, - // Couldn't get swap chain texture this frame - None => return, - }; - - // Render world - /* let mut first_pass = */ - drawer.first_pass(); // Clouds drawer.second_pass().draw_clouds(); // PostProcess and UI