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                usage: None,
105                aspect: wgpu::TextureAspect::All,
106                base_mip_level: 0,
107                mip_level_count: None,
108                base_array_layer: 0,
109                array_layer_count: None,
110            };
111
112            renderer.create_texture_with_data_raw(
113                &texture_info,
114                &view_info,
115                &sampler_info,
116                bytemuck::cast_slice(data),
117            )
118        };
119        let map = create_texture(
120            wgpu::TextureFormat::Rgba8UnormSrgb,
121            lod_base,
122            wgpu::FilterMode::Linear,
123        );
124        //             SamplerInfo {
125        //                 border: border_color,
126        let alt = create_texture(
127            wgpu::TextureFormat::Rgba8Unorm,
128            lod_alt,
129            wgpu::FilterMode::Linear,
130        );
131        //             SamplerInfo {
132        //                 border: [0.0, 0.0, 0.0, 0.0].into(),
133        let horizon = create_texture(
134            wgpu::TextureFormat::Rgba8Unorm,
135            lod_horizon,
136            wgpu::FilterMode::Linear,
137        );
138        //             SamplerInfo {
139        //                 border: [1.0, 0.0, 1.0, 0.0].into(),
140        let weather = {
141            let texture_info = wgpu::TextureDescriptor {
142                label: None,
143                size: wgpu::Extent3d {
144                    width: weather_size.x,
145                    height: weather_size.y,
146                    depth_or_array_layers: 1,
147                },
148                mip_level_count: 1,
149                sample_count: 1,
150                dimension: wgpu::TextureDimension::D2,
151                format: wgpu::TextureFormat::Rgba8Unorm,
152                usage: wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::COPY_DST,
153                view_formats: &[],
154            };
155
156            let sampler_info = wgpu::SamplerDescriptor {
157                label: None,
158                address_mode_u: wgpu::AddressMode::ClampToBorder,
159                address_mode_v: wgpu::AddressMode::ClampToBorder,
160                address_mode_w: wgpu::AddressMode::ClampToBorder,
161                mag_filter: wgpu::FilterMode::Linear,
162                min_filter: wgpu::FilterMode::Linear,
163                mipmap_filter: wgpu::FilterMode::Nearest,
164                border_color: Some(wgpu::SamplerBorderColor::TransparentBlack),
165                ..Default::default()
166            };
167
168            let view_info = wgpu::TextureViewDescriptor {
169                label: None,
170                format: Some(wgpu::TextureFormat::Rgba8Unorm),
171                dimension: Some(wgpu::TextureViewDimension::D2),
172                usage: None,
173                aspect: wgpu::TextureAspect::All,
174                base_mip_level: 0,
175                mip_level_count: None,
176                base_array_layer: 0,
177                array_layer_count: None,
178            };
179
180            renderer.create_texture_with_data_raw(
181                &texture_info,
182                &view_info,
183                &sampler_info,
184                vec![0; weather_size.x as usize * weather_size.y as usize * 4].as_slice(),
185            )
186        };
187        Self {
188            map,
189            alt,
190            horizon,
191            tgt_detail,
192            weather,
193        }
194    }
195}
196
197pub struct LodTerrainPipeline {
198    pub pipeline: wgpu::RenderPipeline,
199}
200
201impl LodTerrainPipeline {
202    pub fn new(
203        device: &wgpu::Device,
204        vs_module: &wgpu::ShaderModule,
205        fs_module: &wgpu::ShaderModule,
206        global_layout: &GlobalsLayouts,
207        aa_mode: AaMode,
208        format: wgpu::TextureFormat,
209    ) -> Self {
210        let render_pipeline_layout =
211            device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
212                label: Some("Lod terrain pipeline layout"),
213                push_constant_ranges: &[],
214                bind_group_layouts: &[&global_layout.globals, &global_layout.shadow_textures],
215            });
216
217        let samples = aa_mode.samples();
218
219        let render_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
220            label: Some("Lod terrain pipeline"),
221            layout: Some(&render_pipeline_layout),
222            vertex: wgpu::VertexState {
223                module: vs_module,
224                entry_point: Some("main"),
225                buffers: &[Vertex::desc()],
226                compilation_options: Default::default(),
227            },
228            primitive: wgpu::PrimitiveState {
229                topology: wgpu::PrimitiveTopology::TriangleList,
230                strip_index_format: None,
231                front_face: wgpu::FrontFace::Ccw,
232                cull_mode: Some(wgpu::Face::Back),
233                unclipped_depth: false,
234                polygon_mode: wgpu::PolygonMode::Fill,
235                conservative: false,
236            },
237            depth_stencil: Some(wgpu::DepthStencilState {
238                format: wgpu::TextureFormat::Depth32Float,
239                depth_write_enabled: true,
240                depth_compare: wgpu::CompareFunction::GreaterEqual,
241                stencil: wgpu::StencilState {
242                    front: wgpu::StencilFaceState::IGNORE,
243                    back: wgpu::StencilFaceState::IGNORE,
244                    read_mask: !0,
245                    write_mask: 0,
246                },
247                bias: wgpu::DepthBiasState {
248                    constant: 0,
249                    slope_scale: 0.0,
250                    clamp: 0.0,
251                },
252            }),
253            multisample: wgpu::MultisampleState {
254                count: samples,
255                mask: !0,
256                alpha_to_coverage_enabled: false,
257            },
258            fragment: Some(wgpu::FragmentState {
259                module: fs_module,
260                entry_point: Some("main"),
261                targets: &[
262                    Some(wgpu::ColorTargetState {
263                        format,
264                        blend: None,
265                        write_mask: wgpu::ColorWrites::ALL,
266                    }),
267                    Some(wgpu::ColorTargetState {
268                        format: wgpu::TextureFormat::Rgba8Uint,
269                        blend: None,
270                        write_mask: wgpu::ColorWrites::ALL,
271                    }),
272                ],
273                compilation_options: Default::default(),
274            }),
275            multiview: None,
276            cache: None,
277        });
278
279        Self {
280            pipeline: render_pipeline,
281        }
282    }
283}