use crate::component::CuboidInstancesBuffer;
use bevy::{
ecs::system::{lifetimeless::*, SystemParamItem},
pbr::{SetMeshBindGroup, SetMeshViewBindGroup},
prelude::*,
render::{
mesh::GpuBufferInfo,
render_asset::RenderAssets,
render_phase::{
EntityRenderCommand, RenderCommandResult, SetItemPipeline, TrackedRenderPass,
},
},
};
pub(crate) type DrawCuboidInstances = (
SetItemPipeline,
SetMeshViewBindGroup<0>,
SetMeshBindGroup<1>,
DrawMeshInstanced,
);
pub(crate) struct DrawMeshInstanced;
impl EntityRenderCommand for DrawMeshInstanced {
type Param = (
SRes<RenderAssets<Mesh>>,
SQuery<Read<Handle<Mesh>>>,
SQuery<Read<CuboidInstancesBuffer>>,
);
#[inline]
fn render<'w>(
_view: Entity,
item: Entity,
(meshes, mesh_query, instance_buffer_query): SystemParamItem<'w, '_, Self::Param>,
pass: &mut TrackedRenderPass<'w>,
) -> RenderCommandResult {
let mesh_handle = mesh_query.get(item).unwrap();
let instance_buffer = instance_buffer_query.get_inner(item).unwrap();
let gpu_mesh = match meshes.into_inner().get(mesh_handle) {
Some(gpu_mesh) => gpu_mesh,
None => return RenderCommandResult::Failure,
};
pass.set_vertex_buffer(0, gpu_mesh.vertex_buffer.slice(..));
pass.set_vertex_buffer(1, instance_buffer.buffer.slice(..));
match &gpu_mesh.buffer_info {
GpuBufferInfo::Indexed {
buffer,
index_format,
count,
} => {
pass.set_index_buffer(buffer.slice(..), 0, *index_format);
pass.draw_indexed(0..*count, 0, 0..instance_buffer.length as u32);
}
GpuBufferInfo::NonIndexed { vertex_count } => {
pass.draw_indexed(0..*vertex_count, 0, 0..instance_buffer.length as u32);
}
}
RenderCommandResult::Success
}
}