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