Multimesh via RenderingServer not showing mesh's material

Godot Version

4.6.1

Question

I'm playing with the RenderingServer to display and update thousands of visual instances at once. In particular I've tried instantiating a multimesh and adding to it a mesh resources that I've created via the editor:

public partial class Server: Node2D
{

const N = 10000;
[Export] Mesh mesh;

Rid rid;
Rid multimesh;

public override _Ready()
{
        rid = RenderingServer.CanvasItemCreate();
        RenderingServer.CanvasItemSetParent(rid, GetCanvasItem());

        multimesh = RenderingServer.MultimeshCreate();
        RenderingServer.MultimeshAllocateData(multimesh, N, RenderingServer.MultimeshTransformFormat.Transform2D);
        RenderingServer.MultimeshSetMesh(multimesh, mesh.GetRid());
        RenderingServer.MultimeshSetVisibleInstances(multimesh, N);
        RenderingServer.CanvasItemAddMultimesh(rid, multimesh);

        for(int i = 0; i < N; i++)
        {
            RenderingServer.MultimeshInstanceSetTransform2D(multimesh, i, Transform2D.Identity.Translated(new Vector2(GD.Randf() * GetViewportRect().Size.X, GD.Randf() * GetViewportRect().Size.Y));
        }

}

}

also in gdscript:

extends Node2D

const N = 10000

@export var mesh : Mesh
var multimesh : RID
var rid : RID

func _ready():
	rid = RenderingServer.canvas_item_create()
	RenderingServer.canvas_item_set_parent(rid, get_canvas_item())

	multimesh = RenderingServer.multimesh_create()
	RenderingServer.multimesh_allocate_data(multimesh, N, RenderingServer.MULTIMESH_TRANSFORM_2D)
	RenderingServer.multimesh_set_visible_instances(multimesh, N)
	RenderingServer.multimesh_set_mesh(multimesh, mesh)

	var t = Transform2D()
	for i in N:
		RenderingServer.multimesh_instance_set_transform_2d(multimesh, i, t.translated(Vector2(randf()*get_viewport_rect().size.x,randf()*get_viewport_rect().size.y)))

	RenderingServer.canvas_item_add_multimesh(rid, multimesh)

The mesh used is a QuadMesh that has a material attached to it, with an Albedo set to a different color than white. However, in both cases at runtime the scene shows all the instances as white squares. I wonder how to properly show the material and, eventual textures added to the mesh. Instantiating a new canvas item for each visual item was easier because I could change their textures directly with RenderingServer.canvas_item_set_texture_rect() (and the performances also looked better so I wonder why would I like to use multimesh over single canvas items ).

You need to set the material for the instance. Try instance_geometry_set_material_override()

Thank you, I’ve tried adding either:

RenderingServer.instance_geometry_set_material_override(multimesh, mesh.material.get_rid())

or:

RenderingServer.instance_geometry_set_material_override(rid, mesh.material.get_rid())

but none of them worked and the debugger printed

E 0:00:01:721 prova.tscn::GDScript_5iyab:17 @ _ready(): Parameter “instance” is null.
<Sorgente C++>servers/rendering/renderer_scene_cull.cpp:1345 @ instance_geometry_set_material_override()
prova.tscn::GDScript_5iyab:17 @ _ready()

in both cases.

Maybe I did not understand how to use it correctly.

Oh, you’re adding a 2d mesh to a canvas item. Then try canvas_item_set_material()

I think I’m adding a mesh to a multimesh via RenderingServer.multimesh_set_mesh(multimesh, mesh) not directly to the canvas item. Then I add the multimesh to the canvas item via RenderingServer.canvas_item_add_multimesh(rid, multimesh).

However I’ve tried as you said, I’ve created a material in the editor, passed to the script via @export var mat : Material and then added with RenderingServer.canvas_item_set_material(rid, mat). Still nothing changed.

StandardMaterial3D won’t work with canvas items. Use CanvasItemMaterial instead.

I’ve tried CanvasItemMaterial too, not working.

Let’s see what you tried. Canvas item materials don’t have any color/albedo properties. Use modulate instead.

What’s your final goal here?

My final goal is to render a custom texture on multiple locations on the screen, updating the positions each frame using the multimesh.