# 网格
网格Mesh
用于存储和管理顶点、索引数据,一般使用流程而言,其直接在模型导入工具的时候会被解析并存储,不需要特别关心。但有时候开发者会有自己构建Mesh的需求,让我们看看它的构造方法。
对于美术开发的网格模型,开发者可以查看资源导入的文档,把FBX,unity中的资源导入到项目中。
# 创建
constructor(
vertexLayout: VertexLayout, vBuffer: ArrayBufferView,
iBuffer: ArrayBufferView, indexType: EIndexType = EIndexType.UINT16
);
可见构造一个Mesh
需要提供好几个参数,他们是:
# VertexLayout
首先是VertexLayout
,用于描述顶点布局,举个例子来说:
const myLayout = new engine.VertexLayout({
attributes: [
{
name: "a_position",
format: engine.EVertexFormat.FLOAT2,
offset: 0,
usage: engine.EVertexLayoutUsage.POSITION,
},
{
name: "a_texCoord",
offset: 8,
format: engine.EVertexFormat.FLOAT2,
usage: engine.EVertexLayoutUsage.UV0,
},
{
name: "a_color",
format: engine.EVertexFormat.UBYTE4,
offset: 16,
usage: engine.EVertexLayoutUsage.COLOR,
}
],
stride: 20
});
这里定义了一个自定义的VertexLayout
,其中有两个参数:
- attributes:描述了顶点的结构,即如何GPU将如何理解传入的顶点数据,比如第一个元素,其表示此顶点属性在shader中名字为
a_position
,格式是FLOAT2
,在顶点Buffer中偏移为0,并且用做POSITION
。 - stride:描述了每个顶点所占带宽的字节数。
# Buffer和Type
后面三个参数分别是顶点数据、索引数据和索引格式,顶点数据按照布局结构存储着整个Mesh的顶点数据,索引数据存储着图元对顶点的索引,而索引格式则是决定了索引数据的存储格式,其可以为UINT16
或者UINT32
,如果为UINT16
,则索引数据中的顶点索引值不得超过65535。
# 设置参数
在创建完一个新的Mesh后,开发者还需要设置一些参数来让它正确得运作起来,主要是SubMesh和包围球。
# SubMesh
有了数据和布局后,Mesh还需要提供一些信息去让渲染器知道如何使用这些数据,我们提供了叫做SubMesh
的抽象,来将Mesh分割为数个部分:
// 添加一个SubMesh,其索引数据长度为`length`个顶点,第一个索引偏移为`offset`
mesh.addSubMesh(length, offset);
// 修改第`subMeshIndex`位置的SubMesh信息
mesh.modifySubMesh(subMeshIndex, length, offset);
这样分割的原因主要是即便是同一个Mesh,也可能拥有不同的材质来处理不同的部分,材质详见后面的章节。
# 包围球
对于每个Mesh来说,在相机的剔除阶段,都需要一个包围球来决定其是否在可视范围内,开发者可以通过以下方案来设置包围球:
// `center`为球心相对于模型原点的偏移,`radius`是球的半径
mesh.setBoundBall(center, radius);
# 更新数据
在某些场合,开发者还会需要去动态更新顶点或索引数据,比如粒子系统,我们也提供了一些方案来完成这种需求:
// 从字节偏移`offset`开始,将`buffer`整个更新到顶点数据。
mesh.uploadVertexBuffer(offset, buffer);
// 从字节偏移`offset`开始,将`buffer`整个更新到索引数据。
mesh.uploadIndexBuffer(offset, buffer);
注意这种更新操作只能在Mesh已经被提交到GPU后使用!