3D Computer Grapihcs Using OpenGL - 05 EBO
本节将采用两种方法绘制两个三角形。
先看第一种方法的代码
MyGlWindow.cpp
1 #include <gl\glew.h> 2 #include "MyGlWindow.h" 3 4 void MyGlWindow::initializeGL() 5 { 6 glewInit(); 7 8 GLfloat verts[] = 9 { 10 +0.0f, +0.0f, 11 +1.0f, +1.0f, 12 -1.0f, +1.0f, 13 14 +0.0f, +0.0f, 15 -1.0f, -1.0f, 16 +1.0f, -1.0f, 17 }; 18 GLuint myBufferID; 19 glGenBuffers(1, &myBufferID); 20 glBindBuffer(GL_ARRAY_BUFFER, myBufferID); 21 glBufferData(GL_ARRAY_BUFFER, sizeof(verts), verts, GL_STATIC_DRAW); 22 glEnableVertexAttribArray(0); 23 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0); 24 } 25 26 void MyGlWindow::paintGL() 27 { 28 glViewport(0, 0, width(), height()); 29 glDrawArrays(GL_TRIANGLES, 0, 6); 30 }
和上一节的代码很相似,区别是verts数组增加了6个元素(能额外表示3个顶点),另外glDrawArrays()函数的最后一个参数变成了6,表示绘制六个顶点。这样当然就可以绘制2个三角形了。
但是这种方法造成了一个浪费,代码中可以看到两次出现了(0.0,0.0)点。
EBO
OpenGL允许我们提供一个索引数组用来指定三角形的顶点组成顺序。这个数组通常被称为EBO。
看第二种绘制三角形的方法:
1 #include <gl\glew.h> 2 #include "MyGlWindow.h" 3 4 void MyGlWindow::initializeGL() 5 { 6 glewInit(); 7 8 GLfloat verts[] = 9 { 10 +0.0f, +0.0f, //0 11 +1.0f, +1.0f, //1 12 -1.0f, +1.0f, //2 13 -1.0f, -1.0f, //3 14 +1.0f, -1.0f, //4 15 }; 16 GLuint vertexBufferID; 17 glGenBuffers(1, &vertexBufferID); 18 glBindBuffer(GL_ARRAY_BUFFER, vertexBufferID); 19 glBufferData(GL_ARRAY_BUFFER, sizeof(verts), verts, GL_STATIC_DRAW); 20 glEnableVertexAttribArray(0); 21 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0); 22 23 GLushort indices[] = 24 { 25 0,1,2, 26 0,3,4, 27 }; 28 GLuint indexBufferID; 29 glGenBuffers(1, &indexBufferID); 30 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBufferID); 31 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW); 32 } 33 34 void MyGlWindow::paintGL() 35 { 36 glViewport(0, 0, width(), height()); 37 glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0); 38 }
*注:为了区分两个Buffer,我们这里把之前的myBufferID改名为vertexBufferID
23-31行和顶点位置设置代码(8-19行)非常相似。
28-29行创建了另外一个BufferObject- indexBuffer
30行把indexBuffer绑定到GL_ELEMENT_ARRAY_BUFFER绑定点上
31行对其填充数据,其数据内容是一个GLushort类型的数组,每三个元素表示一个三角形的顶点索引,索引值是相对于verts数组来说的(参考verts中的注释)。这里使用GLushort而不使用GLint的原因是GLushort给了我们更大的数据存储量,索引始终都是正整数,所以使用unsigned类型更合理。
在paintGL函数中,这次不使用glDrawArrays函数了,改用glDrawElements()函数绘制
第二个参数表示6个顶点
第三个参数表示indices数组的类型
第四个参数表示偏移值
使用EBO在本例中仅节约了一个顶点位置数据,但是在复杂的模型中,会节约非常多的数据。