Finished porting all pipelines

This commit is contained in:
Capucho 2020-09-13 11:03:42 +01:00 committed by Imbris
parent 32a78c3988
commit 4fd9567da5
14 changed files with 2758 additions and 1496 deletions

View File

@ -8,7 +8,7 @@ pub enum RenderError {
CustomError(String),
CouldNotFindAdapter,
ErrorInitializingCompiler,
ShaderError(shaderc::Error)
ShaderError(shaderc::Error),
}
impl From<wgpu::RequestDeviceError> for RenderError {

View File

@ -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,

View File

@ -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<Vertex>,
/* TODO: Consider using mipmaps instead of storing multiple texture atlases for different
@ -139,48 +125,138 @@ impl FigureModel {
pub type BoneMeshes = (Mesh<Vertex>, anim::vek::Aabb<f32>);
//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<<TerrainPipeline as Pipeline>::Vertex> = (),
// // abuf: gfx::VertexBuffer<<TerrainPipeline as Pipeline>::Vertex> =
// (), col_lights: gfx::TextureSampler<[f32; 4]> = "t_col_light",
//
// locals: gfx::ConstantBuffer<Locals> = "u_locals",
// globals: gfx::ConstantBuffer<Globals> = "u_globals",
// bones: gfx::ConstantBuffer<BoneData> = "u_bones",
// lights: gfx::ConstantBuffer<Light> = "u_lights",
// shadows: gfx::ConstantBuffer<Shadow> = "u_shadows",
//
// point_shadow_maps: gfx::TextureSampler<f32> = "t_point_shadow_maps",
// directed_shadow_maps: gfx::TextureSampler<f32> =
// "t_directed_shadow_maps",
//
// alt: gfx::TextureSampler<[f32; 2]> = "t_alt",
// horizon: gfx::TextureSampler<[f32; 4]> = "t_horizon",
//
// noise: gfx::TextureSampler<f32> = "t_noise",
//
// // Shadow stuff
// light_shadows: gfx::ConstantBuffer<shadow::Locals> =
// "u_light_shadows",
//
// tgt_color: gfx::BlendTarget<TgtColorFmt> = ("tgt_color",
// ColorMask::all(), gfx::preset::blend::ALPHA), tgt_depth_stencil:
// gfx::DepthTarget<TgtDepthStencilFmt> = gfx::preset::depth::LESS_EQUAL_WRITE,
// // tgt_depth_stencil: gfx::DepthStencilTarget<TgtDepthStencilFmt> =
// (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,
}
}
}

View File

@ -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<Vertex> = (),
// locals: gfx::ConstantBuffer<TerrainLocals> = "u_locals",
// globals: gfx::ConstantBuffer<Globals> = "u_globals",
// lights: gfx::ConstantBuffer<Light> = "u_lights",
// shadows: gfx::ConstantBuffer<Shadow> = "u_shadows",
// point_shadow_maps: gfx::TextureSampler<f32> = "t_point_shadow_maps",
// directed_shadow_maps: gfx::TextureSampler<f32> =
// "t_directed_shadow_maps",
// alt: gfx::TextureSampler<[f32; 2]> = "t_alt",
// horizon: gfx::TextureSampler<[f32; 4]> = "t_horizon",
// noise: gfx::TextureSampler<f32> = "t_noise",
// waves: gfx::TextureSampler<[f32; 4]> = "t_waves",
// // Shadow stuff
// light_shadows: gfx::ConstantBuffer<shadow::Locals> =
// "u_light_shadows",
// tgt_color: gfx::BlendTarget<TgtColorFmt> = ("tgt_color",
// ColorMask::all(), gfx::preset::blend::ALPHA), tgt_depth_stencil:
// gfx::DepthTarget<TgtDepthStencilFmt> = gfx::preset::depth::LESS_EQUAL_TEST,
// // tgt_depth_stencil: gfx::DepthStencilTarget<TgtDepthStencilFmt> =
// (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::<Self>() 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,
}
}
}

View File

@ -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<Vertex> = (),
// locals: gfx::ConstantBuffer<Locals> = "u_locals",
// globals: gfx::ConstantBuffer<Globals> = "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<f32> = "t_noise",
// tgt_color: gfx::RenderTarget<TgtColorFmt> = "tgt_color",
// tgt_depth_stencil: gfx::DepthTarget<TgtDepthStencilFmt> =
// gfx::preset::depth::LESS_EQUAL_WRITE, // tgt_depth_stencil:
// gfx::DepthStencilTarget<TgtDepthStencilFmt> =
// (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::<Self>() 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,
}
}
}

View File

@ -225,34 +225,201 @@ pub struct GlobalModel {
pub shadow_mats: Consts<shadow::Locals>,
}
//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,
}
}
}

View File

@ -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<Vertex> = (),
// ibuf: gfx::InstanceBuffer<Instance> = (),
//
// globals: gfx::ConstantBuffer<Globals> = "u_globals",
// lights: gfx::ConstantBuffer<Light> = "u_lights",
// shadows: gfx::ConstantBuffer<Shadow> = "u_shadows",
//
// point_shadow_maps: gfx::TextureSampler<f32> = "t_point_shadow_maps",
// directed_shadow_maps: gfx::TextureSampler<f32> =
// "t_directed_shadow_maps",
//
// alt: gfx::TextureSampler<[f32; 2]> = "t_alt",
// horizon: gfx::TextureSampler<[f32; 4]> = "t_horizon",
//
// noise: gfx::TextureSampler<f32> = "t_noise",
//
// // Shadow stuff
// light_shadows: gfx::ConstantBuffer<shadow::Locals> =
// "u_light_shadows",
//
// tgt_color: gfx::BlendTarget<TgtColorFmt> = ("tgt_color",
// ColorMask::all(), gfx::preset::blend::ALPHA), tgt_depth_stencil:
// gfx::DepthTarget<TgtDepthStencilFmt> = gfx::preset::depth::LESS_EQUAL_WRITE,
// // tgt_depth_stencil: gfx::DepthStencilTarget<TgtDepthStencilFmt> =
// (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::<Self>() 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::<Self>() 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,
}
}
}

View File

@ -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<Vertex> = (),
//
// locals: gfx::ConstantBuffer<Locals> = "u_locals",
// globals: gfx::ConstantBuffer<Globals> = "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<<TgtColorFmt as
// gfx::format::Formatted>::View> = "src_color", depth_sampler:
// gfx::TextureSampler<<TgtDepthStencilFmt as gfx::format::Formatted>::View> =
// "src_depth",
//
// noise: gfx::TextureSampler<f32> = "t_noise",
//
// tgt_color: gfx::RenderTarget<WinColorFmt> = "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::<Self>() 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<Vertex> {
let mut mesh = Mesh::new();
@ -78,3 +62,117 @@ pub fn create_mesh() -> Mesh<Vertex> {
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,
}
}
}

View File

@ -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<terrain::Vertex> = (),
// locals: gfx::ConstantBuffer<TerrainLocals> = "u_locals",
// globals: gfx::ConstantBuffer<Globals> = "u_globals",
// // Shadow stuff
// light_shadows: gfx::ConstantBuffer<Locals> = "u_light_shadows",
// tgt_depth_stencil: gfx::DepthTarget<ShadowDepthStencilFmt> =
// gfx::state::Depth { fun: gfx::state::Comparison::Less,
// write: true,
// },
// }
// pipeline figure_pipe {
// // Terrain vertex stuff
// vbuf: gfx::VertexBuffer<terrain::Vertex> = (),
// locals: gfx::ConstantBuffer<figure::Locals> = "u_locals",
// bones: gfx::ConstantBuffer<figure::BoneData> = "u_bones",
// globals: gfx::ConstantBuffer<Globals> = "u_globals",
// // Shadow stuff
// light_shadows: gfx::ConstantBuffer<Locals> = "u_light_shadows",
// tgt_depth_stencil: gfx::DepthTarget<ShadowDepthStencilFmt> =
// 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,
}
}
}

View File

@ -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<Vertex> = (),
// locals: gfx::ConstantBuffer<Locals> = "u_locals",
// globals: gfx::ConstantBuffer<Globals> = "u_globals",
// alt: gfx::TextureSampler<[f32; 2]> = "t_alt",
// horizon: gfx::TextureSampler<[f32; 4]> = "t_horizon",
// noise: gfx::TextureSampler<f32> = "t_noise",
// tgt_color: gfx::RenderTarget<TgtColorFmt> = "tgt_color",
// tgt_depth_stencil: gfx::DepthTarget<TgtDepthStencilFmt> =
// gfx::preset::depth::LESS_EQUAL_TEST, // tgt_depth_stencil:
// gfx::DepthStencilTarget<TgtDepthStencilFmt> =
// (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::<Self>() 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<Vertex> {
let mut mesh = Mesh::new();

View File

@ -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<Vertex> = (),
// ibuf: gfx::InstanceBuffer<Instance> = (),
// col_lights: gfx::TextureSampler<[f32; 4]> = "t_col_light",
//
// locals: gfx::ConstantBuffer<Locals> = "u_locals",
// // A sprite instance is a cross between a sprite and a terrain chunk.
// terrain_locals: gfx::ConstantBuffer<terrain::Locals> =
// "u_terrain_locals", globals: gfx::ConstantBuffer<Globals> =
// "u_globals", lights: gfx::ConstantBuffer<Light> = "u_lights",
// shadows: gfx::ConstantBuffer<Shadow> = "u_shadows",
//
// point_shadow_maps: gfx::TextureSampler<f32> = "t_point_shadow_maps",
// directed_shadow_maps: gfx::TextureSampler<f32> =
// "t_directed_shadow_maps",
//
// alt: gfx::TextureSampler<[f32; 2]> = "t_alt",
// horizon: gfx::TextureSampler<[f32; 4]> = "t_horizon",
//
// noise: gfx::TextureSampler<f32> = "t_noise",
//
// // Shadow stuff
// light_shadows: gfx::ConstantBuffer<shadow::Locals> =
// "u_light_shadows",
//
// tgt_color: gfx::BlendTarget<TgtColorFmt> = ("tgt_color",
// ColorMask::all(), gfx::preset::blend::ALPHA), tgt_depth_stencil:
// gfx::DepthTarget<TgtDepthStencilFmt> = gfx::preset::depth::LESS_EQUAL_WRITE,
// // tgt_depth_stencil: gfx::DepthStencilTarget<TgtDepthStencilFmt> =
// (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::<Self>() 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::<Self>() 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,
}
}
}

View File

@ -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<Vertex> = (),
// col_lights: gfx::TextureSampler<[f32; 4]> = "t_col_light",
// locals: gfx::ConstantBuffer<Locals> = "u_locals",
// globals: gfx::ConstantBuffer<Globals> = "u_globals",
// lights: gfx::ConstantBuffer<Light> = "u_lights",
// shadows: gfx::ConstantBuffer<Shadow> = "u_shadows",
// point_shadow_maps: gfx::TextureSampler<f32> = "t_point_shadow_maps",
// directed_shadow_maps: gfx::TextureSampler<f32> =
// "t_directed_shadow_maps",
// alt: gfx::TextureSampler<[f32; 2]> = "t_alt",
// horizon: gfx::TextureSampler<[f32; 4]> = "t_horizon",
// noise: gfx::TextureSampler<f32> = "t_noise",
// // Shadow stuff
// light_shadows: gfx::ConstantBuffer<shadow::Locals> =
// "u_light_shadows",
// tgt_color: gfx::RenderTarget<TgtColorFmt> = "tgt_color",
// tgt_depth_stencil: gfx::DepthTarget<TgtDepthStencilFmt> =
// gfx::preset::depth::LESS_EQUAL_WRITE, // tgt_depth_stencil:
// gfx::DepthStencilTarget<TgtDepthStencilFmt> =
// (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::<Self>() 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,
}
}
}

View File

@ -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<Vertex> = (),
// locals: gfx::ConstantBuffer<Locals> = "u_locals",
// globals: gfx::ConstantBuffer<Globals> = "u_globals",
// tex: gfx::TextureSampler<[f32; 4]> = "u_tex",
// scissor: gfx::Scissor = (),
// tgt_color: gfx::BlendTarget<WinColorFmt> = ("tgt_color",
// gfx::state::ColorMask::all(), gfx::preset::blend::ALPHA), tgt_depth:
// gfx::DepthTarget<WinDepthFmt> = 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::<Self>() 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<Vec4<f32>> for Locals {
fn from(pos: Vec4<f32>) -> 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<f32>,
uv_rect: Aabr<f32>,

File diff suppressed because it is too large Load Diff