Skip to main content

monstertruck_render/
polygon_instance.rs

1use crate::*;
2
3impl PolygonInstance {
4    /// Clone the instance as another drawn element.
5    #[inline(always)]
6    pub fn clone_instance(&self) -> PolygonInstance {
7        PolygonInstance {
8            polygon: self.polygon.clone(),
9            state: self.state.clone(),
10            shaders: self.shaders.clone(),
11            id: RenderId::generate(),
12        }
13    }
14    /// Returns a reference to the instance descriptor.
15    #[inline(always)]
16    pub const fn instance_state(&self) -> &PolygonState { &self.state }
17    /// Returns the mutable reference to instance descriptor.
18    #[inline(always)]
19    pub fn instance_state_mut(&mut self) -> &mut PolygonState { &mut self.state }
20
21    /// swap vertex buffers and index buffers
22    #[inline(always)]
23    pub fn swap_vertex(&mut self, other: &mut PolygonInstance) {
24        std::mem::swap(&mut self.polygon, &mut other.polygon);
25    }
26
27    #[inline(always)]
28    fn non_textured_bdl(&self, device: &Device) -> BindGroupLayout {
29        let entries = [
30            PolygonState::matrix_bgl_entry(),
31            PolygonState::material_bgl_entry(),
32        ];
33        bind_group_util::create_bind_group_layout(device, &entries)
34    }
35
36    #[inline(always)]
37    fn textured_bdl(&self, device: &Device) -> BindGroupLayout {
38        bind_group_util::create_bind_group_layout(
39            device,
40            &[
41                PolygonState::matrix_bgl_entry(),
42                PolygonState::material_bgl_entry(),
43                PolygonState::textureview_bgl_entry(),
44                PolygonState::sampler_bgl_entry(),
45            ],
46        )
47    }
48
49    #[inline(always)]
50    fn non_textured_bg(&self, device: &Device, layout: &BindGroupLayout) -> BindGroup {
51        bind_group_util::create_bind_group(
52            device,
53            layout,
54            vec![
55                self.state.matrix_buffer(device).binding_resource(),
56                self.state.material.buffer(device).binding_resource(),
57            ],
58        )
59    }
60    #[inline(always)]
61    fn textured_bg(&self, device: &Device, layout: &BindGroupLayout) -> BindGroup {
62        let (view, sampler) = self.state.textureview_and_sampler(device);
63        bind_group_util::create_bind_group(
64            device,
65            layout,
66            vec![
67                self.state.matrix_buffer(device).binding_resource(),
68                self.state.material.buffer(device).binding_resource(),
69                BindingResource::TextureView(&view),
70                BindingResource::Sampler(&sampler),
71            ],
72        )
73    }
74}
75
76impl Rendered for PolygonInstance {
77    impl_render_id!(id);
78
79    #[inline(always)]
80    fn vertex_buffer(&self, _: &DeviceHandler) -> (Arc<BufferHandler>, Option<Arc<BufferHandler>>) {
81        let polygon = self.polygon.clone();
82        (polygon.0, Some(polygon.1))
83    }
84    #[inline(always)]
85    fn bind_group_layout(&self, device_handler: &DeviceHandler) -> Arc<BindGroupLayout> {
86        Arc::new(match self.state.texture.is_some() {
87            true => self.textured_bdl(device_handler.device()),
88            false => self.non_textured_bdl(device_handler.device()),
89        })
90    }
91    #[inline(always)]
92    fn bind_group(
93        &self,
94        device_handler: &DeviceHandler,
95        layout: &BindGroupLayout,
96    ) -> Arc<BindGroup> {
97        Arc::new(match self.state.texture.is_some() {
98            true => self.textured_bg(device_handler.device(), layout),
99            false => self.non_textured_bg(device_handler.device(), layout),
100        })
101    }
102    #[inline(always)]
103    fn pipeline(
104        &self,
105        device_handler: &DeviceHandler,
106        layout: &PipelineLayout,
107        scene_desc: &SceneDescriptor,
108    ) -> Arc<RenderPipeline> {
109        let device = device_handler.device();
110        let (fragment_module, fragment_entry) = match self.state.texture.is_some() {
111            true => (
112                &self.shaders.tex_fragment_module,
113                self.shaders.tex_fragment_entry,
114            ),
115            false => (&self.shaders.fragment_module, self.shaders.fragment_entry),
116        };
117        let cull_mode = match self.state.backface_culling {
118            true => Some(Face::Back),
119            false => None,
120        };
121        let blend = match self.state.material.alpha_blend {
122            true => Some(BlendState::ALPHA_BLENDING),
123            false => Some(BlendState::REPLACE),
124        };
125        let depth_stencil = match scene_desc.backend_buffer.depth_test {
126            true => Some(DepthStencilState {
127                format: TextureFormat::Depth32Float,
128                depth_write_enabled: Some(true),
129                depth_compare: Some(CompareFunction::Less),
130                stencil: Default::default(),
131                bias: Default::default(),
132            }),
133            false => None,
134        };
135        let sample_count = scene_desc.backend_buffer.sample_count;
136        let pipeline = device.create_render_pipeline(&RenderPipelineDescriptor {
137            layout: Some(layout),
138            vertex: VertexState {
139                module: &self.shaders.vertex_module,
140                entry_point: Some(self.shaders.vertex_entry),
141                buffers: &[VertexBufferLayout {
142                    array_stride: size_of::<AttrVertex>() as BufferAddress,
143                    step_mode: VertexStepMode::Vertex,
144                    attributes: &[
145                        VertexAttribute {
146                            format: VertexFormat::Float32x3,
147                            offset: 0,
148                            shader_location: 0,
149                        },
150                        VertexAttribute {
151                            format: VertexFormat::Float32x2,
152                            offset: 3 * 4,
153                            shader_location: 1,
154                        },
155                        VertexAttribute {
156                            format: VertexFormat::Float32x3,
157                            offset: 2 * 4 + 3 * 4,
158                            shader_location: 2,
159                        },
160                    ],
161                }],
162                compilation_options: Default::default(),
163            },
164            fragment: Some(FragmentState {
165                module: fragment_module,
166                entry_point: Some(fragment_entry),
167                targets: &[Some(ColorTargetState {
168                    format: scene_desc.render_texture.format,
169                    blend,
170                    write_mask: ColorWrites::ALL,
171                })],
172                compilation_options: Default::default(),
173            }),
174            primitive: PrimitiveState {
175                topology: PrimitiveTopology::TriangleList,
176                front_face: FrontFace::Ccw,
177                cull_mode,
178                polygon_mode: PolygonMode::Fill,
179                ..Default::default()
180            },
181            depth_stencil,
182            multisample: MultisampleState {
183                count: sample_count,
184                mask: !0,
185                alpha_to_coverage_enabled: sample_count > 1,
186            },
187            label: None,
188            multiview_mask: None,
189            cache: None,
190        });
191        Arc::new(pipeline)
192    }
193}