C++ 最基本的工作 vbo 示例

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5091570/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 17:21:08  来源:igfitidea点击:

Most basic working vbo example

c++opengl

提问by CurtisJC

I want to know the simplest method for using vbo's in OpenGL... I have tried running a few examples that work but are clouded with all other information thats making it really confusing me... at the moment this is what i have

我想知道在 OpenGL 中使用 vbo 的最简单方法……我试过运行一些有效的例子,但被所有其他信息所笼罩,这让我真的很困惑……目前这就是我所拥有的

GLuint vboId = 0;
const int trisize = (m_tris.size()/2)*3;//m_tris is an index array for verts and normals
GLfloat* vertices = new GLfloat[trisize];
GLfloat* normals = new GLfloat[trisize];

int j=0;
for (int i=0; i<m_tris.size(); i+=2) {

    normals[j] = m_normals[m_tris[i+1]*3];
    vertices[j++] = m_vertices[m_tris[i]*3];
    normals[j] = m_normals[m_tris[i+1]*3+1];
    vertices[j++] = m_vertices[m_tris[i]*3+1];
    normals[j] = m_normals[m_tris[i+1]*3+2];
    vertices[j++] = m_vertices[m_tris[i]*3+2];
} //im pretty sure this loop is right as its what i used before to display mesh correctly without vbo's using glVertex3f

glGenBuffersARB(1, &vboId);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, vboId);
glBufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(vertices)+sizeof(normals), 0, GL_STATIC_DRAW_ARB);
glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0, sizeof(vertices), vertices);
glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, sizeof(vertices), sizeof(normals), normals);

glVertexPointer(sizeof(vertices), GL_FLOAT, 3, 0);
glNormalPointer(GL_FLOAT, 3, (void*)sizeof(vertices));

in a render method i have

在渲染方法中我有

glDrawArrays(GL_TRIANGLES, 0, this->getTriNum()); //0 is the vboId?

also i have a method that runs once...

我也有一个运行一次的方法......

glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);

when i try to run my code i get "EXC_BAD_ACCESS"

当我尝试运行我的代码时,我得到“EXC_BAD_ACCESS”

any advice on what im doing wrong... or a very simple implementation of a vbo would be very helpful

关于我做错了什么的任何建议......或者一个非常简单的 vbo 实现都会非常有帮助

回答by Ned Bingham

What you are doing looks right, except sizeof(vertices) gives you the size of the address, not the size of the array. So, when you call glBufferData, you are allocating 8 bytes and when you call glBufferSubData, you fill those 8 bytes with the first four bytes of the vertices array and then the first four bytes of the normals array. Then, when you go to call glDrawArrays, the first indice causes an array index out of bounds exception (Hence the EXC_BAD_ACCESS).

你在做什么看起来是正确的,除了 sizeof(vertices) 给你地址的大小,而不是数组的大小。因此,当您调用 glBufferData 时,您将分配 8 个字节,而当您调用 glBufferSubData 时,您用顶点数组的前四个字节和法线数组的前四个字节填充这 8 个字节。然后,当您调用 glDrawArrays 时,第一个索引会导致数组索引越界异常(因此是 EXC_BAD_ACCESS)。

// Data
GLuint geometry_array = 0;
GLuint indice_array = 0;

GLfloat *geometry;
GLuint *indices;

You can do this initialization differently, but I interleave all my data into a 32 bytes per vertice array. Any way you choose to set up your array works, as long as you use glVertexPointer, glNormalPointer, and glTexCoordPointer correctly.

您可以以不同的方式执行此初始化,但我将所有数据交错到每个顶点 32 字节的数组中。只要您正确使用 glVertexPointer、glNormalPointer 和 glTexCoordPointer,您选择设置数组的任何方式都可以使用。

// Initialize

geometry = new GLfloat[8*num_geometry];
indices = new GLuint[num_indices];

/* Fill geometry: 0, 1, 2 = vertex_xyz 
 *                3, 4, 5 = normal_xyz
 *                6, 7 = tex_coord_uv
 */

glGenBuffers(1, &geometry_array);
glBindBuffer(GL_ARRAY_BUFFER, geometry_array);
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat)*8*num_geometry, NULL, GL_DYNAMIC_DRAW);
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(GLfloat)*8*num_geometry, geometry);

glGenBuffers(1, &indice_array);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indice_array);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint)*num_indices, NULL, GL_STATIC_DRAW);
glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, sizeof(GLuint)*num_indices, indices);

