C++ 使用VBO的渲染结果不正确

C++ 使用VBO的渲染结果不正确,c++,opengl,vbo,voxel,C++,Opengl,Vbo,Voxel,我正在尝试使用高度贴图和分块方法编写简单的体素化地形引擎。我想为每个块构建单独的网格,并将网格加载到单独的VBO中。我已经准备好了所有的逻辑,但我似乎没有让VBO渲染正常工作。我为测试准备了非常简单的heightmap,它应该只渲染2行体素16x16x2=512个立方体,每个立方体总共12个三角形。问题是我的结果看起来与它应该的完全不同-我的意思是: 无论我放大、缩小或扭曲相机多远,线条都会移动一点 下面是我如何做到这一点的: 为CMesh类表示的巴黎网格构造缓冲区: void CMesh::

我正在尝试使用高度贴图和分块方法编写简单的体素化地形引擎。我想为每个块构建单独的网格,并将网格加载到单独的VBO中。我已经准备好了所有的逻辑,但我似乎没有让VBO渲染正常工作。我为测试准备了非常简单的heightmap,它应该只渲染2行体素16x16x2=512个立方体,每个立方体总共12个三角形。问题是我的结果看起来与它应该的完全不同-我的意思是:



无论我放大、缩小或扭曲相机多远,线条都会移动一点
下面是我如何做到这一点的:
为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)
实际上编译并呈现了结果,乍一看,这和我所期望的一样。测试你的建议证明我错了,但我恐怕无法解释为什么编译和渲染实际上对我有效。