1. 程式人生 > >D3D11 IASetVertexBuffers 函數與頂點數據的兩種組織方式

D3D11 IASetVertexBuffers 函數與頂點數據的兩種組織方式

buffer 工作流 都沒有 d3d11 動畫 例子 骨骼動畫 arc ons

D3D11中的 IASetVertexBuffers 函數用來向GPU傳遞頂點數據。
一般情況下,我都是傳入一個buff,也即在0號slot上綁定了一個buff,其他slot都沒有綁定buff。
我傳入的這個buff,是一個存儲了頂點結構體數據的數組,每個頂點結構體中都有Position成員,Color成員,UV成員等等。
用術語來描述我這種做法,就是“交錯的頂點數據”,英文稱呼有這些 Interleaved Vertex Data , an array of structs 。

相對應的,另外一種做法就是“非交錯的頂點數據”“分離的頂點數據

”,英文稱呼有這些 Non-Interleaved Vertex Data , De-Interleaved Vertex Data , separate Vertex Data , a struct of arrays 。

這種做法的具體方案是,把頂點的所有的Position成員填充到buff0中,把所有的Color成員填充到buff1中,把所有的UV成員填充到buff2中,等等。

當執行 IASetVertexBuffers 函數時,0號slot綁定buff0,1號slot綁定buff1,2號slot綁定buff2,等等。

需要註意的是,當為頂點數據創建 InputLayout 時,

如果是交錯的頂點數據,示例如下:
D3D11_INPUT_ELEMENT_DESC vertexDesc[] =
{
{"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0},
{"COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0},
{"TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0},
};
如果是分離的頂點數據,要為每個成員設置正確的slot序號,示例如下:
D3D11_INPUT_ELEMENT_DESC vertexDesc[] =
{
{"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0},
{"COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 1, 0, D3D11_INPUT_PER_VERTEX_DATA, 0},
{"TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 2, 0, D3D11_INPUT_PER_VERTEX_DATA, 0},
};

很多編程教材裏面都是使用“交錯的頂點數據”這種做法,我也長期使用這種做法。
最近上網查詢了一下,很多人都提倡使用“分離的頂點數據”這種做法,優點如下:
1,一個模型有Position成員,Color成員,UV成員。在某些情況下可能只需要向GPU中傳遞一類成員或者兩類成員,本做法能夠節省帶寬。
例子1,繪制ShadowMap時,只需要傳遞Position成員。
例子2,做插值的骨骼動畫時,在slot0中傳遞上一幀的Position和Normal,在slot1中傳遞當前幀的Position和Normal,在slot2中傳遞其他的頂點數據成員。
2,一個模型有Position成員,Color成員,UV成員。其中某一類成員的值需要頻繁的發生變化,本做法能夠降低內存拷貝的大小。例如,Position成員在每幀都要發生變化,那麽只需要更改它的buff。
3,模型1和模型2有相同的Color成員,那麽模型1和模型2就可以共用一個Color buff。本做法能夠節省內存。
4,在GPU渲染時,當GPU需要若幹個Position成員時,只需要從Position buff中讀取若幹個Position成員,需要多少就讀多少,沒有浪費,本做法能夠提升GPU的工作流水線的效率。如果是交錯的頂點數據,GPU必須讀取若幹個頂點結構體,才能拿到若幹個Position成員。

參考鏈接

https://developer.apple.com/library/archive/documentation/3DDrawing/Conceptual/OpenGLES_ProgrammingGuide/TechniquesforWorkingwithVertexData/TechniquesforWorkingwithVertexData.html
https://anteru.net/blog/2016/storing-vertex-data-to-interleave-or-not-to-interleave/
https://gamedev.stackexchange.com/questions/66545/vertex-buffers-interleaved-or-separate
https://stackoverflow.com/questions/19822102/non-interleaved-vertex-buffers-directx11

D3D11 IASetVertexBuffers 函數與頂點數據的兩種組織方式