2016-03-15 32 views
1

根據我的理解,OpenGL中的索引或IBO主要用於減少繪製給定幾何圖形所需的頂點數量。我明白,使用索引緩衝區,OpenGL僅繪製具有給定索引的頂點並跳過任何其他頂點。但是這並不能消除使用紋理的可能性嗎?據我所知,如果你跳過含有索引緩衝區的頂點,它也會跳過它們的頂點屬性?如果我有我的頂點屬性設置是這樣的:索引工作到底如何?

attribute vec4 v_Position; 
attribute vec2 v_TexCoord; 

,然後使用索引緩衝區和glDrawElements(...),不會是消除紋理的使用,還是v_Position得到「重用」?如果他們不這樣做,我如何使用索引緩衝區紋理?

+0

通過索引,您可以選擇要從索引渲染哪個頂點,就好像您已經完成了指定頂點的工作。您可以多次指定一個頂點,在這種情況下,它只會再次渲染(通常作爲不同基元的一部分)。 –

+0

但通過多次指定該頂點,那麼不止一次也會指定其紋理座標?從而使紋理不可能? – calcyss

+0

是的,紋理座標將被指定多次,因爲它是頂點的一部分。不,它不會使紋理不可能,因爲紋理座標是插入到圖元中(除非使用平面着色),並且通常在不同的圖元中重複使用頂點。 –

回答

4

我認爲你誤解了幾個關鍵術語。

「頂點屬性」是定義每個單獨頂點的數據。雖然這些包括紋理座標,但它們還包括位置。事實上,至少如果你不使用固定函數,頂點屬性的含義完全是任意的;它們的含義由頂點着色器如何使用和/或將它們轉發到以下着色器階段來定義。

因此,位置,紋理座標以及任何其他頂點屬性如何轉發給頂點着色器沒有區別。無論索引如何使用(或未使用),它們的解析都完全一樣。

一個例子頂點着色器:

layout(location = 0) in vec4 position; 
layout(location = 1) in vec2 uvAttr; 

out vec2 uv; 

void main() 
{ 
    uv = uvAttr; 
    gl_Position = position; 
} 

和片段着色器的開頭到上述配對:

in vec2 uv; 

頂點着色器的輸出是,你可以看到,基於在頂點屬性上。然後將該輸出內插到原始程序集生成的面上,然後將其發送到片段着色器。原始程序集是索引發揮作用的主要場所:索引決定如何使用頂點着色器輸出來創建實際幾何體。然後,這個幾何被分解成片段,這實際上是影響渲染輸出。來自頂點着色器的輸出成爲片段着色器的輸入。

在頂點着色器之後,頂點屬性停止定義。只有像上面那樣轉發它們,纔可以訪問它們以用於諸如紋理之類的東西。所以,你甚至不會首先使用頂點屬性本身作爲紋理座標:你使用頂點着色器的變量輸出,並在原始程序集/光柵化中進行插值。

「如果你跳過與索引緩衝區的頂點,也跳過了頂點屬性」

是 - 它完全忽略頂點:紋理座標,位置,和其他任何你已經爲該頂點定義。但只有跳過的頂點。其餘部分繼續正常處理,就好像跳過的頂點從不存在一樣。

例如。讓我們說爲了爭論我有5個頂點。如下圖所示,我將這些訂購成蝴蝶結形狀。每個頂點都有一個位置(一個只有x和y的2個分量矢量)和一個單獨的「亮度」作爲顏色。領結的中心頂點只定義一次,但通過索引兩次引用。

Example 1

頂點屬性包括:

  1. [(1,1),0.5],又名[(X,Y),亮度]
  2. [(1,5), 0.5]
  3. [(3,3),0.0]
  4. [(5,5),0.5]
  5. [(5,1),0.5]

索引是:1,2,3,4,5,3。

注意,在這個例子中, 「明亮度」 還不如站在爲您的UV(W)座標。它將被類似地插入,就像一個矢量一樣。正如我之前所說的,頂點屬性的含義是任意的。

現在,既然你問跳過頂點,這裏是輸出會是什麼,如果我改變了指數爲1,2,4:

Example 2

,這將是1,2 ,3:

Example 3

看到這裏的格局? OpenGL關心的是組成它生成的面的頂點,沒有別的。索引僅僅改變這些面的組裝方式(並且可以使它跳過完全計算的不需要的頂點)。它們對所使用的頂點的含義沒有影響,並且會進入臉部。如果跳過黑色頂點#3,則它不會對任何臉部起作用,因爲它不是任何臉部的部分

另外,該標準允許實現在單次繪製調用中重新使用頂點着色器輸出。所以,你應該期望重複使用相同的索引可能不是會導致額外的頂點着色器調用。我說「可能不是」,因爲你的司機實際上做的總是會成爲巫術。

請注意,在此我有意忽略tesselation和幾何着色器。那些超出了這個問題範圍的話題,但是可以對如何處理頂點屬性有一些有趣的含義。我也忽略了這樣一個事實,即頂點的排序可以在着色器中被訪問到一定程度,因此可能會影響輸出。

+0

感謝這個非常徹底的答案:)所以它完全跳過頂點,好吧。現在這意味着,如果我想在每一面繪製具有不同紋理的紋理骰子,那麼我不能使用索引緩衝區來提高性能,因爲紋理座標正在被跳過,因此,立方體不會被正確紋理化? – calcyss

+0

@calcyss這不是我說的。如果跳過頂點,那麼該頂點的紋理座標將被忽略。所有其他人都照常使用。當然,如何組裝頂點(排序+繪製操作)可以影響這些相同頂點屬性如何最終影響輸出,如我的示例所示。但是使用索引不會使紋理座標消失。它只是改變你提供的那些頂點對輸出的貢獻。頂點只對它們所屬的基元有貢獻。如果你跳過的頂點不是給定基元的一部分,跳過它沒有任何影響。 – 2016-03-15 21:20:00

+0

也許我應該用實際的opengl輸出來製作演示圖像。 – 2016-03-15 21:28:46

2

索引緩衝區用於速度。

使用索引緩衝區,頂點緩存用於存儲最近轉換的頂點。在轉換過程中,如果索引所指向的頂點已經在頂點緩存中轉換並可用,否則將被重用,頂點被轉換。如果沒有索引緩衝區,頂點緩存將無法使用,因此頂點總是被轉換。這就是爲什麼命令您的索引最大限度地提高頂點緩存命中率的重要原因。

索引緩衝區也用於減少內存佔用量。

單頂點數據通常很大。例如:存儲位置數據(x,y,z)的單精度浮點數需要12個字節(假設每個浮點數需要4個字節)。如果包含頂點顏色,紋理座標或頂點法線,則此內存需求會變大。

如果您有一個由兩個三角形組成的四邊形,每個頂點只包含位置數據(x,y,z)。如果沒有索引緩衝區,則需要6個頂點(72個字節)來存儲四元組。使用16位索引緩衝區,只需要4個頂點(48個字節)+6個索引(6 * 2個字節= 12個字節)= 60個字節來存儲四元組。使用索引緩衝區時,如果有許多共享頂點,則此內存需求會變小。

+0

感謝您的回答,但我接受威廉姆斯,因爲它是一個更完整:) – calcyss