【问题标题】:OpenGL Problems with Rendering Multiple Objects渲染多个对象的 OpenGL 问题
【发布时间】:2018-11-27 06:52:52
【问题描述】:

我是 OpenGL 的新手,在渲染多个对象时遇到了一些困难。

我有一个向量,每个向量都有自己的 VertexBuffer。然后,在 while 循环中,我自己绘制每个形状。

当我有许多相同的对象(多个立方体等)时,一切都很好,但是,当我添加一个三角形网格时,一切都变得不正常了。

我可以有很多立方体

我可以有一个三角形网格:

但是,当我尝试创建一个立方体,然后是一个三角形网格时,我得到了:

我完全不知道发生了什么。下面提供了我的循环的代码。

while (!glfwWindowShouldClose(window))
    {

        // Get the size of the window
        int width, height;
        glfwGetWindowSize(window, &width, &height);

        float aspect_ratio = 1 * float(height)/float(width); // corresponds to the necessary width scaling

        double xpos, ypos;
        glfwGetCursorPos(window, &xpos, &ypos);

        // Clear the framebuffer
        glClearColor(0.5f, 0.5f, 0.5f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        // Enable depth test
        glEnable(GL_DEPTH_TEST);

        glUniform3f(program.uniform("triangleColor"), 1.0f, 1.0f, 1.0f);

        glUniformMatrix4fv(program.uniform("proj"), 1, GL_FALSE, projection.data());
        glUniformMatrix4fv(program.uniform("view"), 1, GL_FALSE, view.data());

        int tally = 0;
    for (int i = 0; i < surfaces.size(); i++) {

        Surface *s = surfaces[i];

        Vector3f color = s->getColor();

        int tempIndex = triangleIndex;
        Matrix4f model = s->getModel();

        // Convert screen position to world coordinates
        double xworld = ((xpos/double(width))*2)-1;
        double yworld = (((height-1-ypos)/double(height))*2)-1; // NOTE: y axis is flipped in glfw

        if (isPressed && mode == "translate") { 
            if(tempIndex == i) {
                Vector4f center = s->getCenter() + model.col(3);
                Vector4f displacement = Vector4f(xworld, yworld, 0, 1) - center;
                Matrix4f translation = translateMatrix(displacement(0), displacement(1), displacement(2));
                model = translation * s->getModel();
                s->setModel(model);
            }
        }
        glUniform3f(program.uniform("triangleColor"), color(0), color(1), color(2));
        glUniformMatrix4fv(program.uniform("model"), 1, GL_FALSE, model.data()); 
        glDrawArrays(GL_TRIANGLES, 0, s->getVertices().size());
    }

并且我在将对象制作为时初始化每个 VBO

VertexBufferObject VBO;
VBO.init();
VBO.update(Vertices);
program.bindVertexAttribArray("position", VBO);

Surface* s = new Surface(VBO, Vertices, percentScale, 0, transformedCenter, SmoothNormals, FlatNormals, color);
s->setModel(model);
surfaces.push_back(s);

其中 Program::bindVertexAttribArray 定义为

GLint Program::bindVertexAttribArray(
        const std::string &name, VertexBufferObject& VBO) const
{
  GLint id = attrib(name);
  if (id < 0)
    return id;
  if (VBO.id == 0)
  {
    glDisableVertexAttribArray(id);
    return id;
  }
  VBO.bind();
  glEnableVertexAttribArray(id);
  glVertexAttribPointer(id, VBO.rows, GL_FLOAT, GL_FALSE, 0, 0);
  check_gl_error();

  return id;
}

【问题讨论】:

  • 您没有展示如何初始化顶点缓冲区。我怀疑缓冲区有一个模型的数据,然后你试图用另一个模型的元素计数来渲染它。顺便说一句,您正在动态生成顶点缓冲区。这不是应该这样做的。为每个模型创建一个 VAO,并在程序开始时将正确的缓冲区与其数据绑定。然后,在渲染循环中,只需激活 VAO 并绘制它。
  • @NicoSchertier 有没有一种方法可以在两个着色模型(平面与 phong)之间切换而无需动态创建顶点缓冲区?我需要在顶点着色器中使用两组不同的法线,并认为我需要创建 VBO。
  • @NicoSchertier 我认为你是对的,因为它还存在一个问题,即绘制 2 个相反颜色的对象。为什么会有这个切换器?
  • 如果你想要不同的法线集,你可以有两个 VAO 引用两个不同的法线 VBO。
  • 这几乎不清楚。 bindVertexAttribArray、VBO_C.init 和 VBO_C.update 有什么作用?顶点坐标在哪里。您是否错过了更改顶点坐标。你用vertex array object吗?您必须添加更多信息才能使其成为Minimal, Complete, and Verifiable example。

标签: c++ opengl render


【解决方案1】:

在绘制调用之前,您没有绑定任何缓冲区。您可能只是在初始化它们时绘制上次绑定的任何缓冲区。在 glDrawArrays 之前的循环结束时,您需要这样的东西:

...
program.bindVertexAttribArray("position", VBO); // where VBO is the buffer of surface s
glUniform3f(program.uniform("triangleColor"), color(0), color(1), color(2));
glUniformMatrix4fv(program.uniform("model"), 1, GL_FALSE, model.data()); 
glDrawArrays(GL_TRIANGLES, 0, s->getVertices().size());

【讨论】:

  • 哇。那完全奏效了。但这感觉确实效率低下。有没有更好的方法来做到这一点,我只绑定一次对象,但可以操纵它的模型、法线等?
  • 是的,Nico Schertler 在他的评论中写道:每个表面使用 VAO。
猜你喜欢
  • 2015-01-19
  • 1970-01-01
  • 2014-10-16
  • 2013-06-06
  • 1970-01-01
  • 2017-09-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多