The mesh rendering is actually pretty "advanced" in comparison to the simple myModel.Draw()
It's fairly messy and probably easy to get lost in but what I do for all entities:
(excuse the naming)
- when the entity is created I register them in my MeshMaterialLibrary
- this library has an array of MaterialLibraries
- each MaterialLibrary has an array of MeshLibraries (with all the different meshes for each material)
- these MeshLibraries have an array of all the instances of this mesh, plus obviously the bufferdata for the mesh.
The idea is that many objects can use the same material - so let's make sure we batch our rendering by material. If we sort all meshes by material we have the fewest possible render state changes!
In the gameSettings file you can activate this "batchByMaterial" mode with this command, which is "false" by default
public static bool g_BatchByMaterial = true;
You can see how i only draw 39 materials in one mode, and 209 materials (the same as meshes) in the other one.
However, it turns out that fewer state changes of my renderer are irrelevant for performance, actually it's roughly 10% slower!
How is that?
Well even though we draw efficiently in terms of changing materials, it matters more that in the other mode by some luck the object order is more optimal (front to back drawing) and therefore more pixels can be rejected.
Note: At this point I don't control in which order meshes are drawn - the order is basically determined by the order they were registered.
So my idea was - I have to get the distance of each material (square distance is cheaper) from the camera and average the distances of all meshes for each material and then make a list of pointers to the materials with the order from near to far.
So I did that.
But it doesn't help when you have 2 objects with the same material - one in the front and one in the back - the average might be behind some object that is behind the first one.
So now I reverted to not using the method of drawing all meshes with the same material at once. I treat each mesh as if it has a unique material and then I sort them front to back. It's simply more efficient in that case.
Apart from that a pretty neat monogame compiler feature is that the ModelMeshes have bounding spheres created by default. These have to be translated and scaled correctly for each submesh, and I also do that in this whole library. It's pretty complicated how everything is interwoven. Not great maybe.
With these bounding spheres I can easily test frustum culling, so that is great. It makes rendering much more efficient and is submesh specific.