Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Have a look at our Games Focus blog post series which will show what Unity is doing for all game developers – now, next year, and in the future.
    Dismiss Notice

How do I use a Heightmap in Shader Graph?

Discussion in 'Shaders' started by bienenstockhd, Jun 28, 2018.

  1. bienenstockhd

    bienenstockhd

    Joined:
    Jun 28, 2018
    Posts:
    1
    Hello,
    I would like to add a Height Map to my Shader i created with Shader Graph, but it is missing on the Master. How do I add a Height Map?
    upload_2018-6-28_5-25-10.png upload_2018-6-28_5-27-34.png
     
  2. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    11,818
    The original Standard shader's height map parameter is used to drive a version of Parallax Offset Mapping, sometimes just called Offset Mapping, or in Unity's code referred to as Parallax Bump Mapping. This is a simple approximation that basically just smudges the UVs a little based on a height map.

    Here's the code Unity uses:

    Copied from UnityCG.cginc
    Code (CSharp):
    1. // Calculates UV offset for parallax bump mapping
    2. inline float2 ParallaxOffset( half h, half height, half3 viewDir )
    3. {
    4.     h = h * height - height/2.0;
    5.     float3 v = normalize(viewDir);
    6.     v.z += 0.42;
    7.     return h * (v.xy / v.z);
    8. }
    You can add this yourself by building a node graph to do the same. the h is the greyscale value from the height map texture, the height is the scale factor (which should be very, very small; Standard uses a range of 0.005 to 0.08), and the viewDir is the tangent space view direction. The output value should be added to the texture UV.

    The HD pipeline's Lit shaders also have a height map, but it uses it for tessellation displacement (which isn't supported by Shader Graph yet), or for Parallax Occlusion Mapping, which is a much more accurate technique that raymarches through the height field to find an appropriate UV, and is much more expensive than Parallax Offset Mapping. It also requires the use of dynamic loops which node graphs aren't great at handling. And by not great I mean cannot be handled at all without a custom node.

    If replicating the existing Standard Shader's implementation is good enough, the above code should let you recreate it in your own node graph, or let you create a subgraph you can reuse elsewhere. If you want something like what the HD Lit shaders have you'll have to wait for Unity to add support or you can request a Parallax Occlusion Mapping node.
     
  3. Andrey_Graphics

    Andrey_Graphics

    Joined:
    Oct 29, 2015
    Posts:
    128
    Whole set of nodes for Shader graph
    http://u3d.as/1gkf
    - SSS Color,
    - SSS gradient,
    - Parallax mapping,
    - Parallax Mapping iterrations,
    - Parallax Occlusion Mapping,
    - PerturbedNormals (World normal с учетом NormalMap),
    - CreateNormalChannel (для каждого канала текстуры),
    - CreateNormalFloat (для любого значения float, можно делать нормали из процедурных шумов),
    - LightDirection,
    - ProceduralRock (процедурный шум),
    - Range ,
    - TilingShape .
     
  4. RoughSpaghetti3211

    RoughSpaghetti3211

    Joined:
    Aug 11, 2015
    Posts:
    1,688
    I’m a bit confused how to implement a height map in the shader graph, can some one please please provide an example

    Thanks so much
     
  5. SmoothPulsar

    SmoothPulsar

    Joined:
    Apr 21, 2018
    Posts:
    3
    Hello I would like to know more as well, do you have a documentation somewhere ? I can't seem to find it or reproduce it
     
  6. Andrey_Graphics

    Andrey_Graphics

    Joined:
    Oct 29, 2015
    Posts:
    128
    Hello, instead of documentation there are ready examples, shaders are in the folder "Shaders", you need Parallax.
     
  7. GlitchInTheMatrix

    GlitchInTheMatrix

    Joined:
    Apr 12, 2010
    Posts:
    285
    It seems like High map is not supported. Been looking for tessellation without luck.
     
  8. V0odo0

    V0odo0

    Joined:
    Jan 8, 2012
    Posts:
    320
    Here is Sub Graph version of this code:
     
  9. DINKmod

    DINKmod

    Joined:
    Jan 25, 2017
    Posts:
    14
    This is a great literal conversion - but if the master node doesn't have a parallax input, then where would you plug the output of this sub-graph in your main shader graph?

    How would one go about adding some sort of a height field to the LWRP's Master node? Is this just an addition that Unity would be responsible for? The HDRP master lit node doesn't seem to have straight forward parallax support either.
     
    roccobruno78 likes this.
  10. TimNick151297

    TimNick151297

    Joined:
    Apr 21, 2013
    Posts:
    21
    As bgolus said, parallax mapping is just a special way of distorting uvs of a texture sample. If you want to add the illusion of height to your shader, you just need to plug the return of the subgraph above into the UVs of your texture sampler.
     
  11. binaristudios

    binaristudios

    Joined:
    Jun 18, 2018
    Posts:
    2

    Might be a dumb question, but where could i plug a heightmap texture into this shadergraph?
     
  12. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    11,818
    The graph @V0odo0 showed is a Sub Graph, which means it becomes a node in another graph that you would pass the output of other nodes into. To use a texture, add it to the Shader Graph's properties (via the blackboard), then add that texture as a property node along with a Sample Texture 2D node. You'd then pipe the output of that into the Height input of the Sub Shader node.

    Alternatively you could just put all of those nodes into your Shader Graph shader directly and replace the Height node with the Sample Texture 2D node.
     
    mmcveigh33 likes this.
  13. Pivetta

    Pivetta

    Joined:
    Oct 11, 2013
    Posts:
    19
    I can't manage to get this shader to work properly,
    I put it on a quad and used 2 checker textures just to test, everything works fine until I either rotate the quad or I rotate the UVs, then it becomes a mess. I am using the node setup as translate from the code by VOodoO
    How does this apply to local space? I am smashing my head the whole day trying to understand how to get UVs rotation but I bet I'm working in the wrong direction.
    Any clues?

     
  14. Pivetta

    Pivetta

    Joined:
    Oct 11, 2013
    Posts:
    19
    I bought the asset package from Andrey_Graphics and found the solution, I am still not fit enough to read shader code.
    There the node FixedViewDirectionTangent did the trick, I converted it to node tree from code snippet and now I can go on developing my lo-fi parallax.

    PS: Andrey, please do some better naming convention on your package, it's really nice but it's a mess
     
  15. m0nkeybl1tz

    m0nkeybl1tz

    Joined:
    Feb 10, 2013
    Posts:
    18
    @Pivetta I believe you're missing a "height" parameter (the one @bgolus said usually goes from .005 to .08). Use that value to multiply and divide in the top left corner, instead of the checkerboard.

    If you do want to use the checkerboard for your height map, plug it into the 'A' slot in the multiply node instead of the Property + Add .5 nodes (I think those just allow you to set a manual offset for the entire texture). @binaristudios you can plug any texture + a texture sampler into that top left slot and it will act as a height map (see attached).
     

    Attached Files:

  16. DoomPriestK

    DoomPriestK

    Joined:
    Nov 23, 2019
    Posts:
    134
    Since this is the first thread that appears when searching for Heightmap Shader Graph i'll post my HDRP node setup here, this is Height Map with optional Parallax Occlusion Mapping and Normal Map (with option to generate normal from height, although this tends to be less quality), the UV input on the far left is just the UV Channel the user has selected.

    Remember to click the gear icon on the master node and activate the Depth Offset boolean so you can feed in your Parallax Offset to the master node.

    This will automatically Parallax the incoming UVs if you have a Parallax Bool enabled. Simply use the output of the Parallax Bool Check on the left side and feed it into all your UV inputs across your maps.

    This currently works in HDRP 2020.1.9f1

     
    Last edited: Oct 23, 2020
    MadStuntman likes this.
  17. darkdoom973

    darkdoom973

    Joined:
    Jul 21, 2020
    Posts:
    13
  18. Bovine

    Bovine

    Joined:
    Oct 13, 2010
    Posts:
    132
    I have this working nicely but I am applying my adjusted UVs from height map to my normal and other maps. I wanted to pack the height in with something else, i.e. normal, but seems I need the height first to get all the other components at the adjusted UVs. Am I doing something wrong?
     
  19. joshuacwilde

    joshuacwilde

    Joined:
    Feb 4, 2018
    Posts:
    605
    You can't pack it as your main material textures (albedo, normal, etc) depend on the UVs that have been changed via the parallax equation.
     
  20. Bovine

    Bovine

    Joined:
    Oct 13, 2010
    Posts:
    132
    Thanks, yeah. I came to this conclusion pretty much, also posted on redit. Basically I can pack and it will save some texture space but I will need to read once to get the height and then read again to get the adjusted normal. Maybe I will get some cache hits occasionally. I can also LOD the surfaces so parallax only comes into play for nearby objects.
     
  21. joshuacwilde

    joshuacwilde

    Joined:
    Feb 4, 2018
    Posts:
    605
    Yeah it would be interesting to see because yes you will be getting more cache hits, but at the same time, you are also sampling more data than required, as you could store it in a single channel texture instead. I suspect at grazing angles, unpacked will be faster, and at straight-on angles, packed might be faster.
     
  22. Bovine

    Bovine

    Joined:
    Oct 13, 2010
    Posts:
    132
    Yeah on face value packing it has no huge advantage, might even be slower oddly. I might look at the single channel but I suspect those don't perform as well.

    I do see some shimmering artefacts with this. Especially as I get a few units out from the view position in VR and at more acute angles. Anything you can recommend?

    I have to say that normal maps in VR do not work well for large scale objects. Parallax Height Mapping looks great but the shimmering is a bit of a deal breaker - probably there are more expensive algorithms I could try.

    For smaller objects, for third person view puzzlers and platformers, I think normal maps look good, but for large objects, up close, not really adding a huge amount, it has to be said.
     
    Last edited: Apr 19, 2022
  23. Esben-K

    Esben-K

    Joined:
    Jul 22, 2015
    Posts:
    1
    Thanks! This one seemed to just work for me. I just took the basic UV map, and wired it through this node, and lo and behold, it results in a very convincing 3d effect on the material: heightmap.png

    For anybody else who needs to use height maps on their own shaders, there is no output to set the height map to, because this node modifies the UV directly based on it, to "fake" a tesselation effect, as far as I can see.

    You probably also want at least the Amplitude as an input float.

    Thank you @darkdoom973!
     
  24. BusyWizard

    BusyWizard

    Joined:
    Jan 9, 2019
    Posts:
    2
    What node do you plug this into? Can you show us a screenshot of your results?
     
  25. DimitriX89

    DimitriX89

    Joined:
    Jun 3, 2015
    Posts:
    502
    "Parallax UVs" should go into UV input of all the textures used in the material. No idea about "Pixel Depth Offset" though
     
  26. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    11,818
    The Pixel Depth Offset should plug into the Depth Offset of the material node itself, if it has one (only the HDRP supports this at the moment).
     
unityunity