Search Unity

Question Shader Graph - Can I Mask a Normal Vector with a 2D Texture?

Discussion in 'Shader Graph' started by Bahmann, Sep 16, 2019.

  1. Bahmann

    Bahmann

    Joined:
    Mar 5, 2019
    Posts:
    15
    Hello,
    I'm currently working more heavily with Shader Graph. I created a displacement shader but wanted to mask the normal Vector with a 2D Texture out so just certain areas should be affected with the displacement shader. Does anybody know of such a possibility?

    I tried it but can't connect my masked out node with the Position of my PBR Master Node (view image)

    upload_2019-9-16_13-13-33.png
     
  2. Tartiflette

    Tartiflette

    Joined:
    Apr 10, 2015
    Posts:
    84
    Try changing the node used to sample your mask to Sample Texture 2D Lod.
     
  3. Bahmann

    Bahmann

    Joined:
    Mar 5, 2019
    Posts:
    15
    I'm not completely sure that I understood your suggestion?
     
  4. Tartiflette

    Tartiflette

    Joined:
    Apr 10, 2015
    Posts:
    84
    There are several nodes you can use to read textures. You are using the standard one (Sample Texture 2D), but you should use a special one called Sample Texture 2D Lod. The reason for this is that when you read a texture the gpu will work out what mipmap level to use based on how much the coordinates change per pixel, except you are attempting to read it at the vertex level (at which point the gpu has no concept of pixel) and can't figure it out on its own. With the Lod variant, you manually tell it what mipmap to use which should make the shader valid.
     
  5. Bahmann

    Bahmann

    Joined:
    Mar 5, 2019
    Posts:
    15
    Ah thank you this makes a lot of sense. I honestly overlooked the 2D Lod Node.

    Now I "just" need to find a way to correctly mask out my Vector Position without some strange behavior on the rest of the geometry

    upload_2019-9-17_11-54-34.png upload_2019-9-17_11-55-0.png
     
  6. Tartiflette

    Tartiflette

    Joined:
    Apr 10, 2015
    Posts:
    84
    And you will have an even harder time figuring out how to update the normals of the displaced geometry (as you can see, the lighting and shadows look off on the top bit). I'll go as far as saying that it's simply not possible for arbitrary geometry with arbitrary deformation, but I'd love to see someone prove me wrong. :)
     
  7. LandonTownsend

    LandonTownsend

    Unity Technologies

    Joined:
    Aug 21, 2019
    Posts:
    35
    It's not 100% perfect but here's the solution I usually use:
    upload_2019-9-17_16-8-38.png
    (see note at the bottom if you have trouble connecting nodes. Also, that node playing hide and seek is a Vector 2 node, sorry for the mistake!)

    Take whatever code you're using to generate the new positions; isolate the position inputs and the UV inputs. Copy everything else, and paste it twice (good to use subgraphs for this).

    Where you had position plugged in, input the position plus the tangent vector times a very small amount for one, and the position plus the bitangent vector times that same small amount for the other.

    Where you had UV plugged in, input the UV plus a very small amount in the U direction (this should be the same one as the tangent vector) for one and the UV plus a very small amount in the V direction (should be the same one as bitangent vector) for the other.

    Set up what I have in the lower right in order to compute the difference vectors, normalize them and take the cross product to find the new normal. Remember, that normal will be in object space, so make sure to transform it to tangent space (my current project is in 19.2 so the transformation from object to world then from world to tangent is a workaround for a known bug). If the shading doesn't look right, try changing the proportion of the small value you're offsetting your UVs by, to the small value you're offsetting your position by (the shader has no way of knowing what a small change in UV space is in object or world space, so making sure the proportion between offsets is correct is important)

    Here's what it looks like with subgraphs:
    upload_2019-9-17_16-27-34.png

    Note: Sometimes Unity doesn't like you routing the same nodes through both position and any of the other nodes (normal, albedo, etc). In this case, feel free to duplicate the nodes, as seen above. The compiled shader has to duplicate the code to do it both in the vertex and fragment shader anyhow, so you might as well do it yourself and avoid the problems of Unity not letting you plug things in.

    As for the masking problem, try using a lerp node, with the altered position plugged into B, the original position plugged into A, and the mask plugged into T (Assuming I'm understanding what you're trying to do correctly).
     
    Last edited: Sep 18, 2019