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

Question [RESOLVED]Parallax Occlusion Mapping Node, Heightmap Input is a Texture Why?

Discussion in 'Shader Graph' started by JJRivers, Aug 8, 2021.

  1. JJRivers

    JJRivers

    Joined:
    Oct 16, 2018
    Posts:
    137
    The main question is pretty self-explanatory but i will elaborate a bit on why i think it Should not be the case.

    Main problem arising from enforcing a texture input for the heightmap is that it inherently precludes its use in complex shaders that are made up of multiple "passes" that are composited together before rendering.

    Example use case HDRP Terrain Shader Graph:

    It means having to implement the node for all 8 layers separately since i have to fetch a heightmap for each layer (which we already have in the shader but cant reuse for this since loops are forbidden SG)
    Precludes channel packing of textures since i cant feed it the maskmap textures Blue channel only (the default for terrain heightmap).
    Cant reuse already existing assets without reauthoring (the above mentioned heightmaps existing for terrain maskmap already)

    Having done a quick glance over of the POM nodes code from the package, am i missing something? To me it seems you should really be able to just pass the same data as a float instead of a texture. This is a relatively more involved feature to begin with, i do not think it is too much to ask for that the user Know what he is supposed to feed to that input especially considering many master nodes even don't have any tool tipping etc.

    As a Minimum it should have a dropdown to allow the user to pick if he wants to feed it a texture or a float.

    How does this preclude its use you may ask? You're running the POM 8 times on an already heavy shader, the performance tanks even with high end card with nothing But the terrain in view. If i could pass it the composited heightmap from the 8 layers i could run That through the POM node and be done with it in a single pass.
     
  2. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,329
    POM works by ray marching over a height map. That means for each on screen pixel it samples multiple positions across the height map texture.

    This image from LearnOpenGL shows off what's happening pretty well.

    Each of those purple dots is a texture sample position and it's accompanying depth that it uses to test against the (red) height map. The max number of samples it does depends on the Steps input on the node, and how far apart each sample position is depends on the angle of the surface compared to the viewer. Again, each on screen pixel is sampling the height map texture up to that many times!

    If you were to pass in a single float value instead of a texture ... there's nothing POM can do with that. With a single height, presumably sampled at the surface position's UV, you can do Parallax Offset Mapping, aka Bump Offset Mapping, which just kind of mushes the UV around based on the height map and view angle, and can be convincing enough on blobby, indistinct height maps, but looks terrible on anything with sharper details.

    The reality is when it comes to doing POM for a terrain shader, you do kind of have to do it for each individual layer. For more advanced POM you might want to fade between height maps, but then the one POM function would need to know the blending amount at each offset, and all texture layers. Or maybe be able to take an entire function / sub graph as an "input". Not the output of those, but the actual function / sub graph itself so it can be called at each sample position. But that isn't functionality Shader Graph has, nor would I expect Unity to add.

    Ultimately if you want that level of control, you want to use a custom function node and write your own bespoke implementation of POM.
     
    zalogic and lilacsky824 like this.
  3. DanielRiches

    DanielRiches

    Joined:
    Nov 23, 2019
    Posts:
    165

    I'm having trouble with a HDRP Terrain Shader Graph myself.....I managed to get the first 4 layers working but the other 4 doesnt seem to work at all....i'm using _Control0 for the first 4, and _Control1 for the second 4 (since it mentions _Control1 in the default shader code for the extra layers.

    Do you have any insight on why? seems you got the standard 8 layers working at least :(



    I was going to post this as a new topic but since you seem to be on the same journey as me thought I would ask here :p
     
    Last edited: Aug 9, 2021
  4. JJRivers

    JJRivers

    Joined:
    Oct 16, 2018
    Posts:
    137
    So there is a very good reason indeed.
    Thank you for taking the time to elaborate so explicitly and clearly, i had clearly missed the primary point of the occlusion technique vs offset. You are the shader warlock we don't deserve and are glad to have!!
     
  5. JJRivers

    JJRivers

    Joined:
    Oct 16, 2018
    Posts:
    137
    Unity's terrain system presumes you are using a very similar shader to that made by them (which is very outdated with tons of ironious comments mixed in as is most of the basic terrain system itself, you wouldn't even be making your own in most cases if it weren't). This means you won't be finding much documentation but most of it is not too hard to figure out.

    As to your particular issue:

    • You have to either make a wrapper shader that calls the correct defines and keyword used in HDRP/TerrainLit shader such as _TERRAIN_8_LAYERS.
    • The much easier route, you make a script that reads all the relevant data and then setup a material property block with those and apply it to the terrain.

    The terrain mesh Does have tangents, the warning is ironious in the sense that they presume all terrain shaders are constructed like theirs are.
     
  6. DanielRiches

    DanielRiches

    Joined:
    Nov 23, 2019
    Posts:
    165
    Thanks for the advice, i'll give it a shot!
     
    JJRivers likes this.