Megalomaniak Probably because in the rendering pipeline the passes combine into a single shader.
Wouldn't that defeat the purpose of rendering in passes? As the docs say next_pass
"renders the object again using a different material". This sounds like an additional draw call.
@correojon Roughly speaking, Godot has two main categories of objects - nodes and resources. Nodes live and do things in the scene. Resources are tucked somewhere in memory.
Nodes use resources as... well... their data resources. A single resource object is often shared between multiple nodes. This is good because is makes things economical and efficient. For example; many MeshInstance3D
nodes can use the same Mesh
resource, as well as the same Material
resource to draw that mesh. A node never "owns" a resource. It merely holds a reference to its data.
It gets a bit more intricate though. A resource object itself can refer to another resource object, which can in turn refer to yet another and so on, creating a chain of resource references. In your particular case, there is a MeshInstance3D
node that holds a reference to a Material
resource. That reference is stored in node's material_override
property. That Material
in turn holds a reference to another Material
resource. That reference is stored in first material's next_pass
property. So now your resource reference chain looks like this:
MeshInstance3D (node) -> Material (resource) -> Material (resource)
When the node is duplicated at instantiation, the duplicate will keep the reference to the same material resource. Unless you mark the resource local to scene. In that case, the resource object will be duplicated as well. The duplicated node will now hold a reference to the duplicated resource.
But.
That duplicated resource holds a reference to another resource. And that other resource won't be duplicated. Unless, again, you set its local to scene flag.
You can test what happens in all 3 possible cases:
only the first material resource is local to scene. You'll end up with this:
MeshInstance3D (duplicate) -> Material (duplicate) -> Material (shared)
only the second material is local to scene:
MeshInstance3D (duplicate) ->Material (shared) -> Material (shared)
both materials are local to scene
MeshInstance3D (duplicate) -> Material (duplicate) -> Material (duplicate)
You can see that in the second case, even though you set the second resource local to scene, it can't be duplicated because its "parent" resource in that chain is not duplicated. So if the "parent" is not duplicated it means that it will always hold a reference to the same sub-resource. Duplicating that sub-resource would just create an orphaned object, so it makes no sense to do it.
From this follows that local to scene flag for a sub-resource will in practice only have effect if all of its ancestors in the resource chain have their local to scene flag set as well.