Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Shader Graph: Choosing Texture2DArray Index by uv.z

Discussion in 'Shaders' started by Muffty, Jan 8, 2019.

  1. Muffty

    Muffty

    Joined:
    Nov 4, 2016
    Posts:
    8
    Hi,

    I try to achieve the following:
    Given a Texture2DArray with different textures I want to draw a specific one. As I've done it without shader graph I set

    Code (CSharp):
    1. uvs0[index] = new Vector3(uvPosition.x, uvPosition.y, textureArrayIndex);
    2. mesh.SetUVs(0,uvs0);
    and use uv.xy as real uv coordinates and uv.z as my index for choosing the Texture out of Texture2DArray.
    Somehow I do not get it to work with shader graph.

    I use this layout:



    It somehow does not pick the correct index but uses some other (constant) index.
    I have a functioning workaround using another uv channel, but I suppose it should work as I've done above, right?
    Here is my workaround using uv2 only for picking the correct index:

    Code (CSharp):
    1. uvs0[index] = new Vector2(uvPosition.x, uvPosition.y);
    2. uvs2[index] = new Vector2(textureArrayIndex,0);
    3. mesh.SetUVs(0,uvs0);
    4. mesh.SetUVs(2,uvs2);
    With a graph like this:


    So, am I doing it wrong or is there a bug?

    #################################################
    Edit: the reason was found:
    Not yet implemented
    (Jan. 2019)
     
    Last edited: Jan 8, 2019
  2. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,329
    The mesh.uvs2 is UV1 in the shader.

    The "uvs" properties are 1 based, ie .uvs (1), .uvs2, .uvs3, etc. Internally and in shaders they're 0 based, ie UV0, UV1, UV2, etc.

    Also the .uvs array is limited to a Vector2, so in your first example your Vector3 is being implicitly cast to a Vector2 when assigned. You should be using SetUVs() instead.

    https://docs.unity3d.com/ScriptReference/Mesh.SetUVs.html
     
    Last edited: Jan 8, 2019
    Muffty likes this.
  3. Muffty

    Muffty

    Joined:
    Nov 4, 2016
    Posts:
    8
    Thanks for pointing that out.
    But I don't think that I did it wrong. I set
    Mesh.SetUVs(0,uvs0)
    and
    Mesh.SetUVs(2,uvs2)
    .
    Using UV0 and UV2 in the shader seem to be correct then.

    Edit: I've added this to the code above
     
  4. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,329
    If you were originally using mesh.uvs, then that's limited to a Vector2. If you were using SetUVs(0, uvs0) (and uvs0 is a Vector3[]) then it should work.

    As an extra bit of caution, you may want to store your index with a small offset. Some whole number indices will not interpolate exactly across the face of a triangle leading to artifacts across your surface where the index ends up slightly less than your intended number due to floating point accuracy.

    uvs0[index] = new Vector3(uv.x, uv.y, (float)textureArrayIndex + 0.1f);
     
    andywatts and Muffty like this.
  5. Muffty

    Muffty

    Joined:
    Nov 4, 2016
    Posts:
    8
    That's what I'm doing.

    I will try it - but I'm sceptical since it works fine using uv2.x
     
  6. Muffty

    Muffty

    Joined:
    Nov 4, 2016
    Posts:
    8
    I've tested it - still does not work :(

    But I will keep your extra bit of caution for future, thanks so far! :)
     
  7. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,329
    Muffty likes this.
  8. Muffty

    Muffty

    Joined:
    Nov 4, 2016
    Posts:
    8
    Great. Thanks!