基本上,你有一些模型(在你的情況三角形)。
模型是頂點數組:
struct Vertex
{
float3 position;
float3 normal;
float2 texcoord;
float4 color;
// other vertex attributes goes here
};
創建頂點(和索引)(類)緩衝劑一次,在初始化。
std::vector<Vertex> vertices = { /*vertex data goes here*/ };
VertexBuffer vb = renderer->CreateVertexBuffer(&vertices[0], vertices.size());
3D世界是對象這是情況下,你的模型(一個或多個)的的數組。
struct MyObject
{
float3 position;
float3 rotation;
float3 scale;
// other instance attributes goes here (it can be whatever you want)
};
std::vector<MyObject> objects = { /*objects data goes here*/ };
基本上對象的屬性是修飾頂點屬性,因此所有對象都具有相同的型號,但看起來在你的世界的不同(在這個例子中,他們有不同的位置)。
通常在模型空間中定義的每個頂點的位置(以及法線,切線和雙切線)。要將它移動(變換)到世界空間,可以將每個頂點的position
乘以當前對象的矩陣。你不想在CPU上執行它,因爲它非常慢。 頂點緩衝區保持不變(當然你可以改變它,達到變形,鑲嵌等效果,但這不是我們的情況)。
所以,你在頂點(或幾何)着色器中進行變換。您必須以某種方式將當前對象的變換(和其他實例屬性)的信息發送給頂點着色器。
一種方法是恆定緩衝區(s)。
假設你有在頂點着色器cbuffer:
cbuffer Instance
{
matrix worldMatrix;
// other instance parameters goes here
};
而且你必須用數據填充它。
繪製每個對象之前,更新緩衝區當前實例數據(每秒對象(多每幀次)):
renderer->SetVertexBuffer(vb); // Set needed geometry
for(int i = 0; i < objects.size(); ++i) // for each object
{
matrix worldMatrix = CalculateWorldMatrix(objects[i]); // prepare data of current object
renderer->UpdateConstantBuffer(&worldMatrix); // Tell shaders about current object's attributes (world matrix in our case)
renderer->Draw(); // or DrawIndexed();
}
對於n
對象必須n
繪製調用和n
緩衝器更新。
另一種方式是實例緩衝區(s)。
您再創建一個頂點緩衝區其中不包含頂點數據,但包含實例數據,準備供着色器使用。
您計算實例數據,一旦創建實例緩衝:
for(int i = 0; i < objects.size(); ++i) // for each object
{
std::vector<Instance> instances;
instances[i].worldMatrix = CalculateWorldMatrix(objects[i]);
// other instance parameters goes here
}
VertexBuffer instanceBuffer = renderer->CreateVertexBuffer(&instances[0], instances.size());
而且你還必須更改輸入的佈局,所以着色器將希望除了頂點數據實例數據。
繪圖時,只需綁定頂點和實例緩衝區。無需更新緩衝區(如果您的三角形尚未移動)。並且不再需要矩陣計算。所以,沒有for
循環,只有一個(!)繪製調用。
renderer->SetVertexBuffers(2, vb, instanceBuffer); // Set needed model data and instances data
renderer->DrawInstanced(); // or DrawIndexedInstanced();
,如果你的對象改變其參數,你只更新例如緩衝:位置,顏色等
當繪製複雜的場景,你大部分時間同時使用:常量緩衝區(對於所有或許多共享的屬性對象:視圖矩陣,投影矩陣等)和實例化(如果有對象具有相同的模型幾何體,但具有不同的屬性),以利用它們的優點。
是的,您需要將「世界」變換矩陣設置爲一個常量緩衝區,並在頂點着色器中使用它來將每個頂點變換到新位置。 – jcoder
我認爲你的方式是正確的。那也是基於每個「對象」的。你可以做一個for循環,併爲每個三角形做這些步驟。 – zdd
@zdd好的,所以一個一個地做這些都沒有什麼大的性能影響?我的印象是,分批處理(如繪製操作)是一種行之有效的方法,並且逐步地做(一次一個)會影響性能/幀速率等等。當然,這是基於我記得的DX9天... –