When rendering try to keep graphical state changes as low as possible. The driver in a state based API such as Dx11/OpenGl might need to do some background work when you change some of it's state. By having as few state changes as possible and by doing as much as possible with the same state at once you lower the risk for such slowdowns. The ability to send a single large batch of triangles is also good for the GPU. Many small ones can make the GPU starve for work so better to feed it large in chunks.
A batch is the draw call and the graphic API calls to setup the state for the draw call.
Changing textures break the batch.
- Use all texture units: If you render meshes with two textures each you can pack in four of them if you have eight texture units.
- Texture Atlas: Combine textures into one large atlas texture so you do not have to switch texture.
- Virtual Texture: Use a virtual texture on the meshes.
Transform need to change to place the mesh somewhere else.
- Pre-Transform Geometry: For static Geometry transform it and put it into a single vertex buffer. This will trade lower number of batches for more video memory overhead. This can be done from time to time as needed. For example a house that use a single texture but is made up of many parts can be merged on the fly as needed.
- Use instanced draws: With ex glDrawElementsInstanced or DrawInstanced.