0
\$\begingroup\$

Hello i'm generating voxel map but seams are appearing between tile ONLY in camera mode, in the editor everything work fine.

Here in the editor camera: Editor Camera

Here the player camera: Player Camera

So i guess it has something to do with camera setting here is what i have so far: Camera

Edit: I know this kind of issue can be caused by mipmapping i'm pretty sure my texture is not generating mipmap right now:

Texture Config

Code for the chunk generation

using UnityEngine;
using UnityEngine.Rendering;

namespace World
{
    public class Chunk
    {
        private static readonly int x_length = 16;
        private static readonly int z_length = 16;
        private static readonly int y_length = 32;

        public MeshRenderer MeshRenderer;
        public MeshFilter MeshFilter;
        public GameObject ChunkObject;
        
        private Block[] chunkBlock;
        private readonly Vector2 _pos;

        private Vector3[] _vertices;
        private int[] _triangles;
        private Vector2[] _uvs;
        
        private int _verticesIndex;
        private int _trianglesIndex;
        private int _uvsIndex;

        public Chunk(int xPos, int yPos, WorldSpace worldSpace)
        {
            _pos = new Vector2(xPos, yPos);
            ChunkObject = new GameObject("Chunk:" + _pos.x + "|" + _pos.y);
            
            ChunkObject.transform.SetParent(worldSpace.transform);
            MeshRenderer = ChunkObject.AddComponent<MeshRenderer>();
            MeshFilter = ChunkObject.AddComponent<MeshFilter>();
            MeshRenderer.material = worldSpace.texAtlas;

            _vertices = new Vector3[x_length * z_length * y_length * 8];
            _triangles = new int[x_length * z_length * y_length * 36];
            _uvs = new Vector2[x_length * z_length * y_length * 8];
            
            chunkBlock = new Block[x_length * y_length * z_length];
        }
        

        public void GenRandom(float xStart, float yStart, float scale)
        {
            for (int i = 0; i < chunkBlock.Length; ++i)
            {
                Vector3 vecBlock = new Vector3(0, 0, 0);
                vecBlock.x += i % (x_length * z_length) % x_length;
                vecBlock.z += i % (x_length * z_length) / x_length;
                vecBlock.y += i / (x_length * z_length);
                float height = Mathf.PerlinNoise((xStart*16 + vecBlock.x)/scale, (yStart*16 +vecBlock.z)/scale);
                chunkBlock[i] = new Block(vecBlock.y < height*y_length ? 0 : 1); //TODO: Change to random
            }
        }

        public void Draw()
        {
            FillMeshDataBuffer();

            Mesh mesh = new Mesh();
            
            mesh.indexFormat = IndexFormat.UInt32;
            mesh.SetVertices(_vertices, 0, _verticesIndex);
            mesh.SetTriangles(_triangles, 0, _trianglesIndex, 0);
            mesh.SetUVs(0, _uvs, 0, _uvsIndex);
            
            mesh.RecalculateNormals();

            MeshFilter.mesh = mesh;

            ChunkObject.transform.position = new Vector3(_pos.x * x_length, 0f, _pos.y * z_length);
        }

        void FillMeshDataBuffer()
        {
            _verticesIndex = 0;
            _trianglesIndex = 0;
            _uvsIndex = 0;

            for (int i = 0; i < chunkBlock.Length; ++i)
            {
                if (chunkBlock[i].isSolid)
                {
                    if (i % (x_length * z_length) - x_length < 0 ||  i - x_length < 0
                        || !chunkBlock[i - x_length].isSolid)
                    {
                        AddFace(0, i);
                        AddUv(chunkBlock[i].Type, 0);
                    }
                    if (i % (x_length * z_length) + x_length > x_length * z_length - 1
                        || !chunkBlock[i + x_length].isSolid)
                    {
                        AddFace(1, i);
                        AddUv(chunkBlock[i].Type, 1);
                    }
                
                    if (i + x_length * z_length > x_length * z_length * y_length - 1
                        || !chunkBlock[i + x_length * z_length].isSolid)
                    {
                        AddFace(2, i);
                        AddUv(chunkBlock[i].Type, 2);
                    }
                    if (i - x_length * z_length < 0
                        || !chunkBlock[i - x_length * z_length].isSolid)
                    {
                        AddFace(3, i);
                        AddUv(chunkBlock[i].Type, 3);
                    }
                
                    if (i % (x_length * z_length) - 1 < 0
                        || i % (x_length * z_length) % x_length == 0
                        || !chunkBlock[i - 1].isSolid)
                    {
                        AddFace(4, i);
                        AddUv(chunkBlock[i].Type, 4);
                    }
                    if (i % (x_length * z_length) + 1 > x_length * z_length - 1 
                        || i % (x_length * z_length) % x_length == x_length - 1
                        || !chunkBlock[i + 1].isSolid)
                    {
                        AddFace(5, i);
                        AddUv(chunkBlock[i].Type, 5);
                    }
                }
            }
        }
    
