flutter3d
Showcase Changelog 38 packages API reference

Mesh particles

since 0.2.0 or earlier Physics and particles

A billboard is a quad that always faces the camera, which is right for a spark or a puff of smoke and wrong for a shard of debris that should tumble and show its edges. MeshParticleContributor draws every live particle as a copy of a real mesh instead, in one instanced call.

Step 1: One mesh, uploaded once #

The shape is ordinary geometry, built and uploaded exactly the way a wall or a prop would be. Nothing about it knows it is about to become a particle.

// One shape, uploaded once. Every particle is a placement of it rather
// than a separate draw, which is what keeps this a single instanced call
// however many shards are on screen.
final DeviceMesh shard = DeviceMesh.upload(
  context.device,
  CuboidShape(size: Vector3(0.12, 0.12, 0.12)).build(),
);

Step 2: A second contributor, not a second mode #

ParticleContributor and MeshParticleContributor share a pool and a pass and almost nothing else: their vertex buffers, their layouts and their shaders all differ, because a billboard is four vertices built on the CPU and a mesh particle is eight floats of placement next to geometry that is already on the device.

_contributor = context.renderer.addContributor(
  MeshParticleContributor(_particles, mesh: shard),
);

Step 3: What the frame should show #

The claim is the ordinary one for a particle page: the contributor is active, the system holds exactly as many particles as were burst, and the frame actually drew something.

if (!_contributor.isActive) {
  throw StateError('the mesh particles should be alive and drawing');
}
if (_particles.aliveCount != _count || frame.drawCalls < 1) {
  throw StateError('the shards did not reach the frame');
}

Note. One mesh per contributor. Two different shapes of debris in the same burst are two contributors, which is cheap to arrange and honest about the extra draw call it costs.