Search Unity

  1. Looking for a job or to hire someone for a project? Check out the re-opened job forums.
    Dismiss Notice
  2. Unity 2020 LTS & Unity 2021.1 have been released.
    Dismiss Notice
  3. Good news ✨ We have more Unite Now videos available for you to watch on-demand! Come check them out and ask our experts any questions!
    Dismiss Notice

Resolved Blend Multiple Textures

Discussion in 'Shader Graph' started by catapart, Aug 26, 2020.

  1. catapart

    catapart

    Joined:
    Aug 26, 2020
    Posts:
    4
    I'm new to shaders, in general, and new to Shader Graph especially, so I'm trying to figure out how best to blend an entire array of textures (around 10) so that the Y axis in Absolute World space will determine which texture to use.

    Using tutorials, I've developed this graph which successfully blends two textures at a variable height with a variable blend weight. But when I try to add more textures, using the same Lerp method, I get stuck.

    upload_2020-8-26_11-6-0.png

    Every time I Lerp, I'm only ever able to affect change based on half of the full value. In example, the blending between two textures starts at the halfway point, and can be adjusted to blend across half of the texture. But if I add a third texture, the blend can only be adjusted on that third texture to blend across one quarter of the original texture space.

    I come from a code background, so it's hard for me to translate what I would try to accomplish in code to the shader graph. And even if I could, I don't know that it's an appropriate or optimized way to do it in shader graph. So I was hoping someone would have some insight on how to build a shader that blends more than two textures together, based on a vector1 values that determine where each texture should begin, along the Y axis.

    Please let me know if you have any thoughts! Thanks!
     
  2. catapart

    catapart

    Joined:
    Aug 26, 2020
    Posts:
    4
    Well, as is commonplace in these types of situations, I managed to figure out how to get a third texture implemented correctly, so I'm optimistic that I have this figured out.

    I'm still not sure I did it correctly, so if anyone wants to throw in some tips, I'm all ears!

    Otherwise, I'll update this thread with details about my final result, in case anyone else is trying to achieve this same things.

    (Current 3-texture blend graph)
    upload_2020-8-26_11-28-23.png
     
  3. cert

    cert

    Joined:
    Feb 10, 2013
    Posts:
    24
    Last edited: Aug 31, 2020
    catapart likes this.
  4. cert

    cert

    Joined:
    Feb 10, 2013
    Posts:
    24
    @catapart: Did you solve that? I dont know how to choose the index in the texture array based on the height of the input position.
     
    catapart likes this.
  5. catapart

    catapart

    Joined:
    Aug 26, 2020
    Posts:
    4
    Hey, thanks cert! I appreciate you looking in to this and helping out!

    Fortunately, I was able to figure out how to blend n textures just fine, but I got really hung up on an issue where I couldn't blend the entire span of a texture section, so I had to keep monkeying around with it until I got it acting right.

    That took way too long, but I did manage to get it all working, at long last, tonight. Complete with normal, roughness, and occlusion maps, all blending as well.
    Unfortunately, the final shader looks like this (zoomed all the way out):
    upload_2020-9-1_23-17-38.png

    So yeah! If anyone is wondering how to do this, and would like to know, I can certainly write up a breakdown of one of these processes, and then what the difference is between each of the four groups. It's essentially just cascading lerps and using variables to modify them.
    But I make that offer with this disclaimer: I am BRAND NEW to shaders in general, and have done most of my shader work in shader graph. So this may not be efficient, practical, or coherent. All I can tell you is that it works.

    I am VERY MUCH open to anyone with suggestions about either A) how to make this more efficient, or B) how breaking things down into subgraphs can help or hurt performance.
     
  6. cert

    cert

    Joined:
    Feb 10, 2013
    Posts:
    24
    I'm new to shader graph. I got it to work, too. It's good looking for my first shader. Can you upload your shader or make a better screenshot? I don't know how to add tiling and offset for each texture, but this is not a problem with a correct texture. Next step is some randomness for the heights and some water.
     

    Attached Files:

  7. catapart

    catapart

    Joined:
    Aug 26, 2020
    Posts:
    4
    Sure thing!

    Here's a truncated version of one of my texture blends: upload_2020-9-2_8-20-57.png

    So, let's start with the texture index: I see that you're doing a lot to calculate that in the shader. Unfortunately, I have absolutely no reason to calculate that in the shader, so I'm just hard coding it. It seems like you've got that figured out, so that's good, but I'd suggest having a good look at whether you need that dynamic, because the only way I can figure you would need that is if the textures in the array changed. The only reason I'm using an Array is because it mitigates the "Only 16 Texture samples" problem, without resorting to a custom SamplerState.

    On to tiling: You can see from my example that it is as easy as using a tiling and offset node. I add in a division node, because I want to multiply how much tiling is happening (so I don't have to use huge numbers for reasonable results), and I also use a single Vector4 to store both Tiling and Offset, so I have a split node to break those out into their own Vector2 nodes. With that in mind, what you have hooked up in your graph should work just fine?

    As far as the actual process, it breaks down like this:
    1. Get texture 1
    2. Get texture 2
    3. Generate a lerp between texture 1 and 2:
      • Create a smoothstep between the height that the first texture should end and the height that the second texture should end.
      • create a second smoothstep that steps between zero and a property (between 0 and 1) which defines how blended you would like the textures to be (in my graph, that's a mulplication of the BlendSpread and the BlendStrength), based on the output of the first smoothstep.
      • Use the output of the second smoothstep as the input for your lerp.
    4. Get texture 3
    5. Generate a lerp between the output of the first lerp and texture 3:
      • Repeat the substeps from item 3, using a smoothstep between the height of the second texture's end and the height of the third texture's end.
    6. Repeat step 5, substituting the texture and heights for their analogous values, for the rest of the textures you want to display.

    Hopefully, all of that is pretty straightforward, and the images show a natural progression. But if you still have any questions, don't hesitate to ask!
    Like I said, I took this basic pattern, and extended it to use for my normal maps, roughness maps, and occlusion maps. Obviously, there's a lot of optimization to do, but it has already turned up a pretty respectable terrain:
    upload_2020-9-2_8-47-34.png
     
  8. cert

    cert

    Joined:
    Feb 10, 2013
    Posts:
    24
    My TerrainShader is developing nice. My terrain is generated with marching cubes. Adding water seems to be more complex.
     

    Attached Files:

unityunity