Canvas shader access to 3d objects info

Godot Version



I am trying to create a canvas shader that displays a different color for each 3d object in the scene! Is there any way to access some 3d model information that generates the current pixel in order to assign a different color for each object in the shader?

An example in the image of the result I would like to achieve.

Thank you!


1 Like

You could set all the Node’s property use parent material to true. Then, you could set via code the color of the object.

uniform int objectType;

void fragment(){
   if (objectType == 1){
      COLOR = vec3(1,0.5,1);

There are several ways. You can use the set_shader_parameter function to pass a color value or any kind of value that then defines the color in the shader, or you can pass along the INSTANCE_ID of an instanced mode mesh, or you can set vertex color in your mesh, or you can make every vertex in the UV map 0.0,0.0 and then use an UV offset per entity on a gradient or noise texture. There are so many possible solutions!

1 Like

@Rooilo0 I don’t think I can assign parent material to true on a 3D object (?)
I’ll share with you the structure of the project so maybe you can better understand what I want to do.
The canvas_item shader is applied to the SubViewportContainer:
Screenshot 2023-12-09 125256

@Efi : If I understand correctly, however, instance uniforms are only available in space (3D) shaders. And I’m using shader_type canvas_item. ref

Sorry, but I’m just new at this!

Well, you could switch to a spatial shader, but you’re not using instanced meshes anyway, from what I see in your scene tree, but any of the other options work equally well.

Well, that’s my only idea.
I’m not really into 3D games but I think that the property Use Parent Material stays there.
If that doesn’t works, I don’t know what else you can do

Could you go into more detail?

What I’d do:

  1. create a material that writes a unique color. expose the color as an instance uniform.
  2. for each mesh that need to render to that ID buffer, duplicate the mesh node (not the mesh!) and assign in override material the material you made in step 1.
  3. those duplicate meshes should be on a different culling layer, add a camera that renders only that layer
  4. use the resulting viewport texture as ID buffer

Thank you. Following your advice I almost succeeded in accomplishing what I wanted to do. The only problem is that if I want to move an object now I have to move two nodes. Any ideas on how to get around this problem?

Give them a common parent.

Ok, I think I found the solution: Implement CAMERA_VISIBLE_LAYERS as built-in shader variable by NumbuhFour · Pull Request #67387 · godotengine/godot · GitHub
Thanks everyone for the help :muscle: