Search Unity

About welding vertices to get rid of visual artifacts in a tile based game

Discussion in 'Scripting' started by Andefoo, Mar 9, 2011.

  1. Andefoo

    Andefoo

    Joined:
    Mar 9, 2011
    Posts:
    11
    I am making a tile based game where different tile types are represented by prefabs. Levels are built at run time by instantiating tile prefabs and setting their transform (using level files). Tiles can also be moved, rotated, destroyed and created while playing. Some of the tiles are based on cubes and when there are several of them adjacent to each other, there are sometimes black gaps between them. They appear at certain zoom levels or camera positions. Antialiasing makes it happen less often but often the gaps just change place.

    This is probably the same issue: http://answers.unity3d.com/questions/36929/3d-terrain-tiling-graphic-artifact

    So I assume the problem could be that due to floating point inaccuracies and rounding errors, adjacent tiles end up having slightly different vertex positions? But how can I verify and/or fix that? I can access the mesh filter and mesh of an object but the vertex data there seems to be untransformed; the vertex data is the same for all the cube tile objects in different places. So what should I do? Set the transform for each cube tile to 0,0,0 and handle moving by changing vertex data? Surely there must be a better way...
     
  2. Jesse Anders

    Jesse Anders

    Joined:
    Apr 5, 2008
    Posts:
    2,857
    Yes, that seems likely.

    I don't know that it would be easy to verify, as the computations in question generally occur on the hardware side. But in general, geometry undergoing arbitrary transforms can't be expected to align exactly.

    That's right; the transform is applied later in the pipeline.

    Personally I'd probably work with the mesh data directly in order to ensure deterministic results. Doing so isn't entirely trivial, but it might be the best choice for a tile-based game of this sort.

    Maybe someone else will be able to offer a better suggestion though.
     
  3. Krobill

    Krobill

    Joined:
    Nov 10, 2008
    Posts:
    282
    screenshots of your problem might help but maybe it's not geometry gaps you're actually experiencing. If the problem appears at certain zoom levels or camera positions it may just be a problem of texture filtering, If your tile maps are not padded.
     
  4. Andefoo

    Andefoo

    Joined:
    Mar 9, 2011
    Posts:
    11
    Two screenshots:

    http://www.nbl.fi/~nbl2199/gap1.jpg
    http://www.nbl.fi/~nbl2199/gap2.jpg

    The camera position and zoom has to be exactly right for the gaps to appear at certain places. If the camera is moving smoothly, this causes flickering as there is often one-frame gaps somewhere (either fully vertical or fully horizontal).

    The prefabs are made from cubes of size 1 so all the vertex coordinates are either +0.5 or -0.5.

    ...

    I Removed stuff from here since I found a bug in the code I was describing. I learned that if I access prefab's mesh even for reading, it will cause the prefab to lose its link to the mesh. But should it be possible to modify the mesh vertex data of an instantiated prefab without it affecting other instances of the prefab or the prefab itself? I have not managed to make it work yet but there can be a trivial bug somewhere, I will continue to debug it later...
     
    Last edited: Mar 11, 2011
  5. Andefoo

    Andefoo

    Joined:
    Mar 9, 2011
    Posts:
    11
    There was a stupid little bug but I got the relative->absolute vertex coordinate conversion to work now. Unfortunately, it didn't help the actual problem at all. Tiles are now instantiated prefabs of cubes whose the transform position is set to 0,0,0. The mesh vertex data of each instance is set to absolute coordinates, they don't have any rotation and scale is 1. Tiles are in right places but there are still those gaps once in a while. I am running out of ideas to try...
     
  6. Jesse Anders

    Jesse Anders

    Joined:
    Apr 5, 2008
    Posts:
    2,857
    The image links don't seem to work, but regarding the problem in question, are you sure that the shared vertices match exactly? Remember, if there's any math involved (e.g. addition, subtraction, etc.), that can be enough to cause the vertices not to match. To ensure that they match, you really need to ensure specifically that vertices that should have the same value actually do have the same value by using the same value (or the exact same sequence of arithmetic operations) for each.
     
  7. Andefoo

    Andefoo

    Joined:
    Mar 9, 2011
    Posts:
    11
    Yes the images don't work for me either any more, there is clearly something I don't get in the attachment system in this forum, either :).

    I will debug the issue further later today but I am pretty certain the vertices matched exactly. The coordinates were all like 0.5, 1.5, 2.5, 3.5 etc. and since there was no scaling or rotation, I was just adding small integers to them (which should work accurately even with floating point numbers since 0.5f is 1/2). To be more sure I also tried to multiply every vertex coordinate by two, rounded the result and divided by two again. I could try once more by using just rounded integer coordinates but I can't really see how that would change anything.

    Maybe I should make a small simple example project that demonstrates the problem...
     
  8. Andefoo

    Andefoo

    Joined:
    Mar 9, 2011
    Posts:
    11
    I made a simple test project that illustrates the problem: http://www.nbl.fi/~nbl2199/UnityTestProject.zip

    Load tst.unity in the Assets folder.

    There is one prefab named Box and TestScript instantiates it several times to make a grid. Transform for each instance is set to (0,0,0) and vertex data is rounded to integers. Camera is moved automatically when run. When I run it, I keep getting lots of annoying horizontal and vertical black lines appearing here and there all the time.

    Here are working links to the earlier screenshots:

    http://www.nbl.fi/~nbl2199/gap1.jpg
    http://www.nbl.fi/~nbl2199/gap2.jpg
     
    Last edited: Mar 11, 2011
  9. Jesse Anders

    Jesse Anders

    Joined:
    Apr 5, 2008
    Posts:
    2,857
    Are you still trying to solve this problem? If so, post back, and I'll try to take a look at your project.
     
  10. Andefoo

    Andefoo

    Joined:
    Mar 9, 2011
    Posts:
    11
    Well, it is still a problem that I have to solve at some point even though I will be focusing on other things for a while now. If you or anyone has time to check that project and can find a fix, it is definitely appreciated! The code in that project is quite simple and in my opinion, it looks like this could be a bigger issue that could affect other projects, too.

    I noticed that setting near clipping distance to 0 made the problem even worse but setting the value bigger than the default didn't help. What I might try myself next is to see what happens if only the front faces of the cubes were rendered...
     
  11. Andefoo

    Andefoo

    Joined:
    Mar 9, 2011
    Posts:
    11
    Did anyone check that project? The problem is still there...
     
  12. Jesse Anders

    Jesse Anders

    Joined:
    Apr 5, 2008
    Posts:
    2,857
    I took a look at it. I played around with it a bit, and as far as I can tell, the problem actually seems to be caused by the lighting (if I turn off the directional light and set the ambient light to identity, the problem disappears).

    It's not immediately obvious to me why the lighting would cause this effect, but if I happen to think of anything, I'll let you know.

    Sorry I can't be more helpful.
     
  13. niosop2

    niosop2

    Joined:
    Jul 23, 2009
    Posts:
    1,059
    I haven't download the project, but a common problem is that you need to average the vertex normals of the overlapping verts or else you'll get a seam.
     
  14. Krobill

    Krobill

    Joined:
    Nov 10, 2008
    Posts:
    282
    I've been messing around with your project. I may be wrong but I think what you're experiencing is just plain good old Z-fighting. The black lines are in fact the faces of the cubes along the depth axis 'intersecting' with the visible faces. Just place a colored light toward these sides faces to see how the line artifacts change color. Another hint is that if you make your material alpha blended, you won't see anymore the glitches : no z-write, no z-fight. I expected that modifying the near clipping and far clipping planes would improve the situation but as you've already stated, it can only make thing worse not really better...

    I don't think welding the front faces of the cubes will make it better cause I've been able to reproduce the same effect with orthogonal planes 'crossing' inside a polygon and not along some edge. Maybe you should use planes instead of cubes for the elements of your grid which are not on the border.
     
  15. Andefoo

    Andefoo

    Joined:
    Mar 9, 2011
    Posts:
    11
    Thank you to all for your efforts!

    It is probably a good idea anyway to prune those invisible cube faces for optimization reasons. Things can get a bit complicated, though, since new cubes can be added and removed dynamically. So I have to make a system that keeps adding and removing polygons to objects when their neighbors change. I don't know what happens under the hood when a mesh is modified but I guess that adding and removing polygons is not a super slow thing to do?

    By the way, when I was debugging the issue, I noticed that the cube meshes generated by Unity had more than 8 vertices. I didn't dig deeper into this but it was probably because each vertex has many instances of itself with different normals for different faces. Niosop suggested averaging those normals but I guess that would screw up vertex level lighting for cubes, right?
     
  16. Broken-Toy

    Broken-Toy

    Joined:
    Jan 16, 2010
    Posts:
    455
    That depends whether the Unity engine optimizes the rendering to only take visible triangles into account.

    The default mesh generation methods assign brand new vertices to each triangle you create. Basically how a mesh works is by assigning three vertices to each triangle. So: add three vertices in the vertices array, then create one triangle in the triangles array and immediately assign those new vertices to it.

    If you need to weld vertices in a mesh, the brute-force solution I used for my marching cubes project is to check, when creating each vertex, whether a vertex already exists at the same position. If it exists, then instead of adding a new vertex, I assign the existing one to the triangle.

    I run this during triangle creation loops, but it gets very slow with larger meshes (involves a few ifs, which can bring quite some lag when trying to do it in realtime, because it iterates 3 vertices then 6 then 9, etc... adds up pretty fast). I didn't start noticing the effect until I looped through more than 3000 vertices at a time though, which is probably irrelevant in your case unless your combined mesh is made of thousands of tiles and you want to change it every update or something.

    Also, averaging normals looks wonky on 90° edges, and will not really work with separate triangles without normal smoothing math which might be just as complex, if not more, than merging vertices.
     
    Last edited: Mar 28, 2011
  17. Krobill

    Krobill

    Joined:
    Nov 10, 2008
    Posts:
    282
    You could also create the 16 variants of each block (with or without a neighbor in each cardinal direction) and feed the mesh used by your gameobject with the correct one. It would be cheaper that way.


    You're right. The cube needs more than 8 vertices in Unity to preserve the hard edges and you certainly don't want smoothing for your cubes.
     
  18. Andefoo

    Andefoo

    Joined:
    Mar 9, 2011
    Posts:
    11
    This is what I ended up doing. It was not a trivial thing to do since the scene is dynamic and meshes need to be updated when cubes are moved, created or removed. But anyway, it seems to work now and the artifacts are gone!

    Thank you everybody!
     
  19. crafTDev

    crafTDev

    Joined:
    Nov 5, 2008
    Posts:
    1,820
    Im searching through the forums to see if anyone else has these problems and I found this page. Im using tiling to create my levels and I have run in to this problem even though I used vertex snapping. I read the thread but I still don't understand how you solved. Help? Here is a pic

     
  20. Andefoo

    Andefoo

    Joined:
    Mar 9, 2011
    Posts:
    11
    My problem was that my tiles were in fact cubes and the different sides of the same cube had z fight issues. It would seem that your scene is not made of cubes but of just front facing polygons? In that case, the problem is probably something else than mine but I don't know.
     
  21. crafTDev

    crafTDev

    Joined:
    Nov 5, 2008
    Posts:
    1,820
    Mine is just flat mesh planes with sprites on them using SM2.
     
  22. farzher

    farzher

    Joined:
    May 9, 2013
    Posts:
    9
    I'm having the same lines in my grid of cubes.
    I can't believe how big of a problem this is. Isn't everyone making Minecraft clones and voxel games these days.
    There's lines popping up everywhere when I walk around.
     
  23. UtilityFrog

    UtilityFrog

    Joined:
    Dec 25, 2013
    Posts:
    6
    I'm having this problem as well. I'm working on a top down grid based game. At the moment I'm randomly generating a grid of cubes (serving as walls in a maze) and quads (serving as the floor tiles). When I pan the camera horizontally I get intermittent vertical black lines at the edges where cubes meet, and inversely when I pan vertically.

    I kinda suspect that, in my case at least, it's a floating point rounding/accuracy issue. I had a similar problem in another game engine which was primarily 2d focused, so I understand this may not be Unity specific. But if anyone has any insight into this sort of thing I'd really like to hear about it. You don't see professional games with this sort of problem (in my experience anyway) so they must be dealing with it somehow.
     
  24. Squabbler

    Squabbler

    Joined:
    Jan 11, 2013
    Posts:
    11
    Here's what I did to fix this issue:
    1. Create a New Material in your Project Folder
    2. Click on the Material
    3. Change the Shader to "Sprites/Default"
    4. Drag the atlas or spritesheet you are having trouble with into the texture box
    5. Click "Pixel Snap"
    6. Apply this material to your individual sprites
     
  25. hdub

    hdub

    Joined:
    Jul 16, 2014
    Posts:
    1
    I fixed it by rotating all the planes .1degrees towards the camera (60degrees)
    So far it has fixed all quality levels and is unnoticeable (in my case)
     
  26. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,738
    Another option is to scale all your sub-cubes to Vector.one * 1.0001f or some other suitably "just bigger than one" value. What works best may change with camera distance/relative size of objects.

    This means there will always be a tiny bit of overlap, hopefully enough to counteract the floating point error that was causing your gap to be visible.

    Kurt
     
    Freakhealer likes this.
  27. renman3000

    renman3000

    Joined:
    Nov 7, 2011
    Posts:
    6,697
    Hi,
    I just found a solution.
    Set the texture to advanced. I turned off mip maps and selected, fix edges.

    Works like a charm!
     
  28. Lythox

    Lythox

    Joined:
    Sep 24, 2016
    Posts:
    3
    The above solution is not a good solution for me, and possibly not for you, as it simply disables shading on the affected objects, which also explains why the grid lines disappear (in the case of white cubes, the lines would now become white due to lack of shading, hence rendering them "invisible"). So any cube grid that has this solution advanced textures on it will make it so that lighting from different angles will not make the surfaces any darker.

    I HAVE FOUND A SOLUTION THOUGH FOR THIS AWFUL PROBLEM:
    Fiddle around with the "Clipping Planes" of your main camera. I have changed my clipping plane (near) of my main camera from .01 to 1, and suddenly all grid artifacts are gone!
     
    Kurt-Dekker likes this.
  29. daxiongmao

    daxiongmao

    Joined:
    Feb 2, 2016
    Posts:
    412
    It seems there are possibly several problems happening.

    Vertex position matching.
    Normal matching. Even if the vertex position is snapped if the normals are not the same this could cause shading/lighting issues. (Turning off lighting, ambient only)

    Texture mipmapping most likely do to the textures/sprites not having texel padding or a neutral base color. (Disable mipmapping)

    Z buffer depth issues. The depth buffer only has so much precision. So if your max distance from the camera is only 10m there is no point to having the far plane at 1000. (Adjust the far plane)

    All these problems have fairly simple fixes for most of the cases. The notes () are ways to test which problem. Not necessarily the correct fix.
     
  30. guneyozsan

    guneyozsan

    Joined:
    Feb 1, 2012
    Posts:
    99
    In my case I was tiling 6x14 Quad's to build a high resolution sports playing field. I managed to get rid of tile artifacts by setting the Wrap Mode to Clamp. I also had to calculate and set the coords manually after placing the tiles with vertex snapping because its rounding errors were also introducing artifacts especially after placing some number of tiles. Here are my import options:
    upload_2017-3-24_20-2-28.png
    It also works well with Default Texture Type:
    upload_2017-3-24_21-1-52.png
     
    Last edited: Mar 24, 2017
  31. w4der

    w4der

    Joined:
    Sep 17, 2011
    Posts:
    17
    Hi,
    You could also select your main Camera and in the output tab turn off the MSAA.
     
    neocaotical likes this.