So i was trying to make MultiMeshInstance3D create faces with different textures through shaders when i stumbled upon this issue. my original code had a sampler2D array for holding different textures. i tried to minimize and simplify my code to find the issue. in this picture is the minimized version of the shader used to recreate the issue:

and how it looks:

the idea is simple, using Multimesh.SetInstanceCustomData(ID, new Color(0f,0f,0f,0f)); (which is written in c# btw), we tell the shader which texture to use, when INSTANCE_CUSTOM.r is 0, it uses the first texture and when it's 1, the second texture.
here is what happens when we call Multimesh.SetInstanceCustomData(ID, new Color(0f,0f,0f,0f)); on all instances:

the shader uses the first material. now when i use Multimesh.SetInstanceCustomData(ID, new Color(1f,0f,0f,0f)); this happens:

all the faces are Zfighting with what seems to be the default material. as you can see, both of the materials are the same, the code is the same, the MultiMeshInstance3D is the same, the only thing that changed was the INSTANCE_CUSTOM we pass to the shader. any number other than zero will cause this issue.

I'm new to shaders so i don't really know whats going on. any help is much appreciated.
Thanks in advance!

  • xyz replied to this.
  • xyz i figured it out. the solution is the most unintuitive and random thing i have ever seen in godot. so for no reason at all, i decided to change r from float to int. because why not? its not like its gonna change anything. IT WORKED.

    And this not only stopped the Zfighting, but by setting Multimesh.SetInstanceCustomData(ID, new Color(count,0f,0f,0f)); , count being equal to the Instance ID and then spawning two Instances, i got this:

    The two sides of the cube have different textures despite being from the same MultiMeshInstance3D. why did it not work with floats? the type the INSTANCE_CUSTOM.x is in? i don't know. but this fixes it. i will have to experiment some more but i guess this settles it for now.
    thanks for the help anyways.

    Rose19 Do you have multiple instances at the same position?

      xyz I thought the same but no, here is a pic with Multimesh.InstanceCount = 1;

      we can confirm this is the case by checking the Remote scene at runtime:

      there is only one MultiMeshInstance3D in my scene, no other nodes that could cause that exists. and just incase you were wondering, just like before, setting INSTANCE_CUSTOM.r to 0 and using the first material fixes this again:

      you might think its an issue with the material, but the two material are copies of each other, just in different sampler2D inside the shader. i also made a new discovery while trying to fix this. even if there is one material in the condition, the bug will still appear:


      only when if (r == 0.0) and Multimesh.SetInstanceCustomData(ID, new Color(0f,0f,0f,0f)); does the issue get resolved:


      it doesn't have to be 1 either, any number that isn't 0 will cause this.
      I'm completely stumped on this one and i have no idea where to even start fixing this. If anyone knows anything please help.
      thanks in advance!

      • xyz replied to this.

        Rose19 Post a minimal reproduction project.
        Btw what happens if you only put else instead of else if (r==1.0)?

          xyz i figured it out. the solution is the most unintuitive and random thing i have ever seen in godot. so for no reason at all, i decided to change r from float to int. because why not? its not like its gonna change anything. IT WORKED.

          And this not only stopped the Zfighting, but by setting Multimesh.SetInstanceCustomData(ID, new Color(count,0f,0f,0f)); , count being equal to the Instance ID and then spawning two Instances, i got this:

          The two sides of the cube have different textures despite being from the same MultiMeshInstance3D. why did it not work with floats? the type the INSTANCE_CUSTOM.x is in? i don't know. but this fixes it. i will have to experiment some more but i guess this settles it for now.
          thanks for the help anyways.

          • xyz replied to this.

            Rose19 It's not random at all. The problem is caused by floating point rounding error. The thing I suggested should work as well. If the value of r is intended as a per instance boolean switch, you might want to do something like:

            if(INSTANCE_CUSTOM.x > .5){
            ...
            }
            else{
            ...
            }

            Saves you a couple of gpu cycles on float/int casting.