pub struct InstancedCluster {Show 14 fields
pub vertex_offset: usize,
pub vertex_count: usize,
pub index_offset: usize,
pub index_count: usize,
pub texture_slot: usize,
pub normal_map_slot: usize,
pub material: MaterialUniforms,
pub cluster_bb_min: [f32; 3],
pub cluster_bb_max: [f32; 3],
pub local_bb_min: [f32; 3],
pub local_bb_max: [f32; 3],
pub cull_distance: f32,
pub instances: Vec<[[f32; 4]; 4]>,
pub lod_alternates: Vec<LodSlice>,
}Expand description
One GPU-instanced draw: a shared mesh slice + material rendered at many
world-space transforms in a single drawIndexedInstanced / cmd_draw_indexed
(instance_count > 1). The cluster has a single union AABB across all
instances; it is frustum-tested as a whole. Cluster culling trades per-
instance precision for one draw call instead of N.
Fields§
§vertex_offset: usizeByte offset into the shared vertex buffer. Currently unused because
every backend keeps the shared vertex buffer bound at offset 0 and
append_mesh rebases indices accordingly; retained for symmetry with
DrawObject and future per-cluster vertex bindings.
vertex_count: usizeNumber of vertices this cluster’s mesh occupies in the shared vertex
buffer, starting at vertex_offset. Used by the shrinkable-seed
compaction to relocate the cluster’s geometry region when streamed-mesh
gaps are removed from the shared buffer.
index_offset: usizeElement offset into the shared index buffer.
index_count: usizeNumber of indices per instance.
texture_slot: usizeIndex into the shared texture pool for this cluster’s albedo map.
normal_map_slot: usizeIndex into the shared texture pool for this cluster’s normal map, or
NO_NORMAL_MAP_SLOT when the cluster has no normal map.
material: MaterialUniformsPer-cluster material scalars, identical for every instance.
cluster_bb_min: [f32; 3]Union AABB of all per-instance world AABBs; used for cluster-wide frustum culling. A degenerate (NaN) box disables culling.
cluster_bb_max: [f32; 3]Upper corner of the cluster’s union world AABB.
local_bb_min: [f32; 3]Mesh-local (object-space) AABB, identical for every instance. The GPU-driven instanced path transforms this by each instance’s model matrix to get a per-instance world AABB for per-instance frustum/distance/Hi-Z culling; the union AABB above is only the whole-cluster bound.
local_bb_max: [f32; 3]Upper corner of the mesh-local bind AABB.
cull_distance: f32View-distance cutoff applied to the cluster centre. 0 = no cutoff.
instances: Vec<[[f32; 4]; 4]>Per-instance column-major model matrices. Uploaded to a transient GPU buffer each frame.
lod_alternates: Vec<LodSlice>LOD1..N slices for this cluster’s mesh, in ascending switch_distance
order. Empty when the mesh declared lod_levels <= 1. Each per-instance
LOD is picked from camera distance to that instance’s translation; the
per-pass draw loop partitions instances by their picked LOD and issues
one drawIndexedInstanced per non-empty bucket. The vertex set is
shared with LOD0 (QEM decimation preserves vertices), so only
(index_offset, index_count) varies per slice.
Implementations§
Source§impl InstancedCluster
impl InstancedCluster
Sourcepub fn cullable(&self) -> bool
pub fn cullable(&self) -> bool
True when the cluster AABB encodes valid finite bounds suitable for frustum / distance culling.
Sourcepub fn lod_buckets(&self, cam_pos: [f32; 3]) -> Vec<InstancedLodBucket>
pub fn lod_buckets(&self, cam_pos: [f32; 3]) -> Vec<InstancedLodBucket>
Partition the cluster’s instances into LOD buckets keyed by camera
distance to each instance’s translation. Returns one entry per
non-empty bucket, in mesh-LOD order (LOD0 first). With no alternates
every instance lands in a single LOD0 bucket so the caller’s loop
degenerates to the legacy one-drawIndexedInstanced path.
Per-instance distance uses the model-matrix translation rather than a transformed-AABB centre: close enough for distance-keyed swaps without paying the per-instance AABB transform every pass.
Sourcepub fn try_for_each_lod_bucket<E>(
&self,
cam_pos: [f32; 3],
visit: impl FnMut(usize, usize, &[[[f32; 4]; 4]]) -> Result<(), E>,
) -> Result<(), E>
pub fn try_for_each_lod_bucket<E>( &self, cam_pos: [f32; 3], visit: impl FnMut(usize, usize, &[[[f32; 4]; 4]]) -> Result<(), E>, ) -> Result<(), E>
Visit each non-empty LOD bucket for this cluster, calling
visit(index_offset, index_count, instances) once per bucket in
mesh-LOD order (LOD0 first). Stops and returns the first error a visit
produces.
In the common no-alternates case instances borrows self.instances
directly (no allocation, no copy) so a caller that memcpy’s the slice
into a GPU buffer skips the wholesale clone that the owned
lod_buckets makes. Clusters that declared LOD
alternates still regroup their instances per LOD (a copy that separate
per-LOD draw calls genuinely require); that path reuses lod_buckets.