Skip to main content

veloren_voxygen/render/pipelines/
lod_terrain.rs

1use super::super::{
2    ExperimentalShader, GlobalsLayouts, PipelineModes, Renderer, Texture, Vertex as VertexTrait,
3};
4use bytemuck::{Pod, Zeroable};
5use std::mem;
6use vek::*;
7
8#[repr(C)]
9#[derive(Copy, Clone, Debug, Zeroable, Pod)]
10pub struct Vertex {
11    pos: [f32; 2],
12}
13
14impl Vertex {
15    pub fn new(pos: Vec2<f32>) -> Self {
16        Self {
17            pos: pos.into_array(),
18        }
19    }
20
21    fn desc<'a>() -> wgpu::VertexBufferLayout<'a> {
22        const ATTRIBUTES: [wgpu::VertexAttribute; 1] = wgpu::vertex_attr_array![0 => Float32x2];
23        wgpu::VertexBufferLayout {
24            array_stride: Self::STRIDE,
25            step_mode: wgpu::VertexStepMode::Vertex,
26            attributes: &ATTRIBUTES,
27        }
28    }
29}
30
31impl VertexTrait for Vertex {
32    const QUADS_INDEX: Option<wgpu::IndexFormat> = Some(wgpu::IndexFormat::Uint32);
33    const STRIDE: wgpu::BufferAddress = mem::size_of::<Self>() as wgpu::BufferAddress;
34}
35
36pub struct LodData {
37    pub map: Texture,
38    pub alt: Texture,
39    pub horizon: Texture,
40    pub tgt_detail: u32,
41    pub weather: Texture,
42}
43
44impl LodData {
45    pub fn dummy(renderer: &mut Renderer) -> Self {
46        let map_size = Vec2::new(1, 1);
47        //let map_border = [0.0, 0.0, 0.0, 0.0];
48        let map_image = [0];
49        let alt_image = [0];
50        let horizon_image = [0x_00_01_00_01];
51
52        Self::new(
53            renderer,
54            map_size,
55            &map_image,
56            &alt_image,
57            &horizon_image,
58            Vec2::new(1, 1),
59            1,
60            //map_border.into(),
61        )
62    }
63
64    pub fn new(
65        renderer: &mut Renderer,
66        map_size: Vec2<u32>,
67        lod_base: &[u32],
68        lod_alt: &[u32],
69        lod_horizon: &[u32],
70        weather_size: Vec2<u32>,
71        tgt_detail: u32,
72        //border_color: gfx::texture::PackedColor,
73    ) -> Self {
74        let mut create_texture = |format, data, filter| {
75            let texture_info = wgpu::TextureDescriptor {
76                label: None,
77                size: wgpu::Extent3d {
78                    width: map_size.x,
79                    height: map_size.y,
80                    depth_or_array_layers: 1,
81                },
82                mip_level_count: 1,
83                sample_count: 1,
84                dimension: wgpu::TextureDimension::D2,
85                format,
86                usage: wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::COPY_DST,
87                view_formats: &[],
88            };
89
90            let sampler_info = wgpu::SamplerDescriptor {
91                label: None,
92                address_mode_u: wgpu::AddressMode::ClampToEdge,
93                address_mode_v: wgpu::AddressMode::ClampToEdge,
94                address_mode_w: wgpu::AddressMode::ClampToEdge,
95                mag_filter: filter,
96                min_filter: filter,
97                mipmap_filter: wgpu::FilterMode::Nearest,
98                border_color: Some(wgpu::SamplerBorderColor::TransparentBlack),
99                ..Default::default()
100            };
101
102            let view_info = wgpu::TextureViewDescriptor {
103                label: None,
104                format: Some(format),
105                dimension: Some(wgpu::TextureViewDimension::D2),
106                usage: None,
107                aspect: wgpu::TextureAspect::All,
108                base_mip_level: 0,
109                mip_level_count: None,
110                base_array_layer: 0,
111                array_layer_count: None,
112            };
113
114            renderer.create_texture_with_data_raw(
115                &texture_info,
116                &view_info,
117                &sampler_info,
118                bytemuck::cast_slice(data),
119            )
120        };
121        let map = create_texture(
122            wgpu::TextureFormat::Rgba8UnormSrgb,
123            lod_base,
124            wgpu::FilterMode::Linear,
125        );
126        //             SamplerInfo {
127        //                 border: border_color,
128        let alt = create_texture(
129            wgpu::TextureFormat::Rgba8Unorm,
130            lod_alt,
131            wgpu::FilterMode::Linear,
132        );
133        //             SamplerInfo {
134        //                 border: [0.0, 0.0, 0.0, 0.0].into(),
135        let horizon = create_texture(
136            wgpu::TextureFormat::Rgba8Unorm,
137            lod_horizon,
138            wgpu::FilterMode::Linear,
139        );
140        //             SamplerInfo {
141        //                 border: [1.0, 0.0, 1.0, 0.0].into(),
142        let weather = {
143            let texture_info = wgpu::TextureDescriptor {
144                label: None,
145                size: wgpu::Extent3d {
146                    width: weather_size.x,
147                    height: weather_size.y,
148                    depth_or_array_layers: 1,
149                },
150                mip_level_count: 1,
151                sample_count: 1,
152                dimension: wgpu::TextureDimension::D2,
153                format: wgpu::TextureFormat::Rgba8Unorm,
154                usage: wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::COPY_DST,
155                view_formats: &[],
156            };
157
158            let sampler_info = wgpu::SamplerDescriptor {
159                label: None,
160                address_mode_u: wgpu::AddressMode::ClampToBorder,
161                address_mode_v: wgpu::AddressMode::ClampToBorder,
162                address_mode_w: wgpu::AddressMode::ClampToBorder,
163                mag_filter: wgpu::FilterMode::Linear,
164                min_filter: wgpu::FilterMode::Linear,
165                mipmap_filter: wgpu::FilterMode::Nearest,
166                border_color: Some(wgpu::SamplerBorderColor::TransparentBlack),
167                ..Default::default()
168            };
169
170            let view_info = wgpu::TextureViewDescriptor {
171                label: None,
172                format: Some(wgpu::TextureFormat::Rgba8Unorm),
173                dimension: Some(wgpu::TextureViewDimension::D2),
174                usage: None,
175                aspect: wgpu::TextureAspect::All,
176                base_mip_level: 0,
177                mip_level_count: None,
178                base_array_layer: 0,
179                array_layer_count: None,
180            };
181
182            renderer.create_texture_with_data_raw(
183                &texture_info,
184                &view_info,
185                &sampler_info,
186                vec![0; weather_size.x as usize * weather_size.y as usize * 4].as_slice(),
187            )
188        };
189        Self {
190            map,
191            alt,
192            horizon,
193            tgt_detail,
194            weather,
195        }
196    }
197}
198
199pub struct LodTerrainPipeline {
200    pub pipeline: wgpu::RenderPipeline,
201}
202
203impl LodTerrainPipeline {
204    pub fn new(
205        device: &wgpu::Device,
206        vs_module: &wgpu::ShaderModule,
207        fs_module: &wgpu::ShaderModule,
208        global_layout: &GlobalsLayouts,
209        format: wgpu::TextureFormat,
210        pipeline_modes: &PipelineModes,
211    ) -> Self {
212        let render_pipeline_layout =
213            device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
214                label: Some("Lod terrain pipeline layout"),
215                push_constant_ranges: &[],
216                bind_group_layouts: &[&global_layout.globals, &global_layout.shadow_textures],
217            });
218
219        let samples = pipeline_modes.aa.samples();
220
221        let render_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
222            label: Some("Lod terrain pipeline"),
223            layout: Some(&render_pipeline_layout),
224            vertex: wgpu::VertexState {
225                module: vs_module,
226                entry_point: Some("main"),
227                buffers: &[Vertex::desc()],
228                compilation_options: Default::default(),
229            },
230            primitive: wgpu::PrimitiveState {
231                topology: wgpu::PrimitiveTopology::TriangleList,
232                strip_index_format: None,
233                front_face: wgpu::FrontFace::Ccw,
234                cull_mode: Some(wgpu::Face::Back),
235                unclipped_depth: false,
236                polygon_mode: if pipeline_modes
237                    .experimental_shaders
238                    .contains(&ExperimentalShader::Wireframe)
239                {
240                    wgpu::PolygonMode::Line
241                } else {
242                    wgpu::PolygonMode::Fill
243                },
244                conservative: false,
245            },
246            depth_stencil: Some(wgpu::DepthStencilState {
247                format: wgpu::TextureFormat::Depth32Float,
248                depth_write_enabled: true,
249                depth_compare: wgpu::CompareFunction::GreaterEqual,
250                stencil: wgpu::StencilState {
251                    front: wgpu::StencilFaceState::IGNORE,
252                    back: wgpu::StencilFaceState::IGNORE,
253                    read_mask: !0,
254                    write_mask: 0,
255                },
256                bias: wgpu::DepthBiasState {
257                    constant: 0,
258                    slope_scale: 0.0,
259                    clamp: 0.0,
260                },
261            }),
262            multisample: wgpu::MultisampleState {
263                count: samples,
264                mask: !0,
265                alpha_to_coverage_enabled: false,
266            },
267            fragment: Some(wgpu::FragmentState {
268                module: fs_module,
269                entry_point: Some("main"),
270                targets: &[
271                    Some(wgpu::ColorTargetState {
272                        format,
273                        blend: None,
274                        write_mask: wgpu::ColorWrites::ALL,
275                    }),
276                    Some(wgpu::ColorTargetState {
277                        format: wgpu::TextureFormat::Rgba8Uint,
278                        blend: None,
279                        write_mask: wgpu::ColorWrites::ALL,
280                    }),
281                ],
282                compilation_options: Default::default(),
283            }),
284            multiview: None,
285            cache: None,
286        });
287
288        Self {
289            pipeline: render_pipeline,
290        }
291    }
292}