Unity3D - 如何向网格添加纹理

问题描述

我正在制作立方体素游戏。我已经完成了块、世界、块和网格的生成,但有一个问题 - 我无法制作纹理。

我需要的只是在 3D 网格的一侧添加纹理(每个纹理都不同!)。我见过一些实现,但很难阅读其他人的代码(我尝试使用它们,但没有奏效)。我尝试过自己做这件事,但没有结果。

谁能解释一下如何做到这一点??

这是我当前的代码

[ExecuteInEditMode]
[RequireComponent(typeof(MeshFilter))]
[RequireComponent(typeof(MeshRenderer))]
public class Chunk : MonoBehavIoUr
{
    private ushort[] _voxels = new ushort[16 * 16 * 16];
    private MeshFilter meshFilter;
    private Vector3[] cubeVertices = new[] {
        new Vector3 (0,0),new Vector3 (1,1,new Vector3 (0,1),};
    private int[] cubeTriangles = new[] {
        // Front
        0,2,3,// Top
        2,4,5,// Right
        1,6,// Left
        0,7,// Back
        5,// Bottom
        0,6
    };

    public ushort this[int x,int y,int z]
    {
        get { return _voxels[x * 16 * 16 + y * 16 + z]; }
        set { _voxels[x * 16 * 16 + y * 16 + z] = value; }
    }

    void Start()
    {
        meshFilter = GetComponent<MeshFilter>();
    }

    private void Update()
    {
        GenerateMesh();
    }

    public void GenerateMesh()
    {
    Mesh mesh = new Mesh();
    List<Vector3> vertices = new List<Vector3>();
    List<int> triangles = new List<int>();

    for (var x = 0; x < 16; x++)
    {
        for (var y = 0; y < 16; y++)
        {
            for (var z = 0; z < 16; z++)
            {
                var voxelType = this[x,y,z];
                if (voxelType == 0)
                    continue;
                var pos = new Vector3(x,z);
                var verticesPos = vertices.Count;
                foreach (var vert in cubeVertices)
                    vertices.Add(pos + vert);
                foreach (var tri in cubeTriangles)
                    triangles.Add(verticesPos + tri);
            }
        }
    }

    mesh.SetVertices(vertices);
        mesh.SetTriangles(triangles.ToArray(),0);
    meshFilter.mesh = mesh;
    }
}

注意:这是一篇经过多次编辑的转帖,因此它专注于一个问题,并且有更好的解释。对不起。

解决方法

与您的 SetVertices()SetTriangles() 一样,您可以使用纹理上每个顶点的 UV 坐标列表调用 SetUVs()

UV 列表大小必须与顶点列表大小匹配!

UV 坐标表示为 Vector2,其值介于 0 和 1 之间。 例如,要将整个纹理应用到立方体的正面,前 4 个 uv 如下所示:

private Vector2[] cubeUVs = new[] {
    new Vector2 (0,0),new Vector2 (1,1),new Vector2 (0,...
}

...

mesh.SetUVs(0,cubeUVs);

如果您的纹理不是正方形,那么它将被拉伸。

您还应该在 RecalculateBounds() 方法的末尾调用 RecalculateNormals()GenerateMesh() 以避免以后出现一些问题。

编辑

如果您真的想要为立方体的每一面使用不同的纹理文件,那么对我来说最干净、最高效的解决方案是为立方体的每一面设置不同的 VertexColor,例如。 (1,(0,1,(1,1) 和 (0,1).
但是,您必须将所有顶点复制 3 次。 (因为顶点颜色绑定到一个顶点,立方体的每个顶点属于3条边)
(你仍然需要像我之前说的那样设置 UV,但每一面都有整个纹理而不是纹理的一部分)

然后,您必须在输入中创建一个具有 6 个纹理的自定义着色器(每侧一个)。
而在fragment函数中,你根据顶点颜色选择合适的纹理颜色。
你可以为此,做一些 if 来选择纹理,但它的性能不会很好:

float3 finalColor;
if(vertexColor.r > 0.5f && vertexColor.g < 0.5f && vertexColor.b < 0.5f)
{
    finalColor = text2D(_TopTexture,in.uv);
}
else if(...)
{
    ...
}
...

或者如果你想要更多的性能(有很多立方体),你可以做一些乘法来选择正确的纹理:

float3 topTexColor = text2D(_TopTexture,in.uv) * vertexColor.r * (1.0f - vertexColor.g) * (1.0f - vertexColor.b);
float3 frontTexColor = ...;
...
float3 finalColor = topTexColor + frontTexColor + ...;