        void AddFace(int face, int pos)
        {
            Vector3 vertex = VoxelMeshData.VoxelVerts[VoxelMeshData.VoxelTris[face, 0]];
            vertex = AddPos(vertex, pos);
            AddVertexInVertices(vertex);
        
            vertex = VoxelMeshData.VoxelVerts[VoxelMeshData.VoxelTris[face, 1]];
            vertex = AddPos(vertex, pos);
            AddVertexInVertices(vertex);
        
            vertex = VoxelMeshData.VoxelVerts[VoxelMeshData.VoxelTris[face, 2]];
            vertex = AddPos(vertex, pos);
            AddVertexInVertices(vertex);
        
            vertex = VoxelMeshData.VoxelVerts[VoxelMeshData.VoxelTris[face, 3]];
            vertex = AddPos(vertex, pos);
            AddVertexInVertices(vertex);
        
            AddTriangleInTriangles(_verticesIndex - 4);
            AddTriangleInTriangles(_verticesIndex - 3);
            AddTriangleInTriangles(_verticesIndex - 2);
            AddTriangleInTriangles(_verticesIndex - 2);
            AddTriangleInTriangles(_verticesIndex - 3);
            AddTriangleInTriangles(_verticesIndex - 1);
        }

        Vector3 AddPos(Vector3 vertexIn, int pos)
        {
            Vector3 vertex = new Vector3(vertexIn.x, vertexIn.y, vertexIn.z);
            vertex.x += pos % (x_length * z_length) % x_length;
            vertex.z += pos % (x_length * z_length) / x_length;
            vertex.y += pos / (x_length * z_length);
            return vertex;
        }

        private void AddVertexInVertices(Vector3 vertex)
        {
            _vertices[_verticesIndex] = vertex;
            ++_verticesIndex;
        }

        private void AddTriangleInTriangles(int triangle)
        {
            _triangles[_trianglesIndex] = triangle;
            ++_trianglesIndex;
        }

        void AddUv(int type, int face)
        {
            int offset = BlockTypeData.UVData[type,face]; int posX = offset % VoxelMeshData.TextureAtlasSizeInBlocks;
            int posY = offset / VoxelMeshData.TextureAtlasSizeInBlocks;
            float startX = posX * VoxelMeshData.NormalizedBlockTextureSize;
            float startY = posY * VoxelMeshData.NormalizedBlockTextureSize;
            AddUvInUvs(new Vector2(startX, startY));
            AddUvInUvs(new Vector2(startX, startY + VoxelMeshData.NormalizedBlockTextureSize));
            AddUvInUvs(new Vector2(startX + VoxelMeshData.NormalizedBlockTextureSize, startY));
            AddUvInUvs(new Vector2(startX + VoxelMeshData.NormalizedBlockTextureSize, startY + VoxelMeshData.NormalizedBlockTextureSize));
        }

        private void AddUvInUvs(Vector2 uv)
        {
            _uvs[_uvsIndex] = uv;
            ++_uvsIndex;
        }
    }
}
\$\endgroup\$
0

1 Answer 1

2
\$\begingroup\$

Using some info i found here How to remove seams from a tile map in 3D? I implemented a texel correction thingy in my AddUv Method

        void AddUv(int type, int face)
        {
            int tilesetWidth = 32;
            int tilesetHeight = 32;
            Vector2 texelCorrection = new Vector2(1f / tilesetWidth , 1f / tilesetHeight);
            int offset = BlockTypeData.UVData[type,face]; 
            int posX = offset % VoxelMeshData.TextureAtlasSizeInBlocks;
            int posY = offset / VoxelMeshData.TextureAtlasSizeInBlocks;
            float startX = posX * VoxelMeshData.NormalizedBlockTextureSize;
            float startY = posY * VoxelMeshData.NormalizedBlockTextureSize;
            AddUvInUvs(new Vector2(startX, startY) + texelCorrection);
            AddUvInUvs(new Vector2(startX + texelCorrection.x, startY + VoxelMeshData.NormalizedBlockTextureSize - texelCorrection.y));
            AddUvInUvs(new Vector2(startX + VoxelMeshData.NormalizedBlockTextureSize - texelCorrection.x, startY + texelCorrection.y));
            AddUvInUvs(new Vector2(startX + VoxelMeshData.NormalizedBlockTextureSize, startY + VoxelMeshData.NormalizedBlockTextureSize) - texelCorrection);
        }

Edit: This solution only works for short distances, if you want no seams to appear and you have a similar use case, turn off the default unity anti-aliasing + use the Sprite texture type. Then you can remove the texture correction which becomes unnecessary.

\$\endgroup\$
1
  • \$\begingroup\$ You might want to look at using an array texture here. That way each tile can sit on its own layer of the array, with no risk of bleeding from adjacent tiles. \$\endgroup\$
    – DMGregory
    Dec 23, 2021 at 2:49

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .