關於VertexArrayObject(VAO)
前言
VertexArrayObject是從OpenGL3.0以後加入的特性,最近發現我對它的用法有錯誤的見解,在此做個紀錄。內容
最近發現到我對VertexArrayObject的用法有誤,會有錯誤來自於範例很容易是以下void main() { // //... //Set up vao GLuint vao; glGenVertexArrays(1,&vao); glBindVertexArray(vao); //Set up vertex attribute glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,0,0); glVertexAttribPointer(1,3,GL_FLOAT,GL_FALSE,0,(void*)(sizeof(float)*9)); glEnableVertexAttribArray(0); glEnableVertexAttribArray(1); // //... return 0; }
範例鐘用註解分為"Set up vao"與"Set up vertex attribute"兩個部分,在沒有VAO的特性時,只需要做"Set up vertex attribute"的部分,當有VAO的特性時就必須多做"Set up vao"的部分,這一直是我之前的理解,雖然用起來沒問題,但用法卻很容易被誤解。誤解了什麼?誤解的部分是在每個Frame要設定繪圖資料時,會執行glBindVertexArray()與"Set up vertex attribute"的部分,這個想法是錯的!正確的是每個Frame只需執行glBindVertexArray()即可,"Set up vertex attribute"的部分不需再次執行,VAO像是個"紀錄"的物件,當綁過glVertexAttribPointer()與glEnableVertexAttribArray()後會記錄下來,下次只要glBindVertexArray()後就等於做了上次的綁定,這樣可以省下每次設定物件的glVertexAttribPointer()與glEnableVertexAttribArray()。最後來比較一下用法,首先是沒有VAO特性時的用法
//Frame1 glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,0,0); glVertexAttribPointer(1,3,GL_FLOAT,GL_FALSE,0,(void*)(sizeof(float)*9)); glEnableVertexAttribArray(0); glEnableVertexAttribArray(1); //Frame2 glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,0,0); glVertexAttribPointer(1,3,GL_FLOAT,GL_FALSE,0,(void*)(sizeof(float)*9)); glEnableVertexAttribArray(0); glEnableVertexAttribArray(1); //Frame3 glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,0,0); glVertexAttribPointer(1,3,GL_FLOAT,GL_FALSE,0,(void*)(sizeof(float)*9)); glEnableVertexAttribArray(0); glEnableVertexAttribArray(1);
接著是有VAO特性時的用法
//Frame1 glBindVertexArray(vao); glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,0,0); glVertexAttribPointer(1,3,GL_FLOAT,GL_FALSE,0,(void*)(sizeof(float)*9)); glEnableVertexAttribArray(0); glEnableVertexAttribArray(1); //Frame2 glBindVertexArray(vao); //Frame3 glBindVertexArray(vao);
參考資料
OpenGL 3D繪圖互動程式設計,出版者:旗標,作者:賴祐吉, 姚智原, 朱宏國作,ISBN-13:9789863125112
沒有留言:
張貼留言