2014-07-21 36 views
5

我是Open GL的新手,來到這裏清除了我的困惑。我感謝任何幫助!瞭解glVertexAttribPointer?

private int vbo; 
private int ibo; 

vbo = glGenBuffers(); 
ibo = glGenBuffers(); 

glBindBuffer(GL_ARRAY_BUFFER, vbo); 
glBufferData(GL_ARRAY_BUFFER, Util.createFlippedBuffer(vertices), GL_STATIC_DRAW); 

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo); 
glBufferData(GL_ELEMENT_ARRAY_BUFFER, Util.createFlippedBuffer(indices), GL_STATIC_DRAW); 




glEnableVertexAttribArray(0); 
glEnableVertexAttribArray(1); 
//glEnableVertexAttribArray(2); 

//glBindBuffer(GL_ARRAY_BUFFER, vbo); 
glVertexAttribPointer(0, 3, GL_FLOAT, false, Vertex.SIZE * 4, 0); 
glVertexAttribPointer(1, 2, GL_FLOAT, false, Vertex.SIZE * 4, 12); 
//glVertexAttribPointer(2, 3, GL_FLOAT, false, Vertex.SIZE * 4, 20); 

//glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo); 
glDrawElements(GL_TRIANGLES, size, GL_UNSIGNED_INT, 0); 

glDisableVertexAttribArray(0); 
glDisableVertexAttribArray(1); 
//glDisableVertexAttribArray(2); 

頂點着色器的代碼看起來像

#version 330 

layout (location = 0) in vec3 position; 
layout (location = 1) in vec2 texCoord; 

out vec2 texCoord0; 

uniform mat4 transform; 

void main() 
{ 
    gl_Position = transform * vec4(position, 1.0); 
    texCoord0 = texCoord; 
} 

所以,這裏是我的理解。 glVertexAttribPointer的目的是定義頂點緩衝區對象中的數據格式。所以,在VBO如下

buffer.put(vertices[i].getPos().getX()); 
buffer.put(vertices[i].getPos().getY()); 
buffer.put(vertices[i].getPos().getZ()); 
buffer.put(vertices[i].getTexCoord().getX()); 
buffer.put(vertices[i].getTexCoord().getY()); 
buffer.put(vertices[i].getNormal().getX()); 
buffer.put(vertices[i].getNormal().getY()); 
buffer.put(vertices[i].getNormal().getZ()); 

所以,我們有兩個glVertexAttribPointer線,因爲我們在頂點着色器定義的兩個變量是存儲數據。所以基本上我們正在定義這兩個變量指向什麼。因此,第一個glVertexAttribPointer定義第一個變量「position」是一個三個座標爲float的頂點。第二個glVertexAttribPointer定義第二個變量「texCoord」,它是一對紋理座標,每個紋理座標都是浮點型座標。所以,如果我的理解到目前爲止是正確的,那麼我假設我們首先需要綁定頂點緩衝區對象,但即使在註釋掉這一行之後,即使在註釋掉這一行之後也不例外。

它仍然有效。我很困惑。它如何知道我們正在討論哪個緩衝區對象,因爲有兩個vbos?

我很感激任何幫助。非常感謝!

+1

沒有兩個VBO。有一個VBO和一個IBO。他們都可以(並且必須)同時保持約束。 – fintelia

+0

那麼這是否意味着如果有兩個VBO,那麼我們需要顯式綁定它,但既然只有一個,那麼默認綁定它? – user3256520

+2

@fintelia:其實沒有。在調用'gl ... Pointer'後,您可以安全地解除綁定VBO,在調用'gl ... Pointer'函數時與VBO綁定的關聯不會丟失。 – datenwolf

回答

14

@datenwolf已經涵蓋了上面評論中的關鍵方面。詳細說明一下:

你這樣做不是必須在調用glDrawElements()之前再次綁定GL_ARRAY_BUFFER。重要的是,當您爲該屬性調用glVertexAttribPointer()時,要從中獲取給定屬性的緩衝區將被綁定。

以圖片的最佳方法是,當你做這樣的判斷:

glVertexAttribPointer(0, 3, GL_FLOAT, false, Vertex.SIZE * 4, 0); 

你指定要告訴OpenGL從哪裏得到的屬性0的數據(第一個參數)所需的所有狀態,以及如何閱讀它。大多數國家由參數直接給出:

  • 它有3個組成部分
  • 組件是浮點值
  • 頂點具有的20個字節的步幅讀...
  • ...並開始緩衝

的0字節但是,當你撥打電話有狀態的附加隱含一塊也存儲離開屬性0:

  • 將數據從當前綁定到GL_ARRAY_BUFFER

換句話說緩衝器讀出,與每個屬性相關聯的所述狀態包括所述緩衝器中的屬性數據被從源的ID。這可以是多個/所有屬性的相同緩衝區,也可以是每個屬性的不同緩衝區。

請注意,對GL_ELEMENT_ARRAY_BUFFER也是如此。在撥打電話glDrawElements()時需要綁定該號碼。雖然看起來有些不一致,但這是必要的,因爲索引數組沒有相當於glVertexAttribPointer()。 API可能已被定義爲具有這種呼叫,但是......它不是。原因很可能是它沒有必要,因爲只有一個索引數組可用於繪圖調用,而多個頂點緩衝區可以使用。

+0

總之我已經綁定了這兩個緩衝區.. glBindBuffer(GL_ARRAY_BUFFER,vbo); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,ibo);因此我不需要重新綁定......正確? – user3256520

+0

當然,你不需要重新綁定已綁定的緩衝區。我在回答中想要說明的是哪些緩衝區必須針對哪些呼叫進行綁定。 –