2013-04-23 56 views
5

我有一個我一直在編寫的C++ DirectX 11渲染器。在DX10/DX11中使用多個頂點緩衝區

我已經編寫了一個COLLADA 1.4.1加載程序來導入COLLADA數據以用於支持骨骼動畫。

我現在正在驗證加載器(並且之前我在之前使用不同技術編寫的另一個渲染器中支持COLLADA),並且遇到了與DX10/11匹配COLLADA的問題。

我有數據的3個獨立的頂點緩衝器:

獨特頂點位置的頂點緩衝器。 Unique法線的頂點緩衝區。 唯一紋理座標的頂點緩衝區。

這些頂點緩衝器包含不同陣列長度(位置具有2910層的元件,法線具有比9000以上,和紋理座標具有大致3200)

COLLADA提供一個三角形列表這使我的索引到每個這些陣列的對於一個給定的三角形(開始時是冗長而奇怪的,但最終一旦你使用它就變得簡單了)。

知道DX10/11支持多個頂點緩衝區我想填充DX10/11索引這些指數可以是不同的f或三角形的給定點。

換句話說,我可以設置三個頂點緩衝區,設置正確的輸入佈局,然後在索引緩衝區我把相當於:

l_aIndexBuffer[ NumberOfTriangles * 3 ] 

for(i = 0; i < NumberOfTriangles; i++) 
{ 
    l_aIndexBufferData.add(triangle[i].Point1.PositionIndex) 
    l_aIndexBufferData.add(triangle[i].Point1.NormalIndex) 
    l_aIndexBufferData.add(triangle[i].Point1.TextureCoordinateIndex) 
} 

文檔使用多個頂點緩衝區中關於DirectX似乎沒有提供任何有關這將如何影響索引緩衝區的信息(稍後會詳細介紹)。

運行代碼時會產生奇怪的渲染結果,我可以看到我正在間斷地正確繪製的網格物體(奇怪的多邊形但約三分之一的點在正確的位置 - 提示 - 提示)

我想我在這裏(昨天)搞砸了我的數據或我的指數,所以我刻意驗證了這一切,所以我想我正在擰我的輸入或其他東西。我通過使用正常和紋理緩衝區的值來替代設置像素着色器使用的顏色值來消除這種情況,顏色是正確的,所以我沒有遇到填充問題。

最後我得出的結論是DX10/11必須期望以不同的方式排列的數據,所以我嘗試存儲在這個時尚指數:

indices.add(Point1Position index) 
indices.add(Point2Position index) 
indices.add(Point3Position index) 
indices.add(Point1Normal index) 
indices.add(Point2Normal index) 
indices.add(Point3Normal index) 
indices.add(Point1TexCoord index) 
indices.add(Point2TexCoord index) 
indices.add(Point3TexCoord index) 

奇怪的是,這產生了呈現網狀看起來是1/3正確 - 提示 - 提示。

然後我推測,也許DX10/DX11想要存儲「通過頂點緩衝區」的索引,這意味着我將首先添加所有三角形的所有位置索引,然後是所有三角形的所有正常索引,然後是所有紋理協調所有三角形的索引。

這產生了另一個1/3正確的(看)網格。

這讓我覺得 - 當然,DX10/11不會爲您提供從多個頂點緩衝區進行流式處理的能力,然後實際上每個三角形點只有一個索引?

只有在位置的頂點緩衝區中包含索引纔會生成正確渲染的網格,但不幸會使用錯誤的法線和紋理座標。

看起來,將正常和紋理座標索引放入索引緩衝區會導致錯誤地繪製正確渲染的網格。

這是預期的行爲?

多個頂點緩衝區 - 一個索引緩衝區和索引緩衝區只能有一個三角形點的單個索引?

這對我來說確實沒有意義。

幫助!

+0

哦,我的上帝,我從來不知道你可以用這種方式分割你的頂點數據! – Lucius 2013-04-23 18:29:38

+0

不久之前,我遇到了同樣的問題,並在搜索解決方案時遇到了[此答案](http://stackoverflow.com/a/2305383/1798046)。這真的幫助我更深入地瞭解問題。我也可能幫助你。 – Krienie 2013-07-20 19:48:26

回答

2

附帶在我腦海的第一件事:

支持計算着色器(等同於幾乎所有的DirectX 10及更高版本)的所有硬件還支持ByteAddressBuffer S和大部分支持StructuredBuffer秒。因此,您可以將數組綁定爲SRV s,並可隨機訪問着色器中的任何元素。

像這樣(沒有測試,只是僞代碼):

// Indices passed as vertex buffer to shader 
// Think of them as of "references" to real data 
struct VS_INPUT 
{ 
    uint posidx; 
    uint noridx; 
    uint texidx; 
} 

// The real vertex data 
// You pass it as structured buffers (similar to textures) 
StructuredBuffer<float3> pos : register (t0); 
StructuredBuffer<float3> nor : register (t1); 
StructuredBuffer<float2> tex : register (t2); 


VS_OUTPUT main(VS_INPUT indices) 
{ 
    // in shader you read data for current vertex 
    float3 pos = pos[indices.posidx]; 
    float3 nor = nor[indices.noridx]; 
    float2 tex = tex[indices.texidx]; 

    // here you do something 
} 

我們稱之爲 「計算着色器的方式」。您必須使用DirectX 11 API。

你也可以用同樣的方式綁定你的索引,並在着色器中做一些魔術。在這種情況下,你需要找出當前的索引ID。可能你可以從SV_VertexId中獲取它。

也許你可以解決這些緩衝區,並以某種方式綁定數據(DirectX 9兼容紋理採樣!O_o)。

希望它有幫助!

+0

這是一個有趣的解決方法,我將不得不嘗試一下。我希望看到在每個網格基礎上設置它的性能方面。謝謝 – WTH 2013-04-23 19:45:35