我有以下全局变量:
vector<vector<unsigned int> > faces;
vector<float> vertexCoords;
unsigned int modelList;在我的初始化中有这样的代码:
glEnableClientState(GL_VERTEX_ARRAY); // vertex array
glVertexPointer(3, GL_FLOAT, 0, &vertexCoords[0]);
modelList = glGenLists(1); // generate display list
glNewList(modelList, GL_COMPILE);
for (unsigned int i = 0; i < faces.size(); i++) {
glBegin(GL_TRIANGLE_STRIP);
for (vector<unsigned int>::iterator it = faces[i].begin();
it != faces[i].end(); it++)
glArrayElement(*it - 1);
glEnd();
}
glEndList(); // End display list.在我的glutDisplayFunc中,我调用:
glCallList(modelList); // Execute display list.现在,我想使用VBO而不是DisplayList。我如何开始转换这段代码?提前谢谢。
发布于 2014-10-04 18:09:49
你真走运。你的程序结构已经准备就绪了。我们甚至可以绕过这种恼人的基于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);元素数组缓冲区也是如此;您将两个向量“堆叠”到彼此的…中顺便说一句,这并不是很有效。让我们展开这个。首先,再次为缓冲区分配内存,但不要将数据复制到其中。因为每个子向量可能有不同的长度(尽管如果用于特定的原始绘制模式,它们应该都是相同的大小),首先确定元素的总数(使用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,这表明您使用的是固定函数管道。我们可以利用这点。但后来VBOs成为OpenGL的核心功能只有OpenGL-3 (在此之前,它是一个很长时间的扩展)。所以它是glVertexAttribPointer加上一个匹配的着色器。为了保持尽可能小的转换,让我们循环使用glVertexPointer。主要区别在于,我们在进行glVertexPointer调用之前绑定了VBO,并将integer-cast-to-a-pointer (which actually may invoke UB for anything other than 0)偏移量传递到数据参数中:
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);
}https://stackoverflow.com/questions/26189645
复制相似问题