veloren_voxygen/render/pipelines/
lod_object.rs

1use super::super::{AaMode, GlobalsLayouts, Vertex as VertexTrait};
2use bytemuck::{Pod, Zeroable};
3use common::util::srgb_to_linear;
4use std::mem;
5use vek::*;
6
7#[repr(C)]
8#[derive(Copy, Clone, Debug, Zeroable, Pod)]
9pub struct Vertex {
10    pos: [f32; 3],
11    norm: [f32; 3],
12    col: [f32; 3],
13    flags: u32,
14}
15
16impl Vertex {
17    pub fn new(
18        pos: Vec3<f32>,
19        norm: Vec3<f32>,
20        col: Rgb<f32>,
21        flags: crate::scene::lod::VertexFlags,
22    ) -> Self {
23        Self {
24            pos: pos.into_array(),
25            norm: norm.into_array(),
26            col: col.into_array(),
27            flags: flags.bits() as u32,
28        }
29    }
30
31    fn desc<'a>() -> wgpu::VertexBufferLayout<'a> {
32        const ATTRIBUTES: [wgpu::VertexAttribute; 4] =
33            wgpu::vertex_attr_array![0 => Float32x3, 1 => Float32x3, 2 => Float32x3, 3 => Uint32];
34        wgpu::VertexBufferLayout {
35            array_stride: Self::STRIDE,
36            step_mode: wgpu::VertexStepMode::Vertex,
37            attributes: &ATTRIBUTES,
38        }
39    }
40}
41
42impl VertexTrait for Vertex {
43    const QUADS_INDEX: Option<wgpu::IndexFormat> = None;
44    const STRIDE: wgpu::BufferAddress = mem::size_of::<Self>() as wgpu::BufferAddress;
45}
46
47#[repr(C)]
48#[derive(Copy, Clone, Debug, Zeroable, Pod)]
49pub struct Instance {
50    inst_pos: [f32; 3],
51    inst_col: [f32; 3],
52    flags: u32,
53}
54
55impl Instance {
56    pub fn new(inst_pos: Vec3<f32>, col: Rgb<u8>, flags: common::lod::InstFlags) -> Self {
57        Self {
58            inst_pos: inst_pos.into_array(),
59            inst_col: srgb_to_linear(col.map(|c| c as f32 / 255.0)).into_array(),
60            flags: flags.bits() as u32,
61        }
62    }
63
64    fn desc<'a>() -> wgpu::VertexBufferLayout<'a> {
65        const ATTRIBUTES: [wgpu::VertexAttribute; 3] = wgpu::vertex_attr_array![
66            4 => Float32x3,
67            5 => Float32x3,
68            6 => Uint32,
69        ];
70        wgpu::VertexBufferLayout {
71            array_stride: mem::size_of::<Self>() as wgpu::BufferAddress,
72            step_mode: wgpu::VertexStepMode::Instance,
73            attributes: &ATTRIBUTES,
74        }
75    }
76}
77
78// impl Default for Instance {
79//     fn default() -> Self { Self::new(Mat4::identity(), 0.0, 0.0,
80// Vec3::zero(), 0, 1.0, 0.0, 0) } }
81
82// TODO: ColLightsWrapper instead?
83pub struct Locals;
84
85pub struct LodObjectPipeline {
86    pub pipeline: wgpu::RenderPipeline,
87}
88
89impl LodObjectPipeline {
90    pub fn new(
91        device: &wgpu::Device,
92        vs_module: &wgpu::ShaderModule,
93        fs_module: &wgpu::ShaderModule,
94        global_layout: &GlobalsLayouts,
95        aa_mode: AaMode,
96        format: wgpu::TextureFormat,
97    ) -> Self {
98        common_base::span!(_guard, "LodObjectPipeline::new");
99        let render_pipeline_layout =
100            device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
101                label: Some("LoD object pipeline layout"),
102                push_constant_ranges: &[],
103                bind_group_layouts: &[&global_layout.globals, &global_layout.shadow_textures],
104            });
105
106        let samples = aa_mode.samples();
107
108        let render_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
109            label: Some("LoD object pipeline"),
110            layout: Some(&render_pipeline_layout),
111            vertex: wgpu::VertexState {
112                module: vs_module,
113                entry_point: "main",
114                buffers: &[Vertex::desc(), Instance::desc()],
115            },
116            primitive: wgpu::PrimitiveState {
117                topology: wgpu::PrimitiveTopology::TriangleList,
118                strip_index_format: None,
119                front_face: wgpu::FrontFace::Ccw,
120                cull_mode: Some(wgpu::Face::Back),
121                unclipped_depth: false,
122                polygon_mode: wgpu::PolygonMode::Fill,
123                conservative: false,
124            },
125            depth_stencil: Some(wgpu::DepthStencilState {
126                format: wgpu::TextureFormat::Depth32Float,
127                depth_write_enabled: true,
128                depth_compare: wgpu::CompareFunction::GreaterEqual,
129                stencil: wgpu::StencilState {
130                    front: wgpu::StencilFaceState::IGNORE,
131                    back: wgpu::StencilFaceState::IGNORE,
132                    read_mask: !0,
133                    write_mask: 0,
134                },
135                bias: wgpu::DepthBiasState {
136                    constant: 0,
137                    slope_scale: 0.0,
138                    clamp: 0.0,
139                },
140            }),
141            multisample: wgpu::MultisampleState {
142                count: samples,
143                mask: !0,
144                alpha_to_coverage_enabled: false,
145            },
146            fragment: Some(wgpu::FragmentState {
147                module: fs_module,
148                entry_point: "main",
149                targets: &[
150                    Some(wgpu::ColorTargetState {
151                        format,
152                        blend: Some(wgpu::BlendState::REPLACE),
153                        write_mask: wgpu::ColorWrites::ALL,
154                    }),
155                    Some(wgpu::ColorTargetState {
156                        format: wgpu::TextureFormat::Rgba8Uint,
157                        blend: None,
158                        write_mask: wgpu::ColorWrites::ALL,
159                    }),
160                ],
161            }),
162            multiview: None,
163        });
164
165        Self {
166            pipeline: render_pipeline,
167        }
168    }
169}