bevy_sprite_instancing/
draw.rs

1use bevy::{
2    ecs::system::{
3        lifetimeless::{Read, SRes},
4        Res,
5    },
6    render::{
7        mesh::GpuBufferInfo,
8        render_phase::{
9            PhaseItem, RenderCommand, RenderCommandResult, SetItemPipeline, TrackedRenderPass,
10        },
11    },
12    sprite::SetMesh2dViewBindGroup,
13};
14
15use super::{
16    extract::ExtractedSpriteInstancingBuffer, InstancedSpriteMesh, InstancedSpritesheetBindGroup,
17};
18
19pub struct DrawSpritesInstanced;
20
21pub(super) type DrawSpritesInstancedCommands = (
22    SetItemPipeline,
23    // View uniform
24    SetMesh2dViewBindGroup<0>,
25    DrawSpritesInstanced,
26);
27
28impl<P: PhaseItem> RenderCommand<P> for DrawSpritesInstanced {
29    type Param = SRes<InstancedSpriteMesh>;
30    type ViewWorldQuery = ();
31    type ItemWorldQuery = (
32        Read<ExtractedSpriteInstancingBuffer>,
33        Read<InstancedSpritesheetBindGroup>,
34    );
35
36    fn render<'w>(
37        _item: &P,
38        _view: (),
39        (instancing_buffer, instancing_spritesheet): (
40            &'w ExtractedSpriteInstancingBuffer,
41            &'w InstancedSpritesheetBindGroup,
42        ),
43        instancing_mesh: Res<'w, InstancedSpriteMesh>,
44        pass: &mut TrackedRenderPass<'w>,
45    ) -> RenderCommandResult {
46        let instancing_mesh = instancing_mesh.into_inner();
47
48        pass.set_vertex_buffer(0, instancing_mesh.quad.vertex_buffer.slice(..));
49        pass.set_vertex_buffer(1, instancing_buffer.device_buffer.slice(..));
50        pass.set_bind_group(1, &instancing_spritesheet.bind_group, &[]);
51
52        match &instancing_mesh.quad.buffer_info {
53            GpuBufferInfo::NonIndexed { vertex_count } => {
54                pass.draw(0..*vertex_count, 0..instancing_buffer.length as u32);
55            }
56            _ => todo!(),
57        }
58
59        RenderCommandResult::Success
60    }
61}