OpenGL VAO, VBO 使用簡介


參照代碼樣例:

 1 // This function takes in a vertex, color, index and type array 
 2 // And does the initialization for an object.  
 3 // The partner function below it draws the object 
 4 void initobject(GLuint object, GLfloat * vert, GLint sizevert, GLfloat * col, GLint sizecol, GLubyte * inds, GLint sizeind, GLenum type){
 5     int offset = object * numperobj;
 6     // make the new GL_ARRAY_BUFFER active
 7     // 將VAO綁定到當前的context上
 8     glBindVertexArray(VAOs[object]);
 9 
10 
11     // 將顏色數據綁定到VBO上
12     glBindBuffer(GL_ARRAY_BUFFER, buffers[Colors+offset]) ; 
13     glBufferData(GL_ARRAY_BUFFER, sizecol, col,GL_STATIC_DRAW);
14     // 用於關聯 shader (location = 1) color
15     glEnableVertexAttribArray(1);
16     glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), 0);
17 
18 
19     // 將頂點數據綁定到VBO上20     // 將這個buffer關聯到 GL_ARRAY_BUFFER
21     glBindBuffer(GL_ARRAY_BUFFER, buffers[Vertices+offset]);
22     // 將數據傳送到這個buffer 
23     glBufferData(GL_ARRAY_BUFFER, sizevert, vert,GL_STATIC_DRAW);
24     // 用於關聯 shader (location = 0) vertex
25     glEnableVertexAttribArray(0);
27     glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), 0);
28 
29    // 將三角形序列綁定到VBO上
30     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffers[Elements+offset]) ; 
31     glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeind, inds,GL_STATIC_DRAW);
32     PrimType[object] = type;
33     NumElems[object] = sizeind;
34     // Prevent further modification of this VAO by unbinding it
35     glBindVertexArray(0);
36 }
37 
38 void drawobject(GLuint object) {
39     glBindVertexArray(VAOs[object]);
40     glDrawElements(PrimType[object], NumElems[object], GL_UNSIGNED_BYTE, 0); 
41     glBindVertexArray(0);
42 }

 

程序的部分相關初始化代碼:

 1 // Now create the buffer objects to be used in the scene later
 2 // Remember to delete all the VAOs and VBOs when the program terminates!
 3 glGenVertexArrays(numobjects, VAOs);
 4 glGenBuffers(numperobj*numobjects, buffers);
 5 
 6 // Initialize the floors
 7 initobject(FLOOR, (GLfloat *) floorverts, sizeof(floorverts), (GLfloat *) floorcol, sizeof (floorcol), (GLubyte *) floorinds, sizeof (floorinds), GL_TRIANGLES) ; 
 8 initobject(FLOOR2, (GLfloat *) floorverts2, sizeof(floorverts2), (GLfloat *) floorcol2, sizeof (floorcol2), (GLubyte *) floorinds2, sizeof (floorinds2), GL_TRIANGLES) ;
 9 

 

vertex shader

 1 # version 330 core
 2 // Do not modify the above version directive to anything older than 330, as
 3 // modern OpenGL will not work properly due to it not being core at the time.
 4 
 5 // Shader inputs
 6 layout (location = 0) in vec3 position;
 7 layout (location = 1) in vec3 color;
 8 
 9 // Shader outputs, if any
10 out vec3 Color;
11 
12 // Uniform variables
13 uniform mat4 modelview;
14 uniform mat4 projection;
15 
16 void main() {
17     gl_Position = projection * modelview * vec4(position, 1.0f);
18     Color = color; // Just forward this color to the fragment shader
19 }

 

 


 

OpenGL有着許多令人捉摸不着的概念,其中比較重要的便是Vertex Array Object 以及 Vertex Buffer Object。為了理解這兩個概念,還需要注意另一個叫做context(上下文)的概念,因為OpenGL用C寫的,沒有C++那種面向對象的特性,因此在遇到涉及狀態保存的時候(比如為當前物體(而不是其他什么物體)賦值),就需要用context來儲存臨時狀態(比如“我現在編輯的對象是物體1,而不是物體2”)。

 

牢記context這個概念的存在,讓我們看看如何使用代碼創建一個物體並顯示。

 

1. 創建物體

先看initobject函數(見上文),可以看到函數內部代碼大致分成了4塊,我們分別解釋。

代碼就不重復復制了。

offset那個變量不用管,那個是用於區分當前初始化的是第一個物體還是第二個物體的,你們可以默認這個程序只有一個物體然后忽視掉代碼中的所有offset。

 

(1). 將VAO綁定到context

可以簡單的將VAO理解為一個我們將要顯示的物體。這個物體有許多屬性,比如所有頂點,顏色,三角形的頂點序列。而這些屬性都又由VBO來表示。

將其綁定到context這一動作表示:我接下來操作的對象都是1號物體了。

 

(2). 將顏色綁定到VBO上

glBindBuffer(GL_ARRAY_BUFFER, buffers[Colors+offset]) ; 
glBufferData(GL_ARRAY_BUFFER, sizecol, col, GL_STATIC_DRAW);

這兩行代碼應該一起使用,可以將其作用理解為:將col這個數組的數據綁定到buffers[colors] (此處忽略了offset)

也就是說,我們將顏色數據連接到一個VBO上,這樣以后OpenGL便可以通過這個VBO讀取這個顏色數據。

 

由於我們需要在shader中訪問顏色數據,因此我們還需要將其暴露給shader,通過以下代碼。

// 用於關聯 shader (location = 1) color
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), 0);

以上代碼說明shader中的 1 號(可以是任何未使用過的數字) location 處的數據將是我們剛剛綁定的顏色信息

 

(3). 將頂點綁定到VBO上

這一步與綁定顏色的做法重復,先是將我們的頂點數據綁定到一個VBO,然后將其暴露給shader的0號位置。

 

(4). 將三角形序列綁定到VBO

這里就不解釋三角形序列是什么了,這個名字我可能叫錯了。。。總之這個數據定義了那些頂點用來組成三角形。

綁定的過程與上面一樣,不過由於shader中並不需要這個數據,因此我們不用將其暴露給shader

 


 

 

2. 顯示物體

創建完物體,我們可以顯示出來了

在丟給glutDisplayFunc的那個display函數中加上以下代碼

1 glBindVertexArray(VAOs[object]);
2 glDrawElements(PrimType[object], NumElems[object], GL_UNSIGNED_BYTE, 0); 
3 glBindVertexArray(0);

第一行說明我們現在開始操作物體1

第二行讓OpenGL畫出物體1(為什么不是物體2?因為我們上一步已經說明了現在的context是物體1)

第三行解綁物體1

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM