Search Unity

Understanding implementation of terrain pixel error setting

Discussion in 'General Graphics' started by tanoshimi, Aug 7, 2016.

  1. tanoshimi

    tanoshimi

    Joined:
    May 21, 2013
    Posts:
    297
    Does anybody know and can explain the specifics of how the "pixel error" for terrain is implemented? The documentation simply describes it as "Amount of allowable errors in the display of Terrain Geometry. This is essentially a LOD setting.".
    By setting the scene view to wireframe mode and adjusting the slider, it is clear to see the general approach of how the vertex density of the terrain mesh is reduced in patches depending on distance, but it is not entirely obvious how that relates mathematically to the pixel error value set.

    What I'm trying to do is align the vertices of the edge of a procedural mesh to place it exactly lying on the ground. When pixel error = 1, I can achieve this exactly using Terrain.SampleHeight, or accessing the heightvalues in the TerrainData.GetHeights array. However, with higher pixel error values, these methods return the "true" height of the terrain, rather than the approximated height at which the terrain is actually drawn in the game camera based on the pixel error. As a result, my mesh sometimes cuts through the terrain, and sometimes floats slightly above it. If I knew the specifics of how pixel error was implemented, I could reproduce it in my own procedural function that generates the mesh to ensure the vertices match perfectly, but I haven't quite been able to achieve this yet. Any pointers?
     
  2. tomes11

    tomes11

    Joined:
    Apr 22, 2014
    Posts:
    8
    I'm also interested in this one, as road objects that are far away are half way in the terrain.
     
  3. mike_kennedy989

    mike_kennedy989

    Joined:
    Feb 5, 2014
    Posts:
    51
    Same issue with road here too. Can we bump this?
     
  4. zeroyao

    zeroyao

    Unity Technologies

    Joined:
    Mar 28, 2013
    Posts:
    169
    Hey,

    A good question. This part of the code is ancient, the mathmatics look dreadful, and even worse no comments are left. I never figure out how exactly it works. The LOD selected for each patch is computed from the following factors: 1) a "maximum height error" pre-computed from the heightmap data for this particular patch, 2) the "pixel error" setting, 3) the camera's near plane, 4) the camera's FOV and 5) the viewport rect's height.

    A bit more about 1) "maximum height error": Each patch of terrain is always a mesh of 17x17 vertex grid. So for the finest LOD i.e. LOD0 each vertex correspondes to one sample in the heightmap stored in TerrainData asset. With each LOD higher, we skip one more "power of 2" samples between patch vertices. For example for LOD1 patches, there is 1 heightmap sample between each vertex (2-1), and for LOD2 patches there is 3 samples inbetween (4-1). That leaves "errors" between a heightmap sample, and the actual position interpolated from the triangle when the patch mesh is rendered. The "maximum height error" is computed by looping all samples covered by the patch, and take the biggest abs(sampleHeight - interpolatedHeight(v0, v1, v2, v3)). Natually the more "changing" within a patch, the bigger "maximum height error" is.

    Generally, what it seems like is if a patch's heightmap error is high, there's a big chance that a finer LOD will be selected, as the engine tries to preserve the appearance of the terrain as much as possible when LODding. And the "pixel error" setting seems like "how tolerent you are with a difference between the selected LOD mesh and the actual heightmap mesh".

    Sorry I'm not a native English speaker, hope you understand what I mean :p

    Cheers,
    Yao
     
  5. tanoshimi

    tanoshimi

    Joined:
    May 21, 2013
    Posts:
    297
    That's very informative, thanks @zeroyao (although it still leaves us with some way to go before being able to implement the same results in our own code ;)

    Seeing as the terrain adjustment code seems so esoteric, can you suggest any other way to calculate the height of a point on the LOD'ed terrain mesh that has been rendered for a given patch, rather than the "true" height of that point in the underlying terrain data?
     
  6. zeroyao

    zeroyao

    Unity Technologies

    Joined:
    Mar 28, 2013
    Posts:
    169
    Hmm there is currently no API to get the LOD information so it's impossible to know what mesh the terrain uses to render. What do you want to achieve by knowing the height?
     
  7. tanoshimi

    tanoshimi

    Joined:
    May 21, 2013
    Posts:
    297
    As in my first post, I'm simply trying to create a procedural mesh that lies perfectly on the terrain surface.
    - When the mesh is close to the camera, or when pixel error = 1, this is easy to achieve.
    - When the mesh lies on distant terrain with higher pixel error, there is a discrepancy between the "true" sampled terrain height at which the mesh vertices are created and the LOD'd terrain height on which it is placed, leading to it either lying slightly above or beneath the terrain surface in places.
     
    malkere likes this.
  8. zeroyao

    zeroyao

    Unity Technologies

    Joined:
    Mar 28, 2013
    Posts:
    169
    I think it's very hard with the current set of API, but you can try render the terrain with a multi-pass shader.