最基本的工作vbo示例 [英] Most basic working vbo example

查看:147
本文介绍了最基本的工作vbo示例的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想知道在OpenGL中使用vbo的最简单的方法...我已经尝试运行几个例子,但工作,但与所有其他信息,使它真的让我混淆我的...这是什么我有

  GLuint vboId = 0; 
const int trisize =(m_tris.size()/ 2)* 3; // m_tris是一个用于verts和法线的索引数组
GLfloat * vertices = new GLfloat [trisize];
GLfloat * normals = new GLfloat [trisize];

int j = 0;
for(int i = 0; i
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我肯定这个循环是正确的,因为我之前使用显示网格正确无vbo的使用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));



在渲染方法中我有

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

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

  glEnableClientState(GL_VERTEX_ARRAY); 
glEnableClientState(GL_NORMAL_ARRAY);

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


$

解决方案

任何建议对于什么做错了...或者一个非常简单的vbo的实现将是非常有用的

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

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

GLfloat * geometry;
GLuint * indices;

你可以不同地做这个初始化,但是我把所有的数据插入每个顶点数组32字节。只要正确使用glVertexPointer,glNormalPointer和glTexCoordPointer,您就可以选择设置数组的任何方式。

  //初始化

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

/ *填充几何: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);

渲染函数有五个步骤。首先,绑定缓冲区,使OpenGL知道在哪里找到您的几何和indice数据。第二,为每种类型的数据启用各种客户端状态。如果你留下一个,那种类型的数据将不会被渲染,如果将它们全部删除,整个对象将不会被渲染。第三,你必须告诉OpenGL,每种类型的数据都包含在你的数组中。在这种情况下,32字节几何数据以12字节的顶点数据开始,因此起始偏移应为零或NULL。由于每个顶点 - 正常 - 交织组合是32字节,这是步长。 sizeof(GLfloat) 8表示32个字节从偏移NULL,将有另一个顶点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);

//第2步
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
glEnableClientState(GL_VERTEX_ARRAY);

//步骤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);

//第4步
glDrawElements(GL_TRIANGLES,num_indices,GL_UNSIGNED_INT,NULL);

//第5步
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);


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

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"

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

解决方案

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).

// 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.

// 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.

//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);

这篇关于最基本的工作vbo示例的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