veloren_voxygen/render/pipelines/
rain_occlusion.rs

1use super::super::{
2    AaMode, Bound, Consts, FigureLayout, GlobalsLayouts, TerrainLayout, TerrainVertex,
3};
4use bytemuck::{Pod, Zeroable};
5use vek::*;
6
7#[repr(C)]
8#[derive(Copy, Clone, Debug, Zeroable, Pod, Default)]
9pub struct Locals {
10    rain_occlusion_matrices: [[f32; 4]; 4],
11    rain_occlusion_texture_mat: [[f32; 4]; 4],
12    /// A rotation of the direction of the rain, relative to the players
13    /// velocity.
14    rain_dir_mat: [[f32; 4]; 4],
15    /// A value to offset the rain, to make it move over time.
16    integrated_rain_vel: f32,
17    rain_density: f32,
18    // To keep 16-byte-aligned.
19    occlusion_dummy: [f32; 2],
20}
21/// Make sure Locals is 16-byte-aligned.
22const _: () = assert!(core::mem::size_of::<Locals>() % 16 == 0);
23
24impl Locals {
25    pub fn new(
26        rain_occlusion_matrices: Mat4<f32>,
27        rain_occlusion_texture_mat: Mat4<f32>,
28        rain_dir_mat: Mat4<f32>,
29        rain_density: f32,
30        integrated_rain_vel: f32,
31    ) -> Self {
32        Self {
33            rain_occlusion_matrices: rain_occlusion_matrices.into_col_arrays(),
34            rain_occlusion_texture_mat: rain_occlusion_texture_mat.into_col_arrays(),
35            rain_dir_mat: rain_dir_mat.into_col_arrays(),
36            integrated_rain_vel,
37            rain_density,
38            occlusion_dummy: [0.0; 2],
39        }
40    }
41}
42
43pub type BoundLocals = Bound<Consts<Locals>>;
44
45pub struct RainOcclusionLayout {
46    pub locals: wgpu::BindGroupLayout,
47}
48
49impl RainOcclusionLayout {
50    pub fn new(device: &wgpu::Device) -> Self {
51        Self {
52            locals: device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
53                label: None,
54                entries: &[wgpu::BindGroupLayoutEntry {
55                    binding: 0,
56                    visibility: wgpu::ShaderStages::VERTEX_FRAGMENT,
57                    ty: wgpu::BindingType::Buffer {
58                        ty: wgpu::BufferBindingType::Uniform,
59                        has_dynamic_offset: false,
60                        min_binding_size: None,
61                    },
62                    count: None,
63                }],
64            }),
65        }
66    }
67
68    pub fn bind_locals(&self, device: &wgpu::Device, locals: Consts<Locals>) -> BoundLocals {
69        let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
70            label: None,
71            layout: &self.locals,
72            entries: &[wgpu::BindGroupEntry {
73                binding: 0,
74                resource: locals.buf().as_entire_binding(),
75            }],
76        });
77
78        BoundLocals {
79            bind_group,
80            with: locals,
81        }
82    }
83}
84
85pub struct RainOcclusionFigurePipeline {
86    pub pipeline: wgpu::RenderPipeline,
87}
88
89impl RainOcclusionFigurePipeline {
90    pub fn new(
91        device: &wgpu::Device,
92        vs_module: &wgpu::ShaderModule,
93        global_layout: &GlobalsLayouts,
94        figure_layout: &FigureLayout,
95        aa_mode: AaMode,
96    ) -> Self {
97        common_base::span!(_guard, "new");
98
99        let render_pipeline_layout =
100            device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
101                label: Some("Rain occlusion figure pipeline layout"),
102                push_constant_ranges: &[],
103                bind_group_layouts: &[&global_layout.globals, &figure_layout.locals],
104            });
105
106        let samples = aa_mode.samples();
107
108        let render_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
109            label: Some("Rain occlusion figure pipeline"),
110            layout: Some(&render_pipeline_layout),
111            vertex: wgpu::VertexState {
112                module: vs_module,
113                entry_point: "main",
114                buffers: &[TerrainVertex::desc()],
115            },
116            primitive: wgpu::PrimitiveState {
117                topology: wgpu::PrimitiveTopology::TriangleList,
118                strip_index_format: None,
119                front_face: wgpu::FrontFace::Ccw,
120                cull_mode: Some(wgpu::Face::Back),
121                unclipped_depth: true,
122                polygon_mode: wgpu::PolygonMode::Fill,
123                conservative: false,
124            },
125            depth_stencil: Some(wgpu::DepthStencilState {
126                format: wgpu::TextureFormat::Depth24Plus,
127                depth_write_enabled: true,
128                depth_compare: wgpu::CompareFunction::Less,
129                stencil: wgpu::StencilState {
130                    front: wgpu::StencilFaceState::IGNORE,
131                    back: wgpu::StencilFaceState::IGNORE,
132                    read_mask: 0,
133                    write_mask: 0,
134                },
135                bias: wgpu::DepthBiasState {
136                    constant: 0,
137                    slope_scale: 0.0,
138                    clamp: 0.0,
139                },
140            }),
141            multisample: wgpu::MultisampleState {
142                count: samples,
143                mask: !0,
144                alpha_to_coverage_enabled: false,
145            },
146            fragment: None,
147            multiview: None,
148        });
149
150        Self {
151            pipeline: render_pipeline,
152        }
153    }
154}
155
156pub struct RainOcclusionPipeline {
157    pub pipeline: wgpu::RenderPipeline,
158}
159
160impl RainOcclusionPipeline {
161    pub fn new(
162        device: &wgpu::Device,
163        vs_module: &wgpu::ShaderModule,
164        global_layout: &GlobalsLayouts,
165        terrain_layout: &TerrainLayout,
166        aa_mode: AaMode,
167    ) -> Self {
168        let render_pipeline_layout =
169            device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
170                label: Some("Rain occlusion pipeline layout"),
171                push_constant_ranges: &[],
172                bind_group_layouts: &[&global_layout.globals, &terrain_layout.locals],
173            });
174
175        let samples = aa_mode.samples();
176
177        let render_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
178            label: Some("Rain occlusion pipeline"),
179            layout: Some(&render_pipeline_layout),
180            vertex: wgpu::VertexState {
181                module: vs_module,
182                entry_point: "main",
183                buffers: &[TerrainVertex::desc()],
184            },
185            primitive: wgpu::PrimitiveState {
186                topology: wgpu::PrimitiveTopology::TriangleList,
187                strip_index_format: None,
188                front_face: wgpu::FrontFace::Ccw,
189                cull_mode: None,
190                unclipped_depth: true,
191                polygon_mode: wgpu::PolygonMode::Fill,
192                conservative: false,
193            },
194            depth_stencil: Some(wgpu::DepthStencilState {
195                format: wgpu::TextureFormat::Depth24Plus,
196                depth_write_enabled: true,
197                depth_compare: wgpu::CompareFunction::Less,
198                stencil: wgpu::StencilState {
199                    front: wgpu::StencilFaceState::IGNORE,
200                    back: wgpu::StencilFaceState::IGNORE,
201                    read_mask: 0,
202                    write_mask: 0,
203                },
204                bias: wgpu::DepthBiasState {
205                    constant: 0,
206                    slope_scale: 0.0,
207                    clamp: 0.0,
208                },
209            }),
210            multisample: wgpu::MultisampleState {
211                count: samples,
212                mask: !0,
213                alpha_to_coverage_enabled: false,
214            },
215            fragment: None,
216            multiview: None,
217        });
218
219        Self {
220            pipeline: render_pipeline,
221        }
222    }
223}