Godot Version
4.3-stable
Question
Hi,
I have been chasing down an issue for hours involving the number of draw calls for a mesh that should have some degree of batching with the Forward+ renderer.
I’m rendering 524 trees, and there is a y-billboarded Quad mesh that fades in once the tree gets further than 10 m away from the camera - this all works well, but during optimization I was suprised by the number of drawcalls that were popping up for the Quad mesh.
All details are below, but basically, I have a bunch of QuadMeshes being used as a billboard (each on a MeshInstance3D). They are a part of a “tree” packed scene, and there are 9 different StandardMaterial3Ds that are used. I’m expecting 9 draw calls, and I’m getting 100.
Here is the scene with virtually everything stripped out except the sky:
At this point, Godot is reporting 118 draw calls.
If I hide the billboard meshes, the scene becomes empty, and there’s just a single draw call. My “reference” scene has 1 draw call, 1 object, and 12692 primitives. With the billboards in I’m getting around 100 draw calls, 15486 primitives, and around 1400 objects.
The primitive count is in the ballpark for what’s expected for 524 quad meshes (the delta is about 3000 primitives). The drawcalls seem way off to me.
For the billboard quad meshes, there are 9 variant materials,
The mesh is the same every time, and I am careful that the mesh and material are not duplicated. They are set procedurally in code via a dictionary and a lookup key:
const BILLBOARD_MATS = {
"0_0": preload("res://prefabs/tree/billboards/mats3/billboard_green_density0.tres"),
"0_1": preload("res://prefabs/tree/billboards/mats3/billboard_green_density1.tres"),
... 7 more times
And then during the ready() function, this is called:
func load_billboard() -> void:
var key := str(state)+"_"+str(density)
branches_billboard.mesh = BILLBOARD_QUAD_MESH
var mat: StandardMaterial3D = BILLBOARD_MATS[key]
branches_billboard.set_surface_override_material(0, mat)
Branches billboard is just a multi-mesh instance3D.
The materials are all StandardMaterial3Ds, but here are the settings:
- Transparency: Depth Pre-Pass
- Cull Mode: Disabled
- Shading Mode: Per-Vertex
- Albedo Color: f2f2f2
- Albedo Texture: (all use the same branch_billboard.png)
- UV settings are unique for each material
- Shadows: Disable Receive Shadows
- Mode: Y-Billboard
- Keep Scale: On
Some of the settings I’m just experimenting with. The texture looks like this:
Basically just shift UV coords to get whatever tree is desired.
Am I severely misunderstanding how Forward+ batches draw calls? Is there some other limitations I am unaware of?
I know how to use MultiMeshInstance3D, but I’d rather them stay as individual MeshInstance3Ds in this case.