当前位置: 首页 > 知识库问答 >
问题:

用于渲染不同对象的VAOs和VBOs

皇甫鸿远
2023-03-14

我编写了这个“模型”类来加载。obj文件并在VBO中为它们分配数据。它的代码如下所示:(注意它没有使用VAOs)

class Model {...}

void Model::LoadOBJ(const char *file)
{
    //load vertices, normals, UVs, and put them all in _vec, which is a private data member of std::vector<glm::vec3>
    ...

    //if an .obj file is loaded for the first time, generate a buffer object and bind it
    if(glIsBuffer(_vbo) == GL_FALSE)
    {
        glGenBuffers(1, &_vbo);//_vbo is a private data member
        glBindBuffer(GL_ARRAY_BUFFER, _vbo);
    }
    
    //load the data in the array buffer object
    glBufferData(GL_ARRAY_BUFFER, sizeof(glm::vec3) * _vec.size(), &_vec[0][0], GL_STATIC_DRAW);
}

void Model::Draw()
{
    glBindBuffer(GL_ARRAY_BUFFER, _vbo);
    glDrawArrays(GL_TRIANGLES, 0, _numVertices);
    glBindBuffer(GL_ARRAY_BUFFER, 0);
}

我曾经认为下一段代码可以很好地呈现两个不同的对象:

void init()
{
    //vao dummy (?)
    GLuint VAO;
    glGenVertexArrays(1, &VAO);
    glBindVertexArray(VAO);

    //load 3d models
    Model cube = load("cube.obj");
    Model cow = load("cow.obj");

    //the next two lines should be valid for both objects?
    glVertexAttribPointer(prog.GetAttribLocation("vertex"), 3, GL_FLOAT, GL_FALSE, 0, 0);
    glEnableVertexAttribArray(prog.GetAttribLocation("vertex"));
}

void render()
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    
    //draw cube:
    //some matrix transformations
    ...
    cube.Draw();

    //draw cow:
    //some matrix transformations
    ...
    cow.Draw()

    glutSwapBuffers();
}

顺便说一句,我很确定在第一张图片中,opengl确实试图绘制两头牛,但是调用的glDrawArrays()函数包含了立方体所需的顶点数量。

那我错过了什么?每个缓冲区对象都需要不同的VAO吗?

共有1个答案

韩寂离
2023-03-14

glvertexattribpointer(...)的所有调用都建立相对于当前绑定到gl_array_buffer的缓冲区对象的内存指针。我们倾向于将绑定到该位置的缓冲区对象称为顶点缓冲区对象,但实际上单个缓冲区对象可以用于多种目的,它们实际上没有类型。

GLuint GL_ARRAY_BUFFER_BINDING = 0; // Only 1 or 2 commands in GL care about this state
GLuint GL_VERTEX_ARRAY_BINDING = 0; // 0 is an invalid VAO (if this is 0, most vertex commands will generate `GL_INVALID_OPERATION`).

// Generic GPU-side Memory Store
struct GLBufferObject {
  GLsizeiptr* gpu_base_addr;
} *gl_buffer_objects;

// Vertex Array State
struct GLVertexArrayObject {
  GLsizeiptr* attribute_pointers [GL_MAX_VERTEX_ATTRIBUTES];
  GLboolean   attribute_enabled  [GL_MAX_VERTEX_ATTRIBUTES];
  GLuint      GL_ELEMENT_ARRAY_BUFFER_BINDING;
} *gl_array_objects;

void glBindVertexArray (GLuint array)
{
  GL_VERTEX_ARRAY_BINDING = array;
}

void glBindBuffer (GLenum target, GLuint buffer)
{
  if (target == GL_ARRAY_BUFFER)
    GL_ARRAY_BUFFER_BINDING = buffer;
}

void glVertexAttribPointer (GLuint index, ..., const GLvoid* offset)
{
  GLBufferObject*      current_vbo = &gl_buffer_objects [GL_ARRAY_BUFFER_BINDING];
  GLVertexArrayObject* current_vao = &gl_array_objects  [GL_VERTEX_ARRAY_BINDING];

  current_vao->attribute_pointers [index] = current_vbo->gpu_base_addr + offset;
}

这个伪代码的目的是向您展示OpenGL中只有一个命令,您绑定到gl_array_buffer的内容在整个代码中很重要:glvertexattribpointer(...)

所有其他命令,如gldrawarrays(...)实际上使用存储在“current_vao”中的状态,如glvertexattribpointer(...)的模拟实现所示。

最后,您不使用VAOs实际上是一个问题。您正在覆盖软件当前使用的唯一VAO的属性指针,该VAO用于最后加载的模型。

检查GLVeteXArrayObject在伪代码中存储哪些状态,然后考虑重构您自己的代码以利用这一点。否则,每次调用void model::draw()时,都必须至少调用GLVertexattribPointer一次。

关于一个不那么有趣的解释,请参见这个相关的答案。

 类似资料:
  • 我是新的反应,也对stackoverflow, 我正在尝试将 this.state.searchResults 呈现为附加代码 代码运行时没有任何错误,但是没有呈现。我到底做错了什么? 我在我的主js文件中导出这个组件。如果我不使用map方法运行,它会正确地渲染。 请帮帮忙 代码图像

  • This experimental class provides a fast code path for rendering meshes with frequently updated geometry data. When the renderer encounters an instance of ImmediateRenderObject, it only takes care abou

  • 问题内容: 我有一个这样的物体 我的密码 我在遍历对象时遇到麻烦。 获得的错误是这样的 我如何循环通过该对象,以便获得所获得的结果 提前致谢。任何帮助表示赞赏 问题答案: 您正在渲染数组,但是只能从react组件返回一个块,将map函数包装在div中

  • So the great thing about React JS is that it runs on the server too. But that does not mean you can just create any app and run it on the server. You have to make some decisions on the architecture. T

  • 我有一个组件,我想在用户点击后显示/隐藏。 它是这样的: 和 只需将wasPressed属性适当地设置为true或false。我正在使用<代码> 问题是“我的按钮”的“渲染”属性的值。它明确地包括两个方面:解释和显示按钮。 只要始终存在(它只更改它的标签),仅在属性为真时才存在。否则它说: malformedXML:更新期间:找不到解释 我如何解决这个问题? 我不想恢复到在源代码中隐藏元素,所以我

  • 问题内容: 我尝试过一些关于绑定和未绑定方法的代码。当我们调用它们时,我认为它们都会返回对象。但是,当我用于获取一些信息时,它返回的内容我并不理解。 IDE:Eclipse 插件:pydev 输出是… 为什么#1和#2返回相同的ID?他们不是不同的对象吗?如果我们分配和两个变量,#3,#4回报不同的ID。 我认为#3和#4表明它们不是同一对象,而是#1和#2 … 绑定方法的ID和未绑定方法的ID有