The render function is five steps. First, bind the buffers so OpenGL knows where to find your geometry and indice data. Second, Enable the various client states for each type of data. If you leave one out, that type of data will not be rendered, and if leave all of them out, your entire object will not be rendered. Third, you have to tell OpenGL where each type of data is contained in your array. In this case the 32 byte geometry data starts with 12 bytes of vertex data, so the starting offset should be zero or NULL. Since each vertex-normal-texcoord combo is 32 bytes, that is the step size. "sizeof(GLfloat)8" says 32 bytes from offset NULL, there will be another vertice xyz group. In the case of the normals, each normal xyz group is 12 bytes after the offset for the vertice xyz group, hence "(float)(sizeof(GLfloat)*3)" as the starting offset. Again, the step size is 32 bytes. Fourth, you have to tell it to draw all of the triangles associated with the indice array. Finally, you should disable the client states, in case you want to use a different method of rendering.

渲染功能是五个步骤。首先,绑定缓冲区,以便 OpenGL 知道在哪里可以找到几何和索引数据。其次,为每种类型的数据启用各种客户端状态。如果省略一个,则不会呈现该类型的数据,如果省略所有这些,则不会呈现整个对象。第三,您必须告诉 OpenGL 数组中包含每种类型的数据。在这种情况下,32 字节几何数据以 12 字节顶点数据开始,因此起始偏移量应为零或 NULL。由于每个 vertex-normal-texcoord 组合是 32 字节,这就是步长。“sizeof(GLfloat) 8”表示距 NULL 偏移量 32 个字节,将有另一个顶点 xyz 组。在法线的情况下,每个法线 xyz 组是顶点 xyz 组偏移后的 12 个字节,因此“(浮动)(sizeof(GLfloat)*3)" 作为起始偏移量。同样,步长是 32 字节。第四,你必须告诉它绘制与索引数组关联的所有三角形。最后,你应该禁用客户端状态,以防您想使用不同的渲染方法。

//Render
// Step 1
glBindBuffer(GL_ARRAY_BUFFER, geometry_array);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indice_array);

// Step 2
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
glEnableClientState(GL_VERTEX_ARRAY);

// Step 3
glTexCoordPointer(3, GL_FLOAT, sizeof(GLfloat)*8, (float*)(sizeof(GLfloat)*5));
glNormalPointer(GL_FLOAT, sizeof(GLfloat)*8, (float*)(sizeof(GLfloat)*3));
glVertexPointer(3, GL_FLOAT, sizeof(GLfloat)*8, NULL);

// Step 4
glDrawElements(GL_TRIANGLES, num_indices, GL_UNSIGNED_INT, NULL);

// Step 5
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);

回答by B?ови?

This is a VBO tutorial with an working example. The example seams to be simple, so you might use it as a reference.

这是一个带有工作示例的 VBO 教程。该示例接缝很简单,因此您可以将其用作参考。

回答by ap-osd

OpenGL - VBO, Shader, VAOhas a simple example which shows the basic sequence of API calls required for VBO based rendering. The example transitions from legacy immediate mode to modern shader based rendering.

OpenGL - VBO、着色器、VAO有一个简单的例子,它显示了基于 VBO 的渲染所需的 API 调用的基本序列。该示例从传统的即时模式过渡到基于现代着色器的渲染。

The example code can be accessed on Github project OpenGl-Renderand runs on both Windows and Linux.

示例代码可以在Github 项目 OpenGl-Render上访问,并在 Windows 和 Linux 上运行。

回答by kvark

sizeof(vertices)and sizeof(normals)give you 4 both, because verticesand normalsare pointers (not arrays). You should use trisize * sizeof(GLfloat)for all glBuffer* commands.

sizeof(vertices)sizeof(normals)给你 4 个,因为verticesnormals是指针(不是数组)。您应该trisize * sizeof(GLfloat)用于所有 glBuffer* 命令。

Also, for glDrawArrays you should specify the number of vertices (=triangles*3).

此外,对于 glDrawArrays,您应该指定顶点数 (=triangles*3)。

Also, the last 2 commands should look like this for your case:

此外,对于您的情况,最后 2 个命令应如下所示:

glVertexPointer(3,GL_FLOAT,0,NULL)
glNormalPointer(GL_FLOAT,0,(void*)(trisize * sizeof(GLfloat)));

Conclusion: you've made many mistakes in a relatively simply piece of code. You didn't read the basic documentation properly. Perhaps, this question should be closed.

结论:您在一段相对简单的代码中犯了很多错误。您没有正确阅读基本文档。也许,这个问题应该结束了。