C++ 逐个加载对象时OpenGL indexbuffer不工作

C++ 逐个加载对象时OpenGL indexbuffer不工作,c++,opengl,index-buffer,C++,Opengl,Index Buffer,我在学习OpenGL时遇到了一个“障碍”。 我用indexbuffer画了一些房子(砖块和金字塔)。 当将所有顶点(从所有房屋中)加载到vertexbuffer并使用1个大indexbuffer时,这可以正常工作。现在,我想为对象设置动画,并将它们逐个加载到vertexbuffer中,以便可以逐个对对象执行变换。代码与一个大的缓冲区没有太大的不同,但是当我这样做的时候,我只看到一些随机形状在屏幕上四处乱射。我的代码如下: 我有一个世界级的3D对象列表,有一个所有顶点的大列表(供试用),一个索引的

我在学习OpenGL时遇到了一个“障碍”。 我用indexbuffer画了一些房子(砖块和金字塔)。 当将所有顶点(从所有房屋中)加载到vertexbuffer并使用1个大indexbuffer时,这可以正常工作。现在,我想为对象设置动画,并将它们逐个加载到vertexbuffer中,以便可以逐个对对象执行变换。代码与一个大的缓冲区没有太大的不同,但是当我这样做的时候,我只看到一些随机形状在屏幕上四处乱射。我的代码如下:

我有一个世界级的3D对象列表,有一个所有顶点的大列表(供试用),一个索引的大列表(也是试用版),还有一个向世界添加Object3D对象的方法

class World
{
public:
World();
~World();

vector<Object3D> objects;
vector<glm::vec3> Vertices;
vector<GLushort> Indices;

void AddObject(Object3D &object);
当我渲染带有所有顶点和索引的大缓冲区时(如下所示),效果很好

void WorldRenderer::Render()
{
glClearColor(0.0, 0.0, 0.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

glBindVertexArray(Vao); //use vao
glDrawElements(GL_TRIANGLES, World.Indices.size(), GL_UNSIGNED_SHORT, 0);
//glDrawArrays(GL_TRIANGLES, 0, World.Vertices.size());
glBindVertexArray(0); //release vao

//Model = glm::rotate(Model, 0.01f, glm::vec3(0.0f, 1.0f, 0.0f));
Mvp = Projection * View * Model;

glUniformMatrix4fv(UniformMvp, 1, GL_FALSE, glm::value_ptr(Mvp));
glutSwapBuffers();

//glutPostRedisplay();
}

当我在对象中循环并每次加载一个对象(如下所示)缓冲区中对象的顶点时,它会显示一些随机的“形状”,这些形状会不断“四处拍摄”或快速变化。我做错了什么? 提前谢谢你的建议

void WorldRenderer::Render()
{
glClearColor(0.0, 0.0, 0.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

int index = 0;
for each (Object3D mesh in World.objects)
{
    Mvp = Projection * View * Model;

    UpdateBuffer(mesh.Vertices, mesh.Indices);

    glBindVertexArray(Vao); //use vao
    glDrawElements(GL_TRIANGLES, mesh.Indices.size() , GL_UNSIGNED_SHORT, 0);
    glBindVertexArray(0); //release vao
    glUniformMatrix4fv(UniformMvp, 1, GL_FALSE, glm::value_ptr(Mvp));
    index++;
}

glutSwapBuffers();
}
UpdateBuffers方法:

void WorldRenderer::UpdateBuffer(vector<glm::vec3> vertices, vector<unsigned int> indices) {

//fill Vbo
glBindBuffer(GL_ARRAY_BUFFER, Vbo);
glBufferData(GL_ARRAY_BUFFER, vertices.size(), vertices.data(), GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);

//fill ibo
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, Ibo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(unsigned int), indices.data(), GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

glBindVertexArray(Vao);
glBindBuffer(GL_ARRAY_BUFFER, Vbo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, Ibo);
}

我一看到您的
UpdateBuffer
函数,就感觉
vbo
glBufferData
没有正确加载

第二个参数
vertices.size()
只返回向量中的元素数,而不是对象的实际大小

所以第二个参数应该是
vertices.size()*sizeof(glm::vec3)

第三个参数是ok,因为它返回指向底层数组的指针。如果不工作…直接传递第一个元素的地址,如下所示

glBufferData(
   GL_ARRAY_BUFFER,
   vertices.size() * sizeof(glm::vec3),
   &vertices[0],
   GL_STATIC_DRAW
);
总的来说,它应该如下所示

glBufferData(
   GL_ARRAY_BUFFER,
   vertices.size() * sizeof(glm::vec3),
   &vertices[0],
   GL_STATIC_DRAW
);
检查它是否有效

为什么会看到差异?

第一次渲染:

当调用
glpaurements
时,您的缓冲区连续包含顶点的所有世界数据。 因此,这里的网格1的最后一个顶点与网格2的第一个顶点继续。。。。所以你看到一种封闭的形状

第二次渲染:

当调用
glpaurements
时,缓冲区一次只包含一个网格数据

因此,在调用
gldrawerelements
后,每个网格的形状都将结束

要获得与第一次渲染相同的结果,必须首先为所有网格更新单个顶点缓冲区(使用
glBufferSubData


然后调用
glpaurements
一次。然后您将看到相同的结果。

谢谢!:这使我更进一步(我应该更整洁)。但是现在我只看到我画的三角形的一半。indexbuffer和vertexbuffer看起来不错,我尝试移动一些索引并禁用Cull face,但我一直看到每个网格的相同三角形。知道为什么会这样吗?图像良好:。图像不好:尝试在循环外部释放“glBindVertexArray(0);//释放vao…”。。。。我的意思是在for each循环之后…在函数“Render()”中,似乎不起作用:\。还尝试了循环外的glBindVertexArray(Vao)(这似乎是合乎逻辑的),但遗憾的是没有任何更改。glBindVertexArray(Vao)应该仅在循环内,因为您希望世界的每个网格都有“Vao”。对象。。。只需在循环外单独设置“glBindVertexArray(0);”。能否请您发布一下,您是如何创建“Vao”来实现“render()”函数的。。。。我指的是第一个渲染函数中的“Vao”,其中不存在循环。我添加了代码,在其中为两个渲染方法创建并填充缓冲区一次。第一个渲染方法(没有循环)不会更改它们,只是渲染它们。在第二种渲染方法(使用循环)中,数据将被每个网格的数据覆盖。我已经尝试过只将glBindVertexArray(Vao)放在循环内,将glBindVertexArray(0)放在循环外,但不幸的是,它没有改变任何东西。
void WorldRenderer::Init(int argc, char ** argv) {
InitGlutGlew(argc, argv);
InitMatrices();

glDisable(GL_CULL_FACE);
//-------------- init buffers --------------
// vbo vertices
glGenBuffers(1, &Vbo);
glBindBuffer(GL_ARRAY_BUFFER, Vbo);
glBufferData(GL_ARRAY_BUFFER, World.Vertices.size() * sizeof(glm::vec3),
    &World.Vertices[0], GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
//ibo
glGenBuffers(1, &Ibo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, Ibo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, World.Indices.size() * sizeof(unsigned int),
    &World.Indices[0], GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

// VAO setup
glGenVertexArrays(1, &Vao);
glBindVertexArray(Vao);
// Bind vertices to vao
glBindBuffer(GL_ARRAY_BUFFER, Vbo);
//Bind elements
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, Ibo);

//------ init shaders -----------
InitShader();
}
glBufferData(
   GL_ARRAY_BUFFER,
   vertices.size() * sizeof(glm::vec3),
   &vertices[0],
   GL_STATIC_DRAW
);