# 幾何數(shù)據(jù)
渲染的基礎(chǔ)之一是幾何數(shù)據(jù)Geometry資源,它描述了一個(gè)模型的頂點(diǎn)信息、索引信息以及頂點(diǎn)的存取結(jié)構(gòu)。
一般來(lái)講,幾何數(shù)據(jù)是通過(guò)模型中自動(dòng)加載,或使用 內(nèi)置Geometry,但有時(shí)候我們需要去定制一些程序化生成的數(shù)據(jù)比如粒子等等,所以還是要明白如何去定制。
# 定制一個(gè)看看
const geometry = scene.createGeometry(
vertexLayout, vertexBuffer,
indexBuffer, indexType
)
可見(jiàn)構(gòu)造一個(gè)Geometry需要提供好幾個(gè)參數(shù),他們是:
# VertexLayout
首先是VertexLayout,用于描述頂點(diǎn)布局,舉個(gè)例子來(lái)說(shuō):
const layout = new xrFrameSystem.VertexLayout({
attributes: [
{
name: 'a_position',
format: xrFrameSystem.EVertexFormat.FLOAT2,
offset: 0,
usage: xrFrameSystem.EVertexLayoutUsage.POSITION,
},
{
name: 'a_texCoord',
offset: 8,
format: xrFrameSystem.EVertexFormat.FLOAT2,
usage: xrFrameSystem.EVertexLayoutUsage.UV0,
},
{
name: 'a_color',
format: xrFrameSystem.EVertexFormat.UBYTE4,
offset: 16,
usage: xrFrameSystem.EVertexLayoutUsage.COLOR,
}
],
stride: 20
});
這里定義了一個(gè)自定義的VertexLayout,其中有兩個(gè)參數(shù):
- attributes:描述了頂點(diǎn)的結(jié)構(gòu),即如何GPU將如何理解傳入的頂點(diǎn)數(shù)據(jù),比如第一個(gè)元素,其表示此頂點(diǎn)屬性在shader中名字為
a_position,格式是FLOAT2,在頂點(diǎn)Buffer中偏移為0,并且用做POSITION。 - stride:描述了每個(gè)頂點(diǎn)所占帶寬的字節(jié)數(shù)。
usage會(huì)影響到渲染這些數(shù)據(jù)時(shí)開啟的宏,詳見(jiàn)內(nèi)置效果。
# Buffer和Type
后面三個(gè)參數(shù)分別是頂點(diǎn)數(shù)據(jù)、索引數(shù)據(jù)和索引格式,頂點(diǎn)數(shù)據(jù)按照布局結(jié)構(gòu)存儲(chǔ)著整個(gè)Geometry的頂點(diǎn)數(shù)據(jù),索引數(shù)據(jù)存儲(chǔ)著圖元對(duì)頂點(diǎn)的索引,而索引格式則是決定了索引數(shù)據(jù)的存儲(chǔ)格式,其可以為UINT16或者UINT32,如果為UINT16,則索引數(shù)據(jù)中的頂點(diǎn)索引值不得超過(guò)65535。
# 設(shè)置參數(shù)
在創(chuàng)建完一個(gè)新的幾何數(shù)據(jù)后,開發(fā)者還需要設(shè)置一些參數(shù)來(lái)讓它正確得運(yùn)作起來(lái),主要是SubMesh和包圍球/包圍盒。
# SubMesh
有了數(shù)據(jù)和布局后,幾何數(shù)據(jù)還需要提供一些信息去讓渲染器知道如何使用這些數(shù)據(jù),我們提供了叫做SubMesh的抽象,來(lái)將Geometry分割為數(shù)個(gè)部分:
// 添加一個(gè)SubMesh,其索引數(shù)據(jù)長(zhǎng)度為`length`個(gè)頂點(diǎn),第一個(gè)索引偏移為`offset`
geometry.addSubMesh(length, offset);
// 修改第`subMeshIndex`位置的SubMesh信息
geometry.modifySubMesh(subMeshIndex, length, offset);
這樣分割的原因主要是即便是同一個(gè)幾何數(shù)據(jù),也可能擁有不同的材質(zhì)來(lái)處理不同的部分,但是出于綜合考慮,目前渲染時(shí)幾何數(shù)據(jù)和材質(zhì)是一一對(duì)應(yīng)的,所以只支持一個(gè)SubMesh。
# 包圍球和包圍盒
對(duì)于每個(gè)幾何數(shù)據(jù)來(lái)說(shuō),在相機(jī)的剔除階段,都需要一個(gè)包圍球/包圍盒來(lái)決定其是否在可視范圍內(nèi),開發(fā)者可以通過(guò)以下方案來(lái)設(shè)置包圍球:
// `center`為球心相對(duì)于模型原點(diǎn)的偏移,`radius`是球的半徑
geometry.setBoundBall(center, radius);
或是設(shè)置包圍盒:
// `center`為球心相對(duì)于模型原點(diǎn)的偏移,`size`是盒的三維長(zhǎng)度,默認(rèn)會(huì)同步更新包圍球
geometry.setBoundBox(center, size);
# 更新數(shù)據(jù)
在某些場(chǎng)合,開發(fā)者還會(huì)需要去動(dòng)態(tài)更新頂點(diǎn)或索引數(shù)據(jù),比如粒子系統(tǒng),我們也提供了一些方案來(lái)完成這種需求(注意這種更新操作只能在Mesh已經(jīng)被提交到GPU后使用):
// 從字節(jié)偏移`offset`開始,將`buffer`整個(gè)更新到頂點(diǎn)數(shù)據(jù)。
geometry.uploadVertexBuffer(offset, buffer);
// 從字節(jié)偏移`offset`開始,將`buffer`整個(gè)更新到索引數(shù)據(jù)。
geometry.uploadIndexBuffer(offset, buffer);
之后便可以使用這個(gè)幾何數(shù)據(jù)了。
# 注冊(cè)到資源系統(tǒng)
和其他資源一樣,我們提供了一套注冊(cè)機(jī)制來(lái)讓開發(fā)者定制在xml中也可以被引用的幾何數(shù)據(jù):
xrFrameSystem.registerGeometry('custom', scene => {
return scene.createGeometry(
vertexLayout, vertexBuffer,
indexBuffer, indexType
);
});
注冊(cè)后在schema中類型指定為geometry的數(shù)據(jù),便可以使用custom這個(gè)資源id引用到創(chuàng)建的資源了。