|
在Unity中,通过代码绘制mesh,是地形编辑器的基础。本片文章讲如何在Unity中绘制一个Panel的Mesh,并应用一个简单的噪声纹理生成一个随机山形:
01、简单四边面Mesh绘制
一个Mesh常用一下几个信息: vertices mesh中的顶点数据(对象的坐标系) uv 基础的uv纹理坐标 triangles 三角面片 color 顶点色 normals 法线 tangles 切线 * uv2-8 其他纹理坐标数据,按照需要定义
在绘制一个简单的四边面Mesh时,我们需要至少4个顶点数据,并且包含uv、以及三角面片,绘制面片是,我们使用左手螺旋定则来绘制。
参考代码:
//四个顶点
Vector3[] baseVerts = new Vector3[]
{
new Vector3(0,0,0),
new Vector3(1,0,0),
new Vector3(1,0,1),
new Vector3(0,0,1),
};
//每个顶点的uv坐标
Vector2[] baseUVs = new Vector2[]
{
new Vector2(0,0),
new Vector2(1,0),
new Vector2(1,1),
new Vector2(0,1),
};
//每三个顶点组成一个三角面,面朝向依据顶点绘制的左手螺旋定则
int[] baseTriangles = new int[]
{
0,3,1,
1,3,2,
};
//将数据赋值给MeshFilter组件的sharedMesh进行绘制
meshData = new Mesh();
meshData.vertices = baseVerts;
meshData.uv = baseUVs;
meshData.triangles = baseTriangles;
meshFilter.sharedMesh = meshData;开启scene窗口的线框模式
可以看到我们代码生成的4个顶点,两个三角面片,以及uv分布
02、Panel绘制
我们以一个四边型mesh为基础来扩展绘制一个大的panel,通过x与z方向上的偏移设置对应顶点数据、uv数据、三角面片数据。 为了之后便于修改数据,我们可以将数据缓存下来;
//初始化数据
void InitMeshData()
{
meshData = new Mesh();
vertData = new Vector3[vertNumX * vertNumZ];
uvData = new Vector2[vertNumX * vertNumZ];
triData = new int[3 * 2 * countX * countZ];
}
//应用数据
void ApllyMeshChange()
{
meshData.Clear();
meshData.vertices = vertData;
meshData.uv = uvData;
meshData.triangles = triData;
meshFilter.sharedMesh = meshData;
}
//根据方格位置,返回方格的四个顶点的数组下标
int[] GetRectVerts(int x, int y)
{
return new int[]
{
x + y * vertNumX,
x + 1 + y * vertNumX,
x + 1 + (y + 1) * vertNumX,
x + (y + 1) * vertNumX,
};
}
//刷新数据
public void RefreshMeshData()
{
//countX、countY是在x、y方向上网格(四边面)的数目
for (int i = 0; i < countX; i++)
{
for(int j = 0; j < countZ; j++)
{
int[] vertIndex = GetRectVerts(i,j);
//顶点
Vector3 vertOff = new Vector3(i, 0, j);
for(int index = 0; index < 4; index++)
{
Vector3 pos = baseVerts[index] + vertOff;
vertData[vertIndex[index]] = pos;
}
//uv
Vector2 uvCell;
uvCell.x = 1 / ((float)countX);
uvCell.y = 1 / ((float)countZ);
Vector2 uvOff = new Vector2(i,j);
for (int posIndex = 0; posIndex < 4; posIndex++)
{
uvData[vertIndex[posIndex]] = (baseUVs[posIndex] + uvOff) * uvCell;
}
//面片(每个四边形面要绘制两个三角面)
int rectIndex = i + j * countX;
for (int subTriIndex = 0; subTriIndex < 2; subTriIndex++)
{
int fargIndex = 2 * rectIndex + subTriIndex;
for (int posIndex = 0; posIndex < 3; posIndex++)
{
int pos = baseTriangles[subTriIndex * 3 + posIndex];
triData[3 * fargIndex + posIndex] = vertIndex[pos];
}
}
}
}
}绘制结果:
03、增加一个高度纹理
我们新增一个可读写的噪声纹理,作为高度值输入。
vertpos.y = heightMap[samplePos].r * maxheight;绘制结果:
04、尾声
Panel的绘制大致如此,这只是一次简单代码绘制的尝试,但动态的Mesh+Texture数据组合也是实现一些高级的工具或特效的基础,在一些高计算量的地方,可以考虑使用ComputeShader优化。 |
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有账号?立即注册
×
|