Hello everyone!

I don't think this is a bug with godot, So I post it here for help!

In my project, I need to get the position of each instance in shader to do some computation.

I have tried NODE_POSITION_WORLD and VERTEX.
The NODE_POSITION_WORLD can get the position of the MultiMeshInstance node. All the instances have the same value!

shader_type spatial;
//render_mode world_vertex_coords;

void fragment() {
    ALBEDO = NODE_POSITION_WORLD.xyz;
}

Image:

And VERTEX looks like it would return the position of each pixel in view space.

shader_type spatial;
//render_mode world_vertex_coords;

void fragment() {
    ALBEDO = VERTEX.xyz;
}

Image:

Is there a way to get the position of each instance in MultiMeshInstance at fragment()?

  • xyz replied to this.
  • Looks like MODEL_MATRIX in fragment() is node's matrix. However in vertex() it is indeed per instance matrix. Hopefully that's intentional 🙂. Didn't find anything about this in docs. You can simply send it from vertex to fragment via varying.

    varying vec3 instance_pos;
    
    void vertex() {
    	instance_pos = WORLD_MATRIX[3].xyz;
    }
    
    void fragment() {
    	ALBEDO = instance_pos;
    }

    SneaK1ng NODE_POSITION_WORLD will always give you the same result because it's the position of the whole MultiMeshInstance node.
    You can extract instance's position from model-to-world transformation matrix:

    vec3 instance_pos = WORLD_MATRIX[3].xyz

    I think they changed the name of this built-in in v4:

    vec3 instance_pos = MODEL_MATRIX[3].xyz

      xyz
      Thanks for your reply!
      I tried MODEL_MATRIX[3].xyz in my project a few minutes ago. It returned the same value as well.

      And I found some code below from Godot sources.

      In scene_shader_forward_clustered.cpp Line 558:
      actions.renames["MODEL_MATRIX"] = "read_model_matrix";
      Line 631
      actions.renames["NODE_POSITION_WORLD"] = "read_model_matrix[3].xyz";

      So does it mean NODE_POSITION_WORLD = MODEL_MATRIX[3].xyz?

      Looks like MODEL_MATRIX in fragment() is node's matrix. However in vertex() it is indeed per instance matrix. Hopefully that's intentional 🙂. Didn't find anything about this in docs. You can simply send it from vertex to fragment via varying.

      varying vec3 instance_pos;
      
      void vertex() {
      	instance_pos = WORLD_MATRIX[3].xyz;
      }
      
      void fragment() {
      	ALBEDO = instance_pos;
      }

        xyz
        It works! 

        shader_type spatial;
        
        varying vec3 instance_pos;
        
        void vertex() {
        	instance_pos = MODEL_MATRIX[3].xyz;
        }
        
        void fragment() {
        	ALBEDO = instance_pos.rgb;
        }

        Thanks for your support and patience.

        But this workaround looks a bit odd.

        I created an issue about this on Github, but I haven't received any response yet.

        See:
        https://github.com/godotengine/godot/issues/76292

        • xyz replied to this.

          SneaK1ng I wouldn't exactly call it a workaround. Passing per object stuff from vertex to fragment shader actually happens quite often as an optimization technique to avoid unnecessary per pixel calculations. I think this difference is by design. It's similar with VERTEX built in for example; it's in object space in vertex function, while in camera space in fragment function.
          The only problem is that documentation is currently not clear about the distinction for MODEL_MATRIX when used with multi-instanced meshes.