你很幸运。您的程序结构已经准备就绪。我们甚至可以绕过烦人的基于 1 的索引。
首先创建一个VBO:
GLuint vbo_id;
GLuint eabo_id; /* EIB = Element Array Buffer */
size_t eabo_n_elements;
void make_vbo()
{
GLuint genbuf_ids;
glGenBuffers(2, genbuf_ids);
vbo_id = genbuf_ids[0];
eabo_id = genbuf_ids[1];
glBindBuffer(GL_ARRAY_BUFFER, vbo_id);
为数据分配空间,任意复制顶点数据到缓冲区。由于您的顶点元素索引数组被移动了一个,我们再分配一个顶点并使用偏移量将数据复制到其中(我们也可以使用GL_ARB_draw_elements_base_vertex
扩展,但我想以这种方式显示它:
glBufferData(
GL_ARRAY_BUFFER,
(vertexCoords.size() + 3)*sizeof(vertexCoords[0]),
NULL,
GL_STATIC_DRAW );
glBufferSubData(
GL_ARRAY_BUFFER,
sizeof(vertexCoords[0])*3, /* offset by 1 vertex */
(vertexCoords.size())*sizeof(vertexCoords[0],
&vertexCoords[0]);
glBindBuffer(GL_ARRAY_BUFFER, 0);
元素数组缓冲区也是如此;您将两个向量“堆叠”在一起……顺便说一句,这不是很有效。让我们展开这个。首先再次为 tha 缓冲区分配内存,但不要将数据复制到其中。由于每个子向量可能有不同的长度(尽管如果用于特定的图元绘制模式,它们应该都是相同的大小)首先确定元素的总数(使用 C++11 特性auto
来节省一些输入,这样我们就可以使用迭代器);稍后我们需要知道该数字来绘制它们:
eabo_n_elements = 0;
for(auto i = faces.begin(); i != faces.end(); i++) {
eabo_n_elements += i.size();
}
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, eabo_id);
glBufferData(
GL_ELEMENT_ARRAY_BUFFER,
sizeof(faces[0][0]) * eabo_n_elements,
NULL,
GL_STATIC_DRAW );
将人脸数据展开复制到 EAB
size_t offset = 0;
for(auto i = faces.begin(); i != faces.end(); i++) {
size_t const len = i.size() * sizeof(i[0]);
glBufferSubData(
GL_ELEMENT_ARRAY_BUFFER,
offset,
len,
&i[0] );
offset += len;
}
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
}
现在我们可以画出来了。从技术上讲,我们可以使用 VAO(对于 OpenGL-4,我们必须有一个),但让我们放心。绘制 VBO 与从客户端顶点数组绘制非常相似。现在您使用glVertexPointer
which 表示您正在使用固定功能管道。我们可以使用它。但后来 VBO 成为 OpenGL 的核心功能,只有 OpenGL-3 (在此之前它作为扩展可用很长时间)。所以它glVertexAttribPointer
加上一个匹配的着色器。为了使过渡尽可能小,让我们回收您对glVertexPointer
. 主要区别在于,我们在glVertexPointer
调用之前绑定了 VBO,并将整数转换为指针(实际上可能为 0 以外的任何值调用 UB)偏移量传递给数据参数:
void draw_vbo()
{
glEnableClientState(GL_VERTEX_ARRAY);
glBindBuffer(GL_ARRAY_BUFFER, vbo_id);
glVertexPointer(3, GL_FLOAT, 0, (void*)0);
一旦 VBO 被“链接”到顶点数组访问中,我们就可以取消绑定它。数据仍将从 VBO 获取。
glBindBuffer(GL_ARRAY_BUFFER, 0);
最后进行抽签。请记住,我们在将顶点数据复制到 VBO 时应用了 1 元素偏移量。所以我们只通过面顶点元素索引。与 VBO 相同的模式:绑定,将整数偏移量转换为指针并将其传递给 glDrawElements
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, eabo_id);
glDrawElements(GL_TRIANGLE_STRIP, eabo_n_elements, GL_UNSIGNED_INT, (void*)0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
}