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.
Auto Trait Implementations§
impl Freeze for InstancedCluster
impl RefUnwindSafe for InstancedCluster
impl Send for InstancedCluster
impl Sync for InstancedCluster
impl Unpin for InstancedCluster
impl UnsafeUnpin for InstancedCluster
impl UnwindSafe for InstancedCluster
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
impl<S, T> Duplex<S> for Twhere
T: FromSample<S> + ToSample<S>,
Source§impl<S> FromSample<S> for S
impl<S> FromSample<S> for S
fn from_sample_(s: S) -> S
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more