Search Unity

Snow Deformation - Strange Inaccuracies on the edge of the mesh

Discussion in 'Shaders' started by Mr_Admirals, Jan 27, 2019.

  1. Mr_Admirals

    Mr_Admirals

    Joined:
    May 13, 2017
    Posts:
    86
    Hello!

    I'm finally approaching the end of development on this feature and at this point, when I fix one issue, another one seems to pop up in its place. Anyway, hopefully I can articulate this issue. I think it'll be kind of complicated to explain.

    How It Works

    Okay, so the basis of the tech is that you have two cameras capturing depth. One for the depth of objects, and the other for the depth of the terrain. Using those two depth maps, I get a third depth map that is "flattened" so the height of the terrain doesn't influence the depth of objects incorrectly. From there, I use depth map to displace the vertices of a mesh and apply tessellation. Now, this part of the tech only works efficiently on a small scale, which isn't satisfactory, so I had to devise a means to extend its functionality to a large scale.

    To do that, I created a mesh cutting algorithm that recursively divides a planar mesh into quadrants. These quadrants (tiles) have an overlap to them that ends up blending the deformation across the borders so that cracks aren't created at the seams of the tiles. From there, snow deformation modules are placed on each of the tiles and are turned on and off when objects enter and leave them.

    The Problem

    Once I got to everything I described above working properly, I naturally decided to test it out by running over all the tiles. What I found is that all the center and corner tiles work flawlessly. The rim/edge tiles however, have some strange inaccuracies with them. For the first half of the mesh, the displaced vertices occur slightly off from where the footsteps are. And then for the second half of the mesh, the footsteps are suddenly correct.

    Here's a clip (As there's currently not proper lighting or shadows on the snow, I've colored the ground red to make the deformation more clear):



    upload_2019-1-26_23-53-57.png


    My Thoughts and Questions

    So, right now, I'm not really sure where to begin debugging this. Everything seems to be set up properly. One of the previous problems I ran into was with the triangle indices on the same tiles actually. I don't think that's related, but it might be worth mentioning since these tiles have given me problems in the past.

    1. Any thoughts on how to debug this issue to identify what's causing the problem?

    2. What could cause the cameras to write incorrectly to the depth textures?
     
    Last edited: Jan 27, 2019
  2. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,352
    Use a known texture, like a gradient colored & numbered checkerboard, which is obvious when some part of it isn't correctly displayed, ie: if a section is offset, or in the wrong spot, stretched, inverted, etc. Display that on your mesh using the same UVs as your depth map, without any displacement or tessellation.

    I suspect #2 is a red herring and the above will show you what's wrong.
     
    Mr_Admirals likes this.
  3. Mr_Admirals

    Mr_Admirals

    Joined:
    May 13, 2017
    Posts:
    86
    The UVs are displaying as expected without displacement or tessellation. Which means that it must be the displacement UVs - somehow.

    Here's the code on how I calculate them (I believe it was you who helped me with this part).

    Code (CSharp):
    1. // Set up displacement UVs
    2.         List<Vector4> baseUVs = new List<Vector4>();
    3.         mesh.GetUVs(0, baseUVs);
    4.         for (int i = 0; i < mesh.vertexCount; i++)
    5.         {
    6.             baseUVs[i] = new Vector4(baseUVs[i].x,
    7.                                      baseUVs[i].y,
    8.                                      (float)(i % meshSideX) / (meshSideX - 1),
    9.                                      1 - (float)(i / meshSideZ) / (meshSideZ - 1));
    10.         }
    11.         mesh.SetUVs(0, baseUVs);
    I'll keep messing around in the meantime. Let me know if anything seems off to you about the code or if you suggest doing it a different way.
     
  4. Mr_Admirals

    Mr_Admirals

    Joined:
    May 13, 2017
    Posts:
    86
    Okay, so I swapped out the normal UVs for the displacement ones, and here's what I got on an edge tile:

    upload_2019-1-27_11-34-58.png

    If you'll note, the three and 2 are distorted, as well as some strange distortion going on in the center. As I said before, I'll keep messing around in the meantime. Let me know if you have any suggestions or thoughts.

    EDIT:

    Also, here's how I calculate the number of vertices on the X and Z axis.

    Code (CSharp):
    1. float row = mesh.vertices[0].z;
    2.         List<Vector3> row0 = new List<Vector3>();
    3.         for (int i = 0; i < mesh.vertexCount; i++)
    4.         {
    5.             if(mesh.vertices[i].z == row)
    6.             {
    7.                 row0.Add(mesh.vertices[i]);
    8.             }
    9.         }
    10.         int meshSideX = row0.Count;
    11.         int meshSideZ = mesh.vertexCount / meshSideX;
    EDIT:

    I've been thinking, the texture I'm using for displacement is a square in its resolution. Could that possibly be distorting the image since it's being placed on a non square tile?
     
    Last edited: Jan 27, 2019
  5. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,352
    There’s nothing obvious in the code you’ve shown in any of your posts on this topic, but it seems somewhere your vertex position and UV code is out of step with each other.
     
  6. Mr_Admirals

    Mr_Admirals

    Joined:
    May 13, 2017
    Posts:
    86
    Okay, so I managed to fix it. The catch is that I have no idea why the fix works.

    Basically, after messing around with my code, I had a hunch that something was wrong with how I was getting the UV coordinates originally. So I used Catlike Coding's tutorial on procedural mesh generation to get my UV coordinates. Now, to my eyes, my code looks like it should be getting the same numbers, but evidently that wasn't the case

    Here's a before and after:

    Code (CSharp):
    1.         // Set up displacement UVs
    2.         List<Vector4> baseUVs = new List<Vector4>();
    3.         mesh.GetUVs(0, baseUVs);
    4.         //for (int i = 0; i < mesh.vertexCount; i++)
    5.         //{
    6.         //    baseUVs[i] = new Vector4((float)(i % meshSideX) / (meshSideX - 1),
    7.         //                             1 - (float)(i / meshSideZ) / (meshSideZ - 1),
    8.         //                             (float)(i % meshSideX) / (meshSideX - 1),
    9.         //                             1 - (float)(i / meshSideZ) / (meshSideZ - 1));
    10.         //}
    11.         for (int i = 0, y = 0; y < meshSideZ; y++)
    12.         {
    13.             for (int x = 0; x < meshSideX; x++, i++)
    14.             {
    15.                 baseUVs[i] = new Vector4(baseUVs[i].x,
    16.                                          baseUVs[i].y,
    17.                                          (float)x / (meshSideX - 1),
    18.                                          1 - (float)y / (meshSideZ - 1));
    19.             }
    20.         }
    21.         mesh.SetUVs(0, baseUVs);