OpenGL:调用glDrawArrays时阅读位置时发生访问冲突

zkure5ic  于 2022-11-04  发布在  其他
关注(0)|答案(1)|浏览(193)

我正在尝试做一个类似于Minecraft的游戏,目前,我被困在列表中的块工作上。当我这样做的时候,它工作得很好:

Chunk ch1(0, 0, 0);
ch1.fillVertices();
ch1.updateVBO();

Chunk ch2(0, 0, 17);
ch2.fillVertices();
ch2.updateVBO();

ch1.draw();
ch2.draw():

但我不能将它们放在列表中并从列表中使用它们:

std::list<Chunk> chunks;
chunks.emplace_back(0, 0, 0);
chunks.emplace_back(16, 0, 0);

for (Chunk& chunk : chunks) {
    chunk.fillVertices();
    chunk.updateVBO();
}

for (Chunk& chunk : chunks) {
    chunk.draw();
}

因为我在glDrawArrays处收到了“Access violation阅读location”错误消息。

struct Chunk {

    Block* blocks = nullptr;
    unsigned int VAO = 0;
    unsigned int VBO = 0;
    float chunkPosX = 0, chunkPosY = 0, chunkPosZ = 0;
    std::vector<Vertex> vertices;
    int chunkPosUniformLoc = 0;

    Chunk(float x = 0.0f, float y = 0.0f, float z = 0.0f) : chunkPosX(x), chunkPosY(y), chunkPosZ(z) {
        blocks = new Block[CHUNK_WIDTH * CHUNK_DEPTH * CHUNK_HEIGHT];
        if (!blocks)
            CLOG("Couldn't mallocate blocks!");

        glGenVertexArrays(1, &VAO);
        glBindVertexArray(VAO);

        glGenBuffers(1, &VBO);
        glBindBuffer(GL_ARRAY_BUFFER, VBO);
        glUseProgram(sp);
        glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)0);
        glEnableVertexAttribArray(0);
        glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)(3 * sizeof(float)));
        glEnableVertexAttribArray(1);

        chunkPosUniformLoc = glGetUniformLocation(sp, "chunkPos");
    }

    void updateVBO() {
        if (vertices.size() != 0) {
            glBindVertexArray(VAO);
            glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(Vertex), &(vertices[0]), GL_DYNAMIC_DRAW);
        }
    }

    void fillVertices() {
        vertices.clear();

        for (int y = 0; y < CHUNK_HEIGHT; y++) {
            for (int x = 0; x < CHUNK_WIDTH; x++) {
                for (int z = 0; z < CHUNK_DEPTH; z++) {
                    unsigned int id = blocks[y * CHUNK_WIDTH * CHUNK_DEPTH + x * CHUNK_DEPTH + z].id;
                    BlockInfo bi = globalRe->getInfo(id);
                    if (blocks[y * CHUNK_WIDTH * CHUNK_DEPTH + x * CHUNK_WIDTH + z].id == BLOCKID::AIR)
                        continue;

                    if (z == 15 || !blocks[y * 16 * 16 + x * 16 + (z + 1)].isSolid()) { // Front
                        vertices.emplace_back( x, y, 1 + z, bi.textCoord[0][0].left, bi.textCoord[0][0].bottom );
                        vertices.emplace_back( 1 + x, y, 1 + z, bi.textCoord[0][0].right, bi.textCoord[0][0].bottom );
                        vertices.emplace_back( 1 + x, 1 + y, 1 + z, bi.textCoord[0][0].right, bi.textCoord[0][0].top );
                        vertices.emplace_back( 1 + x, 1 + y, 1 + z, bi.textCoord[0][0].right, bi.textCoord[0][0].top );
                        vertices.emplace_back( x, 1 + y, 1 + z, bi.textCoord[0][0].left, bi.textCoord[0][0].top );
                        vertices.emplace_back( x, y, 1 + z, bi.textCoord[0][0].left, bi.textCoord[0][0].bottom );
                    }

                    // Other faces
                    }
                }
            }
        }
    }

    void draw() {
        glBindVertexArray(VAO);
        glUseProgram(sp);
        glUniform3f(chunkPosUniformLoc, chunkPosX, chunkPosY, chunkPosZ);
        auto s = vertices.size();
        glDrawArrays(GL_TRIANGLES, 0, s);
    }

    ~Chunk() {
        delete[] blocks;
    }

};

使用:

  • grad
  • 玻璃纤维
  • OpenGL核心4.3
  • C++语言20
  • 英特尔高清显卡5500

我怀疑我的内存管理有问题,虽然Visual Studio调试器没有这么说,但在某个地方有损坏的内存。我只是不明白为什么它作为单独的变量工作,而不是在列表中。

nkoocmlb

nkoocmlb1#

绑定到GL_ARRAY_BUFFER的缓冲区不是 VAO 状态的一部分。VAO存储用于每个属性的缓冲区(调用glVertexAttribPointer时的GL_ARRAY_BUFFER)和GL_ELEMENT_ARRAY_BUFFER。
因此,您的updateVBO正在写入最新构造的块的VBO,而不是写入它所调用的块的VBO。
修复:在glBufferData之前绑定VBO

相关问题