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, 0),
new Vector3 (1, 0, 0),
new Vector3 (1, 1, 0),
new Vector3 (0, 1, 0),
new Vector3 (0, 1, 1),
new Vector3 (1, 1, 1),
new Vector3 (1, 0, 1),
new Vector3 (0, 0, 1),
};
private int[] cubeTriangles = new[] {
// Front
0, 2, 1,
0, 3, 2,
// Top
2, 3, 4,
2, 4, 5,
// Right
1, 2, 5,
1, 5, 6,
// Left
0, 7, 4,
0, 4, 3,
// Back
5, 4, 7,
5, 7, 6,
// Bottom
0, 6, 7,
0, 1, 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, y, 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, 0),
new Vector2 (1, 1),
new Vector2 (0, 1),
...
}
...
mesh.SetUVs(0, cubeUVs);

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

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

编辑

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

然后,你将不得不创建一个自定义着色器,在输入中有6个纹理(每边一个)。
在fragment函数中,根据顶点颜色选择合适的纹理颜色。
你可以这样做,如果选择纹理,但它将不是很性能:

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 + ...;

最新更新