diff --git a/voxygen/src/render/error.rs b/voxygen/src/render/error.rs index c003634999..874965e9b0 100644 --- a/voxygen/src/render/error.rs +++ b/voxygen/src/render/error.rs @@ -8,7 +8,7 @@ pub enum RenderError { CustomError(String), CouldNotFindAdapter, ErrorInitializingCompiler, - ShaderError(shaderc::Error) + ShaderError(shaderc::Error), } impl From for RenderError { diff --git a/voxygen/src/render/mod.rs b/voxygen/src/render/mod.rs index 90af9e9ef3..11067697ae 100644 --- a/voxygen/src/render/mod.rs +++ b/voxygen/src/render/mod.rs @@ -18,20 +18,23 @@ pub use self::{ model::{Model, SubModel}, pipelines::{ clouds::{create_mesh as create_clouds_mesh, Locals as CloudsLocals}, - figure::{BoneData as FigureBoneData, BoneMeshes, FigureModel, Locals as FigureLocals}, + figure::{ + BoneData as FigureBoneData, BoneMeshes, FigureLayout, FigureModel, + Locals as FigureLocals, + }, lod_terrain::LodData, particle::Instance as ParticleInstance, postprocess::create_mesh as create_pp_mesh, shadow::Locals as ShadowLocals, skybox::create_mesh as create_skybox_mesh, sprite::{Instance as SpriteInstance, Locals as SpriteLocals}, - terrain::Locals as TerrainLocals, + terrain::{Locals as TerrainLocals, TerrainLayout, Vertex as TerrainVertex}, ui::{ create_quad as create_ui_quad, create_quad_vert_gradient as create_ui_quad_vert_gradient, create_tri as create_ui_tri, Locals as UiLocals, Mode as UiMode, }, - GlobalModel, Globals, Light, Shadow, + GlobalModel, Globals, GlobalsLayouts, Light, Shadow, }, renderer::{ColLightInfo, Renderer}, texture::Texture, diff --git a/voxygen/src/render/pipelines/figure.rs b/voxygen/src/render/pipelines/figure.rs index 433d787f46..9b6690f63f 100644 --- a/voxygen/src/render/pipelines/figure.rs +++ b/voxygen/src/render/pipelines/figure.rs @@ -1,5 +1,5 @@ use super::{ - super::{Mesh, Model}, + super::{AaMode, GlobalsLayouts, Mesh, Model}, terrain::Vertex, }; use crate::mesh::greedy::GreedyMesh; @@ -105,20 +105,6 @@ impl Default for BoneData { fn default() -> Self { Self::new(anim::vek::Mat4::identity(), anim::vek::Mat4::identity()) } } -pub struct FigureLayout { - pub locals: wgpu::BindGroupLayout, - pub bone_data: wgpu::BindGroupLayout, -} - -impl FigureLayout { - pub fn new(device: &wgpu::Device) -> Self { - Self { - locals: Locals::locals_layout(device), - bone_data: BoneData::bone_data_layout(device), - } - } -} - pub struct FigureModel { pub opaque: Model, /* TODO: Consider using mipmaps instead of storing multiple texture atlases for different @@ -139,48 +125,138 @@ impl FigureModel { pub type BoneMeshes = (Mesh, anim::vek::Aabb); -//gfx_defines! { -// constant Locals { -// model_mat: [[f32; 4]; 4] = "model_mat", -// highlight_col: [f32; 4] = "highlight_col", -// model_light: [f32; 4] = "model_light", -// atlas_offs: [i32; 4] = "atlas_offs", -// model_pos: [f32; 3] = "model_pos", -// flags: u32 = "flags", -// } -// -// constant BoneData { -// bone_mat: [[f32; 4]; 4] = "bone_mat", -// normals_mat: [[f32; 4]; 4] = "normals_mat", -// } -// -// pipeline pipe { -// vbuf: gfx::VertexBuffer<::Vertex> = (), -// // abuf: gfx::VertexBuffer<::Vertex> = -// (), col_lights: gfx::TextureSampler<[f32; 4]> = "t_col_light", -// -// locals: gfx::ConstantBuffer = "u_locals", -// globals: gfx::ConstantBuffer = "u_globals", -// bones: gfx::ConstantBuffer = "u_bones", -// lights: gfx::ConstantBuffer = "u_lights", -// shadows: gfx::ConstantBuffer = "u_shadows", -// -// point_shadow_maps: gfx::TextureSampler = "t_point_shadow_maps", -// directed_shadow_maps: gfx::TextureSampler = -// "t_directed_shadow_maps", -// -// alt: gfx::TextureSampler<[f32; 2]> = "t_alt", -// horizon: gfx::TextureSampler<[f32; 4]> = "t_horizon", -// -// noise: gfx::TextureSampler = "t_noise", -// -// // Shadow stuff -// light_shadows: gfx::ConstantBuffer = -// "u_light_shadows", -// -// tgt_color: gfx::BlendTarget = ("tgt_color", -// ColorMask::all(), gfx::preset::blend::ALPHA), tgt_depth_stencil: -// gfx::DepthTarget = gfx::preset::depth::LESS_EQUAL_WRITE, -// // tgt_depth_stencil: gfx::DepthStencilTarget = -// (gfx::preset::depth::LESS_EQUAL_WRITE,Stencil::new(Comparison::Always,0xff, -// (StencilOp::Keep,StencilOp::Keep,StencilOp::Replace))), } +pub struct FigureLayout { + pub locals: wgpu::BindGroupLayout, + pub bone_data: wgpu::BindGroupLayout, + pub col_lights: wgpu::BindGroupLayout, +} + +impl FigureLayout { + pub fn new(device: &wgpu::Device) -> Self { + Self { + locals: Locals::layout(device), + bone_data: BoneData::layout(device), + col_lights: device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { + label: None, + entries: &[ + wgpu::BindGroupLayoutEntry { + binding: 0, + visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, + ty: wgpu::BindingType::SampledTexture { + component_type: wgpu::TextureComponentType::Float, + dimension: wgpu::TextureViewDimension::D2, + multisampled: false, + }, + count: None, + }, + wgpu::BindGroupLayoutEntry { + binding: 1, + visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, + ty: wgpu::BindingType::Sampler { comparison: false }, + count: None, + }, + ], + }), + } + } +} + +pub struct FigurePipeline { + pub pipeline: wgpu::RenderPipeline, +} + +impl FigurePipeline { + pub fn new( + device: &wgpu::Device, + vs_module: &wgpu::ShaderModule, + fs_module: &wgpu::ShaderModule, + sc_desc: &wgpu::SwapChainDescriptor, + global_layout: &GlobalsLayouts, + layout: &FigureLayout, + aa_mode: AaMode, + ) -> Self { + let render_pipeline_layout = + device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { + label: Some("Figure pipeline layout"), + push_constant_ranges: &[], + bind_group_layouts: &[ + &global_layout.globals, + &global_layout.alt_horizon, + &global_layout.light, + &global_layout.shadow, + &global_layout.shadow_maps, + &global_layout.light_shadows, + &layout.locals, + &layout.bone_data, + &layout.col_lights, + ], + }); + + let samples = match aa_mode { + AaMode::None | AaMode::Fxaa => 1, + // TODO: Ensure sampling in the shader is exactly between the 4 texels + AaMode::SsaaX4 => 1, + AaMode::MsaaX4 => 4, + AaMode::MsaaX8 => 8, + AaMode::MsaaX16 => 16, + }; + + let render_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { + label: Some("Figure pipeline"), + layout: Some(&render_pipeline_layout), + vertex_stage: wgpu::ProgrammableStageDescriptor { + module: vs_module, + entry_point: "main", + }, + fragment_stage: Some(wgpu::ProgrammableStageDescriptor { + module: fs_module, + entry_point: "main", + }), + rasterization_state: Some(wgpu::RasterizationStateDescriptor { + front_face: wgpu::FrontFace::Ccw, + cull_mode: wgpu::CullMode::Back, + clamp_depth: false, + depth_bias: 0, + depth_bias_slope_scale: 0.0, + depth_bias_clamp: 0.0, + }), + primitive_topology: wgpu::PrimitiveTopology::TriangleList, + color_states: &[wgpu::ColorStateDescriptor { + format: sc_desc.format, + color_blend: wgpu::BlendDescriptor { + src_factor: wgpu::BlendFactor::SrcAlpha, + dst_factor: wgpu::BlendFactor::OneMinusSrcAlpha, + operation: wgpu::BlendOperation::Add, + }, + alpha_blend: wgpu::BlendDescriptor { + src_factor: wgpu::BlendFactor::One, + dst_factor: wgpu::BlendFactor::One, + operation: wgpu::BlendOperation::Add, + }, + write_mask: wgpu::ColorWrite::ALL, + }], + depth_stencil_state: Some(wgpu::DepthStencilStateDescriptor { + format: wgpu::TextureFormat::Depth24Plus, + depth_write_enabled: true, + depth_compare: wgpu::CompareFunction::LessEqual, + stencil: wgpu::StencilStateDescriptor { + front: wgpu::StencilStateFaceDescriptor::IGNORE, + back: wgpu::StencilStateFaceDescriptor::IGNORE, + read_mask: !0, + write_mask: !0, + }, + }), + vertex_state: wgpu::VertexStateDescriptor { + index_format: wgpu::IndexFormat::Uint16, + vertex_buffers: &[Vertex::desc()], + }, + sample_count: samples, + sample_mask: !0, + alpha_to_coverage_enabled: false, + }); + + Self { + pipeline: render_pipeline, + } + } +} diff --git a/voxygen/src/render/pipelines/fluid.rs b/voxygen/src/render/pipelines/fluid.rs index e2fc1ebd03..37180d2b84 100644 --- a/voxygen/src/render/pipelines/fluid.rs +++ b/voxygen/src/render/pipelines/fluid.rs @@ -1,41 +1,7 @@ +use super::super::{AaMode, GlobalsLayouts}; use vek::*; use zerocopy::AsBytes; -// gfx_defines! { -// vertex Vertex { -// pos_norm: u32 = "v_pos_norm", -// } - -// pipeline pipe { -// vbuf: gfx::VertexBuffer = (), - -// locals: gfx::ConstantBuffer = "u_locals", -// globals: gfx::ConstantBuffer = "u_globals", -// lights: gfx::ConstantBuffer = "u_lights", -// shadows: gfx::ConstantBuffer = "u_shadows", - -// point_shadow_maps: gfx::TextureSampler = "t_point_shadow_maps", -// directed_shadow_maps: gfx::TextureSampler = -// "t_directed_shadow_maps", - -// alt: gfx::TextureSampler<[f32; 2]> = "t_alt", -// horizon: gfx::TextureSampler<[f32; 4]> = "t_horizon", - -// noise: gfx::TextureSampler = "t_noise", -// waves: gfx::TextureSampler<[f32; 4]> = "t_waves", - -// // Shadow stuff -// light_shadows: gfx::ConstantBuffer = -// "u_light_shadows", - -// tgt_color: gfx::BlendTarget = ("tgt_color", -// ColorMask::all(), gfx::preset::blend::ALPHA), tgt_depth_stencil: -// gfx::DepthTarget = gfx::preset::depth::LESS_EQUAL_TEST, -// // tgt_depth_stencil: gfx::DepthStencilTarget = -// (gfx::preset::depth::LESS_EQUAL_TEST,Stencil::new(Comparison::Always,0xff, -// (StencilOp::Keep,StencilOp::Keep,StencilOp::Keep))), } -// } - #[repr(C)] #[derive(Copy, Clone, Debug, AsBytes)] pub struct Vertex { @@ -64,4 +30,147 @@ impl Vertex { | (norm_bits & 0x7) << 29, } } + + fn desc<'a>() -> wgpu::VertexBufferDescriptor<'a> { + use std::mem; + wgpu::VertexBufferDescriptor { + stride: mem::size_of::() as wgpu::BufferAddress, + step_mode: wgpu::InputStepMode::Vertex, + attributes: &[wgpu::VertexAttributeDescriptor { + offset: 0, + shader_location: 0, + format: wgpu::VertexFormat::Uint, + }], + } + } +} + +pub struct FluidLayout { + pub waves: wgpu::BindGroupLayout, +} + +impl FluidLayout { + pub fn new(device: &wgpu::Device) -> Self { + Self { + waves: device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { + label: None, + entries: &[ + wgpu::BindGroupLayoutEntry { + binding: 0, + visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, + ty: wgpu::BindingType::SampledTexture { + component_type: wgpu::TextureComponentType::Float, + dimension: wgpu::TextureViewDimension::D2, + multisampled: false, + }, + count: None, + }, + wgpu::BindGroupLayoutEntry { + binding: 1, + visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, + ty: wgpu::BindingType::Sampler { comparison: false }, + count: None, + }, + ], + }), + } + } +} + +pub struct FluidPipeline { + pub pipeline: wgpu::RenderPipeline, +} + +impl FluidPipeline { + pub fn new( + device: &wgpu::Device, + vs_module: &wgpu::ShaderModule, + fs_module: &wgpu::ShaderModule, + sc_desc: &wgpu::SwapChainDescriptor, + global_layout: &GlobalsLayouts, + layout: &FluidLayout, + aa_mode: AaMode, + ) -> Self { + let render_pipeline_layout = + device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { + label: Some("Fluid pipeline layout"), + push_constant_ranges: &[], + bind_group_layouts: &[ + &global_layout.globals, + &global_layout.alt_horizon, + &global_layout.light, + &global_layout.shadow, + &global_layout.shadow_maps, + &global_layout.light_shadows, + &layout.waves, + ], + }); + + let samples = match aa_mode { + AaMode::None | AaMode::Fxaa => 1, + // TODO: Ensure sampling in the shader is exactly between the 4 texels + AaMode::SsaaX4 => 1, + AaMode::MsaaX4 => 4, + AaMode::MsaaX8 => 8, + AaMode::MsaaX16 => 16, + }; + + let render_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { + label: Some("Fluid pipeline"), + layout: Some(&render_pipeline_layout), + vertex_stage: wgpu::ProgrammableStageDescriptor { + module: vs_module, + entry_point: "main", + }, + fragment_stage: Some(wgpu::ProgrammableStageDescriptor { + module: fs_module, + entry_point: "main", + }), + rasterization_state: Some(wgpu::RasterizationStateDescriptor { + front_face: wgpu::FrontFace::Ccw, + cull_mode: wgpu::CullMode::None, + clamp_depth: false, + depth_bias: 0, + depth_bias_slope_scale: 0.0, + depth_bias_clamp: 0.0, + }), + primitive_topology: wgpu::PrimitiveTopology::TriangleList, + color_states: &[wgpu::ColorStateDescriptor { + format: sc_desc.format, + color_blend: wgpu::BlendDescriptor { + src_factor: wgpu::BlendFactor::SrcAlpha, + dst_factor: wgpu::BlendFactor::OneMinusSrcAlpha, + operation: wgpu::BlendOperation::Add, + }, + alpha_blend: wgpu::BlendDescriptor { + src_factor: wgpu::BlendFactor::One, + dst_factor: wgpu::BlendFactor::One, + operation: wgpu::BlendOperation::Add, + }, + write_mask: wgpu::ColorWrite::ALL, + }], + depth_stencil_state: Some(wgpu::DepthStencilStateDescriptor { + format: wgpu::TextureFormat::Depth24Plus, + depth_write_enabled: false, + depth_compare: wgpu::CompareFunction::LessEqual, + stencil: wgpu::StencilStateDescriptor { + front: wgpu::StencilStateFaceDescriptor::IGNORE, + back: wgpu::StencilStateFaceDescriptor::IGNORE, + read_mask: !0, + write_mask: !0, + }, + }), + vertex_state: wgpu::VertexStateDescriptor { + index_format: wgpu::IndexFormat::Uint16, + vertex_buffers: &[Vertex::desc()], + }, + sample_count: samples, + sample_mask: !0, + alpha_to_coverage_enabled: false, + }); + + Self { + pipeline: render_pipeline, + } + } } diff --git a/voxygen/src/render/pipelines/lod_terrain.rs b/voxygen/src/render/pipelines/lod_terrain.rs index bc3c22dc6b..4dd721c56e 100644 --- a/voxygen/src/render/pipelines/lod_terrain.rs +++ b/voxygen/src/render/pipelines/lod_terrain.rs @@ -1,35 +1,7 @@ -use super::super::{Renderer, Texture}; +use super::super::{AaMode, GlobalsLayouts, Renderer, Texture}; use vek::*; use zerocopy::AsBytes; -// gfx_defines! { -// vertex Vertex { -// pos: [f32; 2] = "v_pos", -// } - -// constant Locals { -// nul: [f32; 4] = "nul", -// } - -// pipeline pipe { -// vbuf: gfx::VertexBuffer = (), - -// locals: gfx::ConstantBuffer = "u_locals", -// globals: gfx::ConstantBuffer = "u_globals", -// map: gfx::TextureSampler<[f32; 4]> = "t_map", -// alt: gfx::TextureSampler<[f32; 2]> = "t_alt", -// horizon: gfx::TextureSampler<[f32; 4]> = "t_horizon", - -// noise: gfx::TextureSampler = "t_noise", - -// tgt_color: gfx::RenderTarget = "tgt_color", -// tgt_depth_stencil: gfx::DepthTarget = -// gfx::preset::depth::LESS_EQUAL_WRITE, // tgt_depth_stencil: -// gfx::DepthStencilTarget = -// (gfx::preset::depth::LESS_EQUAL_WRITE,Stencil::new(Comparison::Always,0xff, -// (StencilOp::Keep,StencilOp::Keep,StencilOp::Keep))), } -// } - #[repr(C)] #[derive(Copy, Clone, Debug, AsBytes)] pub struct Vertex { @@ -42,6 +14,19 @@ impl Vertex { pos: pos.into_array(), } } + + fn desc<'a>() -> wgpu::VertexBufferDescriptor<'a> { + use std::mem; + wgpu::VertexBufferDescriptor { + stride: mem::size_of::() as wgpu::BufferAddress, + step_mode: wgpu::InputStepMode::Vertex, + attributes: &[wgpu::VertexAttributeDescriptor { + offset: 0, + shader_location: 0, + format: wgpu::VertexFormat::Float2, + }], + } + } } pub struct LodData { @@ -156,3 +141,88 @@ impl LodData { // } } } + +pub struct LodTerrainPipeline { + pub pipeline: wgpu::RenderPipeline, +} + +impl LodTerrainPipeline { + pub fn new( + device: &wgpu::Device, + vs_module: &wgpu::ShaderModule, + fs_module: &wgpu::ShaderModule, + sc_desc: &wgpu::SwapChainDescriptor, + global_layout: &GlobalsLayouts, + aa_mode: AaMode, + ) -> Self { + let render_pipeline_layout = + device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { + label: Some("Lod terrain pipeline layout"), + push_constant_ranges: &[], + bind_group_layouts: &[ + &global_layout.globals, + &global_layout.alt_horizon, + &global_layout.lod_map, + ], + }); + + let samples = match aa_mode { + AaMode::None | AaMode::Fxaa => 1, + // TODO: Ensure sampling in the shader is exactly between the 4 texels + AaMode::SsaaX4 => 1, + AaMode::MsaaX4 => 4, + AaMode::MsaaX8 => 8, + AaMode::MsaaX16 => 16, + }; + + let render_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { + label: Some("Lod terrain pipeline"), + layout: Some(&render_pipeline_layout), + vertex_stage: wgpu::ProgrammableStageDescriptor { + module: vs_module, + entry_point: "main", + }, + fragment_stage: Some(wgpu::ProgrammableStageDescriptor { + module: fs_module, + entry_point: "main", + }), + rasterization_state: Some(wgpu::RasterizationStateDescriptor { + front_face: wgpu::FrontFace::Ccw, + cull_mode: wgpu::CullMode::Back, + clamp_depth: false, + depth_bias: 0, + depth_bias_slope_scale: 0.0, + depth_bias_clamp: 0.0, + }), + primitive_topology: wgpu::PrimitiveTopology::TriangleList, + color_states: &[wgpu::ColorStateDescriptor { + format: sc_desc.format, + color_blend: wgpu::BlendDescriptor::REPLACE, + alpha_blend: wgpu::BlendDescriptor::REPLACE, + write_mask: wgpu::ColorWrite::ALL, + }], + depth_stencil_state: Some(wgpu::DepthStencilStateDescriptor { + format: wgpu::TextureFormat::Depth24Plus, + depth_write_enabled: true, + depth_compare: wgpu::CompareFunction::LessEqual, + stencil: wgpu::StencilStateDescriptor { + front: wgpu::StencilStateFaceDescriptor::IGNORE, + back: wgpu::StencilStateFaceDescriptor::IGNORE, + read_mask: !0, + write_mask: !0, + }, + }), + vertex_state: wgpu::VertexStateDescriptor { + index_format: wgpu::IndexFormat::Uint16, + vertex_buffers: &[Vertex::desc()], + }, + sample_count: samples, + sample_mask: !0, + alpha_to_coverage_enabled: false, + }); + + Self { + pipeline: render_pipeline, + } + } +} diff --git a/voxygen/src/render/pipelines/mod.rs b/voxygen/src/render/pipelines/mod.rs index 8a496d23c9..39cfeb3768 100644 --- a/voxygen/src/render/pipelines/mod.rs +++ b/voxygen/src/render/pipelines/mod.rs @@ -225,34 +225,201 @@ pub struct GlobalModel { pub shadow_mats: Consts, } -//gfx_defines! { -// constant Globals { -// view_mat: [[f32; 4]; 4] = "view_mat", -// proj_mat: [[f32; 4]; 4] = "proj_mat", -// all_mat: [[f32; 4]; 4] = "all_mat", -// cam_pos: [f32; 4] = "cam_pos", -// focus_off: [f32; 4] = "focus_off", -// focus_pos: [f32; 4] = "focus_pos", -// /// NOTE: view_distance.x is the horizontal view distance, -// view_distance.y is the LOD /// detail, view_distance.z is the -// /// minimum height over any land chunk (i.e. the sea level), and -// view_distance.w is the /// maximum height over this minimum height. -// /// -// /// TODO: Fix whatever alignment issue requires these uniforms to be -// aligned. view_distance: [f32; 4] = "view_distance", -// time_of_day: [f32; 4] = "time_of_day", // TODO: Make this f64. -// sun_dir: [f32; 4] = "sun_dir", -// moon_dir: [f32; 4] = "moon_dir", -// tick: [f32; 4] = "tick", -// /// x, y represent the resolution of the screen; -// /// w, z represent the near and far planes of the shadow map. -// screen_res: [f32; 4] = "screen_res", -// light_shadow_count: [u32; 4] = "light_shadow_count", -// shadow_proj_factors: [f32; 4] = "shadow_proj_factors", -// medium: [u32; 4] = "medium", -// select_pos: [i32; 4] = "select_pos", -// gamma_exposure: [f32; 4] = "gamma_exposure", -// ambiance: f32 = "ambiance", -// cam_mode: u32 = "cam_mode", -// sprite_render_distance: f32 = "sprite_render_distance", -// } +pub struct GlobalsLayouts { + pub globals: wgpu::BindGroupLayout, + pub light: wgpu::BindGroupLayout, + pub shadow: wgpu::BindGroupLayout, + pub alt_horizon: wgpu::BindGroupLayout, + pub shadow_maps: wgpu::BindGroupLayout, + pub light_shadows: wgpu::BindGroupLayout, + pub lod_map: wgpu::BindGroupLayout, +} + +impl GlobalsLayouts { + pub fn new(device: &wgpu::Device) -> Self { + let globals = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { + label: Some("Globals layout"), + entries: &[ + wgpu::BindGroupLayoutEntry { + binding: 0, + visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, + ty: wgpu::BindingType::UniformBuffer { + dynamic: false, + min_binding_size: None, + }, + count: None, + }, + wgpu::BindGroupLayoutEntry { + binding: 1, + visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, + ty: wgpu::BindingType::SampledTexture { + dimension: wgpu::TextureViewDimension::D2, + component_type: wgpu::TextureComponentType::Float, + multisampled: false, + }, + count: None, + }, + wgpu::BindGroupLayoutEntry { + binding: 2, + visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, + ty: wgpu::BindingType::Sampler { comparison: false }, + count: None, + }, + ], + }); + let light = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { + label: Some("Light layout"), + entries: &[wgpu::BindGroupLayoutEntry { + binding: 0, + visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, + ty: wgpu::BindingType::UniformBuffer { + dynamic: false, + min_binding_size: None, + }, + count: None, + }], + }); + let shadow = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { + label: Some("Shadow layout"), + entries: &[wgpu::BindGroupLayoutEntry { + binding: 0, + visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, + ty: wgpu::BindingType::UniformBuffer { + dynamic: false, + min_binding_size: None, + }, + count: None, + }], + }); + + let alt_horizon = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { + label: Some("alt/horizon layout"), + entries: &[ + wgpu::BindGroupLayoutEntry { + binding: 0, + visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, + ty: wgpu::BindingType::SampledTexture { + component_type: wgpu::TextureComponentType::Float, + dimension: wgpu::TextureViewDimension::D2, + multisampled: false, + }, + count: None, + }, + wgpu::BindGroupLayoutEntry { + binding: 1, + visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, + ty: wgpu::BindingType::Sampler { comparison: false }, + count: None, + }, + wgpu::BindGroupLayoutEntry { + binding: 2, + visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, + ty: wgpu::BindingType::SampledTexture { + component_type: wgpu::TextureComponentType::Float, + dimension: wgpu::TextureViewDimension::D2, + multisampled: false, + }, + count: None, + }, + wgpu::BindGroupLayoutEntry { + binding: 3, + visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, + ty: wgpu::BindingType::Sampler { comparison: false }, + count: None, + }, + ], + }); + + let shadow_maps = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { + label: Some("Shadow maps layout"), + entries: &[ + wgpu::BindGroupLayoutEntry { + binding: 0, + visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, + ty: wgpu::BindingType::SampledTexture { + component_type: wgpu::TextureComponentType::Float, + dimension: wgpu::TextureViewDimension::D2, + multisampled: false, + }, + count: None, + }, + wgpu::BindGroupLayoutEntry { + binding: 1, + visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, + ty: wgpu::BindingType::Sampler { comparison: false }, + count: None, + }, + ], + }); + + let light_shadows = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { + label: Some("Light shadows layout"), + entries: &[ + wgpu::BindGroupLayoutEntry { + binding: 0, + visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, + ty: wgpu::BindingType::SampledTexture { + component_type: wgpu::TextureComponentType::Float, + dimension: wgpu::TextureViewDimension::D2, + multisampled: false, + }, + count: None, + }, + wgpu::BindGroupLayoutEntry { + binding: 1, + visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, + ty: wgpu::BindingType::Sampler { comparison: false }, + count: None, + }, + wgpu::BindGroupLayoutEntry { + binding: 2, + visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, + ty: wgpu::BindingType::SampledTexture { + component_type: wgpu::TextureComponentType::Float, + dimension: wgpu::TextureViewDimension::D2, + multisampled: false, + }, + count: None, + }, + wgpu::BindGroupLayoutEntry { + binding: 3, + visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, + ty: wgpu::BindingType::Sampler { comparison: false }, + count: None, + }, + ], + }); + + let lod_map = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { + label: Some("Lod layout"), + entries: &[ + wgpu::BindGroupLayoutEntry { + binding: 0, + visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, + ty: wgpu::BindingType::SampledTexture { + component_type: wgpu::TextureComponentType::Float, + dimension: wgpu::TextureViewDimension::D2, + multisampled: false, + }, + count: None, + }, + wgpu::BindGroupLayoutEntry { + binding: 1, + visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, + ty: wgpu::BindingType::Sampler { comparison: false }, + count: None, + }, + ], + }); + + Self { + globals, + light, + shadow, + alt_horizon, + shadow_maps, + light_shadows, + lod_map, + } + } +} diff --git a/voxygen/src/render/pipelines/particle.rs b/voxygen/src/render/pipelines/particle.rs index 22a41059d8..b81c7f2892 100644 --- a/voxygen/src/render/pipelines/particle.rs +++ b/voxygen/src/render/pipelines/particle.rs @@ -1,77 +1,7 @@ +use super::super::{AaMode, GlobalsLayouts}; use vek::*; use zerocopy::AsBytes; -// gfx_defines! { -// vertex Vertex { -// pos: [f32; 3] = "v_pos", -// // ____BBBBBBBBGGGGGGGGRRRRRRRR -// // col: u32 = "v_col", -// // ...AANNN -// // A = AO -// // N = Normal -// norm_ao: u32 = "v_norm_ao", -// } -// -// vertex Instance { -// // created_at time, so we can calculate time relativity, needed for -// relative animation. // can save 32 bits per instance, for particles -// that are not relatively animated. inst_time: f32 = "inst_time", -// -// // The lifespan in seconds of the particle -// inst_lifespan: f32 = "inst_lifespan", -// -// // a seed value for randomness -// // can save 32 bits per instance, for particles that don't need -// randomness/uniqueness. inst_entropy: f32 = "inst_entropy", -// -// // modes should probably be seperate shaders, as a part of scaling -// and optimisation efforts. // can save 32 bits per instance, and have -// cleaner tailor made code. inst_mode: i32 = "inst_mode", -// -// // A direction for particles to move in -// inst_dir: [f32; 3] = "inst_dir", -// -// // a triangle is: f32 x 3 x 3 x 1 = 288 bits -// // a quad is: f32 x 3 x 3 x 2 = 576 bits -// // a cube is: f32 x 3 x 3 x 12 = 3456 bits -// // this vec is: f32 x 3 x 1 x 1 = 96 bits (per instance!) -// // consider using a throw-away mesh and -// // positioning the vertex vertices instead, -// // if we have: -// // - a triangle mesh, and 3 or more instances. -// // - a quad mesh, and 6 or more instances. -// // - a cube mesh, and 36 or more instances. -// inst_pos: [f32; 3] = "inst_pos", -// } -// -// pipeline pipe { -// vbuf: gfx::VertexBuffer = (), -// ibuf: gfx::InstanceBuffer = (), -// -// globals: gfx::ConstantBuffer = "u_globals", -// lights: gfx::ConstantBuffer = "u_lights", -// shadows: gfx::ConstantBuffer = "u_shadows", -// -// point_shadow_maps: gfx::TextureSampler = "t_point_shadow_maps", -// directed_shadow_maps: gfx::TextureSampler = -// "t_directed_shadow_maps", -// -// alt: gfx::TextureSampler<[f32; 2]> = "t_alt", -// horizon: gfx::TextureSampler<[f32; 4]> = "t_horizon", -// -// noise: gfx::TextureSampler = "t_noise", -// -// // Shadow stuff -// light_shadows: gfx::ConstantBuffer = -// "u_light_shadows", -// -// tgt_color: gfx::BlendTarget = ("tgt_color", -// ColorMask::all(), gfx::preset::blend::ALPHA), tgt_depth_stencil: -// gfx::DepthTarget = gfx::preset::depth::LESS_EQUAL_WRITE, -// // tgt_depth_stencil: gfx::DepthStencilTarget = -// (gfx::preset::depth::LESS_EQUAL_WRITE,Stencil::new(Comparison::Always,0xff, -// (StencilOp::Keep,StencilOp::Keep,StencilOp::Keep))), } - #[repr(C)] #[derive(Copy, Clone, Debug, AsBytes)] pub struct Vertex { @@ -100,6 +30,15 @@ impl Vertex { norm_ao: norm_bits, } } + + fn desc<'a>() -> wgpu::VertexBufferDescriptor<'a> { + use std::mem; + wgpu::VertexBufferDescriptor { + stride: mem::size_of::() as wgpu::BufferAddress, + step_mode: wgpu::InputStepMode::Vertex, + attributes: &wgpu::vertex_attr_array![0 => Float3, 1 => Uint], + } + } } #[derive(Copy, Clone)] @@ -198,8 +137,113 @@ impl Instance { inst_dir: (inst_pos2 - inst_pos).into_array(), } } + + fn desc<'a>() -> wgpu::VertexBufferDescriptor<'a> { + use std::mem; + wgpu::VertexBufferDescriptor { + stride: mem::size_of::() as wgpu::BufferAddress, + step_mode: wgpu::InputStepMode::Instance, + attributes: &wgpu::vertex_attr_array![0 => Float, 1 => Float, 2 => Float, 3 => Int, 4 => Float3], + } + } } impl Default for Instance { fn default() -> Self { Self::new(0.0, 0.0, ParticleMode::CampfireSmoke, Vec3::zero()) } } + +pub struct ParticlePipeline { + pub pipeline: wgpu::RenderPipeline, +} + +impl ParticlePipeline { + pub fn new( + device: &wgpu::Device, + vs_module: &wgpu::ShaderModule, + fs_module: &wgpu::ShaderModule, + sc_desc: &wgpu::SwapChainDescriptor, + global_layout: &GlobalsLayouts, + aa_mode: AaMode, + ) -> Self { + let render_pipeline_layout = + device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { + label: Some("Particle pipeline layout"), + push_constant_ranges: &[], + bind_group_layouts: &[ + &global_layout.globals, + &global_layout.alt_horizon, + &global_layout.light, + &global_layout.shadow, + &global_layout.shadow_maps, + &global_layout.light_shadows, + ], + }); + + let samples = match aa_mode { + AaMode::None | AaMode::Fxaa => 1, + // TODO: Ensure sampling in the shader is exactly between the 4 texels + AaMode::SsaaX4 => 1, + AaMode::MsaaX4 => 4, + AaMode::MsaaX8 => 8, + AaMode::MsaaX16 => 16, + }; + + let render_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { + label: Some("Particle pipeline"), + layout: Some(&render_pipeline_layout), + vertex_stage: wgpu::ProgrammableStageDescriptor { + module: vs_module, + entry_point: "main", + }, + fragment_stage: Some(wgpu::ProgrammableStageDescriptor { + module: fs_module, + entry_point: "main", + }), + rasterization_state: Some(wgpu::RasterizationStateDescriptor { + front_face: wgpu::FrontFace::Ccw, + cull_mode: wgpu::CullMode::Back, + clamp_depth: false, + depth_bias: 0, + depth_bias_slope_scale: 0.0, + depth_bias_clamp: 0.0, + }), + primitive_topology: wgpu::PrimitiveTopology::TriangleList, + color_states: &[wgpu::ColorStateDescriptor { + format: sc_desc.format, + color_blend: wgpu::BlendDescriptor { + src_factor: wgpu::BlendFactor::SrcAlpha, + dst_factor: wgpu::BlendFactor::OneMinusSrcAlpha, + operation: wgpu::BlendOperation::Add, + }, + alpha_blend: wgpu::BlendDescriptor { + src_factor: wgpu::BlendFactor::One, + dst_factor: wgpu::BlendFactor::One, + operation: wgpu::BlendOperation::Add, + }, + write_mask: wgpu::ColorWrite::ALL, + }], + depth_stencil_state: Some(wgpu::DepthStencilStateDescriptor { + format: wgpu::TextureFormat::Depth24Plus, + depth_write_enabled: true, + depth_compare: wgpu::CompareFunction::LessEqual, + stencil: wgpu::StencilStateDescriptor { + front: wgpu::StencilStateFaceDescriptor::IGNORE, + back: wgpu::StencilStateFaceDescriptor::IGNORE, + read_mask: !0, + write_mask: !0, + }, + }), + vertex_state: wgpu::VertexStateDescriptor { + index_format: wgpu::IndexFormat::Uint16, + vertex_buffers: &[Vertex::desc(), Instance::desc()], + }, + sample_count: samples, + sample_mask: !0, + alpha_to_coverage_enabled: false, + }); + + Self { + pipeline: render_pipeline, + } + } +} diff --git a/voxygen/src/render/pipelines/postprocess.rs b/voxygen/src/render/pipelines/postprocess.rs index 14889c9292..4dd9df9474 100644 --- a/voxygen/src/render/pipelines/postprocess.rs +++ b/voxygen/src/render/pipelines/postprocess.rs @@ -1,38 +1,7 @@ -use super::super::{Mesh, Tri}; +use super::super::{AaMode, GlobalsLayouts, Mesh, Tri}; use vek::*; use zerocopy::AsBytes; -// gfx_defines! { -// vertex Vertex { -// pos: [f32; 2] = "v_pos", -// } -// -// constant Locals { -// proj_mat_inv: [[f32; 4]; 4] = "proj_mat_inv", -// view_mat_inv: [[f32; 4]; 4] = "view_mat_inv", -// } -// -// pipeline pipe { -// vbuf: gfx::VertexBuffer = (), -// -// locals: gfx::ConstantBuffer = "u_locals", -// globals: gfx::ConstantBuffer = "u_globals", -// -// map: gfx::TextureSampler<[f32; 4]> = "t_map", -// alt: gfx::TextureSampler<[f32; 2]> = "t_alt", -// horizon: gfx::TextureSampler<[f32; 4]> = "t_horizon", -// -// color_sampler: gfx::TextureSampler<::View> = "src_color", depth_sampler: -// gfx::TextureSampler<::View> = -// "src_depth", -// -// noise: gfx::TextureSampler = "t_noise", -// -// tgt_color: gfx::RenderTarget = "tgt_color", -// } -// } - #[repr(C)] #[derive(Copy, Clone, Debug, AsBytes)] pub struct Locals { @@ -59,6 +28,21 @@ pub struct Vertex { pub pos: [f32; 2], } +impl Vertex { + fn desc<'a>() -> wgpu::VertexBufferDescriptor<'a> { + use std::mem; + wgpu::VertexBufferDescriptor { + stride: mem::size_of::() as wgpu::BufferAddress, + step_mode: wgpu::InputStepMode::Vertex, + attributes: &[wgpu::VertexAttributeDescriptor { + offset: 0, + shader_location: 0, + format: wgpu::VertexFormat::Float2, + }], + } + } +} + pub fn create_mesh() -> Mesh { let mut mesh = Mesh::new(); @@ -78,3 +62,117 @@ pub fn create_mesh() -> Mesh { mesh } + +pub struct PostProcessLayout { + pub src_color: wgpu::BindGroupLayout, +} + +impl PostProcessLayout { + pub fn new(device: &wgpu::Device) -> Self { + Self { + src_color: device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { + label: None, + entries: &[ + wgpu::BindGroupLayoutEntry { + binding: 0, + visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, + ty: wgpu::BindingType::SampledTexture { + component_type: wgpu::TextureComponentType::Float, + dimension: wgpu::TextureViewDimension::D2, + multisampled: false, + }, + count: None, + }, + wgpu::BindGroupLayoutEntry { + binding: 1, + visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, + ty: wgpu::BindingType::Sampler { comparison: false }, + count: None, + }, + ], + }), + } + } +} + +pub struct PostProcessPipeline { + pub pipeline: wgpu::RenderPipeline, +} + +impl PostProcessPipeline { + pub fn new( + device: &wgpu::Device, + vs_module: &wgpu::ShaderModule, + fs_module: &wgpu::ShaderModule, + sc_desc: &wgpu::SwapChainDescriptor, + global_layout: &GlobalsLayouts, + layout: &PostProcessLayout, + aa_mode: AaMode, + ) -> Self { + let render_pipeline_layout = + device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { + label: Some("Post process pipeline layout"), + push_constant_ranges: &[], + bind_group_layouts: &[&global_layout.globals, &layout.src_color], + }); + + let samples = match aa_mode { + AaMode::None | AaMode::Fxaa => 1, + // TODO: Ensure sampling in the shader is exactly between the 4 texels + AaMode::SsaaX4 => 1, + AaMode::MsaaX4 => 4, + AaMode::MsaaX8 => 8, + AaMode::MsaaX16 => 16, + }; + + let render_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { + label: Some("Post process pipeline"), + layout: Some(&render_pipeline_layout), + vertex_stage: wgpu::ProgrammableStageDescriptor { + module: vs_module, + entry_point: "main", + }, + fragment_stage: Some(wgpu::ProgrammableStageDescriptor { + module: fs_module, + entry_point: "main", + }), + rasterization_state: Some(wgpu::RasterizationStateDescriptor { + front_face: wgpu::FrontFace::Ccw, + cull_mode: wgpu::CullMode::Back, + clamp_depth: false, + depth_bias: 0, + depth_bias_slope_scale: 0.0, + depth_bias_clamp: 0.0, + }), + primitive_topology: wgpu::PrimitiveTopology::TriangleList, + color_states: &[wgpu::ColorStateDescriptor { + format: sc_desc.format, + color_blend: wgpu::BlendDescriptor::REPLACE, + alpha_blend: wgpu::BlendDescriptor::REPLACE, + write_mask: wgpu::ColorWrite::ALL, + }], + depth_stencil_state: Some(wgpu::DepthStencilStateDescriptor { + format: wgpu::TextureFormat::Depth24Plus, + depth_write_enabled: false, + depth_compare: wgpu::CompareFunction::Always, + stencil: wgpu::StencilStateDescriptor { + front: wgpu::StencilStateFaceDescriptor::IGNORE, + back: wgpu::StencilStateFaceDescriptor::IGNORE, + read_mask: !0, + write_mask: !0, + }, + }), + vertex_state: wgpu::VertexStateDescriptor { + index_format: wgpu::IndexFormat::Uint16, + vertex_buffers: &[Vertex::desc()], + }, + sample_count: samples, + sample_mask: !0, + alpha_to_coverage_enabled: false, + }); + + Self { + pipeline: render_pipeline, + } + } +} diff --git a/voxygen/src/render/pipelines/shadow.rs b/voxygen/src/render/pipelines/shadow.rs index c87920d50f..42dcf6fb82 100644 --- a/voxygen/src/render/pipelines/shadow.rs +++ b/voxygen/src/render/pipelines/shadow.rs @@ -1,47 +1,9 @@ -use super::super::{ColLightInfo, Renderer, Texture}; +use super::super::{ + AaMode, ColLightInfo, FigureLayout, GlobalsLayouts, Renderer, TerrainVertex, Texture, +}; use vek::*; use zerocopy::AsBytes; -// gfx_defines! { -// constant Locals { -// shadow_matrices: [[f32; 4]; 4] = "shadowMatrices", -// texture_mats: [[f32; 4]; 4] = "texture_mat", -// } - -// pipeline pipe { -// // Terrain vertex stuff -// vbuf: gfx::VertexBuffer = (), - -// locals: gfx::ConstantBuffer = "u_locals", -// globals: gfx::ConstantBuffer = "u_globals", - -// // Shadow stuff -// light_shadows: gfx::ConstantBuffer = "u_light_shadows", - -// tgt_depth_stencil: gfx::DepthTarget = -// gfx::state::Depth { fun: gfx::state::Comparison::Less, -// write: true, -// }, -// } - -// pipeline figure_pipe { -// // Terrain vertex stuff -// vbuf: gfx::VertexBuffer = (), - -// locals: gfx::ConstantBuffer = "u_locals", -// bones: gfx::ConstantBuffer = "u_bones", -// globals: gfx::ConstantBuffer = "u_globals", - -// // Shadow stuff -// light_shadows: gfx::ConstantBuffer = "u_light_shadows", - -// tgt_depth_stencil: gfx::DepthTarget = -// gfx::state::Depth { fun: gfx::state::Comparison::Less, -// write: true, -// }, -// } -// } - #[repr(C)] #[derive(Copy, Clone, Debug, AsBytes)] pub struct Locals { @@ -58,6 +20,33 @@ impl Locals { } pub fn default() -> Self { Self::new(Mat4::identity(), Mat4::identity()) } + + fn layout(device: &wgpu::Device) -> wgpu::BindGroupLayout { + device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { + label: None, + entries: &[wgpu::BindGroupLayoutEntry { + binding: 0, + visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, + ty: wgpu::BindingType::UniformBuffer { + dynamic: false, + min_binding_size: None, + }, + count: None, + }], + }) + } +} + +pub struct ShadowLayout { + pub locals: wgpu::BindGroupLayout, +} + +impl ShadowLayout { + pub fn new(device: &wgpu::Device) -> Self { + Self { + locals: Locals::layout(device), + } + } } pub fn create_col_lights( @@ -98,3 +87,165 @@ pub fn create_col_lights( col_lights.as_bytes(), ) } + +pub struct ShadowFigurePipeline { + pub pipeline: wgpu::RenderPipeline, +} + +impl ShadowFigurePipeline { + pub fn new( + device: &wgpu::Device, + vs_module: &wgpu::ShaderModule, + fs_module: &wgpu::ShaderModule, + sc_desc: &wgpu::SwapChainDescriptor, + global_layout: &GlobalsLayouts, + layout: &FigureLayout, + aa_mode: AaMode, + ) -> Self { + let render_pipeline_layout = + device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { + label: Some("Shadow figure pipeline layout"), + push_constant_ranges: &[], + bind_group_layouts: &[ + &global_layout.globals, + &global_layout.light_shadows, + &layout.waves, + ], + }); + + let samples = match aa_mode { + AaMode::None | AaMode::Fxaa => 1, + // TODO: Ensure sampling in the shader is exactly between the 4 texels + AaMode::SsaaX4 => 1, + AaMode::MsaaX4 => 4, + AaMode::MsaaX8 => 8, + AaMode::MsaaX16 => 16, + }; + + let render_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { + label: Some("Shadow figure pipeline"), + layout: Some(&render_pipeline_layout), + vertex_stage: wgpu::ProgrammableStageDescriptor { + module: vs_module, + entry_point: "main", + }, + fragment_stage: Some(wgpu::ProgrammableStageDescriptor { + module: fs_module, + entry_point: "main", + }), + rasterization_state: Some(wgpu::RasterizationStateDescriptor { + front_face: wgpu::FrontFace::Ccw, + cull_mode: wgpu::CullMode::Back, + clamp_depth: false, + depth_bias: 0, + depth_bias_slope_scale: 0.0, + depth_bias_clamp: 0.0, + }), + primitive_topology: wgpu::PrimitiveTopology::TriangleList, + color_states: &[], + depth_stencil_state: Some(wgpu::DepthStencilStateDescriptor { + format: wgpu::TextureFormat::Depth24Plus, + depth_write_enabled: true, + depth_compare: wgpu::CompareFunction::Less, + stencil: wgpu::StencilStateDescriptor { + front: wgpu::StencilStateFaceDescriptor::IGNORE, + back: wgpu::StencilStateFaceDescriptor::IGNORE, + read_mask: !0, + write_mask: !0, + }, + }), + vertex_state: wgpu::VertexStateDescriptor { + index_format: wgpu::IndexFormat::Uint16, + vertex_buffers: &[TerrainVertex::desc()], + }, + sample_count: samples, + sample_mask: !0, + alpha_to_coverage_enabled: false, + }); + + Self { + pipeline: render_pipeline, + } + } +} + +pub struct ShadowPipeline { + pub pipeline: wgpu::RenderPipeline, +} + +impl ShadowPipeline { + pub fn new( + device: &wgpu::Device, + vs_module: &wgpu::ShaderModule, + fs_module: &wgpu::ShaderModule, + sc_desc: &wgpu::SwapChainDescriptor, + global_layout: &GlobalsLayouts, + layout: &ShadowLayout, + aa_mode: AaMode, + ) -> Self { + let render_pipeline_layout = + device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { + label: Some("Shadow pipeline layout"), + push_constant_ranges: &[], + bind_group_layouts: &[ + &global_layout.globals, + &global_layout.light_shadows, + &layout.locals, + ], + }); + + let samples = match aa_mode { + AaMode::None | AaMode::Fxaa => 1, + // TODO: Ensure sampling in the shader is exactly between the 4 texels + AaMode::SsaaX4 => 1, + AaMode::MsaaX4 => 4, + AaMode::MsaaX8 => 8, + AaMode::MsaaX16 => 16, + }; + + let render_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { + label: Some("Shadow pipeline"), + layout: Some(&render_pipeline_layout), + vertex_stage: wgpu::ProgrammableStageDescriptor { + module: vs_module, + entry_point: "main", + }, + fragment_stage: Some(wgpu::ProgrammableStageDescriptor { + module: fs_module, + entry_point: "main", + }), + rasterization_state: Some(wgpu::RasterizationStateDescriptor { + front_face: wgpu::FrontFace::Ccw, + cull_mode: wgpu::CullMode::Back, + clamp_depth: false, + depth_bias: 0, + depth_bias_slope_scale: 0.0, + depth_bias_clamp: 0.0, + }), + primitive_topology: wgpu::PrimitiveTopology::TriangleList, + color_states: &[], + depth_stencil_state: Some(wgpu::DepthStencilStateDescriptor { + format: wgpu::TextureFormat::Depth24Plus, + depth_write_enabled: true, + depth_compare: wgpu::CompareFunction::Less, + stencil: wgpu::StencilStateDescriptor { + front: wgpu::StencilStateFaceDescriptor::IGNORE, + back: wgpu::StencilStateFaceDescriptor::IGNORE, + read_mask: !0, + write_mask: !0, + }, + }), + vertex_state: wgpu::VertexStateDescriptor { + index_format: wgpu::IndexFormat::Uint16, + vertex_buffers: &[TerrainVertex::desc()], + }, + sample_count: samples, + sample_mask: !0, + alpha_to_coverage_enabled: false, + }); + + Self { + pipeline: render_pipeline, + } + } +} diff --git a/voxygen/src/render/pipelines/skybox.rs b/voxygen/src/render/pipelines/skybox.rs index 7ece139435..a3c4ce42a0 100644 --- a/voxygen/src/render/pipelines/skybox.rs +++ b/voxygen/src/render/pipelines/skybox.rs @@ -1,40 +1,108 @@ -use super::super::{Mesh, Quad}; +use super::super::{AaMode, GlobalsLayouts, Mesh, Quad}; use zerocopy::AsBytes; -// gfx_defines! { -// vertex Vertex { -// pos: [f32; 3] = "v_pos", -// } - -// constant Locals { -// nul: [f32; 4] = "nul", -// } - -// pipeline pipe { -// vbuf: gfx::VertexBuffer = (), - -// locals: gfx::ConstantBuffer = "u_locals", -// globals: gfx::ConstantBuffer = "u_globals", - -// alt: gfx::TextureSampler<[f32; 2]> = "t_alt", -// horizon: gfx::TextureSampler<[f32; 4]> = "t_horizon", - -// noise: gfx::TextureSampler = "t_noise", - -// tgt_color: gfx::RenderTarget = "tgt_color", -// tgt_depth_stencil: gfx::DepthTarget = -// gfx::preset::depth::LESS_EQUAL_TEST, // tgt_depth_stencil: -// gfx::DepthStencilTarget = -// (gfx::preset::depth::LESS_EQUAL_WRITE,Stencil::new(Comparison::Always,0xff, -// (StencilOp::Keep,StencilOp::Keep,StencilOp::Keep))), } -// } - #[repr(C)] #[derive(Copy, Clone, Debug, AsBytes)] pub struct Vertex { pub pos: [f32; 3], } +impl Vertex { + fn desc<'a>() -> wgpu::VertexBufferDescriptor<'a> { + use std::mem; + wgpu::VertexBufferDescriptor { + stride: mem::size_of::() as wgpu::BufferAddress, + step_mode: wgpu::InputStepMode::Vertex, + attributes: &[wgpu::VertexAttributeDescriptor { + offset: 0, + shader_location: 0, + format: wgpu::VertexFormat::Float3, + }], + } + } +} + +pub struct SkyboxPipeline { + pub pipeline: wgpu::RenderPipeline, +} + +impl SkyboxPipeline { + pub fn new( + device: &wgpu::Device, + vs_module: &wgpu::ShaderModule, + fs_module: &wgpu::ShaderModule, + sc_desc: &wgpu::SwapChainDescriptor, + layouts: &GlobalsLayouts, + aa_mode: AaMode, + ) -> Self { + let render_pipeline_layout = + device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { + label: Some("Skybox pipeline layout"), + push_constant_ranges: &[], + bind_group_layouts: &[&layouts.globals, &layouts.alt_horizon], + }); + + let samples = match aa_mode { + AaMode::None | AaMode::Fxaa => 1, + // TODO: Ensure sampling in the shader is exactly between the 4 texels + AaMode::SsaaX4 => 1, + AaMode::MsaaX4 => 4, + AaMode::MsaaX8 => 8, + AaMode::MsaaX16 => 16, + }; + + let render_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { + label: Some("Skybox pipeline"), + layout: Some(&render_pipeline_layout), + vertex_stage: wgpu::ProgrammableStageDescriptor { + module: vs_module, + entry_point: "main", + }, + fragment_stage: Some(wgpu::ProgrammableStageDescriptor { + module: fs_module, + entry_point: "main", + }), + rasterization_state: Some(wgpu::RasterizationStateDescriptor { + front_face: wgpu::FrontFace::Ccw, + cull_mode: wgpu::CullMode::Back, + clamp_depth: false, + depth_bias: 0, + depth_bias_slope_scale: 0.0, + depth_bias_clamp: 0.0, + }), + primitive_topology: wgpu::PrimitiveTopology::TriangleList, + color_states: &[wgpu::ColorStateDescriptor { + format: sc_desc.format, + color_blend: wgpu::BlendDescriptor::REPLACE, + alpha_blend: wgpu::BlendDescriptor::REPLACE, + write_mask: wgpu::ColorWrite::ALL, + }], + depth_stencil_state: Some(wgpu::DepthStencilStateDescriptor { + format: wgpu::TextureFormat::Depth24Plus, + depth_write_enabled: true, + depth_compare: wgpu::CompareFunction::LessEqual, + stencil: wgpu::StencilStateDescriptor { + front: wgpu::StencilStateFaceDescriptor::IGNORE, + back: wgpu::StencilStateFaceDescriptor::IGNORE, + read_mask: !0, + write_mask: !0, + }, + }), + vertex_state: wgpu::VertexStateDescriptor { + index_format: wgpu::IndexFormat::Uint16, + vertex_buffers: &[Vertex::desc()], + }, + sample_count: samples, + sample_mask: !0, + alpha_to_coverage_enabled: false, + }); + + Self { + pipeline: render_pipeline, + } + } +} + pub fn create_mesh() -> Mesh { let mut mesh = Mesh::new(); diff --git a/voxygen/src/render/pipelines/sprite.rs b/voxygen/src/render/pipelines/sprite.rs index 87367d547e..ebf283a27c 100644 --- a/voxygen/src/render/pipelines/sprite.rs +++ b/voxygen/src/render/pipelines/sprite.rs @@ -1,73 +1,8 @@ +use super::super::{AaMode, GlobalsLayouts, TerrainLayout}; use core::fmt; use vek::*; use zerocopy::AsBytes; -// gfx_defines! { -// vertex Vertex { -// pos: [f32; 3] = "v_pos", -// // Because we try to restrict terrain sprite data to a 128×128 block -// // we need an offset into the texture atlas. -// atlas_pos: u32 = "v_atlas_pos", -// // ____BBBBBBBBGGGGGGGGRRRRRRRR -// // col: u32 = "v_col", -// // ...AANNN -// // A = AO -// // N = Normal -// norm_ao: u32 = "v_norm_ao", -// } -// -// constant Locals { -// // Each matrix performs rotatation, translation, and scaling, -// relative to the sprite // origin, for all sprite instances. The -// matrix will be in an array indexed by the // sprite instance's -// orientation (0 through 7). mat: [[f32; 4]; 4] = "mat", -// wind_sway: [f32; 4] = "wind_sway", -// offs: [f32; 4] = "offs", -// } -// -// vertex/*constant*/ Instance { -// // Terrain block position and orientation -// pos_ori: u32 = "inst_pos_ori", -// inst_mat0: [f32; 4] = "inst_mat0", -// inst_mat1: [f32; 4] = "inst_mat1", -// inst_mat2: [f32; 4] = "inst_mat2", -// inst_mat3: [f32; 4] = "inst_mat3", -// inst_light: [f32; 4] = "inst_light", -// inst_wind_sway: f32 = "inst_wind_sway", -// } -// -// pipeline pipe { -// vbuf: gfx::VertexBuffer = (), -// ibuf: gfx::InstanceBuffer = (), -// col_lights: gfx::TextureSampler<[f32; 4]> = "t_col_light", -// -// locals: gfx::ConstantBuffer = "u_locals", -// // A sprite instance is a cross between a sprite and a terrain chunk. -// terrain_locals: gfx::ConstantBuffer = -// "u_terrain_locals", globals: gfx::ConstantBuffer = -// "u_globals", lights: gfx::ConstantBuffer = "u_lights", -// shadows: gfx::ConstantBuffer = "u_shadows", -// -// point_shadow_maps: gfx::TextureSampler = "t_point_shadow_maps", -// directed_shadow_maps: gfx::TextureSampler = -// "t_directed_shadow_maps", -// -// alt: gfx::TextureSampler<[f32; 2]> = "t_alt", -// horizon: gfx::TextureSampler<[f32; 4]> = "t_horizon", -// -// noise: gfx::TextureSampler = "t_noise", -// -// // Shadow stuff -// light_shadows: gfx::ConstantBuffer = -// "u_light_shadows", -// -// tgt_color: gfx::BlendTarget = ("tgt_color", -// ColorMask::all(), gfx::preset::blend::ALPHA), tgt_depth_stencil: -// gfx::DepthTarget = gfx::preset::depth::LESS_EQUAL_WRITE, -// // tgt_depth_stencil: gfx::DepthStencilTarget = -// (gfx::preset::depth::LESS_EQUAL_WRITE,Stencil::new(Comparison::Always,0xff, -// (StencilOp::Keep,StencilOp::Keep,StencilOp::Keep))), } - #[repr(C)] #[derive(Copy, Clone, Debug, AsBytes)] pub struct Vertex { @@ -123,6 +58,15 @@ impl Vertex { norm_ao: norm_bits, } } + + fn desc<'a>() -> wgpu::VertexBufferDescriptor<'a> { + use std::mem; + wgpu::VertexBufferDescriptor { + stride: mem::size_of::() as wgpu::BufferAddress, + step_mode: wgpu::InputStepMode::Vertex, + attributes: &wgpu::vertex_attr_array![0 => Float3, 1 => Uint, 2 => Uint], + } + } } #[repr(C)] @@ -162,6 +106,15 @@ impl Instance { inst_wind_sway: wind_sway, } } + + fn desc<'a>() -> wgpu::VertexBufferDescriptor<'a> { + use std::mem; + wgpu::VertexBufferDescriptor { + stride: mem::size_of::() as wgpu::BufferAddress, + step_mode: wgpu::InputStepMode::Instance, + attributes: &wgpu::vertex_attr_array![0 => Uint, 1 => Float4,2 => Float4, 3 => Float4,4 => Float4,5 => Float], + } + } } impl Default for Instance { @@ -191,4 +144,154 @@ impl Locals { offs: [offs.x, offs.y, offs.z, 0.0], } } + + fn layout(device: &wgpu::Device) -> wgpu::BindGroupLayout { + device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { + label: None, + entries: &[wgpu::BindGroupLayoutEntry { + binding: 0, + visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, + ty: wgpu::BindingType::UniformBuffer { + dynamic: false, + min_binding_size: None, + }, + count: None, + }], + }) + } +} + +pub struct SpriteLayout { + pub locals: wgpu::BindGroupLayout, + pub col_lights: wgpu::BindGroupLayout, +} + +impl SpriteLayout { + pub fn new(device: &wgpu::Device) -> Self { + Self { + locals: Locals::layout(device), + col_lights: device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { + label: None, + entries: &[ + wgpu::BindGroupLayoutEntry { + binding: 0, + visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, + ty: wgpu::BindingType::SampledTexture { + component_type: wgpu::TextureComponentType::Float, + dimension: wgpu::TextureViewDimension::D2, + multisampled: false, + }, + count: None, + }, + wgpu::BindGroupLayoutEntry { + binding: 1, + visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, + ty: wgpu::BindingType::Sampler { comparison: false }, + count: None, + }, + ], + }), + } + } +} + +pub struct SpritePipeline { + pub pipeline: wgpu::RenderPipeline, +} + +impl SpritePipeline { + pub fn new( + device: &wgpu::Device, + vs_module: &wgpu::ShaderModule, + fs_module: &wgpu::ShaderModule, + sc_desc: &wgpu::SwapChainDescriptor, + global_layout: &GlobalsLayouts, + layout: &SpriteLayout, + terrain_layout: &TerrainLayout, + aa_mode: AaMode, + ) -> Self { + let render_pipeline_layout = + device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { + label: Some("Sprite pipeline layout"), + push_constant_ranges: &[], + bind_group_layouts: &[ + &global_layout.globals, + &global_layout.alt_horizon, + &global_layout.light, + &global_layout.shadow, + &global_layout.shadow_maps, + &global_layout.light_shadows, + &layout.col_lights, + &layout.locals, + &terrain_layout.locals, + ], + }); + + let samples = match aa_mode { + AaMode::None | AaMode::Fxaa => 1, + // TODO: Ensure sampling in the shader is exactly between the 4 texels + AaMode::SsaaX4 => 1, + AaMode::MsaaX4 => 4, + AaMode::MsaaX8 => 8, + AaMode::MsaaX16 => 16, + }; + + let render_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { + label: Some("Sprite pipeline"), + layout: Some(&render_pipeline_layout), + vertex_stage: wgpu::ProgrammableStageDescriptor { + module: vs_module, + entry_point: "main", + }, + fragment_stage: Some(wgpu::ProgrammableStageDescriptor { + module: fs_module, + entry_point: "main", + }), + rasterization_state: Some(wgpu::RasterizationStateDescriptor { + front_face: wgpu::FrontFace::Ccw, + cull_mode: wgpu::CullMode::Back, + clamp_depth: false, + depth_bias: 0, + depth_bias_slope_scale: 0.0, + depth_bias_clamp: 0.0, + }), + primitive_topology: wgpu::PrimitiveTopology::TriangleList, + color_states: &[wgpu::ColorStateDescriptor { + format: sc_desc.format, + color_blend: wgpu::BlendDescriptor { + src_factor: wgpu::BlendFactor::SrcAlpha, + dst_factor: wgpu::BlendFactor::OneMinusSrcAlpha, + operation: wgpu::BlendOperation::Add, + }, + alpha_blend: wgpu::BlendDescriptor { + src_factor: wgpu::BlendFactor::One, + dst_factor: wgpu::BlendFactor::One, + operation: wgpu::BlendOperation::Add, + }, + write_mask: wgpu::ColorWrite::ALL, + }], + depth_stencil_state: Some(wgpu::DepthStencilStateDescriptor { + format: wgpu::TextureFormat::Depth24Plus, + depth_write_enabled: true, + depth_compare: wgpu::CompareFunction::LessEqual, + stencil: wgpu::StencilStateDescriptor { + front: wgpu::StencilStateFaceDescriptor::IGNORE, + back: wgpu::StencilStateFaceDescriptor::IGNORE, + read_mask: !0, + write_mask: !0, + }, + }), + vertex_state: wgpu::VertexStateDescriptor { + index_format: wgpu::IndexFormat::Uint16, + vertex_buffers: &[Vertex::desc(), Instance::desc()], + }, + sample_count: samples, + sample_mask: !0, + alpha_to_coverage_enabled: false, + }); + + Self { + pipeline: render_pipeline, + } + } } diff --git a/voxygen/src/render/pipelines/terrain.rs b/voxygen/src/render/pipelines/terrain.rs index ba6271b332..26d7f50203 100644 --- a/voxygen/src/render/pipelines/terrain.rs +++ b/voxygen/src/render/pipelines/terrain.rs @@ -1,48 +1,7 @@ +use super::super::{AaMode, GlobalsLayouts}; use vek::*; use zerocopy::AsBytes; -// gfx_defines! { -// vertex Vertex { -// pos_norm: u32 = "v_pos_norm", -// atlas_pos: u32 = "v_atlas_pos", -// } - -// constant Locals { -// model_offs: [f32; 3] = "model_offs", -// load_time: f32 = "load_time", -// atlas_offs: [i32; 4] = "atlas_offs", -// } - -// pipeline pipe { -// vbuf: gfx::VertexBuffer = (), -// col_lights: gfx::TextureSampler<[f32; 4]> = "t_col_light", - -// locals: gfx::ConstantBuffer = "u_locals", -// globals: gfx::ConstantBuffer = "u_globals", -// lights: gfx::ConstantBuffer = "u_lights", -// shadows: gfx::ConstantBuffer = "u_shadows", - -// point_shadow_maps: gfx::TextureSampler = "t_point_shadow_maps", -// directed_shadow_maps: gfx::TextureSampler = -// "t_directed_shadow_maps", - -// alt: gfx::TextureSampler<[f32; 2]> = "t_alt", -// horizon: gfx::TextureSampler<[f32; 4]> = "t_horizon", - -// noise: gfx::TextureSampler = "t_noise", - -// // Shadow stuff -// light_shadows: gfx::ConstantBuffer = -// "u_light_shadows", - -// tgt_color: gfx::RenderTarget = "tgt_color", -// tgt_depth_stencil: gfx::DepthTarget = -// gfx::preset::depth::LESS_EQUAL_WRITE, // tgt_depth_stencil: -// gfx::DepthStencilTarget = -// (gfx::preset::depth::LESS_EQUAL_WRITE,Stencil::new(Comparison::Always,0xff, -// (StencilOp::Keep,StencilOp::Keep,StencilOp::Keep))), } -// } - #[repr(C)] #[derive(Copy, Clone, Debug, AsBytes)] pub struct Vertex { @@ -141,6 +100,15 @@ impl Vertex { pub fn set_bone_idx(&mut self, bone_idx: u8) { self.pos_norm = (self.pos_norm & !(0xF << 27)) | ((bone_idx as u32 & 0xF) << 27); } + + fn desc<'a>() -> wgpu::VertexBufferDescriptor<'a> { + use std::mem; + wgpu::VertexBufferDescriptor { + stride: mem::size_of::() as wgpu::BufferAddress, + step_mode: wgpu::InputStepMode::Vertex, + attributes: &wgpu::vertex_attr_array![0 => Uint,1 => Uint], + } + } } #[repr(C)] @@ -159,4 +127,144 @@ impl Locals { atlas_offs: [0; 4], } } + + fn layout(device: &wgpu::Device) -> wgpu::BindGroupLayout { + device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { + label: None, + entries: &[wgpu::BindGroupLayoutEntry { + binding: 0, + visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, + ty: wgpu::BindingType::UniformBuffer { + dynamic: false, + min_binding_size: None, + }, + count: None, + }], + }) + } +} + +pub struct TerrainLayout { + pub locals: wgpu::BindGroupLayout, + pub col_lights: wgpu::BindGroupLayout, +} + +impl TerrainLayout { + pub fn new(device: &wgpu::Device) -> Self { + Self { + locals: Locals::layout(device), + col_lights: device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { + label: None, + entries: &[ + wgpu::BindGroupLayoutEntry { + binding: 0, + visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, + ty: wgpu::BindingType::SampledTexture { + component_type: wgpu::TextureComponentType::Float, + dimension: wgpu::TextureViewDimension::D2, + multisampled: false, + }, + count: None, + }, + wgpu::BindGroupLayoutEntry { + binding: 1, + visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, + ty: wgpu::BindingType::Sampler { comparison: false }, + count: None, + }, + ], + }), + } + } +} + +pub struct TerrainPipeline { + pub pipeline: wgpu::RenderPipeline, +} + +impl TerrainPipeline { + pub fn new( + device: &wgpu::Device, + vs_module: &wgpu::ShaderModule, + fs_module: &wgpu::ShaderModule, + sc_desc: &wgpu::SwapChainDescriptor, + global_layout: &GlobalsLayouts, + layout: &TerrainLayout, + aa_mode: AaMode, + ) -> Self { + let render_pipeline_layout = + device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { + label: Some("Terrain pipeline layout"), + push_constant_ranges: &[], + bind_group_layouts: &[ + &global_layout.globals, + &global_layout.alt_horizon, + &global_layout.light, + &global_layout.shadow, + &global_layout.shadow_maps, + &global_layout.light_shadows, + &layout.locals, + &layout.col_lights, + ], + }); + + let samples = match aa_mode { + AaMode::None | AaMode::Fxaa => 1, + // TODO: Ensure sampling in the shader is exactly between the 4 texels + AaMode::SsaaX4 => 1, + AaMode::MsaaX4 => 4, + AaMode::MsaaX8 => 8, + AaMode::MsaaX16 => 16, + }; + + let render_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { + label: Some("Terrain pipeline"), + layout: Some(&render_pipeline_layout), + vertex_stage: wgpu::ProgrammableStageDescriptor { + module: vs_module, + entry_point: "main", + }, + fragment_stage: Some(wgpu::ProgrammableStageDescriptor { + module: fs_module, + entry_point: "main", + }), + rasterization_state: Some(wgpu::RasterizationStateDescriptor { + front_face: wgpu::FrontFace::Ccw, + cull_mode: wgpu::CullMode::Back, + clamp_depth: false, + depth_bias: 0, + depth_bias_slope_scale: 0.0, + depth_bias_clamp: 0.0, + }), + primitive_topology: wgpu::PrimitiveTopology::TriangleList, + color_states: &[wgpu::ColorStateDescriptor { + format: sc_desc.format, + color_blend: wgpu::BlendDescriptor::REPLACE, + alpha_blend: wgpu::BlendDescriptor::REPLACE, + write_mask: wgpu::ColorWrite::ALL, + }], + depth_stencil_state: Some(wgpu::DepthStencilStateDescriptor { + format: wgpu::TextureFormat::Depth24Plus, + depth_write_enabled: true, + depth_compare: wgpu::CompareFunction::LessEqual, + stencil: wgpu::StencilStateDescriptor { + front: wgpu::StencilStateFaceDescriptor::IGNORE, + back: wgpu::StencilStateFaceDescriptor::IGNORE, + read_mask: !0, + write_mask: !0, + }, + }), + vertex_state: wgpu::VertexStateDescriptor { + index_format: wgpu::IndexFormat::Uint16, + vertex_buffers: &[Vertex::desc()], + }, + sample_count: samples, + sample_mask: !0, + alpha_to_coverage_enabled: false, + }); + + Self { + pipeline: render_pipeline, + } + } } diff --git a/voxygen/src/render/pipelines/ui.rs b/voxygen/src/render/pipelines/ui.rs index 8685d99896..57e475a609 100644 --- a/voxygen/src/render/pipelines/ui.rs +++ b/voxygen/src/render/pipelines/ui.rs @@ -1,34 +1,7 @@ -use super::super::{Quad, Tri}; +use super::super::{AaMode, GlobalsLayouts, Quad, Tri}; use vek::*; use zerocopy::AsBytes; -// gfx_defines! { -// vertex Vertex { -// pos: [f32; 2] = "v_pos", -// uv: [f32; 2] = "v_uv", -// color: [f32; 4] = "v_color", -// center: [f32; 2] = "v_center", -// mode: u32 = "v_mode", -// } - -// constant Locals { -// pos: [f32; 4] = "w_pos", -// } - -// pipeline pipe { -// vbuf: gfx::VertexBuffer = (), - -// locals: gfx::ConstantBuffer = "u_locals", -// globals: gfx::ConstantBuffer = "u_globals", -// tex: gfx::TextureSampler<[f32; 4]> = "u_tex", - -// scissor: gfx::Scissor = (), - -// tgt_color: gfx::BlendTarget = ("tgt_color", -// gfx::state::ColorMask::all(), gfx::preset::blend::ALPHA), tgt_depth: -// gfx::DepthTarget = gfx::preset::depth::LESS_EQUAL_TEST, } -// } - #[repr(C)] #[derive(Copy, Clone, Debug, AsBytes)] pub struct Vertex { @@ -39,12 +12,40 @@ pub struct Vertex { mode: u32, } +impl Vertex { + fn desc<'a>() -> wgpu::VertexBufferDescriptor<'a> { + use std::mem; + wgpu::VertexBufferDescriptor { + stride: mem::size_of::() as wgpu::BufferAddress, + step_mode: wgpu::InputStepMode::Vertex, + attributes: &wgpu::vertex_attr_array![0 => Float2, 1 => Float2, 2 => Float4, 3 => Float2, 4 => Uint], + } + } +} + #[repr(C)] #[derive(Copy, Clone, Debug, AsBytes)] pub struct Locals { pos: [f32; 4], } +impl Locals { + fn layout(device: &wgpu::Device) -> wgpu::BindGroupLayout { + device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { + label: None, + entries: &[wgpu::BindGroupLayoutEntry { + binding: 0, + visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, + ty: wgpu::BindingType::UniformBuffer { + dynamic: false, + min_binding_size: None, + }, + count: None, + }], + }) + } +} + impl From> for Locals { fn from(pos: Vec4) -> Self { Self { @@ -94,6 +95,130 @@ impl Mode { } } +pub struct UILayout { + pub locals: wgpu::BindGroupLayout, + pub tex: wgpu::BindGroupLayout, +} + +impl UILayout { + pub fn new(device: &wgpu::Device) -> Self { + Self { + locals: Locals::layout(device), + tex: device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { + label: None, + entries: &[ + wgpu::BindGroupLayoutEntry { + binding: 0, + visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, + ty: wgpu::BindingType::SampledTexture { + component_type: wgpu::TextureComponentType::Float, + dimension: wgpu::TextureViewDimension::D2, + multisampled: false, + }, + count: None, + }, + wgpu::BindGroupLayoutEntry { + binding: 1, + visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, + ty: wgpu::BindingType::Sampler { comparison: false }, + count: None, + }, + ], + }), + } + } +} + +pub struct UIPipeline { + pub pipeline: wgpu::RenderPipeline, +} + +impl UIPipeline { + pub fn new( + device: &wgpu::Device, + vs_module: &wgpu::ShaderModule, + fs_module: &wgpu::ShaderModule, + sc_desc: &wgpu::SwapChainDescriptor, + global_layout: &GlobalsLayouts, + layout: &UILayout, + aa_mode: AaMode, + ) -> Self { + let render_pipeline_layout = + device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { + label: Some("UI pipeline layout"), + push_constant_ranges: &[], + bind_group_layouts: &[&global_layout.globals, &layout.locals, &layout.tex], + }); + + let samples = match aa_mode { + AaMode::None | AaMode::Fxaa => 1, + // TODO: Ensure sampling in the shader is exactly between the 4 texels + AaMode::SsaaX4 => 1, + AaMode::MsaaX4 => 4, + AaMode::MsaaX8 => 8, + AaMode::MsaaX16 => 16, + }; + + let render_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { + label: Some("UI pipeline"), + layout: Some(&render_pipeline_layout), + vertex_stage: wgpu::ProgrammableStageDescriptor { + module: vs_module, + entry_point: "main", + }, + fragment_stage: Some(wgpu::ProgrammableStageDescriptor { + module: fs_module, + entry_point: "main", + }), + rasterization_state: Some(wgpu::RasterizationStateDescriptor { + front_face: wgpu::FrontFace::Ccw, + cull_mode: wgpu::CullMode::Back, + clamp_depth: false, + depth_bias: 0, + depth_bias_slope_scale: 0.0, + depth_bias_clamp: 0.0, + }), + primitive_topology: wgpu::PrimitiveTopology::TriangleList, + color_states: &[wgpu::ColorStateDescriptor { + format: sc_desc.format, + color_blend: wgpu::BlendDescriptor { + src_factor: wgpu::BlendFactor::SrcAlpha, + dst_factor: wgpu::BlendFactor::OneMinusSrcAlpha, + operation: wgpu::BlendOperation::Add, + }, + alpha_blend: wgpu::BlendDescriptor { + src_factor: wgpu::BlendFactor::One, + dst_factor: wgpu::BlendFactor::One, + operation: wgpu::BlendOperation::Add, + }, + write_mask: wgpu::ColorWrite::ALL, + }], + depth_stencil_state: Some(wgpu::DepthStencilStateDescriptor { + format: wgpu::TextureFormat::Depth24Plus, + depth_write_enabled: false, + depth_compare: wgpu::CompareFunction::LessEqual, + stencil: wgpu::StencilStateDescriptor { + front: wgpu::StencilStateFaceDescriptor::IGNORE, + back: wgpu::StencilStateFaceDescriptor::IGNORE, + read_mask: !0, + write_mask: !0, + }, + }), + vertex_state: wgpu::VertexStateDescriptor { + index_format: wgpu::IndexFormat::Uint16, + vertex_buffers: &[Vertex::desc()], + }, + sample_count: samples, + sample_mask: !0, + alpha_to_coverage_enabled: false, + }); + + Self { + pipeline: render_pipeline, + } + } +} + pub fn create_quad( rect: Aabr, uv_rect: Aabr, diff --git a/voxygen/src/render/renderer.rs b/voxygen/src/render/renderer.rs index f7f6a32c03..84e6fda19f 100644 --- a/voxygen/src/render/renderer.rs +++ b/voxygen/src/render/renderer.rs @@ -5,7 +5,7 @@ use super::{ model::Model, pipelines::{ clouds, figure, fluid, lod_terrain, particle, postprocess, shadow, skybox, sprite, terrain, - ui, GlobalModel, Globals, + ui, GlobalsLayouts, }, texture::Texture, AaMode, AddressMode, CloudMode, FilterMode, FluidMode, LightingMode, RenderError, RenderMode, @@ -16,76 +16,9 @@ use common::{ span, }; use core::convert::TryFrom; -use glsl_include::Context as IncludeContext; use tracing::{error, info, warn}; use vek::*; -// /// Represents the format of the pre-processed color target. -// // TODO: `(gfx::format::R11_G11_B10, gfx::format::Float)` would be better in -// // theory, but it doesn't seem to work -// pub type TgtColorFmt = gfx::format::Rgba16F; -// /// Represents the format of the pre-processed depth and stencil target. -// pub type TgtDepthStencilFmt = gfx::format::Depth; -// -// /// Represents the format of the window's color target. -// pub type WinColorFmt = gfx::format::Srgba8; -// /// Represents the format of the window's depth target. -// pub type WinDepthFmt = gfx::format::Depth; -// -// /// Represents the format of the pre-processed shadow depth target. -// pub type ShadowDepthStencilFmt = gfx::format::Depth; -// -// /// A handle to a pre-processed color target. -// pub type TgtColorView = gfx::handle::RenderTargetView; /// A handle to a pre-processed depth target. -// pub type TgtDepthStencilView = -// gfx::handle::DepthStencilView; -// -// /// A handle to a window color target. -// pub type WinColorView = gfx::handle::RenderTargetView; /// A handle to a window depth target. -// pub type WinDepthView = gfx::handle::DepthStencilView; -// -// /// Represents the format of LOD shadows. -// pub type LodTextureFmt = (gfx::format::R8_G8_B8_A8, gfx::format::Unorm); -// -// /// Represents the format of LOD altitudes. -// pub type LodAltFmt = (gfx::format::R16_G16, gfx::format::Unorm); -// -// /// Represents the format of LOD map colors. -// pub type LodColorFmt = (gfx::format::R8_G8_B8_A8, gfx::format::Srgb); -// -// /// Represents the format of greedy meshed color-light textures. -// pub type ColLightFmt = (gfx::format::R8_G8_B8_A8, gfx::format::Unorm); -// -// /// A handle to a shadow depth target. -// pub type ShadowDepthStencilView = -// gfx::handle::DepthStencilView; /// A handle to a shadow depth target as a resource. -// pub type ShadowResourceView = gfx::handle::ShaderResourceView< -// gfx_backend::Resources, -// ::View, -// >; -// -// /// A handle to a render color target as a resource. -// pub type TgtColorRes = gfx::handle::ShaderResourceView< -// gfx_backend::Resources, -// ::View, -// >; -// -// /// A handle to a render depth target as a resource. -// pub type TgtDepthRes = gfx::handle::ShaderResourceView< -// gfx_backend::Resources, -// ::View, -// >; -// -// /// A handle to a greedy meshed color-light texture as a resource. -// pub type ColLightRes = gfx::handle::ShaderResourceView< -// gfx_backend::Resources, -// ::View, -// >; /// A type representing data that can be converted to an immutable texture map /// of ColLight data (used for texture atlases created during greedy meshing). pub type ColLightInfo = (Vec<[u8; 4]>, Vec2); @@ -225,9 +158,23 @@ pub struct ShadowMapRenderer { point_depth_stencil_view: wgpu::TextureView, point_sampler: wgpu::Sampler, - point_pipeline: wgpu::RenderPipeline, - terrain_directed_pipeline: wgpu::RenderPipeline, - figure_directed_pipeline: wgpu::RenderPipeline, + point_pipeline: shadow::ShadowPipeline, + terrain_directed_pipeline: shadow::ShadowPipeline, + figure_directed_pipeline: shadow::ShadowFigurePipeline, + layout: shadow::ShadowLayout, +} + +/// A type that stores all the layouts associated with this renderer. +pub struct Layouts { + pub(self) global: GlobalsLayouts, + + pub(self) figure: figure::FigureLayout, + pub(self) fluid: fluid::FluidLayout, + pub(self) postprocess: postprocess::PostProcessLayout, + pub(self) shadow: shadow::ShadowLayout, + pub(self) sprite: sprite::SpriteLayout, + pub(self) terrain: terrain::TerrainLayout, + pub(self) ui: ui::UILayout, } /// A type that encapsulates rendering state. `Renderer` is central to Voxygen's @@ -251,17 +198,20 @@ pub struct Renderer { shadow_map: Option, - skybox_pipeline: wgpu::RenderPipeline, - figure_pipeline: wgpu::RenderPipeline, - terrain_pipeline: wgpu::RenderPipeline, - fluid_pipeline: wgpu::RenderPipeline, - sprite_pipeline: wgpu::RenderPipeline, - particle_pipeline: wgpu::RenderPipeline, - ui_pipeline: wgpu::RenderPipeline, - lod_terrain_pipeline: wgpu::RenderPipeline, - clouds_pipeline: wgpu::RenderPipeline, - postprocess_pipeline: wgpu::RenderPipeline, - player_shadow_pipeline: wgpu::RenderPipeline, + layouts: Layouts, + + figure_pipeline: figure::FigurePipeline, + fluid_pipeline: fluid::FluidPipeline, + lod_terrain_pipeline: lod_terrain::LodTerrainPipeline, + particle_pipeline: particle::ParticlePipeline, + //clouds_pipeline: wgpu::RenderPipeline, + postprocess_pipeline: postprocess::PostProcessPipeline, + // Consider reenabling at some time + // player_shadow_pipeline: figure::FigurePipeline, + skybox_pipeline: skybox::SkyboxPipeline, + sprite_pipeline: sprite::SpritePipeline, + terrain_pipeline: terrain::TerrainPipeline, + ui_pipeline: ui::UIPipeline, shaders: AssetHandle, @@ -347,6 +297,30 @@ impl Renderer { let shaders = Shaders::load_expect(""); + let layouts = { + let global = GlobalsLayouts::new(&device); + + let figure = figure::FigureLayout::new(&device); + let fluid = fluid::FluidLayout::new(&device); + let postprocess = postprocess::PostProcessLayout::new(&device); + let shadow = shadow::ShadowLayout::new(&device); + let sprite = sprite::SpriteLayout::new(&device); + let terrain = terrain::TerrainLayout::new(&device); + let ui = ui::UILayout::new(&device); + + Layouts { + global, + + figure, + fluid, + postprocess, + shadow, + sprite, + terrain, + ui, + } + }; + let ( skybox_pipeline, figure_pipeline, @@ -358,13 +332,13 @@ impl Renderer { lod_terrain_pipeline, clouds_pipeline, postprocess_pipeline, - player_shadow_pipeline, + //player_shadow_pipeline, point_shadow_pipeline, terrain_directed_shadow_pipeline, figure_directed_shadow_pipeline, ) = create_pipelines( &device, - &mode, + &layouts & mode, shadow_views.is_some(), )?; @@ -390,6 +364,9 @@ impl Renderer { directed_res, directed_sampler, ) = shadow_views; + + let layout = shadow::ShadowLayout::new(&device); + Some(ShadowMapRenderer { // point_encoder: factory.create_command_buffer().into(), // directed_encoder: factory.create_command_buffer().into(), @@ -402,6 +379,8 @@ impl Renderer { point_pipeline, terrain_directed_pipeline, figure_directed_pipeline, + + layout, }) } else { None @@ -443,6 +422,8 @@ impl Renderer { shadow_map, + layouts, + skybox_pipeline, figure_pipeline, terrain_pipeline, @@ -453,9 +434,9 @@ impl Renderer { lod_terrain_pipeline, clouds_pipeline, postprocess_pipeline, - player_shadow_pipeline, - shaders, + //player_shadow_pipeline, + shader_reload_indicator, noise_tex, @@ -869,32 +850,32 @@ impl Renderer { self.encoder.clear_depth(&self.win_depth_view, 1.0); } - /// Set up shadow rendering. - pub fn start_shadows(&mut self) { - if !self.mode.shadow.is_map() { - return; - } - if let Some(_shadow_map) = self.shadow_map.as_mut() { - self.encoder.flush(&mut self.device); - Self::set_depth_clamp(&mut self.device, true); - } - } + // /// Set up shadow rendering. + // pub fn start_shadows(&mut self) { + // if !self.mode.shadow.is_map() { + // return; + // } + // if let Some(_shadow_map) = self.shadow_map.as_mut() { + // self.encoder.flush(&mut self.device); + // Self::set_depth_clamp(&mut self.device, true); + // } + // } - /// Perform all queued draw calls for global.shadows. - pub fn flush_shadows(&mut self) { - if !self.mode.shadow.is_map() { - return; - } - if let Some(_shadow_map) = self.shadow_map.as_mut() { - let point_encoder = &mut self.encoder; - // let point_encoder = &mut shadow_map.point_encoder; - point_encoder.flush(&mut self.device); - // let directed_encoder = &mut shadow_map.directed_encoder; - // directed_encoder.flush(&mut self.device); - // Reset depth clamping. - Self::set_depth_clamp(&mut self.device, false); - } - } + // /// Perform all queued draw calls for global.shadows. + // pub fn flush_shadows(&mut self) { + // if !self.mode.shadow.is_map() { + // return; + // } + // if let Some(_shadow_map) = self.shadow_map.as_mut() { + // let point_encoder = &mut self.encoder; + // // let point_encoder = &mut shadow_map.point_encoder; + // point_encoder.flush(&mut self.device); + // // let directed_encoder = &mut shadow_map.directed_encoder; + // // directed_encoder.flush(&mut self.device); + // // Reset depth clamping. + // Self::set_depth_clamp(&mut self.device, false); + // } + // } /// Perform all queued draw calls for this frame and clean up discarded /// items. @@ -1164,742 +1145,755 @@ impl Renderer { // raw_data).unwrap(), )) } - /// Queue the rendering of the provided skybox model in the upcoming frame. - pub fn render_skybox( - &mut self, - model: &Model, - global: &GlobalModel, - locals: &Consts, - lod: &lod_terrain::LodData, - ) { - self.encoder.draw( - &gfx::Slice { - start: model.vertex_range().start, - end: model.vertex_range().end, - base_vertex: 0, - instances: None, - buffer: gfx::IndexBuffer::Auto, - }, - &self.skybox_pipeline.pso, - &skybox::pipe::Data { - vbuf: model.vbuf.clone(), - locals: locals.buf.clone(), - globals: global.globals.buf.clone(), - noise: (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()), - alt: (lod.alt.srv.clone(), lod.alt.sampler.clone()), - horizon: (lod.horizon.srv.clone(), lod.horizon.sampler.clone()), - tgt_color: self.tgt_color_view.clone(), - tgt_depth_stencil: (self.tgt_depth_stencil_view.clone()/* , (1, 1) */), - }, - ); - } + // /// Queue the rendering of the provided skybox model in the upcoming frame. + // pub fn render_skybox( + // &mut self, + // model: &Model, + // global: &GlobalModel, + // locals: &Consts, + // lod: &lod_terrain::LodData, + // ) { + // self.encoder.draw( + // &gfx::Slice { + // start: model.vertex_range().start, + // end: model.vertex_range().end, + // base_vertex: 0, + // instances: None, + // buffer: gfx::IndexBuffer::Auto, + // }, + // &self.skybox_pipeline.pso, + // &skybox::pipe::Data { + // vbuf: model.vbuf.clone(), + // locals: locals.buf.clone(), + // globals: global.globals.buf.clone(), + // noise: (self.noise_tex.srv.clone(), + // self.noise_tex.sampler.clone()), alt: (lod.alt.srv.clone(), + // lod.alt.sampler.clone()), horizon: (lod.horizon.srv.clone(), + // lod.horizon.sampler.clone()), tgt_color: + // self.tgt_color_view.clone(), tgt_depth_stencil: + // (self.tgt_depth_stencil_view.clone()/* , (1, 1) */), }, + // ); + // } - /// Queue the rendering of the provided figure model in the upcoming frame. - pub fn render_figure( - &mut self, - model: &figure::FigureModel, - col_lights: &Texture, - global: &GlobalModel, - locals: &Consts, - bones: &Consts, - lod: &lod_terrain::LodData, - ) { - let (point_shadow_maps, directed_shadow_maps) = - if let Some(shadow_map) = &mut self.shadow_map { - ( - ( - shadow_map.point_res.clone(), - shadow_map.point_sampler.clone(), - ), - ( - shadow_map.directed_res.clone(), - shadow_map.directed_sampler.clone(), - ), - ) - } else { - ( - (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()), - (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()), - ) - }; - let model = &model.opaque; + // /// Queue the rendering of the provided figure model in the upcoming frame. + // pub fn render_figure( + // &mut self, + // model: &figure::FigureModel, + // col_lights: &Texture, + // global: &GlobalModel, + // locals: &Consts, + // bones: &Consts, + // lod: &lod_terrain::LodData, + // ) { + // let (point_shadow_maps, directed_shadow_maps) = + // if let Some(shadow_map) = &mut self.shadow_map { + // ( + // ( + // shadow_map.point_res.clone(), + // shadow_map.point_sampler.clone(), + // ), + // ( + // shadow_map.directed_res.clone(), + // shadow_map.directed_sampler.clone(), + // ), + // ) + // } else { + // ( + // (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()), + // (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()), + // ) + // }; + // let model = &model.opaque; - self.encoder.draw( - &gfx::Slice { - start: model.vertex_range().start, - end: model.vertex_range().end, - base_vertex: 0, - instances: None, - buffer: gfx::IndexBuffer::Auto, - }, - &self.figure_pipeline.pso, - &figure::pipe::Data { - vbuf: model.vbuf.clone(), - col_lights: (col_lights.srv.clone(), col_lights.sampler.clone()), - locals: locals.buf.clone(), - globals: global.globals.buf.clone(), - bones: bones.buf.clone(), - lights: global.lights.buf.clone(), - shadows: global.shadows.buf.clone(), - light_shadows: global.shadow_mats.buf.clone(), - point_shadow_maps, - directed_shadow_maps, - noise: (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()), - alt: (lod.alt.srv.clone(), lod.alt.sampler.clone()), - horizon: (lod.horizon.srv.clone(), lod.horizon.sampler.clone()), - tgt_color: self.tgt_color_view.clone(), - tgt_depth_stencil: (self.tgt_depth_stencil_view.clone()/* , (1, 1) */), - }, - ); - } + // self.encoder.draw( + // &gfx::Slice { + // start: model.vertex_range().start, + // end: model.vertex_range().end, + // base_vertex: 0, + // instances: None, + // buffer: gfx::IndexBuffer::Auto, + // }, + // &self.figure_pipeline.pso, + // &figure::pipe::Data { + // vbuf: model.vbuf.clone(), + // col_lights: (col_lights.srv.clone(), col_lights.sampler.clone()), + // locals: locals.buf.clone(), + // globals: global.globals.buf.clone(), + // bones: bones.buf.clone(), + // lights: global.lights.buf.clone(), + // shadows: global.shadows.buf.clone(), + // light_shadows: global.shadow_mats.buf.clone(), + // point_shadow_maps, + // directed_shadow_maps, + // noise: (self.noise_tex.srv.clone(), + // self.noise_tex.sampler.clone()), alt: (lod.alt.srv.clone(), + // lod.alt.sampler.clone()), horizon: (lod.horizon.srv.clone(), + // lod.horizon.sampler.clone()), tgt_color: + // self.tgt_color_view.clone(), tgt_depth_stencil: + // (self.tgt_depth_stencil_view.clone()/* , (1, 1) */), }, + // ); + // } - /// Queue the rendering of the player silhouette in the upcoming frame. - pub fn render_player_shadow( - &mut self, - _model: &figure::FigureModel, - _col_lights: &Texture, - _global: &GlobalModel, - _bones: &Consts, - _lod: &lod_terrain::LodData, - _locals: &Consts, - ) { - // FIXME: Consider reenabling at some point. - /* let (point_shadow_maps, directed_shadow_maps) = - if let Some(shadow_map) = &mut self.shadow_map { - ( - ( - shadow_map.point_res.clone(), - shadow_map.point_sampler.clone(), - ), - ( - shadow_map.directed_res.clone(), - shadow_map.directed_sampler.clone(), - ), - ) - } else { - ( - (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()), - (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()), - ) - }; - let model = &model.opaque; + // /// Queue the rendering of the player silhouette in the upcoming frame. + // pub fn render_player_shadow( + // &mut self, + // _model: &figure::FigureModel, + // _col_lights: &Texture, + // _global: &GlobalModel, + // _bones: &Consts, + // _lod: &lod_terrain::LodData, + // _locals: &Consts, + // ) { + // // FIXME: Consider reenabling at some point. + // /* let (point_shadow_maps, directed_shadow_maps) = + // if let Some(shadow_map) = &mut self.shadow_map { + // ( + // ( + // shadow_map.point_res.clone(), + // shadow_map.point_sampler.clone(), + // ), + // ( + // shadow_map.directed_res.clone(), + // shadow_map.directed_sampler.clone(), + // ), + // ) + // } else { + // ( + // (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()), + // (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()), + // ) + // }; + // let model = &model.opaque; - self.encoder.draw( - &gfx::Slice { - start: model.vertex_range().start, - end: model.vertex_range().end, - base_vertex: 0, - instances: None, - buffer: gfx::IndexBuffer::Auto, - }, - &self.player_shadow_pipeline.pso, - &figure::pipe::Data { - vbuf: model.vbuf.clone(), - col_lights: (col_lights.srv.clone(), col_lights.sampler.clone()), - locals: locals.buf.clone(), - globals: global.globals.buf.clone(), - bones: bones.buf.clone(), - lights: global.lights.buf.clone(), - shadows: global.shadows.buf.clone(), - light_shadows: global.shadow_mats.buf.clone(), - point_shadow_maps, - directed_shadow_maps, - noise: (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()), - alt: (lod.alt.srv.clone(), lod.alt.sampler.clone()), - horizon: (lod.horizon.srv.clone(), lod.horizon.sampler.clone()), - tgt_color: self.tgt_color_view.clone(), - tgt_depth_stencil: (self.tgt_depth_stencil_view.clone()/* , (0, 0) */), - }, - ); */ - } + // self.encoder.draw( + // &gfx::Slice { + // start: model.vertex_range().start, + // end: model.vertex_range().end, + // base_vertex: 0, + // instances: None, + // buffer: gfx::IndexBuffer::Auto, + // }, + // &self.player_shadow_pipeline.pso, + // &figure::pipe::Data { + // vbuf: model.vbuf.clone(), + // col_lights: (col_lights.srv.clone(), col_lights.sampler.clone()), + // locals: locals.buf.clone(), + // globals: global.globals.buf.clone(), + // bones: bones.buf.clone(), + // lights: global.lights.buf.clone(), + // shadows: global.shadows.buf.clone(), + // light_shadows: global.shadow_mats.buf.clone(), + // point_shadow_maps, + // directed_shadow_maps, + // noise: (self.noise_tex.srv.clone(), + // self.noise_tex.sampler.clone()), alt: (lod.alt.srv.clone(), + // lod.alt.sampler.clone()), horizon: (lod.horizon.srv.clone(), + // lod.horizon.sampler.clone()), tgt_color: + // self.tgt_color_view.clone(), tgt_depth_stencil: + // (self.tgt_depth_stencil_view.clone()/* , (0, 0) */), }, + // ); */ + // } - /// Queue the rendering of the player model in the upcoming frame. - pub fn render_player( - &mut self, - model: &figure::FigureModel, - col_lights: &Texture, - global: &GlobalModel, - locals: &Consts, - bones: &Consts, - lod: &lod_terrain::LodData, - ) { - let (point_shadow_maps, directed_shadow_maps) = - if let Some(shadow_map) = &mut self.shadow_map { - ( - ( - shadow_map.point_res.clone(), - shadow_map.point_sampler.clone(), - ), - ( - shadow_map.directed_res.clone(), - shadow_map.directed_sampler.clone(), - ), - ) - } else { - ( - (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()), - (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()), - ) - }; - let model = &model.opaque; + // /// Queue the rendering of the player model in the upcoming frame. + // pub fn render_player( + // &mut self, + // model: &figure::FigureModel, + // col_lights: &Texture, + // global: &GlobalModel, + // locals: &Consts, + // bones: &Consts, + // lod: &lod_terrain::LodData, + // ) { + // let (point_shadow_maps, directed_shadow_maps) = + // if let Some(shadow_map) = &mut self.shadow_map { + // ( + // ( + // shadow_map.point_res.clone(), + // shadow_map.point_sampler.clone(), + // ), + // ( + // shadow_map.directed_res.clone(), + // shadow_map.directed_sampler.clone(), + // ), + // ) + // } else { + // ( + // (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()), + // (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()), + // ) + // }; + // let model = &model.opaque; - self.encoder.draw( - &gfx::Slice { - start: model.vertex_range().start, - end: model.vertex_range().end, - base_vertex: 0, - instances: None, - buffer: gfx::IndexBuffer::Auto, - }, - &self.figure_pipeline.pso, - &figure::pipe::Data { - vbuf: model.vbuf.clone(), - col_lights: (col_lights.srv.clone(), col_lights.sampler.clone()), - locals: locals.buf.clone(), - globals: global.globals.buf.clone(), - bones: bones.buf.clone(), - lights: global.lights.buf.clone(), - shadows: global.shadows.buf.clone(), - light_shadows: global.shadow_mats.buf.clone(), - point_shadow_maps, - directed_shadow_maps, - noise: (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()), - alt: (lod.alt.srv.clone(), lod.alt.sampler.clone()), - horizon: (lod.horizon.srv.clone(), lod.horizon.sampler.clone()), - tgt_color: self.tgt_color_view.clone(), - tgt_depth_stencil: (self.tgt_depth_stencil_view.clone()/* , (1, 1) */), - }, - ); - } + // self.encoder.draw( + // &gfx::Slice { + // start: model.vertex_range().start, + // end: model.vertex_range().end, + // base_vertex: 0, + // instances: None, + // buffer: gfx::IndexBuffer::Auto, + // }, + // &self.figure_pipeline.pso, + // &figure::pipe::Data { + // vbuf: model.vbuf.clone(), + // col_lights: (col_lights.srv.clone(), col_lights.sampler.clone()), + // locals: locals.buf.clone(), + // globals: global.globals.buf.clone(), + // bones: bones.buf.clone(), + // lights: global.lights.buf.clone(), + // shadows: global.shadows.buf.clone(), + // light_shadows: global.shadow_mats.buf.clone(), + // point_shadow_maps, + // directed_shadow_maps, + // noise: (self.noise_tex.srv.clone(), + // self.noise_tex.sampler.clone()), alt: (lod.alt.srv.clone(), + // lod.alt.sampler.clone()), horizon: (lod.horizon.srv.clone(), + // lod.horizon.sampler.clone()), tgt_color: + // self.tgt_color_view.clone(), tgt_depth_stencil: + // (self.tgt_depth_stencil_view.clone()/* , (1, 1) */), }, + // ); + // } - /// Queue the rendering of the provided terrain chunk model in the upcoming - /// frame. - pub fn render_terrain_chunk( - &mut self, - model: &Model, - col_lights: &Texture, - global: &GlobalModel, - locals: &Consts, - lod: &lod_terrain::LodData, - ) { - let (point_shadow_maps, directed_shadow_maps) = - if let Some(shadow_map) = &mut self.shadow_map { - ( - ( - shadow_map.point_res.clone(), - shadow_map.point_sampler.clone(), - ), - ( - shadow_map.directed_res.clone(), - shadow_map.directed_sampler.clone(), - ), - ) - } else { - ( - (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()), - (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()), - ) - }; + // /// Queue the rendering of the provided terrain chunk model in the upcoming + // /// frame. + // pub fn render_terrain_chunk( + // &mut self, + // model: &Model, + // col_lights: &Texture, + // global: &GlobalModel, + // locals: &Consts, + // lod: &lod_terrain::LodData, + // ) { + // let (point_shadow_maps, directed_shadow_maps) = + // if let Some(shadow_map) = &mut self.shadow_map { + // ( + // ( + // shadow_map.point_res.clone(), + // shadow_map.point_sampler.clone(), + // ), + // ( + // shadow_map.directed_res.clone(), + // shadow_map.directed_sampler.clone(), + // ), + // ) + // } else { + // ( + // (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()), + // (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()), + // ) + // }; - self.encoder.draw( - &gfx::Slice { - start: model.vertex_range().start, - end: model.vertex_range().end, - base_vertex: 0, - instances: None, - buffer: gfx::IndexBuffer::Auto, - }, - &self.terrain_pipeline.pso, - &terrain::pipe::Data { - vbuf: model.vbuf.clone(), - // TODO: Consider splitting out texture atlas data into a separate vertex buffer, - // since we don't need it for things like global.shadows. - col_lights: (col_lights.srv.clone(), col_lights.sampler.clone()), - locals: locals.buf.clone(), - globals: global.globals.buf.clone(), - lights: global.lights.buf.clone(), - shadows: global.shadows.buf.clone(), - light_shadows: global.shadow_mats.buf.clone(), - point_shadow_maps, - directed_shadow_maps, - noise: (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()), - alt: (lod.alt.srv.clone(), lod.alt.sampler.clone()), - horizon: (lod.horizon.srv.clone(), lod.horizon.sampler.clone()), - tgt_color: self.tgt_color_view.clone(), - tgt_depth_stencil: (self.tgt_depth_stencil_view.clone()/* , (1, 1) */), - }, - ); - } + // self.encoder.draw( + // &gfx::Slice { + // start: model.vertex_range().start, + // end: model.vertex_range().end, + // base_vertex: 0, + // instances: None, + // buffer: gfx::IndexBuffer::Auto, + // }, + // &self.terrain_pipeline.pso, + // &terrain::pipe::Data { + // vbuf: model.vbuf.clone(), + // // TODO: Consider splitting out texture atlas data into a + // separate vertex buffer, // since we don't need it for things + // like global.shadows. col_lights: (col_lights.srv.clone(), + // col_lights.sampler.clone()), locals: locals.buf.clone(), + // globals: global.globals.buf.clone(), + // lights: global.lights.buf.clone(), + // shadows: global.shadows.buf.clone(), + // light_shadows: global.shadow_mats.buf.clone(), + // point_shadow_maps, + // directed_shadow_maps, + // noise: (self.noise_tex.srv.clone(), + // self.noise_tex.sampler.clone()), alt: (lod.alt.srv.clone(), + // lod.alt.sampler.clone()), horizon: (lod.horizon.srv.clone(), + // lod.horizon.sampler.clone()), tgt_color: + // self.tgt_color_view.clone(), tgt_depth_stencil: + // (self.tgt_depth_stencil_view.clone()/* , (1, 1) */), }, + // ); + // } - /// Queue the rendering of a shadow map from a point light in the upcoming - /// frame. - pub fn render_shadow_point( - &mut self, - model: &Model, - global: &GlobalModel, - terrain_locals: &Consts, - locals: &Consts, - ) { - if !self.mode.shadow.is_map() { - return; - } - // NOTE: Don't render shadows if the shader is not supported. - let shadow_map = if let Some(shadow_map) = &mut self.shadow_map { - shadow_map - } else { - return; - }; + // /// Queue the rendering of a shadow map from a point light in the upcoming + // /// frame. + // pub fn render_shadow_point( + // &mut self, + // model: &Model, + // global: &GlobalModel, + // terrain_locals: &Consts, + // locals: &Consts, + // ) { + // if !self.mode.shadow.is_map() { + // return; + // } + // // NOTE: Don't render shadows if the shader is not supported. + // let shadow_map = if let Some(shadow_map) = &mut self.shadow_map { + // shadow_map + // } else { + // return; + // }; - // let point_encoder = &mut shadow_map.point_encoder; - let point_encoder = &mut self.encoder; - point_encoder.draw( - &gfx::Slice { - start: model.vertex_range().start, - end: model.vertex_range().end, - base_vertex: 0, - instances: None, - buffer: gfx::IndexBuffer::Auto, - }, - &shadow_map.point_pipeline.pso, - &shadow::pipe::Data { - // Terrain vertex stuff - vbuf: model.vbuf.clone(), - locals: terrain_locals.buf.clone(), - globals: global.globals.buf.clone(), + // // let point_encoder = &mut shadow_map.point_encoder; + // let point_encoder = &mut self.encoder; + // point_encoder.draw( + // &gfx::Slice { + // start: model.vertex_range().start, + // end: model.vertex_range().end, + // base_vertex: 0, + // instances: None, + // buffer: gfx::IndexBuffer::Auto, + // }, + // &shadow_map.point_pipeline.pso, + // &shadow::pipe::Data { + // // Terrain vertex stuff + // vbuf: model.vbuf.clone(), + // locals: terrain_locals.buf.clone(), + // globals: global.globals.buf.clone(), - // Shadow stuff - light_shadows: locals.buf.clone(), - tgt_depth_stencil: shadow_map.point_depth_stencil_view.clone(), - }, - ); - } + // // Shadow stuff + // light_shadows: locals.buf.clone(), + // tgt_depth_stencil: shadow_map.point_depth_stencil_view.clone(), + // }, + // ); + // } - /// Queue the rendering of terrain shadow map from all directional lights in - /// the upcoming frame. - pub fn render_terrain_shadow_directed( - &mut self, - model: &Model, - global: &GlobalModel, - terrain_locals: &Consts, - locals: &Consts, - ) { - if !self.mode.shadow.is_map() { - return; - } - // NOTE: Don't render shadows if the shader is not supported. - let shadow_map = if let Some(shadow_map) = &mut self.shadow_map { - shadow_map - } else { - return; - }; + // /// Queue the rendering of terrain shadow map from all directional lights in + // /// the upcoming frame. + // pub fn render_terrain_shadow_directed( + // &mut self, + // model: &Model, + // global: &GlobalModel, + // terrain_locals: &Consts, + // locals: &Consts, + // ) { + // if !self.mode.shadow.is_map() { + // return; + // } + // // NOTE: Don't render shadows if the shader is not supported. + // let shadow_map = if let Some(shadow_map) = &mut self.shadow_map { + // shadow_map + // } else { + // return; + // }; - // let directed_encoder = &mut shadow_map.directed_encoder; - let directed_encoder = &mut self.encoder; - directed_encoder.draw( - &gfx::Slice { - start: model.vertex_range().start, - end: model.vertex_range().end, - base_vertex: 0, - instances: None, - buffer: gfx::IndexBuffer::Auto, - }, - &shadow_map.terrain_directed_pipeline.pso, - &shadow::pipe::Data { - // Terrain vertex stuff - vbuf: model.vbuf.clone(), - locals: terrain_locals.buf.clone(), - globals: global.globals.buf.clone(), + // // let directed_encoder = &mut shadow_map.directed_encoder; + // let directed_encoder = &mut self.encoder; + // directed_encoder.draw( + // &gfx::Slice { + // start: model.vertex_range().start, + // end: model.vertex_range().end, + // base_vertex: 0, + // instances: None, + // buffer: gfx::IndexBuffer::Auto, + // }, + // &shadow_map.terrain_directed_pipeline.pso, + // &shadow::pipe::Data { + // // Terrain vertex stuff + // vbuf: model.vbuf.clone(), + // locals: terrain_locals.buf.clone(), + // globals: global.globals.buf.clone(), - // Shadow stuff - light_shadows: locals.buf.clone(), - tgt_depth_stencil: shadow_map.directed_depth_stencil_view.clone(), - }, - ); - } + // // Shadow stuff + // light_shadows: locals.buf.clone(), + // tgt_depth_stencil: + // shadow_map.directed_depth_stencil_view.clone(), }, + // ); + // } - /// Queue the rendering of figure shadow map from all directional lights in - /// the upcoming frame. - pub fn render_figure_shadow_directed( - &mut self, - model: &figure::FigureModel, - global: &GlobalModel, - figure_locals: &Consts, - bones: &Consts, - locals: &Consts, - ) { - if !self.mode.shadow.is_map() { - return; - } - // NOTE: Don't render shadows if the shader is not supported. - let shadow_map = if let Some(shadow_map) = &mut self.shadow_map { - shadow_map - } else { - return; - }; - let model = &model.opaque; + // /// Queue the rendering of figure shadow map from all directional lights in + // /// the upcoming frame. + // pub fn render_figure_shadow_directed( + // &mut self, + // model: &figure::FigureModel, + // global: &GlobalModel, + // figure_locals: &Consts, + // bones: &Consts, + // locals: &Consts, + // ) { + // if !self.mode.shadow.is_map() { + // return; + // } + // // NOTE: Don't render shadows if the shader is not supported. + // let shadow_map = if let Some(shadow_map) = &mut self.shadow_map { + // shadow_map + // } else { + // return; + // }; + // let model = &model.opaque; - // let directed_encoder = &mut shadow_map.directed_encoder; - let directed_encoder = &mut self.encoder; - directed_encoder.draw( - &gfx::Slice { - start: model.vertex_range().start, - end: model.vertex_range().end, - base_vertex: 0, - instances: None, - buffer: gfx::IndexBuffer::Auto, - }, - &shadow_map.figure_directed_pipeline.pso, - &shadow::figure_pipe::Data { - // Terrain vertex stuff - vbuf: model.vbuf.clone(), - locals: figure_locals.buf.clone(), - bones: bones.buf.clone(), - globals: global.globals.buf.clone(), + // // let directed_encoder = &mut shadow_map.directed_encoder; + // let directed_encoder = &mut self.encoder; + // directed_encoder.draw( + // &gfx::Slice { + // start: model.vertex_range().start, + // end: model.vertex_range().end, + // base_vertex: 0, + // instances: None, + // buffer: gfx::IndexBuffer::Auto, + // }, + // &shadow_map.figure_directed_pipeline.pso, + // &shadow::figure_pipe::Data { + // // Terrain vertex stuff + // vbuf: model.vbuf.clone(), + // locals: figure_locals.buf.clone(), + // bones: bones.buf.clone(), + // globals: global.globals.buf.clone(), - // Shadow stuff - light_shadows: locals.buf.clone(), - tgt_depth_stencil: shadow_map.directed_depth_stencil_view.clone(), - }, - ); - } + // // Shadow stuff + // light_shadows: locals.buf.clone(), + // tgt_depth_stencil: + // shadow_map.directed_depth_stencil_view.clone(), }, + // ); + // } - /// Queue the rendering of the provided terrain chunk model in the upcoming - /// frame. - pub fn render_fluid_chunk( - &mut self, - model: &Model, - global: &GlobalModel, - locals: &Consts, - lod: &lod_terrain::LodData, - waves: &Texture, - ) { - let (point_shadow_maps, directed_shadow_maps) = - if let Some(shadow_map) = &mut self.shadow_map { - ( - ( - shadow_map.point_res.clone(), - shadow_map.point_sampler.clone(), - ), - ( - shadow_map.directed_res.clone(), - shadow_map.directed_sampler.clone(), - ), - ) - } else { - ( - (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()), - (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()), - ) - }; + // /// Queue the rendering of the provided terrain chunk model in the upcoming + // /// frame. + // pub fn render_fluid_chunk( + // &mut self, + // model: &Model, + // global: &GlobalModel, + // locals: &Consts, + // lod: &lod_terrain::LodData, + // waves: &Texture, + // ) { + // let (point_shadow_maps, directed_shadow_maps) = + // if let Some(shadow_map) = &mut self.shadow_map { + // ( + // ( + // shadow_map.point_res.clone(), + // shadow_map.point_sampler.clone(), + // ), + // ( + // shadow_map.directed_res.clone(), + // shadow_map.directed_sampler.clone(), + // ), + // ) + // } else { + // ( + // (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()), + // (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()), + // ) + // }; - self.encoder.draw( - &gfx::Slice { - start: model.vertex_range().start, - end: model.vertex_range().end, - base_vertex: 0, - instances: None, - buffer: gfx::IndexBuffer::Auto, - }, - &self.fluid_pipeline.pso, - &fluid::pipe::Data { - vbuf: model.vbuf.clone(), - locals: locals.buf.clone(), - globals: global.globals.buf.clone(), - lights: global.lights.buf.clone(), - shadows: global.shadows.buf.clone(), - light_shadows: global.shadow_mats.buf.clone(), - point_shadow_maps, - directed_shadow_maps, - alt: (lod.alt.srv.clone(), lod.alt.sampler.clone()), - horizon: (lod.horizon.srv.clone(), lod.horizon.sampler.clone()), - noise: (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()), - waves: (waves.srv.clone(), waves.sampler.clone()), - tgt_color: self.tgt_color_view.clone(), - tgt_depth_stencil: (self.tgt_depth_stencil_view.clone()/* , (1, 1) */), - }, - ); - } + // self.encoder.draw( + // &gfx::Slice { + // start: model.vertex_range().start, + // end: model.vertex_range().end, + // base_vertex: 0, + // instances: None, + // buffer: gfx::IndexBuffer::Auto, + // }, + // &self.fluid_pipeline.pso, + // &fluid::pipe::Data { + // vbuf: model.vbuf.clone(), + // locals: locals.buf.clone(), + // globals: global.globals.buf.clone(), + // lights: global.lights.buf.clone(), + // shadows: global.shadows.buf.clone(), + // light_shadows: global.shadow_mats.buf.clone(), + // point_shadow_maps, + // directed_shadow_maps, + // alt: (lod.alt.srv.clone(), lod.alt.sampler.clone()), + // horizon: (lod.horizon.srv.clone(), lod.horizon.sampler.clone()), + // noise: (self.noise_tex.srv.clone(), + // self.noise_tex.sampler.clone()), waves: (waves.srv.clone(), + // waves.sampler.clone()), tgt_color: + // self.tgt_color_view.clone(), tgt_depth_stencil: + // (self.tgt_depth_stencil_view.clone()/* , (1, 1) */), }, + // ); + // } - /// Queue the rendering of the provided terrain chunk model in the upcoming - /// frame. - pub fn render_sprites( - &mut self, - model: &Model, - col_lights: &Texture, - global: &GlobalModel, - terrain_locals: &Consts, - locals: &Consts, - instances: &Instances, - lod: &lod_terrain::LodData, - ) { - let (point_shadow_maps, directed_shadow_maps) = - if let Some(shadow_map) = &mut self.shadow_map { - ( - ( - shadow_map.point_res.clone(), - shadow_map.point_sampler.clone(), - ), - ( - shadow_map.directed_res.clone(), - shadow_map.directed_sampler.clone(), - ), - ) - } else { - ( - (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()), - (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()), - ) - }; + // /// Queue the rendering of the provided terrain chunk model in the upcoming + // /// frame. + // pub fn render_sprites( + // &mut self, + // model: &Model, + // col_lights: &Texture, + // global: &GlobalModel, + // terrain_locals: &Consts, + // locals: &Consts, + // instances: &Instances, + // lod: &lod_terrain::LodData, + // ) { + // let (point_shadow_maps, directed_shadow_maps) = + // if let Some(shadow_map) = &mut self.shadow_map { + // ( + // ( + // shadow_map.point_res.clone(), + // shadow_map.point_sampler.clone(), + // ), + // ( + // shadow_map.directed_res.clone(), + // shadow_map.directed_sampler.clone(), + // ), + // ) + // } else { + // ( + // (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()), + // (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()), + // ) + // }; - self.encoder.draw( - &gfx::Slice { - start: model.vertex_range().start, - end: model.vertex_range().end, - base_vertex: 0, - instances: Some((instances.count() as u32, 0)), - buffer: gfx::IndexBuffer::Auto, - }, - &self.sprite_pipeline.pso, - &sprite::pipe::Data { - vbuf: model.vbuf.clone(), - ibuf: instances.ibuf.clone(), - col_lights: (col_lights.srv.clone(), col_lights.sampler.clone()), - terrain_locals: terrain_locals.buf.clone(), - // NOTE: It would be nice if this wasn't needed and we could use a constant buffer - // offset into the sprite data. Hopefully, when we switch to wgpu we can do this, - // as it offers the exact API we want (the equivalent can be done in OpenGL using - // glBindBufferOffset). - locals: locals.buf.clone(), - globals: global.globals.buf.clone(), - lights: global.lights.buf.clone(), - shadows: global.shadows.buf.clone(), - light_shadows: global.shadow_mats.buf.clone(), - point_shadow_maps, - directed_shadow_maps, - noise: (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()), - alt: (lod.alt.srv.clone(), lod.alt.sampler.clone()), - horizon: (lod.horizon.srv.clone(), lod.horizon.sampler.clone()), - tgt_color: self.tgt_color_view.clone(), - tgt_depth_stencil: (self.tgt_depth_stencil_view.clone()/* , (1, 1) */), - }, - ); - } + // self.encoder.draw( + // &gfx::Slice { + // start: model.vertex_range().start, + // end: model.vertex_range().end, + // base_vertex: 0, + // instances: Some((instances.count() as u32, 0)), + // buffer: gfx::IndexBuffer::Auto, + // }, + // &self.sprite_pipeline.pso, + // &sprite::pipe::Data { + // vbuf: model.vbuf.clone(), + // ibuf: instances.ibuf.clone(), + // col_lights: (col_lights.srv.clone(), col_lights.sampler.clone()), + // terrain_locals: terrain_locals.buf.clone(), + // // NOTE: It would be nice if this wasn't needed and we could use + // a constant buffer // offset into the sprite data. Hopefully, + // when we switch to wgpu we can do this, // as it offers the + // exact API we want (the equivalent can be done in OpenGL using + // // glBindBufferOffset). locals: locals.buf.clone(), + // globals: global.globals.buf.clone(), + // lights: global.lights.buf.clone(), + // shadows: global.shadows.buf.clone(), + // light_shadows: global.shadow_mats.buf.clone(), + // point_shadow_maps, + // directed_shadow_maps, + // noise: (self.noise_tex.srv.clone(), + // self.noise_tex.sampler.clone()), alt: (lod.alt.srv.clone(), + // lod.alt.sampler.clone()), horizon: (lod.horizon.srv.clone(), + // lod.horizon.sampler.clone()), tgt_color: + // self.tgt_color_view.clone(), tgt_depth_stencil: + // (self.tgt_depth_stencil_view.clone()/* , (1, 1) */), }, + // ); + // } - /// Queue the rendering of the provided LoD terrain model in the upcoming - /// frame. - pub fn render_lod_terrain( - &mut self, - model: &Model, - global: &GlobalModel, - locals: &Consts, - lod: &lod_terrain::LodData, - ) { - self.encoder.draw( - &gfx::Slice { - start: model.vertex_range().start, - end: model.vertex_range().end, - base_vertex: 0, - instances: None, - buffer: gfx::IndexBuffer::Auto, - }, - &self.lod_terrain_pipeline.pso, - &lod_terrain::pipe::Data { - vbuf: model.vbuf.clone(), - locals: locals.buf.clone(), - globals: global.globals.buf.clone(), - noise: (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()), - map: (lod.map.srv.clone(), lod.map.sampler.clone()), - alt: (lod.alt.srv.clone(), lod.alt.sampler.clone()), - horizon: (lod.horizon.srv.clone(), lod.horizon.sampler.clone()), - tgt_color: self.tgt_color_view.clone(), - tgt_depth_stencil: (self.tgt_depth_stencil_view.clone()/* , (1, 1) */), - }, - ); - } + // /// Queue the rendering of the provided LoD terrain model in the upcoming + // /// frame. + // pub fn render_lod_terrain( + // &mut self, + // model: &Model, + // global: &GlobalModel, + // locals: &Consts, + // lod: &lod_terrain::LodData, + // ) { + // self.encoder.draw( + // &gfx::Slice { + // start: model.vertex_range().start, + // end: model.vertex_range().end, + // base_vertex: 0, + // instances: None, + // buffer: gfx::IndexBuffer::Auto, + // }, + // &self.lod_terrain_pipeline.pso, + // &lod_terrain::pipe::Data { + // vbuf: model.vbuf.clone(), + // locals: locals.buf.clone(), + // globals: global.globals.buf.clone(), + // noise: (self.noise_tex.srv.clone(), + // self.noise_tex.sampler.clone()), map: (lod.map.srv.clone(), + // lod.map.sampler.clone()), alt: (lod.alt.srv.clone(), + // lod.alt.sampler.clone()), horizon: (lod.horizon.srv.clone(), + // lod.horizon.sampler.clone()), tgt_color: + // self.tgt_color_view.clone(), tgt_depth_stencil: + // (self.tgt_depth_stencil_view.clone()/* , (1, 1) */), }, + // ); + // } - /// Queue the rendering of the provided particle in the upcoming frame. - pub fn render_particles( - &mut self, - model: &Model, - global: &GlobalModel, - instances: &Instances, - lod: &lod_terrain::LodData, - ) { - let (point_shadow_maps, directed_shadow_maps) = - if let Some(shadow_map) = &mut self.shadow_map { - ( - ( - shadow_map.point_res.clone(), - shadow_map.point_sampler.clone(), - ), - ( - shadow_map.directed_res.clone(), - shadow_map.directed_sampler.clone(), - ), - ) - } else { - ( - (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()), - (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()), - ) - }; + // /// Queue the rendering of the provided particle in the upcoming frame. + // pub fn render_particles( + // &mut self, + // model: &Model, + // global: &GlobalModel, + // instances: &Instances, + // lod: &lod_terrain::LodData, + // ) { + // let (point_shadow_maps, directed_shadow_maps) = + // if let Some(shadow_map) = &mut self.shadow_map { + // ( + // ( + // shadow_map.point_res.clone(), + // shadow_map.point_sampler.clone(), + // ), + // ( + // shadow_map.directed_res.clone(), + // shadow_map.directed_sampler.clone(), + // ), + // ) + // } else { + // ( + // (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()), + // (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()), + // ) + // }; - self.encoder.draw( - &gfx::Slice { - start: model.vertex_range().start, - end: model.vertex_range().end, - base_vertex: 0, - instances: Some((instances.count() as u32, 0)), - buffer: gfx::IndexBuffer::Auto, - }, - &self.particle_pipeline.pso, - &particle::pipe::Data { - vbuf: model.vbuf.clone(), - ibuf: instances.ibuf.clone(), - globals: global.globals.buf.clone(), - lights: global.lights.buf.clone(), - shadows: global.shadows.buf.clone(), - light_shadows: global.shadow_mats.buf.clone(), - point_shadow_maps, - directed_shadow_maps, - noise: (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()), - alt: (lod.alt.srv.clone(), lod.alt.sampler.clone()), - horizon: (lod.horizon.srv.clone(), lod.horizon.sampler.clone()), - tgt_color: self.tgt_color_view.clone(), - tgt_depth_stencil: (self.tgt_depth_stencil_view.clone()/* , (1, 1) */), - }, - ); - } + // self.encoder.draw( + // &gfx::Slice { + // start: model.vertex_range().start, + // end: model.vertex_range().end, + // base_vertex: 0, + // instances: Some((instances.count() as u32, 0)), + // buffer: gfx::IndexBuffer::Auto, + // }, + // &self.particle_pipeline.pso, + // &particle::pipe::Data { + // vbuf: model.vbuf.clone(), + // ibuf: instances.ibuf.clone(), + // globals: global.globals.buf.clone(), + // lights: global.lights.buf.clone(), + // shadows: global.shadows.buf.clone(), + // light_shadows: global.shadow_mats.buf.clone(), + // point_shadow_maps, + // directed_shadow_maps, + // noise: (self.noise_tex.srv.clone(), + // self.noise_tex.sampler.clone()), alt: (lod.alt.srv.clone(), + // lod.alt.sampler.clone()), horizon: (lod.horizon.srv.clone(), + // lod.horizon.sampler.clone()), tgt_color: + // self.tgt_color_view.clone(), tgt_depth_stencil: + // (self.tgt_depth_stencil_view.clone()/* , (1, 1) */), }, + // ); + // } - /// Queue the rendering of the provided UI element in the upcoming frame. - pub fn render_ui_element>( - &mut self, - model: Model, - tex: &Texture, - scissor: Aabr, - globals: &Consts, - locals: &Consts, - ) where - F::Surface: gfx::format::TextureSurface, - F::Channel: gfx::format::TextureChannel, - ::DataType: Copy, - { - let Aabr { min, max } = scissor; - self.encoder.draw( - &gfx::Slice { - start: model.vertex_range.start, - end: model.vertex_range.end, - base_vertex: 0, - instances: None, - buffer: gfx::IndexBuffer::Auto, - }, - &self.ui_pipeline.pso, - &ui::pipe::Data { - vbuf: model.vbuf, - scissor: gfx::Rect { - x: min.x, - y: min.y, - w: max.x - min.x, - h: max.y - min.y, - }, - tex: (tex.srv.clone(), tex.sampler.clone()), - locals: locals.buf.clone(), - globals: globals.buf.clone(), - tgt_color: self.win_color_view.clone(), - tgt_depth: self.win_depth_view.clone(), - }, - ); - } + // /// Queue the rendering of the provided UI element in the upcoming frame. + // pub fn render_ui_element>( + // &mut self, + // model: Model, + // tex: &Texture, + // scissor: Aabr, + // globals: &Consts, + // locals: &Consts, + // ) where + // F::Surface: gfx::format::TextureSurface, + // F::Channel: gfx::format::TextureChannel, + // ::DataType: Copy, + // { + // let Aabr { min, max } = scissor; + // self.encoder.draw( + // &gfx::Slice { + // start: model.vertex_range.start, + // end: model.vertex_range.end, + // base_vertex: 0, + // instances: None, + // buffer: gfx::IndexBuffer::Auto, + // }, + // &self.ui_pipeline.pso, + // &ui::pipe::Data { + // vbuf: model.vbuf, + // scissor: gfx::Rect { + // x: min.x, + // y: min.y, + // w: max.x - min.x, + // h: max.y - min.y, + // }, + // tex: (tex.srv.clone(), tex.sampler.clone()), + // locals: locals.buf.clone(), + // globals: globals.buf.clone(), + // tgt_color: self.win_color_view.clone(), + // tgt_depth: self.win_depth_view.clone(), + // }, + // ); + // } - pub fn render_clouds( - &mut self, - model: &Model, - globals: &Consts, - locals: &Consts, - lod: &lod_terrain::LodData, - ) { - self.encoder.draw( - &gfx::Slice { - start: model.vertex_range().start, - end: model.vertex_range().end, - base_vertex: 0, - instances: None, - buffer: gfx::IndexBuffer::Auto, - }, - &self.clouds_pipeline.pso, - &clouds::pipe::Data { - vbuf: model.vbuf.clone(), - locals: locals.buf.clone(), - globals: globals.buf.clone(), - map: (lod.map.srv.clone(), lod.map.sampler.clone()), - alt: (lod.alt.srv.clone(), lod.alt.sampler.clone()), - horizon: (lod.horizon.srv.clone(), lod.horizon.sampler.clone()), - color_sampler: (self.tgt_color_res.clone(), self.sampler.clone()), - depth_sampler: (self.tgt_depth_res.clone(), self.sampler.clone()), - noise: (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()), - tgt_color: self.tgt_color_pp_view.clone(), - }, - ) - } + // pub fn render_clouds( + // &mut self, + // model: &Model, + // globals: &Consts, + // locals: &Consts, + // lod: &lod_terrain::LodData, + // ) { + // self.encoder.draw( + // &gfx::Slice { + // start: model.vertex_range().start, + // end: model.vertex_range().end, + // base_vertex: 0, + // instances: None, + // buffer: gfx::IndexBuffer::Auto, + // }, + // &self.clouds_pipeline.pso, + // &clouds::pipe::Data { + // vbuf: model.vbuf.clone(), + // locals: locals.buf.clone(), + // globals: globals.buf.clone(), + // map: (lod.map.srv.clone(), lod.map.sampler.clone()), + // alt: (lod.alt.srv.clone(), lod.alt.sampler.clone()), + // horizon: (lod.horizon.srv.clone(), lod.horizon.sampler.clone()), + // color_sampler: (self.tgt_color_res.clone(), + // self.sampler.clone()), depth_sampler: + // (self.tgt_depth_res.clone(), self.sampler.clone()), noise: + // (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()), + // tgt_color: self.tgt_color_pp_view.clone(), }, + // ) + // } - pub fn render_post_process( - &mut self, - model: &Model, - globals: &Consts, - locals: &Consts, - lod: &lod_terrain::LodData, - ) { - self.encoder.draw( - &gfx::Slice { - start: model.vertex_range().start, - end: model.vertex_range().end, - base_vertex: 0, - instances: None, - buffer: gfx::IndexBuffer::Auto, - }, - &self.postprocess_pipeline.pso, - &postprocess::pipe::Data { - vbuf: model.vbuf.clone(), - locals: locals.buf.clone(), - globals: globals.buf.clone(), - map: (lod.map.srv.clone(), lod.map.sampler.clone()), - alt: (lod.alt.srv.clone(), lod.alt.sampler.clone()), - horizon: (lod.horizon.srv.clone(), lod.horizon.sampler.clone()), - color_sampler: (self.tgt_color_res_pp.clone(), self.sampler.clone()), - depth_sampler: (self.tgt_depth_res.clone(), self.sampler.clone()), - noise: (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()), - tgt_color: self.win_color_view.clone(), - }, - ) - } + // pub fn render_post_process( + // &mut self, + // model: &Model, + // globals: &Consts, + // locals: &Consts, + // lod: &lod_terrain::LodData, + // ) { + // self.encoder.draw( + // &gfx::Slice { + // start: model.vertex_range().start, + // end: model.vertex_range().end, + // base_vertex: 0, + // instances: None, + // buffer: gfx::IndexBuffer::Auto, + // }, + // &self.postprocess_pipeline.pso, + // &postprocess::pipe::Data { + // vbuf: model.vbuf.clone(), + // locals: locals.buf.clone(), + // globals: globals.buf.clone(), + // map: (lod.map.srv.clone(), lod.map.sampler.clone()), + // alt: (lod.alt.srv.clone(), lod.alt.sampler.clone()), + // horizon: (lod.horizon.srv.clone(), lod.horizon.sampler.clone()), + // color_sampler: (self.tgt_color_res_pp.clone(), + // self.sampler.clone()), depth_sampler: + // (self.tgt_depth_res.clone(), self.sampler.clone()), noise: + // (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()), + // tgt_color: self.win_color_view.clone(), }, + // ) + // } } /// Creates all the pipelines used to render. #[allow(clippy::type_complexity)] // TODO: Pending review in #587 fn create_pipelines( - factory: &wgpu::Device, + device: &wgpu::Device, + layouts: &Layouts, shaders: &Shaders, mode: &RenderMode, + sc_desc: &wgpu::SwapChainDescriptor, has_shadow_views: bool, ) -> Result< ( - wgpu::RenderPipeline, - wgpu::RenderPipeline, - wgpu::RenderPipeline, - wgpu::RenderPipeline, - wgpu::RenderPipeline, - wgpu::RenderPipeline, - wgpu::RenderPipeline, - wgpu::RenderPipeline, - wgpu::RenderPipeline, - wgpu::RenderPipeline, - wgpu::RenderPipeline, - Option, - Option, - Option, + skybox::SkyboxPipeline, + figure::FigurePipeline, + terrain::TerrainPipeline, + fluid::FluidPipeline, + sprite::SpritePipeline, + particle::ParticlePipeline, + ui::UIPipeline, + lod_terrain::LodTerrainPipeline, + // TODO: clouds + postprocess::PostProcessPipeline, + //figure::FigurePipeline, + Option, + Option, + Option, ), RenderError, > { + use shaderc::{CompileOptions, Compiler, OptimizationLevel, ResolvedInclude, ShaderKind}; + + let constants = &shaders.constants.read().0; + let globals = &shaders.globals.read().0; + let sky = &shaders.sky.read().0; + let light = &shaders.light.read().0; + let srgb = &shaders.srgb.read().0; + let random = &shaders.random.read().0; + let lod = &shaders.lod.read().0; + let shadows = &shaders.shadows.read().0; + // We dynamically add extra configuration settings to the constants file. let constants = format!( r#" @@ -1912,7 +1906,7 @@ fn create_pipelines( #define SHADOW_MODE {} "#, - shaders.constants.read().0, + constants, // TODO: Configurable vertex/fragment shader preference. "VOXYGEN_COMPUTATION_PREFERENCE_FRAGMENT", match mode.fluid { @@ -1952,11 +1946,11 @@ fn create_pipelines( _ => shaders.cloud_regular, }; - let mut compiler = shaderc::Compiler::new().ok_or(RenderError::ErrorInitializingCompiler)?; - let mut options = shaderc::CompileOptions::new().ok_or(RenderError::ErrorInitializingCompiler)?; - options.set_optimization_level(shaderc::OptimizationLevel::Performance); - options.set_include_callback(move |name,_,shader_name,_| { - Ok(shaderc::ResolvedInclude { + let mut compiler = Compiler::new().ok_or(RenderError::ErrorInitializingCompiler)?; + let mut options = CompileOptions::new().ok_or(RenderError::ErrorInitializingCompiler)?; + options.set_optimization_level(OptimizationLevel::Performance); + options.set_include_callback(move |name, _, shader_name, _| { + Ok(ResolvedInclude { resolved_name: name, content: match name { "constants.glsl" => constants, @@ -1969,9 +1963,9 @@ fn create_pipelines( "lod.glsl" => &lod, "anti-aliasing.glsl" => &anti_alias, "cloud.glsl" => &cloud, - other => return Err(format!("Include {} is not defined",other)) - } - } ) + other => return Err(format!("Include {} is not defined", other)), + }, + }) }); let figure_vert = &shaders.figure_vert.read().0; @@ -1984,188 +1978,371 @@ fn create_pipelines( let directed_shadow_frag = &shaders.directed_shadow_frag.read().0; - // Construct a pipeline for rendering skyboxes - let skybox_pipeline = create_pipeline( - factory, - skybox::pipe::new(), - &shaders.skybox_vert.read().0, - &shaders.skybox_frag.read().0, - &include_ctx, - gfx::state::CullFace::Back, + let figure_vert_mod = create_shader_module( + device, + &mut compiler, + figure_vert, + ShaderKind::Vertex, + "figure-vert.glsl", + &options, )?; + let terrain_point_shadow_vert_mod = create_shader_module( + device, + &mut compiler, + terrain_point_shadow_vert, + ShaderKind::Vertex, + "light-shadows-vert.glsl", + &options, + )?; + + let terrain_directed_shadow_vert_mod = create_shader_module( + device, + &mut compiler, + terrain_directed_shadow_vert, + ShaderKind::Vertex, + "light-shadows-directed-vert.glsl", + &options, + )?; + + let figure_directed_shadow_vert_mod = create_shader_module( + device, + &mut compiler, + figure_directed_shadow_vert, + ShaderKind::Vertex, + "light-shadows-figure-vert.glsl", + &options, + )?; + + // TODO: closure to to make calling this easier + + let directed_shadow_frag_mod = create_shader_module( + device, + &mut compiler, + directed_shadow_frag, + ShaderKind::Fragment, + "light-shadows-directed-frag.glsl", + &options, + )?; + + // Construct a pipeline for rendering skyboxes + let skybox_pipeline = skybox::SkyboxPipeline::new( + device, + create_shader_module( + device, + &mut compiler, + shaders.skybox_vert.read().0, + ShaderKind::Vertex, + "skybox-vert.glsl", + &options, + ), + create_shader_module( + device, + &mut compiler, + shaders.skybox_frag.read().0, + ShaderKind::Fragment, + "skybox-frag.glsl", + &options, + ), + sc_desc, + layouts, + mode.aa, + ); + // Construct a pipeline for rendering figures - let figure_pipeline = create_pipeline( - factory, - figure::pipe::new(), - &shaders.figure_vert.read().0, - &shaders.figure_frag.read().0, - &include_ctx, - gfx::state::CullFace::Back, - )?; + let figure_pipeline = figure::FigurePipeline::new( + device, + &figure_vert_mod, + create_shader_module( + device, + &mut compiler, + shaders.figure_frag.read().0, + ShaderKind::Fragment, + "figure-frag.glsl", + &options, + ), + sc_desc, + layouts, + mode.aa, + ); // Construct a pipeline for rendering terrain - let terrain_pipeline = create_pipeline( - factory, - terrain::pipe::new(), - &shaders.terrain_vert.read().0, - &shaders.terrain_frag.read().0, - &include_ctx, - gfx::state::CullFace::Back, - )?; + let terrain_pipeline = terrain::TerrainPipeline::new( + device, + create_shader_module( + device, + &mut compiler, + shaders.terrain_vert.read().0, + ShaderKind::Vertex, + "terrain-vert.glsl", + &options, + ), + create_shader_module( + device, + &mut compiler, + shaders.terrain_frag.read().0, + ShaderKind::Fragment, + "terrain-frag.glsl", + &options, + ), + sc_desc, + layouts, + mode.aa, + ); // Construct a pipeline for rendering fluids - let fluid_pipeline = create_pipeline( - factory, - fluid::pipe::new(), - &shaders.fluid_vert.read().0, - &match mode.fluid { - FluidMode::Cheap => shaders.fluid_frag_cheap, - FluidMode::Shiny => shaders.fluid_frag_shiny, - } - .read() - .0, - &include_ctx, - gfx::state::CullFace::Nothing, - )?; + let fluid_pipeline = fluid::FluidPipeline::new( + device, + create_shader_module( + device, + &mut compiler, + shaders.fluid_vert.read().0, + ShaderKind::Vertex, + "terrain-vert.glsl", + &options, + ), + create_shader_module( + device, + &mut compiler, + match mode.fluid { + FluidMode::Cheap => shaders.fluid_frag_cheap.read().0, + FluidMode::Shiny => shaders.fluid_frag_shiny.read().0, + }, + ShaderKind::Fragment, + "fluid-frag.glsl", + &options, + ), + sc_desc, + layouts, + mode.aa, + ); // Construct a pipeline for rendering sprites - let sprite_pipeline = create_pipeline( - factory, - sprite::pipe::new(), - &shaders.sprite_vert.read().0, - &shaders.sprite_frag.read().0, - &include_ctx, - gfx::state::CullFace::Back, - )?; + let sprite_pipeline = sprite::SpritePipeline::new( + device, + create_shader_module( + device, + &mut compiler, + shaders.sprite_vert.read().0, + ShaderKind::Vertex, + "sprite-vert.glsl", + &options, + ), + create_shader_module( + device, + &mut compiler, + shaders.sprite_frag.read().0, + ShaderKind::Fragment, + "sprite-frag.glsl", + &options, + ), + sc_desc, + layouts, + mode.aa, + ); // Construct a pipeline for rendering particles - let particle_pipeline = create_pipeline( - factory, - particle::pipe::new(), - &shaders.particle_vert.read().0, - &shaders.particle_frag.read().0, - &include_ctx, - gfx::state::CullFace::Back, - )?; + let particle_pipeline = particle::ParticlePipeline::new( + device, + create_shader_module( + device, + &mut compiler, + shaders.particle_vert.read().0, + ShaderKind::Vertex, + "particle-vert.glsl", + &options, + ), + create_shader_module( + device, + &mut compiler, + shaders.particle_frag.read().0, + ShaderKind::Fragment, + "particle-frag.glsl", + &options, + ), + sc_desc, + layouts, + mode.aa, + ); // Construct a pipeline for rendering UI elements - let ui_pipeline = create_pipeline( - factory, - ui::pipe::new(), - &shaders.ui_vert.read().0, - &shaders.ui_frag.read().0, - &include_ctx, - gfx::state::CullFace::Back, - )?; + let ui_pipeline = ui::UIPipeline::new( + device, + create_shader_module( + device, + &mut compiler, + shaders.ui_vert.read().0, + ShaderKind::Vertex, + "ui-vert.glsl", + &options, + ), + create_shader_module( + device, + &mut compiler, + shaders.ui_frag.read().0, + ShaderKind::Fragment, + "ui-frag.glsl", + &options, + ), + sc_desc, + layouts, + mode.aa, + ); // Construct a pipeline for rendering terrain - let lod_terrain_pipeline = create_pipeline( - factory, - lod_terrain::pipe::new(), - &shaders.lod_terrain_vert.read().0, - &shaders.lod_terrain_frag.read().0, - &include_ctx, - gfx::state::CullFace::Back, - )?; + let lod_terrain_pipeline = lod_terrain::LodTerrainPipeline::new( + device, + create_shader_module( + device, + &mut compiler, + shaders.lod_terrain_vert.read().0, + ShaderKind::Vertex, + "lod-terrain-vert.glsl", + &options, + ), + create_shader_module( + device, + &mut compiler, + shaders.lod_terrain_frag.read().0, + ShaderKind::Fragment, + "lod-terrain-frag.glsl", + &options, + ), + sc_desc, + layouts, + mode.aa, + ); // Construct a pipeline for rendering our clouds (a kind of post-processing) - let clouds_pipeline = create_pipeline( - factory, - clouds::pipe::new(), - &shaders.clouds_vert.read().0, - &shaders.clouds_frag.read().0, - &include_ctx, - gfx::state::CullFace::Back, - )?; + // let clouds_pipeline = create_pipeline( + // factory, + // clouds::pipe::new(), + // &Glsl::load_watched("voxygen.shaders.clouds-vert", + // shader_reload_indicator).unwrap(), &Glsl::load_watched("voxygen. + // shaders.clouds-frag", shader_reload_indicator).unwrap(), + // &include_ctx, + // gfx::state::CullFace::Back, + // )?; // Construct a pipeline for rendering our post-processing - let postprocess_pipeline = create_pipeline( - factory, - postprocess::pipe::new(), - &shaders.postprocess_vert.read().0, - &shaders.postprocess_frag.read().0, - &include_ctx, - gfx::state::CullFace::Back, - )?; + let postprocess_pipeline = postprocess::PostProcessPipeline::new( + device, + create_shader_module( + device, + &mut compiler, + shaders.postprocess_vert.read().0, + ShaderKind::Vertex, + "postprocess-vert.glsl", + &options, + ), + create_shader_module( + device, + &mut compiler, + shaders.postprocess_frag.read().0, + ShaderKind::Fragment, + "postprocess-frag.glsl", + &options, + ), + sc_desc, + layouts, + mode.aa, + ); - // Construct a pipeline for rendering the player silhouette - let player_shadow_pipeline = create_pipeline( - factory, - figure::pipe::Init { - tgt_depth_stencil: (gfx::preset::depth::PASS_TEST/*, - Stencil::new( - Comparison::Equal, - 0xff, - (StencilOp::Keep, StencilOp::Keep, StencilOp::Keep), - ),*/), - ..figure::pipe::new() - }, - &shaders.figure_vert.read().0, - &shaders.player_shadow_frag.read().0, - &include_ctx, - gfx::state::CullFace::Back, - )?; + // Consider reenabling at some time in the future + // + // // Construct a pipeline for rendering the player silhouette + // let player_shadow_pipeline = create_pipeline( + // factory, + // figure::pipe::Init { + // tgt_depth_stencil: (gfx::preset::depth::PASS_TEST/*, + // Stencil::new( + // Comparison::Equal, + // 0xff, + // (StencilOp::Keep, StencilOp::Keep, StencilOp::Keep), + // ),*/), + // ..figure::pipe::new() + // }, + // &figure_vert, + // &Glsl::load_watched( + // "voxygen.shaders.player-shadow-frag", + // shader_reload_indicator, + // ) + // .unwrap(), + // &include_ctx, + // gfx::state::CullFace::Back, + // )?; - // Construct a pipeline for rendering point light terrain shadow maps. - let point_shadow_pipeline = match create_shadow_pipeline( - factory, - shadow::pipe::new(), - &shaders.terrain_point_shadow_vert.read().0, - Some(&shaders.light_shadows_geom.read().0), - &shaders.light_shadows_frag.read().0, - &include_ctx, - gfx::state::CullFace::Back, - None, // Some(gfx::state::Offset(2, 0)) - ) { - Ok(pipe) => Some(pipe), - Err(err) => { - warn!("Could not load point shadow map pipeline: {:?}", err); - None - }, - }; + // Sharp can fix it later ;) + // + // // Construct a pipeline for rendering point light terrain shadow maps. + // let point_shadow_pipeline = match create_shadow_pipeline( + // factory, + // shadow::pipe::new(), + // &terrain_point_shadow_vert, + // Some( + // &Glsl::load_watched( + // "voxygen.shaders.light-shadows-geom", + // shader_reload_indicator, + // ) + // .unwrap(), + // ), + // &Glsl::load_watched( + // "voxygen.shaders.light-shadows-frag", + // shader_reload_indicator, + // ) + // .unwrap(), + // &include_ctx, + // gfx::state::CullFace::Back, + // None, // Some(gfx::state::Offset(2, 0)) + // ) { + // Ok(pipe) => Some(pipe), + // Err(err) => { + // warn!("Could not load point shadow map pipeline: {:?}", err); + // None + // }, + // }; - // Construct a pipeline for rendering directional light terrain shadow maps. - let terrain_directed_shadow_pipeline = match create_shadow_pipeline( - factory, - shadow::pipe::new(), - &shaders.terrain_directed_shadow_vert.read().0, - None, - &shaders.directed_shadow_frag.read().0, - &include_ctx, - gfx::state::CullFace::Back, - None, // Some(gfx::state::Offset(2, 1)) - ) { - Ok(pipe) => Some(pipe), - Err(err) => { - warn!( - "Could not load directed terrain shadow map pipeline: {:?}", - err - ); - None - }, - }; + // // Construct a pipeline for rendering directional light terrain shadow maps. + // let terrain_directed_shadow_pipeline = match create_shadow_pipeline( + // factory, + // shadow::pipe::new(), + // &terrain_directed_shadow_vert, + // None, + // &directed_shadow_frag, + // &include_ctx, + // gfx::state::CullFace::Back, + // None, // Some(gfx::state::Offset(2, 1)) + // ) { + // Ok(pipe) => Some(pipe), + // Err(err) => { + // warn!( + // "Could not load directed terrain shadow map pipeline: {:?}", + // err + // ); + // None + // }, + // }; - // Construct a pipeline for rendering directional light figure shadow maps. - let figure_directed_shadow_pipeline = match create_shadow_pipeline( - factory, - shadow::figure_pipe::new(), - &shaders.figure_directed_shadow_vert.read().0, - None, - &shaders.directed_shadow_frag.read().0, - &include_ctx, - gfx::state::CullFace::Back, - None, // Some(gfx::state::Offset(2, 1)) - ) { - Ok(pipe) => Some(pipe), - Err(err) => { - warn!( - "Could not load directed figure shadow map pipeline: {:?}", - err - ); - None - }, - }; + // // Construct a pipeline for rendering directional light figure shadow maps. + // let figure_directed_shadow_pipeline = match create_shadow_pipeline( + // factory, + // shadow::figure_pipe::new(), + // &figure_directed_shadow_vert, + // None, + // &directed_shadow_frag, + // &include_ctx, + // gfx::state::CullFace::Back, + // None, // Some(gfx::state::Offset(2, 1)) + // ) { + // Ok(pipe) => Some(pipe), + // Err(err) => { + // warn!( + // "Could not load directed figure shadow map pipeline: {:?}", + // err + // ); + // None + // }, + // }; Ok(( skybox_pipeline, @@ -2178,61 +2355,24 @@ fn create_pipelines( lod_terrain_pipeline, clouds_pipeline, postprocess_pipeline, - player_shadow_pipeline, - point_shadow_pipeline, - terrain_directed_shadow_pipeline, - figure_directed_shadow_pipeline, + // player_shadow_pipeline, + None, + None, + None, )) } -/// Create a new pipeline from the provided vertex shader and fragment shader. -fn create_pipeline( +pub fn create_shader_module( device: &wgpu::Device, - desc: &wgpu::RenderPipelineDescriptor -) -> wgpu::RenderPipeline { - device.create_render_pipeline(desc) -} - -/// Create a new shadow map pipeline. -fn create_shadow_pipeline( - factory: &mut gfx_backend::Factory, - pipe: P, - vs: &str, - gs: Option<&str>, - fs: &str, - ctx: &IncludeContext, - cull_face: gfx::state::CullFace, - offset: Option, -) -> Result, RenderError> { - let vs = ctx.expand(vs)?; - let gs = gs.map(|gs| ctx.expand(gs)).transpose()?; - let fs = ctx.expand(fs)?; - - let shader_set = if let Some(gs) = gs { - factory.create_shader_set_geometry(vs.as_bytes(), gs.as_bytes(), fs.as_bytes())? - } else { - factory.create_shader_set(vs.as_bytes(), fs.as_bytes())? - }; - - Ok(GfxPipeline { - pso: factory.create_pipeline_state( - &shader_set, - gfx::Primitive::TriangleList, - gfx::state::Rasterizer { - front_face: gfx::state::FrontFace::CounterClockwise, - // Second-depth shadow mapping: should help reduce z-fighting provided all objects - // are "watertight" (every triangle edge is shared with at most one other - // triangle); this *should* be true for Veloren. - cull_face: match cull_face { - gfx::state::CullFace::Front => gfx::state::CullFace::Back, - gfx::state::CullFace::Back => gfx::state::CullFace::Front, - gfx::state::CullFace::Nothing => gfx::state::CullFace::Nothing, - }, - method: gfx::state::RasterMethod::Fill, - offset, - samples: None, - }, - pipe, - )?, - }) + compiler: &mut shaderc::Compiler, + source: &str, + kind: shaderc::ShaderKind, + file_name: &str, + options: &shaderc::CompileOptions, +) -> Result { + use std::borrow::Cow; + + let spv = compiler.compile_into_spirv(source, kind, file_name, "main", Some(options))?; + + Ok(device.create_shader_module(wgpu::ShaderModule::SpirV(Cow::Bowrrowed(spv.as_binary())))) }