由于某种原因,OpenGL VAO 指向地址 0

OpenGL VAO is pointing to address 0 for some reason

我的 VAO 绑定不正确(至少我认为是这样)。

所以,我正在做的是我有一个 class 从一些原始数据创建 vbo 和 vao,在本例中是指向浮点数组的指针。

RawModel* Loader::loadToVao(float* positions, int sizeOfPositions) {
    unsigned int vaoID = this->createVao();
    this->storeDataInAttributeList(vaoID, positions, sizeOfPositions);
    this->unbindVao();
    return new RawModel(vaoID, sizeOfPositions / 3);
}

unsigned int Loader::createVao() {
    unsigned int vaoID;
    glGenVertexArrays(1, &vaoID);
    glBindVertexArray(vaoID);

    unsigned int copyOfVaoID = vaoID;
    vaos.push_back(copyOfVaoID);
    return vaoID;
}

void Loader::storeDataInAttributeList(unsigned int attributeNumber, float* data, int dataSize) {
    unsigned int vboID;
    glGenBuffers(1, &vboID);
    glBindBuffer(GL_ARRAY_BUFFER, vboID);
    glBufferData(GL_ARRAY_BUFFER, dataSize * sizeof(float), data, GL_STATIC_DRAW);
    glVertexAttribPointer(attributeNumber, 3, GL_FLOAT, false, 0, 0);
    glBindBuffer(GL_ARRAY_BUFFER, 0);

    unsigned int copyOfVboID = vboID;
    vbos.push_back(copyOfVboID);
}

void Loader::unbindVao() {
    glBindVertexArray(0);
}

RawModel 只是一个 class,它应该接受浮点数组并创建一个 vbo 和一个 vao。我正在使用的向量 vbosvaos 只是用来跟踪所有 ID,这样我就可以在使用完所有数据后删除它们。

我有 90% 的信心这一切都可以正常工作。但是,当我去尝试 运行 一些可以绘制它的代码时,OpenGL 正在退出,因为它试图从地址 0x0000000 读取并且它不喜欢那样。我将在此之前从代码创建的原始模型传递到渲染器中的函数中,如下所示:

void Renderer::render(RawModel* model) {
    glBindVertexArray(model->getVaoID());
    glEnableVertexAttribArray(0);   
    glDrawArrays(GL_TRIANGLES, 0, model->getVertexCount());
    glDisableVertexAttribArray(0);
    glBindVertexArray(0);
}

我已检查以确保创建 vao 时和尝试检索 vao 时 VaoID 相同。其实是一样的

我不知道如何读取当前存储在任何 OpenGL 当前绑定为顶点属性数组的地址,因此我无法测试它是否指向顶点数据。不过,我很确定它出于某种原因指向地址 0。

编辑:

原来不是硬编码的 0 有问题。它消除了 Visual Studio 和 OpenGL 给我的错误,但实际错误在其他地方。我意识到我在上面的一些代码中将 vaoID 作为 attributeNumber 传递,而我应该传递一个硬编码的 0。我在这里编辑了我的代码:

RawModel* Loader::loadToVao(float* positions, int sizeOfPositions) {
    unsigned int vaoID = this->createVao();
    this->storeDataInAttributeList(0, positions, sizeOfPositions);
    this->unbindVao();
    return new RawModel(vaoID, sizeOfPositions / 3);
}

我将 this->storeDataInAttributeList(vaoID, positions, sizeOfPositions); 行更改为您在上面看到的内容,并带有一个硬编码的 0。因此,事实证明我什至没有将数组绑定到 vbo 中的正确位置。但是,更改后它工作正常。

您应该将顶点属性索引与 glVertexAttribPointerglEnableVertexAttribArrayglDisableVertexAttribArray 一起使用,但您得到的是:

  • glVertexAttribPointer
  • 一起使用的 VAO id
  • 硬编码 0glEnableVertexAttribArrayglDisableVertexAttribArray 一起使用(这不一定是错误,但如果您确定该值)

如果您不确定索引值(例如,如果您没有在着色器中指定布局),那么您可以通过 glGetAttribLocation 调用获取它:

// The code assumes `program` is created with glCreateProgram
// and `position` is the attribute name in your vertex shader

const auto index = glGetAttribLocation(program, "position");

然后就可以使用index上面提到的调用了。