OpenGL复制顶点缓冲对象



我试图通过复制赋值操作符将两个顶点缓冲区对象从一个Mesh对象复制到另一个。最初,我的顶点数组对象和缓冲区被初始化如下:

void Mesh::construct(Vertex* vertices, unsigned int nVerts) {
    vertexCount = nVerts;
    glGenVertexArrays(1, &vao);
    glBindVertexArray(vao);
    std::vector<glm::vec3> positions;
    std::vector<glm::vec2> texCoords;
    positions.reserve(nVerts);
    texCoords.reserve(nVerts);
    for (unsigned int i = 0; i < nVerts; i++) {
        positions.push_back(vertices[i].getPosition());
        texCoords.push_back(vertices[i].getTexCoord());
    }
    for (int i = 0; i < NUM_BUFFERS; i++) {
        glGenBuffers(1, &vab[i]);
    }
    glBindBuffer(GL_ARRAY_BUFFER, vab[POSITION_VB]);
    glBufferData(GL_ARRAY_BUFFER, nVerts * sizeof (positions[0]), &positions[0], GL_STATIC_DRAW);
    glBindBuffer(GL_ARRAY_BUFFER, vab[TEXCOORD_VB]);
    glBufferData(GL_ARRAY_BUFFER, nVerts * sizeof (texCoords[0]), &texCoords[0], GL_STATIC_DRAW);
    glEnableVertexAttribArray(1);
    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, 0);
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glBindVertexArray(0);
}

在实例化Mesh对象并调用:

时可以正常工作。
void Mesh::render() {
    glBindVertexArray(vao);
    glDrawArrays(GL_TRIANGLES, 0, vertexCount);
    glBindVertexArray(0);
}

然而,当我尝试将网格复制到另一个,并渲染它时,我在glDrawArrays(GL_TRIANGLES, 0, vertexCount);线上得到分割错误。这是我的复制赋值操作符:

Mesh& Mesh::operator=(const Mesh& param) {
    if (this == &param) {
        return *this;
    } else {
        GLint size = 0;
        glGenVertexArrays(1, &vao);
        glBindVertexArray(vao);
        for (int i = 0; i < NUM_BUFFERS; i++) {
            glGenBuffers(1, &vab[i]);
        }
        // Vertices
        // Bind Buffers
        glBindBuffer(GL_COPY_READ_BUFFER, param.vab[POSITION_VB]);
        glGetBufferParameteriv(GL_COPY_READ_BUFFER, GL_BUFFER_SIZE, &size);
        glBindBuffer(GL_COPY_WRITE_BUFFER, vab[POSITION_VB]);
        glBufferData(GL_COPY_WRITE_BUFFER, size, nullptr, GL_STATIC_DRAW);
        glEnableVertexAttribArray(0);
        glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
        // Copy Data
        glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_COPY_WRITE_BUFFER, 0, 0, size);
        // Texture Coords
        // Bind Buffers
        glBindBuffer(GL_COPY_READ_BUFFER, param.vab[TEXCOORD_VB]);
        glGetBufferParameteriv(GL_COPY_READ_BUFFER, GL_BUFFER_SIZE, &size);
        glBindBuffer(GL_COPY_WRITE_BUFFER, vab[TEXCOORD_VB]);
        glBufferData(GL_COPY_WRITE_BUFFER, size, nullptr, GL_STATIC_DRAW);
        glEnableVertexAttribArray(1);
        glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, 0);
        // Copy Data
        glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_COPY_WRITE_BUFFER, 0, 0, size);
        // Unbind buffers
        glBindVertexArray(0);
        this->vertexCount = param.vertexCount;
        return *this;
    }
}

有人能看出这有什么问题吗?我已经检查了从glGetBufferParameteriv(GL_COPY_READ_BUFFER, GL_BUFFER_SIZE, &size);返回的大小在两种情况下都是正确的(对于位置和纹理坐标缓冲区)。在两次调用glCopyBufferSubData之后,我也检查了glGetError(),它们都返回0。不知道下一步该尝试什么?我的错误可能在其他地方,但这是我第一次尝试复制缓冲区,所以我想检查我做的那部分是正确的。如果有帮助的话,我的Mesh析构函数是:

Mesh::~Mesh() {
    glDeleteVertexArrays(1, &vao);
    glDeleteBuffers(NUM_BUFFERS, vab);
}

通过调试器,我可以看到,这当然被调用了一次,在

行之后:
this->mesh = Mesh(*texture);

这是简单地构建一个网格,然后分配它(纹理只是大小的四边形纹理的大小,并调用构造函数显示在正确的顶点位置开始)。

您复制数组,但您从未将复制的版本绑定到GL_ARRAY_BUFFER,这意味着您的glVertexAttribPointer调用没有指向任何东西。

我对这段代码也有点担心:

glBindBuffer(GL_ARRAY_BUFFER, vab[POSITION_VB]);
glBufferData(GL_ARRAY_BUFFER, nVerts * sizeof (positions[0]), &positions[0], GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, vab[TEXCOORD_VB]);
glBufferData(GL_ARRAY_BUFFER, nVerts * sizeof (texCoords[0]), &texCoords[0], GL_STATIC_DRAW);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);

似乎位置顶点指针将引用纹理数据,因为这是当前绑定的顶点缓冲区,当你调用glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);

我想你会希望顺序是这样的:

glBindBuffer(GL_ARRAY_BUFFER, vab[POSITION_VB]);
glBufferData(GL_ARRAY_BUFFER, nVerts * sizeof (positions[0]), &positions[0], GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, vab[TEXCOORD_VB]);
glBufferData(GL_ARRAY_BUFFER, nVerts * sizeof (texCoords[0]), &texCoords[0], GL_STATIC_DRAW);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, 0);

但是我不确定。我通常将所有顶点属性交织到一个顶点缓冲区中。

最新更新