我正在尝试做一个类似于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调试器没有这么说,但在某个地方有损坏的内存。我只是不明白为什么它作为单独的变量工作,而不是在列表中。
1条答案
按热度按时间nkoocmlb1#
绑定到GL_ARRAY_BUFFER的缓冲区不是 VAO 状态的一部分。VAO存储用于每个属性的缓冲区(调用glVertexAttribPointer时的GL_ARRAY_BUFFER)和GL_ELEMENT_ARRAY_BUFFER。
因此,您的
updateVBO
正在写入最新构造的块的VBO,而不是写入它所调用的块的VBO。修复:在
glBufferData
之前绑定VBO