Pass value to shader using INSTANCE_CUSTOM

Godot Version

4.4

Question

Hello, I’m trying to pass a value to my shader from the script in my scene, but I’t seems that is not working…

I use:
multimesh.use_custom_data = true

and
multimesh.set_instance_custom_data(i, Color(2.0, 0.0, 0.0, 0.0))

but in the shader it seems that always recieve a 0.0…

this is the code of my script:


extends Node3D
@onready var grass: MultiMeshInstance3D = $Grass

@export var distance_threshold: float = 40.0

# Called when the node enters the scene tree for the first time.
func _ready() -> void:
 # Asegurarse de que el MultiMesh tiene habilitado el uso de custom_data
	grass.multimesh.use_custom_data = true

# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta: float) -> void:
	
	var camera = get_viewport().get_camera_3d()
	if camera == null:
		return
	
	var multimesh = grass.multimesh
	multimesh.use_custom_data = true
	var instance_count = grass.multimesh.instance_count
	
	# Iterar sobre cada instancia del MultiMesh
	for i in range(instance_count):
		# Obtener la transformación de la instancia
		var transform = multimesh.get_instance_transform(i)
		var instance_pos = transform.origin
		
		# Calcular la distancia a la cámara
		var distance = instance_pos.distance_to(camera.global_transform.origin)
		#print(distance)
		# Determinar si la distancia supera el umbral
		var should_move = 1.0 if distance <= distance_threshold else 0.0
		#print(should_move)
		# Establecer el custom_data (usamos el primer componente del Vector4)
		#multimesh.set_instance_custom_data(i, Color(should_move, 0.0, 0.0, 0.0))
		multimesh.set_instance_custom_data(i, Color(2.0, 0.0, 0.0, 0.0))

and the code in the shader:

shader_type spatial;
render_mode cull_disabled;

uniform vec3 color:source_color;
uniform vec3 shadow_color:source_color;
uniform float wind_strength : hint_range(0.0, 2.0) = 0.5;
uniform float wind_speed : hint_range(0.0, 5.0) = 1.0;
uniform vec3  wind_direction = vec3(1.0, 0.0, 0.5); // dirección del viento
uniform float sway_amount = 0.2;

//varying float should_move; // Recibe el custom_data del MultiMesh
varying float should_move;

void vertex() {
	
	should_move = INSTANCE_CUSTOM.x;
		
	if (should_move != 0.0){
	
	// Altura relativa del vértice (de 0 en la base a 1 en la punta)
	    float height_factor = clamp(VERTEX.y / 1.0, 0.0, 1.0); // 1.0 = altura máxima esperada de la brizna

	    // Movimiento de viento (usamos tiempo y coordenadas)
	    float time = TIME * wind_speed;
	    float sway = sin((VERTEX.x + VERTEX.z) + time);

	    // Dirección del viento normalizada, vector unitario
	    vec3 dir = normalize(wind_direction);

	    // Aplicar desplazamiento proporcional a la altura del vértice
	    VERTEX += dir * sway * sway_amount * height_factor * wind_strength;
	}
}

void fragment() {
	ALBEDO = mix(color, shadow_color  * color, UV.y);
	//if (should_move != 0.0) {
        //ALBEDO = vec3(1.0, 0.0, 0.0);  // Rojo si se mueve
    //} else {
        //ALBEDO = vec3(0.0, 0.0, 1.0);  // Azul si no se mueve
    //}
}

Any tip?
Thanks in advance

You can only enable the custom data when the MultiMesh.instance_count is 0 or less as explained in the documentation MultiMesh.use_custom_data

If true, the MultiMesh will use custom data (see set_instance_custom_data()). Can only be set when instance_count is 0 or less. This means that you need to call this method before setting the instance count, or temporarily reset it to 0.