2013-08-29 41 views
2

我是DirectX的新手,我對理解我認爲的一些基礎知識有點問題。假設我有10個三角形,並且我想以不同的速率旋轉它們中的每一個,以便隨着時間的推移它們會「旋轉」。D3D11:旋轉多個三角形

到目前爲止,我有我的三角形出現,但我不太明白如何單獨旋轉它們。從我可以告訴我會做每三角這樣的事情?

  1. 計算旋轉矩陣,並將其設置爲常量數據。
  2. 用常數數據更新常量緩衝區。
  3. 用上述數據更新頂點着色器。
  4. DrawPrimitives,使我的三角形出現在根據步驟#1中的矩陣旋轉的屏幕上。 (通過頂點着色器)

是嗎?它似乎來來回回。我是否應該依靠頂點着色器來進行變換,或者有什麼不同的方法來在每個「對象」(三角形)的基礎上應用旋轉?

我很抱歉,如果我的問題沒有道理,就像我說的,我認爲我有一個概念/理解問題。

+0

是的,您需要將「世界」變換矩陣設置爲一個常量緩衝區,並在頂點着色器中使用它來將每個頂點變換到新位置。 – jcoder

+0

我認爲你的方式是正確的。那也是基於每個「對象」的。你可以做一個for循環,併爲每個三角形做這些步驟。 – zdd

+0

@zdd好的,所以一個一個地做這些都沒有什麼大的性能影響?我的印象是,分批處理(如繪製操作)是一種行之有效的方法,並且逐步地做(一次一個)會影響性能/幀速率等等。當然,這是基於我記得的DX9天... –

回答

2

基本上,你有一些模型(在你的情況三角形)。

模型是頂點數組:

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(); 

,如果你的對象改變其參數,你只更新例如緩衝:位置,顏色等

當繪製複雜的場景,你大部分時間同時使用:常量緩衝區(對於所有或許多共享的屬性對象:視圖矩陣,投影矩陣等)和實例化(如果有對象具有相同的模型幾何體,但具有不同的屬性),以利用它們的優點。

+0

你在這裏介紹的兩種方法的主要區別是什麼,即優缺點? –

+0

進入UpdateBuffer的代碼是什麼?這似乎是知道的一件好事。 –