Godot Version
4.2
Question
Some context before I get into the meat of the question: I am using Compatibility rendering so I can deploy in a browser (and will target other platforms too). The nodes I am talking about below roughly have this structure:
Tree (Node3D)
- TreeTrunk (MeshInstance3D)
- Leaves (MultiMeshInstance3D)
There are many instances of this tree across the map.
I am implementing a “fade out” function via Tweening an alpha shader material parameter.
Clearly I will have many instances which use the same material and shader parameters (e.g. I have many Tree mesh instance 3Ds, which all use the same material).
The obvious issue is that when I set the shader parameter, it sets the alpha on ALL instances of this material, not just that MeshInstance3D.
To get around this, I do the following (instance uniforms don’t work in compatibility mode btw…)
func _ready() -> void:
var tree_mat: ShaderMaterial = tree.get_surface_override_material(0).duplicate()
tree_mat.set_shader_parameter("albedo", BARK)
tree.set_surface_override_material(0, tree_mat)
So, effectively, as soon as the node is loaded (actually, its parent), the material is duplicated and then I can tweak the shader parameters however I want for that individual MeshInstance3D.
The Problem
This works great, until I get to my MultiMeshInstance3D
nodes.
I have tried a million different combinations of this (includingduplicate()
with deep copy set to true), but this is the simplest one that I would expect to work:
func _ready() -> void:
multimesh.mesh = multimesh.mesh.duplicate()
var mesh_mat: ShaderMaterial = multimesh.mesh.surface_get_material(0).duplicate()
multimesh.mesh.surface_set_material(0, mesh_mat)
It simply duplicates the mesh that the multimesh uses, then sets that as the multimesh.mesh (to decouple it from the original resource), then I’m doing a similar thing with the surface material. The material is duplicated (once again, to decouple it from the original resource) then set as the surface.
Despite my best efforts, this does not work, and setting shader parameters via:
var leaves_mat: ShaderMaterial = leaves.multimesh.mesh.surface_get_material(0)
leaves_mat.set_shader_parameter("alpha", alpha)
Sets the shader parameter on all instances of that multimesh.
Help plz. Trying to release a game soon ish.