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: Some("main"),
114                buffers: &[Vertex::desc(), Instance::desc()],
115                compilation_options: Default::default(),
116            },
117            primitive: wgpu::PrimitiveState {
118                topology: wgpu::PrimitiveTopology::TriangleList,
119                strip_index_format: None,
120                front_face: wgpu::FrontFace::Ccw,
121                cull_mode: Some(wgpu::Face::Back),
122                unclipped_depth: false,
123                polygon_mode: wgpu::PolygonMode::Fill,
124                conservative: false,
125            },
126            depth_stencil: Some(wgpu::DepthStencilState {
127                format: wgpu::TextureFormat::Depth32Float,
128                depth_write_enabled: true,
129                depth_compare: wgpu::CompareFunction::GreaterEqual,
130                stencil: wgpu::StencilState {
131                    front: wgpu::StencilFaceState::IGNORE,
132                    back: wgpu::StencilFaceState::IGNORE,
133                    read_mask: !0,
134                    write_mask: 0,
135                },
136                bias: wgpu::DepthBiasState {
137                    constant: 0,
138                    slope_scale: 0.0,
139                    clamp: 0.0,
140                },
141            }),
142            multisample: wgpu::MultisampleState {
143                count: samples,
144                mask: !0,
145                alpha_to_coverage_enabled: false,
146            },
147            fragment: Some(wgpu::FragmentState {
148                module: fs_module,
149                entry_point: Some("main"),
150                targets: &[
151                    Some(wgpu::ColorTargetState {
152                        format,
153                        blend: Some(wgpu::BlendState::REPLACE),
154                        write_mask: wgpu::ColorWrites::ALL,
155                    }),
156                    Some(wgpu::ColorTargetState {
157                        format: wgpu::TextureFormat::Rgba8Uint,
158                        blend: None,
159                        write_mask: wgpu::ColorWrites::ALL,
160                    }),
161                ],
162                compilation_options: Default::default(),
163            }),
164            multiview: None,
165            cache: None,
166        });
167
168        Self {
169            pipeline: render_pipeline,
170        }
171    }
172}