I am spawning 100 instances of MeshInstance3D and while spawning them, I am adjusting their albedo color. At the moment I am using:

var material = node.get_surface_override_material(0).duplicate()
var color = nextRGB() 

material.albedo_color = color
node.set_surface_override_material(0, material)

nextRGB() is a custom function providing the color value. Is this the most efficient way or is there a way to create each instance with its own material already so I don't have to duplicate them all the time?

Max

    max_godot How many different colors are there? Maybe you could create a prototype configured for each color and then duplicate those.

      max_godot Extra question: is it actually more efficient to use a shader to change the color or is changing the StandardMaterial preferred?

      Toxe Sorry for the imprecise answer: yes, each node has a different color 🙂

      Doesn't look like that on the screenshot but in the end they should all have a unique color.

      What do you mean exactly by "fastest"? If you're only setting color once, it's not a big deal. If you're worried about rendering many different materials, there are optimizations you can make to share one material even with the different colors. What issue are you encountering?

      Since it's super easy, I went ahead and converted the the StandardMaterial to a ShaderMaterial and added an instance uniform to it:

      // NOTE: Shader automatically converted from Godot Engine 4.2's StandardMaterial3D.
      
      shader_type spatial;
      render_mode blend_mix,depth_draw_opaque,cull_back,diffuse_burley,specular_schlick_ggx;
      instance uniform vec4 albedo : source_color;
      uniform sampler2D texture_albedo : source_color,filter_linear_mipmap,repeat_enable;
      uniform float point_size : hint_range(0,128);
      uniform float roughness : hint_range(0,1);
      uniform sampler2D texture_metallic : hint_default_white,filter_linear_mipmap,repeat_enable;
      uniform vec4 metallic_texture_channel;
      uniform sampler2D texture_roughness : hint_roughness_r,filter_linear_mipmap,repeat_enable;
      uniform float specular;
      uniform float metallic;
      uniform vec3 uv1_scale;
      uniform vec3 uv1_offset;
      uniform vec3 uv2_scale;
      uniform vec3 uv2_offset;
      
      void vertex() {
      	UV=UV*uv1_scale.xy+uv1_offset.xy;
      }
      
      void fragment() {
      	vec2 base_uv = UV;
      	vec4 albedo_tex = texture(texture_albedo,base_uv);
      	ALBEDO = albedo.rgb * albedo_tex.rgb;
      	float metallic_tex = dot(texture(texture_metallic,base_uv),metallic_texture_channel);
      	METALLIC = metallic_tex * metallic;
      	vec4 roughness_texture_channel = vec4(1.0,0.0,0.0,0.0);
      	float roughness_tex = dot(texture(texture_roughness,base_uv),roughness_texture_channel);
      	ROUGHNESS = roughness_tex * roughness;
      	SPECULAR = specular;
      }

      All you need to do is set up the StandardMaterial with the parameters you want, then right click it, click "Convert to Shader Material", then in the shader add instance in front of uniform vec4 albedo : source_color; Done!

      Note that albedo will no longer be a member of the material, and will instead be added to GeometryInstance3D: