Class EntityInstancing
- Namespace
- Stride.CommunityToolkit.Rendering.Instancing
- Assembly
- Stride.CommunityToolkit.dll
Draws many entities in a single draw call by collecting their world matrices every frame.
public class EntityInstancing : InstancingUserArray, IInstancing
- Inheritance
-
EntityInstancing
- Implements
- Derived
- Inherited Members
Examples
game.AddInstancingSupport();
var instancing = new EntityInstancing();
var master = new Entity("Master") { new ModelComponent(model), new InstancingComponent { Type = instancing } };
master.Scene = scene;
foreach (var entity in crowd) instancing.AddInstance(entity);
Remarks
This is a faster alternative to Stride's InstancingEntityTransform. Both do the same job - a master entity carries the ModelComponent and an InstancingComponent, while the instances contribute only their transforms - but this one keeps direct TransformComponent references, gathers and inverts in one parallel pass, reuses its arrays, and removes instances in constant time.
Instances are registered explicitly with AddInstance(Entity) rather than by adding an InstanceComponent, because the engine's registration hooks are internal to Stride.Engine. Instance entities must not have a ModelComponent of their own, or they are drawn twice - once individually and once by the master.
Use BepuEntityInstancing from Stride.CommunityToolkit.Bepu instead when the instances are
physics bodies: it skips the whole update while every body is asleep, which is where most of the
saving comes from for settled scenes.
Properties
AssumeRigidTransforms
Gets or sets a value indicating whether instance transforms are rigid - rotation and translation only, with no scale or shear. Defaults to true.
public bool AssumeRigidTransforms { get; set; }
Property Value
Remarks
A rigid inverse is roughly an order of magnitude cheaper than a general 4x4 inverse and is exact for physics bodies, which never scale. Set to false if instances can be scaled or sheared, which switches to a SIMD-accelerated general inverse. Leaving it true for scaled instances produces incorrect lighting, because the inverse matrices are what the shader uses to transform normals.
BoundingBox
public override BoundingBox BoundingBox { get; }
Property Value
GatheredMatrices
Gets the world matrices of the registered instances, in registration order.
protected ReadOnlySpan<Matrix> GatheredMatrices { get; }
Property Value
Remarks
Only the first InstanceCount entries are valid.
LastUpdateMilliseconds
Gets how long the last Update() took. Intended for diagnostics and on-screen counters.
public double LastUpdateMilliseconds { get; }
Property Value
ModelTransformUsage
public override ModelTransformUsage ModelTransformUsage { get; }
Property Value
Remarks
Instance matrices are already in world space, so the master's own transform is ignored.
ParallelThreshold
Gets or sets the instance count from which the gather runs in parallel. Defaults to 2048.
public int ParallelThreshold { get; set; }
Property Value
Remarks
Below this count it runs sequentially, because forking to the thread pool costs more than the work it spreads - and Stride's instancing processor already dispatches masters in parallel. The default is where the two met on the benchmark machine: sequential is six times faster at 256 instances, they draw level at 2048, and parallel is three times faster by 8192. Machines with different core counts will cross over elsewhere, so tune this if it matters; set it to MaxValue to always stay sequential.
RegisteredInstanceCount
Gets the number of registered instances, which is not necessarily the number drawn: disabled or skipped frames aside, InstanceCount is what the renderer uses.
public int RegisteredInstanceCount { get; }
Property Value
StructureDirty
Gets a value indicating whether the registered instances changed since the last update.
protected bool StructureDirty { get; }
Property Value
Remarks
CanSkipUpdate() implementations must not skip while this is true.
UpdateSkippedLastFrame
Gets a value indicating whether the last update was skipped because nothing had moved.
public bool UpdateSkippedLastFrame { get; }
Property Value
Remarks
Always false here; see BepuEntityInstancing.
Methods
AddInstance(Entity)
Registers an entity as an instance. Its TransformComponent is captured once, so the entity must not be reparented into a different transform component afterwards.
public bool AddInstance(Entity entity)
Parameters
entityEntityThe entity to draw as an instance. Must not carry a ModelComponent.
Returns
CanSkipUpdate()
Determines whether this frame's gather can be skipped because no instance has moved since the last one.
protected virtual bool CanSkipUpdate()
Returns
- bool
true to reuse the previous frame's matrices, inverses and bounding box verbatim. The base implementation always returns false, because without physics there is no cheap way to know whether a transform changed.
Remarks
Called only when the registered instances are unchanged, so implementations need not check StructureDirty. It must be cheaper than the gather it avoids, and must never return true when a transform has in fact changed - the frame would render stale positions.
Clear()
Unregisters every instance.
public void Clear()
OnInstanceAdded(Entity)
Called after an instance is appended, for derived classes keeping parallel data.
protected virtual void OnInstanceAdded(Entity entity)
Parameters
entityEntityThe newly registered entity, now at index RegisteredInstanceCount - 1.
OnInstanceRemoved(int, int)
Called after an instance is removed by swapping the last one into its place, for derived classes keeping parallel data.
protected virtual void OnInstanceRemoved(int index, int lastIndex)
Parameters
indexintThe index that was vacated and has just been overwritten.
lastIndexintThe index the surviving instance came from, now past the end.
Remarks
Derived data must mirror this exactly: copy lastIndex to
index when they differ, then drop lastIndex.
OnInstancesCleared()
Called after every instance is unregistered, for derived classes keeping parallel data.
protected virtual void OnInstancesCleared()
RemoveInstance(Entity)
Unregisters an entity. Removing the entity from the scene does not unregister it, unlike the engine's InstanceComponent.
public bool RemoveInstance(Entity entity)
Parameters
entityEntityThe entity to stop drawing.
Returns
Update()
Called by Stride's instancing processor once per frame, possibly on a worker thread.
public override void Update()