Don't see a lot of 3d here, here's a chunk that may help somebody else out down the road:
Here's a simple MeshBatcher that roughly follows order your graphics draw calls around. It's meant for general purpose use (not specialized cases like fields of grass) and assumes that a modern lighting method is used (Forward+, clustered, deferred) as it makes no considerations regarding lighting needs.
The sort key is organized to prioritize by layer then effect since the Effect is where the more costly state changes are (shader, uniforms, textures), and lastly by vtx/idx data and whether instancing is forced-off (ie: for skeletal animated meshes). The resulting draws will be fairly optimal and whenever possible instancing will be used (min/max range is configurable).
Basically you throw crap at it, which it organizes, and later you call
Render with an arbitrary
passID and it runs through it in as close to an optimal sequence as you're going to get.
Only real bits required for someone to use it are:
- Add instanced Technique variations to your Effects
VertexShaderOutput MainVSInstanced(in VertexShaderInput input, in float4x4 InstanceTransform : TEXCOORD1)
- Replace/remap the
Camera type of mine that isn't included
- add whatever helpers you need
- Actual functions are all raw, passing vtx / idx buffers
- decide whether to keep the
IMeshBatchEffect interface for
Effect classes or to instead rely on conventions (ie. it's always a shader-constant named
Note: the Begin/End functions in that interface are there to deal with GPU state concerns (depth-equal, etc) and pumping in uniform values, if you ditch the interface you might have more work
- Change vertex data semantics for the additional instance transforms buffer if desired
An naive/trivial implementation of the
IMeshBatchEffect interface looks like:
public bool PrepareInstanced(int passID)
CurrentTechnique = Techniques.Last();
public bool PrepareOneOff(Matrix transform, int passID)
CurrentTechnique = Techniques.First();
public bool EffectSelected(int passID)
public void EffectDeselected()
If you try to use it and have questions, ask.