Search Unity

Any easy solution to terrain poking through roads?

Discussion in 'General Graphics' started by JoeStrout, Apr 25, 2016.

  1. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    I've got a terrain that is already (more or less) flat in all the right places. Now I'm adding a dynamically-created road mesh on top, but...



    Is there any easy way to keep the road from poking through the terrain?

    It just occurred to me that I might be able to use two cameras; one for just the terrain, and one for everything else, with the everything-else camera drawing on top. I suppose that would work, but it feels a bit heavy-handed. And it would fail badly if there's ever a case where a hill should be blocking your view of the road.

    And I can't really raise the road up — when I raise it enough to eliminate all poke-throughs, then it becomes obvious at some angles that the road is no longer in contact with the terrain.

    I don't suppose there's any easy way to clear the terrain (set its alpha to zero) under the road mesh, or give the terrain a penalty on all depth sorting, or something like that? Some clever solution I may be overlooking?

    Thanks,
    - Joe
     
  2. Stardog

    Stardog

    Joined:
    Jun 28, 2010
    Posts:
    1,913
    I guess you'd want to just lower the terrain's vertices that are under the road. I'm not sure you can modify a terrain like that, so you might have to convert it to a mesh, then adjust the vertices.
     
  3. tawdry

    tawdry

    Joined:
    Sep 3, 2014
    Posts:
    1,357
    If that is unity terrain just shift click and lower terrain put opacity and brush size low so it reduces by small amounts?
     
  4. SpookyCat

    SpookyCat

    Joined:
    Jan 25, 2010
    Posts:
    3,765
  5. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    Aha, Offset in the shader might be just the thing. (Yesterday I went with making parts of the terrain transparent using the Terrain Hole System from the asset store, but if a simple tweak to the shader of the road can do the job, I'd like that even better!)
     
  6. raphael-ernaelsten-heaj

    raphael-ernaelsten-heaj

    Joined:
    Mar 9, 2016
    Posts:
    78
    Use shader stencils :)
     
  7. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    This appears to be a great solution. I just created a new surface shader, inserted "Offset -50, -100" into the SubShader (right between Tags and LOD), applied it to my road material, and presto! No more poke-through.

    The actual values required a bit of fiddling and experimenting, and are much higher than I expected to need... but I imagine it depends on the scale of the scene, the hither/yon values of the camera, etc. At any rate, I'm satisfied for now. @SpookyCat, thanks for pointing me in the right direction!
     
  8. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    OK, just to follow up: messing with the road shader led to all sorts of grief (it overdrew the vehicles, so then I tried applying the same offset shader to the vehicles, but that resulted in all sorts of visual artifacts, scissoring, exposing of the vehicle's private parts, and other unpleasantness).

    So now I am instead offsetting the terrain back a little bit, and that's working much better.

    For the record, here are the steps:
    1. Download the standard Unity Built-in Shaders from the downloads page.
    2. Dig up DefaultResourcesExtra/TerrainShaders/Splats/FirstPass.shader, and copy this to your project.
    3. Edit that shader. Change the name to something else (I used "Custom/Terrain/Diffuse", and add "Offset 10, 10" right after the Tags block.
    4. Make a new material, using this shader.
    5. Select your terrain, click the gear icon, and change the Material option to "Custom." Drag in your custom material.
    This is working beautifully for me so far... perhaps it will be useful to someone else, too!
     
    shotoutgames likes this.
  9. raphael-ernaelsten-heaj

    raphael-ernaelsten-heaj

    Joined:
    Mar 9, 2016
    Posts:
    78
  10. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    Well you keep smiling or winking when you say that, so I thought you were joking!

    Also this isn't really enough detail to get me started. Are you suggesting I modify the terrain shader to use a stencil image? But that would need to be a fairly enormous image to have decent resolution, wouldn't it?

    It seems like a better way would be to make use of the splat maps to define where we want to not draw pixels... but that's exactly what the Terrain Hole System does. That worked, but I found it far too fiddly; every time I move my roads (which are generated from data files), I have to hand-paint (or remove) holes in the terrain. The nice thing about the offset in the terrain shader (which hardly counts as "patches over patches" — it's a single simple change) is that it works across the board; I don't have to change anything when I move stuff around.

    But maybe I've misunderstood what you have in mind with the stencil feature... if you can explain a bit more, perhaps it will turn out to be a much better solution!
     
    SAMYTHEBIGJUICY likes this.
  11. raphael-ernaelsten-heaj

    raphael-ernaelsten-heaj

    Joined:
    Mar 9, 2016
    Posts:
    78
    Ho :) I am actually always smiling and winking. I think that keeping a positive and benevolent attitude opens up the mind and leads to better wellness :p

    No actually you'll just have to modify your road shader and your terrain shader but no texture involved.
    Here is how I think you should proceed :

    • Draw your road first with a stencil reference value (like the example in the link)
    • (use queue index in the shaders to make sure you draw the road before the terrain)
    • Then draw the terrain and make a stencil comparison value such as NotEqual to the reference value of the stencil of the shader of the road.
    In that way, the terrain will only draw in the pixels which are not covered by the road.
    Read the page and i think you will exactly get what i mean :)

    Cheerz!
     
  12. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    Ah, but I can imagine a negative side-effect of that approach... a road behind a hill will be drawn on top of (i.e. show through) the hill.

    This can happen with the terrain offset technique too, if I set the offset too high... but with reasonable values, it's easy to offset it just enough to avoid poking through the road, but not cause roads to draw in front of some completely unrelated terrain feature.

    I do really appreciate the time you took to point this out, though... I'm sure I'll find a use for it sooner or later!
     
  13. bart_the_13th

    bart_the_13th

    Joined:
    Jan 16, 2012
    Posts:
    498
    wouldn't terrain offset give you trouble when the camera is closer to the terrain? Like when it's 1st/3rd person view?
    I'd suggest raising the road and extending the road mesh edge down (and give it concrete texture) to cover the gap between the road and the terrain
     
  14. raphael-ernaelsten-heaj

    raphael-ernaelsten-heaj

    Joined:
    Mar 9, 2016
    Posts:
    78
    Actually no, I already did this before. There is a way to do it so the depth-test is still performing. My example was just illustrative sorry :) I don't have much time to do it now but I am 98.58422174% sure it can be done. :p
     
  15. Seb88250

    Seb88250

    Joined:
    Jul 27, 2020
    Posts:
    11
    I would like to know how you did it, because after several hours I was not able to achieve the effect.
    So for now, the issue is the fact that a road behind a hill will be drawn on top of (i.e. show through) the hill.

    Look at this :

    Screenshot_66.png
    We should not be able to see the road from the other side :
    Screenshot_67.png