veloren_voxygen/render/pipelines/
lod_terrain.rs

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