openGL 3.3-使用glDrawArrays/glDrawElements的VBO绘图
openGL 3.3 - VBO drawing with glDrawArrays / glDrawElements
我将VC++2010与GLFW3和GLEW一起用于openGL。我已经制作了一个OBJ加载器来加载三角网格。在某个时刻,我在VBOMesh2对象中填充以下数组。
GLfloat *vertices;
GLfloat *normals;
GLuint *indices;
因此,我得到了我用于VBO:的数据
- 顶点:顶点=[v0x,v0y,v0z,v1x,v1y,v1z,…]
- (已排序)法线:法线=[n0x,n0y,n0z,n1x,n1y,n1z,…]
- 索引:inices={face0i0,face0i1,face0i2,face1i0,face1i1,face1i2,…]
下一步是使用VBOMesh2对象中的init()-method绑定Buffers。vertexVBOID、normalsVBOID和indexVBOID是GLuint。
void VBOMesh2::init(void)
{
vertexVBOID = 0;
glGenBuffers(1, &vertexVBOID);
glBindBuffer(GL_ARRAY_BUFFER, vertexVBOID);
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat)*numFaces*3*3, vertices, GL_STATIC_DRAW);
normalsVBOID = 0;
glGenBuffers(1, &normalsVBOID);
glBindBuffer(GL_ARRAY_BUFFER, normalsVBOID);
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat)*numFaces*3*3, normals, GL_STATIC_DRAW);
indexVBOID = 0;
glGenBuffers(1, &indexVBOID);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexVBOID);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint)*numFaces*3, indices, GL_STATIC_DRAW);
}
好的。。。我用画画
void VBOMesh2::draw(void)
{
glEnableClientState(GL_VERTEX_ARRAY);
glBindBuffer(GL_ARRAY_BUFFER, vertexVBOID);
glVertexPointer(3, GL_FLOAT, sizeof(float)*3, 0);
glEnableClientState(GL_NORMAL_ARRAY);
glBindBuffer(GL_ARRAY_BUFFER, normalsVBOID);
glNormalPointer(GL_FLOAT, sizeof(float)*3, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexVBOID);
glPushMatrix();
glTranslatef(x, y, z);
glRotatef(rx, 1, 0, 0);
glRotatef(ry, 0, 1, 0);
glRotatef(rz, 0, 0, 1);
glDrawArrays(GL_TRIANGLES, indices[0], numIndices);
glPopMatrix();
glDisableClientState(GL_NORMAL_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
}
我可以用加载网格
OBJLoader objLoader;
MeshData meshData;
objLoader.loadFile("temp/quad_smooth.obj");
meshData = objLoader.getMeshData();
VBOMesh2 tmpMesh(meshData);
并用绘制(在openGL循环中)
tmpMesh.draw();
我得到以下结果:
一个四元
太棒了!
现在我想,让我们用以下代码画500个四边形:
OBJLoader objLoader;
MeshData meshData;
objLoader.loadFile("temp/quad_smooth.obj");
meshData = objLoader.getMeshData();
for(int i = 0; i < 500; i++)
{
VBOMesh2 tmpMesh(meshData);
meshes.push_back(tmpMesh);
meshes[i].init();
// Do stuff for position and rotation like meshes[i].setX(x); and so on
}
在openGL循环中,我做:
for(int i = 0; i < meshes.size(); i++)
{
meshes[i].draw();
}
顺便说一句。网格是一个向量:
vector<VBOMesh2> meshes;
我得到了以下结果:
500 Quads
哦,不!!!
现在我不知道为什么我的网格(不是全部,而是一些)被破坏了。。。或者我做错了什么。。。。该代码可以在没有任何可视化错误的情况下渲染一个四边形,但当我使用相同的meshData创建500个四边形时(来自oneQuad的相同数据),我得到了损坏的四边形。。。。
而不是使用
glDrawArrays(GL_TRIANGLES, indices[0], numIndices);
我试过
glDrawElements(GL_TRIANGLES, numIndices, GL_UNSIGNED_INT, 0);
为此,我用其他方法填充了数组的顶点、法线和索引(如果需要,我可以发布),但我遇到了同样的问题。。。我可以画一个Quad而没有错误,但当我试图画500个Quad时,我得到了访问违规0x000005。
Btw。我更新了我的显卡驱动程序(但问题仍然存在)
有人能给我一个提示吗?
不要使用std::vector<VBOMesh2>
,因为矢量对值进行运算。如果您已经实现了~VBOMesh2
来删除数组,那么您可能正在绘制悬挂指针(即indices[0]
)。请使用VBOMesh2
或std::vector<VBOMesh2*>
的简单数组。
glDrawArrays(GL_TRIANGLES, indices[0], numIndices);
这不是绘制索引网格的方法。第二个参数是前面用glVertexPointer
和glNormalPointer
绑定的数组的偏移量。在您的情况下,它应该始终为0。
你需要决定是否要使用索引网格,你的问题还不清楚。如果需要,则需要使用glDrawElements
。但是,顶点和法线数据的大小不正确。但我怀疑你知道这一点。看起来有点像是您第一次实现了索引网格的代码,当它不起作用时,您尝试将其转换为非索引网格。
- OpenGL VBO Indexing ( How to compute Index Array)
- QT QOpenGLWidget:如何在不使用数据块复制的情况下修改VBO中的单个顶点值?
- 将单个未唱的 int 发送到 VBO
- glDrawElements GL 错误类型 = 0x824c,严重性 = 0x9146,消息 = GL_INVALID
- VBO必须在VAO之后绑定
- 使用 glDrawElements 绘制一个 std::vector
- GLSL C++ glVertexAttribPointer & glDrawElements return GL_INVALID_OPERATION
- 如何在顶点着色器中使用VBO数据作为位置数据,在片段着色器中使用统一数据作为颜色数据
- OpenGL:第二个VBO破坏了第一个VBO
- 如何告诉 VBO 处理给定的数据?(布料模拟)
- 我们是否需要序列化 VAO 和 VBO
- OpenGL VAO VBO resize
- glVertexAttribDivisor 存储在哪里 - VAO、VBO 或全局状态?
- glDrawElements成功,但glDrawElementsInstance失败并GL_INVALID_OPERAT
- 将VAO与glDrawElements一起使用
- 将 OpenGL VBO 与自定义类/数据结构一起使用
- Qtopengl,为什么不能用不同的vbo画两个立方体
- OpenGL C++:VBO 的结构包装器不会初始化成员
- glDrawElements gives EXC_BAD_ACCESS with VBO
- openGL 3.3-使用glDrawArrays/glDrawElements的VBO绘图