veloren_voxygen/render/pipelines/
clouds.rs

1use super::{
2    super::{AaMode, Consts},
3    GlobalsLayouts,
4};
5use bytemuck::{Pod, Zeroable};
6use vek::*;
7
8#[repr(C)]
9#[derive(Copy, Clone, Debug, Zeroable, Pod)]
10pub struct Locals {
11    all_mat_inv: [[f32; 4]; 4],
12}
13
14impl Default for Locals {
15    fn default() -> Self { Self::new(Mat4::identity(), Mat4::identity()) }
16}
17
18impl Locals {
19    pub fn new(proj_mat_inv: Mat4<f32>, view_mat_inv: Mat4<f32>) -> Self {
20        Self {
21            all_mat_inv: (view_mat_inv * proj_mat_inv).into_col_arrays(),
22        }
23    }
24}
25
26pub struct BindGroup {
27    pub(in super::super) bind_group: wgpu::BindGroup,
28}
29
30pub struct CloudsLayout {
31    pub layout: wgpu::BindGroupLayout,
32}
33
34impl CloudsLayout {
35    pub fn new(device: &wgpu::Device) -> Self {
36        Self {
37            layout: device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
38                label: None,
39                entries: &[
40                    // Color source
41                    wgpu::BindGroupLayoutEntry {
42                        binding: 0,
43                        visibility: wgpu::ShaderStages::FRAGMENT,
44                        ty: wgpu::BindingType::Texture {
45                            sample_type: wgpu::TextureSampleType::Float { filterable: true },
46                            view_dimension: wgpu::TextureViewDimension::D2,
47                            multisampled: false,
48                        },
49                        count: None,
50                    },
51                    wgpu::BindGroupLayoutEntry {
52                        binding: 1,
53                        visibility: wgpu::ShaderStages::FRAGMENT,
54                        ty: wgpu::BindingType::Sampler(wgpu::SamplerBindingType::Filtering),
55                        count: None,
56                    },
57                    // Depth source
58                    wgpu::BindGroupLayoutEntry {
59                        binding: 2,
60                        visibility: wgpu::ShaderStages::FRAGMENT,
61                        ty: wgpu::BindingType::Texture {
62                            sample_type: wgpu::TextureSampleType::Float { filterable: false },
63                            view_dimension: wgpu::TextureViewDimension::D2,
64                            multisampled: false,
65                        },
66                        count: None,
67                    },
68                    wgpu::BindGroupLayoutEntry {
69                        binding: 3,
70                        visibility: wgpu::ShaderStages::FRAGMENT,
71                        ty: wgpu::BindingType::Sampler(wgpu::SamplerBindingType::NonFiltering),
72                        count: None,
73                    },
74                    // Locals
75                    wgpu::BindGroupLayoutEntry {
76                        binding: 4,
77                        visibility: wgpu::ShaderStages::FRAGMENT,
78                        ty: wgpu::BindingType::Buffer {
79                            ty: wgpu::BufferBindingType::Uniform,
80                            has_dynamic_offset: false,
81                            min_binding_size: None,
82                        },
83                        count: None,
84                    },
85                    // Materials source
86                    wgpu::BindGroupLayoutEntry {
87                        binding: 5,
88                        visibility: wgpu::ShaderStages::FRAGMENT,
89                        ty: wgpu::BindingType::Texture {
90                            sample_type: wgpu::TextureSampleType::Uint,
91                            view_dimension: wgpu::TextureViewDimension::D2,
92                            multisampled: false,
93                        },
94                        count: None,
95                    },
96                ],
97            }),
98        }
99    }
100
101    pub fn bind(
102        &self,
103        device: &wgpu::Device,
104        src_color: &wgpu::TextureView,
105        src_mat: &wgpu::TextureView,
106        src_depth: &wgpu::TextureView,
107        sampler: &wgpu::Sampler,
108        depth_sampler: &wgpu::Sampler,
109        locals: &Consts<Locals>,
110    ) -> BindGroup {
111        let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
112            label: None,
113            layout: &self.layout,
114            entries: &[
115                wgpu::BindGroupEntry {
116                    binding: 0,
117                    resource: wgpu::BindingResource::TextureView(src_color),
118                },
119                wgpu::BindGroupEntry {
120                    binding: 1,
121                    resource: wgpu::BindingResource::Sampler(sampler),
122                },
123                wgpu::BindGroupEntry {
124                    binding: 2,
125                    resource: wgpu::BindingResource::TextureView(src_depth),
126                },
127                wgpu::BindGroupEntry {
128                    binding: 3,
129                    resource: wgpu::BindingResource::Sampler(depth_sampler),
130                },
131                wgpu::BindGroupEntry {
132                    binding: 4,
133                    resource: locals.buf().as_entire_binding(),
134                },
135                wgpu::BindGroupEntry {
136                    binding: 5,
137                    resource: wgpu::BindingResource::TextureView(src_mat),
138                },
139            ],
140        });
141
142        BindGroup { bind_group }
143    }
144}
145
146pub struct CloudsPipeline {
147    pub pipeline: wgpu::RenderPipeline,
148}
149
150impl CloudsPipeline {
151    pub fn new(
152        device: &wgpu::Device,
153        vs_module: &wgpu::ShaderModule,
154        fs_module: &wgpu::ShaderModule,
155        global_layout: &GlobalsLayouts,
156        layout: &CloudsLayout,
157        aa_mode: AaMode,
158        format: wgpu::TextureFormat,
159    ) -> Self {
160        common_base::span!(_guard, "CloudsPipeline::new");
161        let render_pipeline_layout =
162            device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
163                label: Some("Clouds pipeline layout"),
164                push_constant_ranges: &[],
165                bind_group_layouts: &[
166                    &global_layout.globals,
167                    &global_layout.shadow_textures,
168                    &layout.layout,
169                ],
170            });
171
172        let samples = aa_mode.samples();
173
174        let render_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
175            label: Some("Clouds pipeline"),
176            layout: Some(&render_pipeline_layout),
177            vertex: wgpu::VertexState {
178                module: vs_module,
179                entry_point: "main",
180                buffers: &[],
181            },
182            primitive: wgpu::PrimitiveState {
183                topology: wgpu::PrimitiveTopology::TriangleList,
184                strip_index_format: None,
185                front_face: wgpu::FrontFace::Ccw,
186                cull_mode: None,
187                unclipped_depth: false,
188                polygon_mode: wgpu::PolygonMode::Fill,
189                conservative: false,
190            },
191            depth_stencil: None,
192            multisample: wgpu::MultisampleState {
193                count: samples,
194                mask: !0,
195                alpha_to_coverage_enabled: false,
196            },
197            fragment: Some(wgpu::FragmentState {
198                module: fs_module,
199                entry_point: "main",
200                targets: &[Some(wgpu::ColorTargetState {
201                    format,
202                    blend: None,
203                    write_mask: wgpu::ColorWrites::ALL,
204                })],
205            }),
206            multiview: None,
207        });
208
209        Self {
210            pipeline: render_pipeline,
211        }
212    }
213}