gpt4 book ai didi

c++ - OpenGL - 从 DisplayList 转换为使用 VBO

转载 作者:行者123 更新时间:2023-11-28 06:39:40 25 4
gpt4 key购买 nike

我有以下全局变量:

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。我该如何转换这段代码?提前致谢。

最佳答案

你很幸运。您的程序结构已经准备就绪。我们甚至可以绕过烦人的基于 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);

元素数组缓冲区同理;您将两个 vector “堆叠”在一起……顺便说一下,这不是很有效。让我们展开这个。首先再次为缓冲区分配内存,但不要将数据复制到其中。由于每个子 vector 可能有不同的长度(尽管如果用于特定的原始绘制模式,它们应该都是相同的大小)首先确定元素的总数(使用 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,这表明您正在使用固定功能管道。我们可以使用它。但随后 VBO 仅在 OpenGL-3 中成为 OpenGL 核心功能(在此之前它作为扩展可用了很长时间)。所以它是 glVertexAttribPointer 加上一个匹配的着色器。为了使转换尽可能小,让我们重新使用 glVertexPointer。主要区别在于,我们在调用 glVertexPointer 之前绑定(bind) 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 被“链接”到顶点数组访问中,我们就可以解除绑定(bind)。数据仍将从 VBO 中获取。

    glBindBuffer(GL_ARRAY_BUFFER, 0);

最后进行绘制调用。请记住,我们在将顶点数据复制到 VBO 时应用了 1 元素偏移量。所以我们只是通过面顶点元素索引。与 VBO 相同的模式:绑定(bind),将整数偏移量转换为指针并将其传递给 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);
}

关于c++ - OpenGL - 从 DisplayList 转换为使用 VBO,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26189645/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com