參照代碼樣例:數組
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 shaderui
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」)。this
牢記context這個概念的存在,讓咱們看看如何使用代碼建立一個物體並顯示。spa
先看initobject函數(見上文),能夠看到函數內部代碼大體分紅了4塊,咱們分別解釋。code
代碼就不重複複製了。orm
offset那個變量不用管,那個是用於區分當前初始化的是第一個物體仍是第二個物體的,大家能夠默認這個程序只有一個物體而後忽視掉代碼中的全部offset。對象
(1). 將VAO綁定到contextblog
能夠簡單的將VAO理解爲一個咱們將要顯示的物體。這個物體有許多屬性,好比全部頂點,顏色,三角形的頂點序列。而這些屬性都又由VBO來表示。input
將其綁定到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
建立完物體,咱們能夠顯示出來了
在丟給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