Search Unity

Offset texture so that it start where last mesh ended (shader graph + code)

Discussion in 'Shaders' started by MCrafterzz, Jan 29, 2019.

  1. MCrafterzz

    MCrafterzz

    Joined:
    Jun 3, 2017
    Posts:
    354
    Hello, I calculate a textures tiling which is set with code and works perfectly for the first segment. The problem I have now tho is that the second segment (mesh) starts at 0 causing the texture to start over instead of continue from the last mesh.

    I know which how to set the shader's offset the problem is what value to use. I tried with:
    Code (CSharp):
    1. material.SetVector("Vector2_8B2FB416", new Vector2(0, Mathf.Ceil(lastTextureRepeation) - lastTextureRepeation));
    But that give similar results to above. I've also tried 1 - that value but with no success. What I want is if the texture ends halfway on the first segment it should start halfway for the next. Any ideas?
     
  2. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,348
    How are the road meshes created? Is there a reason the UVs for the meshes themselves can't be corrected?

    And without more information about how you're calculating the first mesh's UVs, the and how the tiling and offset is being applied in the shader, I'm not sure anyone can give useful information.
     
  3. MCrafterzz

    MCrafterzz

    Joined:
    Jun 3, 2017
    Posts:
    354
    Here comes some more information:
    Shader:

    Code:
    Code (CSharp):
    1. IEnumerator FixTextureStretch(float length, int i)
    2.     {
    3.         yield return new WaitForSeconds(0.01f);
    4.  
    5.         if (transform.GetChild(0).childCount > i)
    6.         {
    7.             float textureRepeat = length / 4;
    8.  
    9.             for (int j = 0; j < transform.GetChild(0).GetChild(i).GetChild(1).childCount; j++)
    10.             {
    11.                 if (transform.GetChild(0).GetChild(i).GetChild(1).GetChild(j).GetComponent<MeshRenderer>().sharedMaterial != null)
    12.                 {
    13.                     float textureRepeation = textureRepeat * transform.GetChild(0).GetChild(i).GetComponent<RoadSegment>().textureTilingY;
    14.  
    15.                     Material material = new Material(transform.GetChild(0).GetChild(i).GetChild(1).GetChild(j).GetComponent<MeshRenderer>().sharedMaterial);
    16.                     material.SetVector("Vector2_79C0D9A3", new Vector2(1, textureRepeation));
    17.  
    18.                     if (i > 0)
    19.                     {
    20.                         float lastTextureRepeat = transform.GetChild(0).GetChild(i - 1).GetChild(1).GetChild(0).GetComponent<MeshRenderer>().sharedMaterial.GetVector("Vector2_79C0D9A3").y;
    21.                         material.SetVector("Vector2_8B2FB416", new Vector2(0, (Mathf.Ceil(lastTextureRepeat) - lastTextureRepeat)));
    22.                     }
    23.  
    24.                     transform.GetChild(0).GetChild(i).GetChild(1).GetChild(j).GetComponent<MeshRenderer>().sharedMaterial = material;
    25.  
    26.                      }
    27.                 }
    28.             }
    29.         }
    lenght is the length of the segment

    Need anything more?
    Also thanks for always being so helpful bgolus
     
  4. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,348
    Yeah ... That code is unintelligible with out a lot more context. You know you can also rename the random Shader Graph property names to something sane, yes?

    Anyway, assuming each road section is UV'd using a 0.0 to 1.0 range which you are then scaling with that textureRepeation value, then all you should need to do is:
    Vector2(0f, lastTextureRepeat % 1.0f)

    However this assumes both road UVs are going the same direction, ie: the mesh on one side is the UV 0 edge, and the other is the UV 1 edge. If they're UV 1 to UV 1, then you'll need to work out the offset needed to line up the other edge. For that you need to multiply (or divide, I can't remember) the offset by the current scale.


    It still doesn't answer the question of, why aren't you doing this in on the mesh itself?
     
  5. MCrafterzz

    MCrafterzz

    Joined:
    Jun 3, 2017
    Posts:
    354
    Didn't know it was possible to rename property names, should defently do that. Thought you code would work but apparently not, some segments do but some don't like in the picture:

    I have printed out all the uvs and they are correct so no problem there, they go from 0 to one so the end of the first segment is 1 and the start of the next is 0. Updated code:
    Code (CSharp):
    1. for (int j = 0; j < transform.GetChild(0).GetChild(i).GetChild(1).childCount; j++)
    2.             {
    3.                 if (transform.GetChild(0).GetChild(i).GetChild(1).GetChild(j).GetComponent<MeshRenderer>().sharedMaterial != null)
    4.                 {
    5.                     float textureRepeat = length / 4 * transform.GetChild(0).GetChild(i).GetComponent<RoadSegment>().textureTilingY;
    6.  
    7.                     Material material = new Material(transform.GetChild(0).GetChild(i).GetChild(1).GetChild(j).GetComponent<MeshRenderer>().sharedMaterial);
    8.                     material.SetVector("Vector2_79C0D9A3", new Vector2(1, textureRepeat));
    9.  
    10.                     if (i > 0)
    11.                     {
    12.                         float lastTextureRepeat = transform.GetChild(0).GetChild(i - 1).GetChild(1).GetChild(0).GetComponent<MeshRenderer>().sharedMaterial.GetVector("Vector2_79C0D9A3").y;
    13.                         material.SetVector("Vector2_8B2FB416", new Vector2(0, (lastTextureRepeat % 1.0f)));
    14.                     }
    15.  
    16.                     transform.GetChild(0).GetChild(i).GetChild(1).GetChild(j).GetComponent<MeshRenderer>().sharedMaterial = material;
    17.                 }
    18.             }
    Full source code:
    https://github.com/MCrafterzz/roadcreator

    The only unnormal thing is this that you helped me with a while ago:
    https://forum.unity.com/threads/hel...-the-mesh-in-a-weird-way.545413/#post-3605017
    But that only affects the x-axis so it shouldn't be the cause of this

    Why would I do this on the mesh? The easiest way should be to just use the tiling and offset shader graph that I am currently. I don't really understand how it should be done on the mesh, modifying all the uvs will mess up other parts of the code.
     
    Last edited: Jan 31, 2019
  6. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,348
    Because if you do it on the mesh you don't need unique materials per road section, which is much better for performance, and usability.
     
  7. MCrafterzz

    MCrafterzz

    Joined:
    Jun 3, 2017
    Posts:
    354
    Thanks for you help. The missing piece was adding the last segments offset to the current one, so it now all works as expected.:)