veloren_voxygen/render/pipelines/
lod_object.rs1use super::super::{ExperimentalShader, GlobalsLayouts, PipelineModes, 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
78pub 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 format: wgpu::TextureFormat,
96 pipeline_modes: &PipelineModes,
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 = pipeline_modes.aa.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: if pipeline_modes
124 .experimental_shaders
125 .contains(&ExperimentalShader::Wireframe)
126 {
127 wgpu::PolygonMode::Line
128 } else {
129 wgpu::PolygonMode::Fill
130 },
131 conservative: false,
132 },
133 depth_stencil: Some(wgpu::DepthStencilState {
134 format: wgpu::TextureFormat::Depth32Float,
135 depth_write_enabled: true,
136 depth_compare: wgpu::CompareFunction::GreaterEqual,
137 stencil: wgpu::StencilState {
138 front: wgpu::StencilFaceState::IGNORE,
139 back: wgpu::StencilFaceState::IGNORE,
140 read_mask: !0,
141 write_mask: 0,
142 },
143 bias: wgpu::DepthBiasState {
144 constant: 0,
145 slope_scale: 0.0,
146 clamp: 0.0,
147 },
148 }),
149 multisample: wgpu::MultisampleState {
150 count: samples,
151 mask: !0,
152 alpha_to_coverage_enabled: false,
153 },
154 fragment: Some(wgpu::FragmentState {
155 module: fs_module,
156 entry_point: Some("main"),
157 targets: &[
158 Some(wgpu::ColorTargetState {
159 format,
160 blend: Some(wgpu::BlendState::REPLACE),
161 write_mask: wgpu::ColorWrites::ALL,
162 }),
163 Some(wgpu::ColorTargetState {
164 format: wgpu::TextureFormat::Rgba8Uint,
165 blend: None,
166 write_mask: wgpu::ColorWrites::ALL,
167 }),
168 ],
169 compilation_options: Default::default(),
170 }),
171 multiview: None,
172 cache: None,
173 });
174
175 Self {
176 pipeline: render_pipeline,
177 }
178 }
179}