最基本的工作vbo示例

Cur*_*sJC 18 c++ opengl

我想知道在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));
Run Code Online (Sandbox Code Playgroud)

在我有一个渲染方法

glDrawArrays(GL_TRIANGLES, 0, this->getTriNum()); //0 is the vboId?
Run Code Online (Sandbox Code Playgroud)

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

glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
Run Code Online (Sandbox Code Playgroud)

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

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

Ned*_*ham 24

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

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

GLfloat *geometry;
GLuint *indices;
Run Code Online (Sandbox Code Playgroud)

您可以以不同方式进行此初始化,但我将所有数据交错为每个顶点数组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);
Run Code Online (Sandbox Code Playgroud)

渲染功能是五个步骤.首先,绑定缓冲区,以便OpenGL知道在哪里找到几何和indice数据.其次,为每种类型的数据启用各种客户端状态.如果你留下一个,那么这种类型的数据将不会被渲染,如果将它们全部删除,你的整个对象将不会被渲染.第三,你必须告诉OpenGL你的数组中包含每种类型的数据.在这种情况下,32字节几何数据以12字节的顶点数据开始,因此起始偏移应为零或NULL.由于每个vertex-normal-texcoord组合是32个字节,即步长."sizeof(GLfloat)8"表示从偏移量为NULL的32个字节,将有另一个顶点xyz组.在法线的情况下,每个正常xyz组在顶点xyz组的偏移之后是12个字节,因此"(float)(sizeof(GLfloat)*3)"作为起始偏移.同样,步长为32个字节.第四,你必须告诉它绘制与indice数组相关的所有三角形.最后,如果要使用其他渲染方法,则应禁用客户端状态.

//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);
Run Code Online (Sandbox Code Playgroud)