C++ 使用VBO的渲染结果不正确
我正在尝试使用高度贴图和分块方法编写简单的体素化地形引擎。我想为每个块构建单独的网格,并将网格加载到单独的VBO中。我已经准备好了所有的逻辑,但我似乎没有让VBO渲染正常工作。我为测试准备了非常简单的heightmap,它应该只渲染2行体素16x16x2=512个立方体,每个立方体总共12个三角形。问题是我的结果看起来与它应该的完全不同-我的意思是:C++ 使用VBO的渲染结果不正确,c++,opengl,vbo,voxel,C++,Opengl,Vbo,Voxel,我正在尝试使用高度贴图和分块方法编写简单的体素化地形引擎。我想为每个块构建单独的网格,并将网格加载到单独的VBO中。我已经准备好了所有的逻辑,但我似乎没有让VBO渲染正常工作。我为测试准备了非常简单的heightmap,它应该只渲染2行体素16x16x2=512个立方体,每个立方体总共12个三角形。问题是我的结果看起来与它应该的完全不同-我的意思是: 无论我放大、缩小或扭曲相机多远,线条都会移动一点 下面是我如何做到这一点的: 为CMesh类表示的巴黎网格构造缓冲区: void CMesh::
无论我放大、缩小或扭曲相机多远,线条都会移动一点
下面是我如何做到这一点的:
为CMesh类表示的巴黎网格构造缓冲区:
void CMesh::generateVertexBufferData()
{
this->vertexBuffer = new GLuint();
glGenBuffers(1,vertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, *this->vertexBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat)*meshVertexData->size(),&meshVertexData[0],GL_STATIC_DRAW);
this->vertexCount = meshVertexData->size();
}
void CMesh::generateIndexBufferData()
{
this->indexBuffer = new GLuint();
glGenBuffers(1,this->indexBuffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, *this->indexBuffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint)*meshIndexData->size(),&meshIndexData[0],GL_STATIC_DRAW);
this->indexCount = meshIndexData->size();
}
由GeometryManager类完成的渲染:
glPushMatrix();
pRenderer->ImmediateColorAlpha(1.0f,1.0f,1.0f,1.0f);
pRenderer->SetRenderMode(GL_LINE);
pRenderer->TranslateWorldMatrix(geometryPosition.x*Chunk::CHUNK_SIZE,
geometryPosition.y*Chunk::CHUNK_SIZE,
geometryPosition.z*Chunk::CHUNK_SIZE);
glBindBuffer(GL_ARRAY_BUFFER,*meshArray->at(geometryID)->getBuffer(VERTEX_BUFFER));
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3,GL_FLOAT,0,BUFFER_OFFSET(0));
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,*meshArray->at(geometryID)->getBuffer(INDEX_BUFFER));
glDrawElements(GL_TRIANGLES,meshArray->at(geometryID)->indexCount,GL_UNSIGNED_INT,BUFFER_OFFSET(0));
glPopMatrix();
我已经检查了我是否正确地计算顶点位置,方法是直接从std::vector*meshVertexData使用简单的立即模式渲染顶点位置:
for(int i=0; i < meshArray->at(geometryID)->meshVertexData->size(); i+=3)
{
glBegin(GL_POINTS);
glVertex3f(meshArray->at(geometryID)->meshVertexData->at(i),
meshArray->at(geometryID)->meshVertexData->at(i+1),
meshArray->at(geometryID)->meshVertexData->at(i+2));
glEnd();
}
for(int i=0;iat(geometryID)->meshVertexData->size();i+=3)
{
glBegin(总分);
glVertex3f(网格阵列->at(geometryID)->网格顶点数据->at(i),
meshArray->at(geometryID)->meshVertexData->at(i+1),
meshArray->at(geometryID)->meshVertexData->at(i+2));
格伦德();
}
结果似乎是。
我对此完全感到困惑,我不确定在用数据填充VBO和渲染(使其看起来像这样)之间会发生什么。在这件事上我谦虚地请求帮助,我真的不知道我做错了什么。我的方法是完全有缺陷还是缺少了一些简单的东西?
如果有人对帮助我解决问题非常感兴趣,但需要更多信息,我愿意提供您要求的任何信息,包括pastebin上的完整CMesh和GeometryManager代码。
经过一段时间的调试和测试建议的解决方案,我终于找到了错误。结果表明,对于
std::vector
而言,此表达式&meshVertexData[0]
不等于此表达式&(meshVertexData->at(0))
。因此,它无法在VBO中正确分配数据。将glBufferData
分配更改为后者,代码运行正常。我希望有人能从我的错误中吸取教训。感谢大家帮助我了解你的见解 indexBuffer
真的需要成为指针吗?这似乎过于复杂-每次生成VBO或IBO时都必须分配GLuint
。这样做并不是为了节省存储空间,你必须在你的类中存储一个指针,通常是32位或64位,然后你必须分配另外4个字节的内存来保存ID。您不妨在类中创建一个实际的GLuint
,然后将其地址传递给glGenBuffers(…)
。谢谢您的快速回复!我认为你在这一点上是对的,按照你的建议,我将两个缓冲区都公开为非指针GLuint
。这当然让事情变得不那么复杂,但不幸的是,这并不能解决我的问题。顺便说一句,glGenBuffers
生成的每个缓冲区都会自动获取ID,而不考虑调用的时间、方式以及调用的类是什么样的,glGenBuffers
对吗?是的,每次调用glGenBuffers(…)
它将返回1个或多个未使用的ID,然后保留这些ID,以便对glGenBuffers
的另一次调用也不会返回它们。它不一定每次调用时都增加ID,它可能会回收调用glDeleteBuffers(…)
后不再使用的旧ID。在任何情况下,工作代码和非工作代码之间的最大区别实际上是原语类型。最后一段代码使用了GL_点
,点与点之间没有任何连接,因此如果你的问题实际上是你绘制顶点的顺序,那么它就不会出现。经过一段时间的调试,我终于找到了这个bug,原来它是在我发布的代码中。对于std::vector
而言,此表达式&meshVertexData[0]
似乎不等于&meshVertexData->at(0)
。将glBufferData
分配更改为后者,代码运行正常。我希望有人能从我的错误中吸取教训。感谢大家帮助我了解你的见解!它看起来像是指向向量的指针。这似乎很不寻常,我从未见过有人这样做。在这种情况下,meshVertexData[0]
是矢量对象,&meshVertexData[0]
是矢量对象的地址,这确实不是您想要的。我认为&v->at(0)
不正确,这会导致编译错误。您将需要&(v->at(0))`或&(*meshVertexData)[0]
。既然您提到了这一点,这就很有意义了meshVertexData
实际上是指向向量的指针。当我想起来的时候,使用你提到的表达方式会更有意义。我查过了,你是绝对正确的&(meshVertexData->at(0))
是正确的。虽然&meshVertexData->at(0)
实际上编译并呈现了结果,乍一看,这和我所期望的一样。测试你的建议证明我错了,但我恐怕无法解释为什么编译和渲染实际上对我有效。