diff --git a/source/client/graphics/ChunkRenderer.cpp b/source/client/graphics/ChunkRenderer.cpp index 0baec6f2..95e8b53d 100644 --- a/source/client/graphics/ChunkRenderer.cpp +++ b/source/client/graphics/ChunkRenderer.cpp @@ -150,7 +150,7 @@ void ChunkRenderer::drawChunks(gk::RenderTarget &target, gk::RenderStates states states.shader->setUniform("u_modelMatrix", it.second); - target.drawVertexBuffer(it.first->getVBO(layer), GL_TRIANGLES, 0, (GLsizei)verticesCount); + target.drawVertexBuffer(it.first->getVertexBuffer(), GL_TRIANGLES, it.first->getBufferOffset(layer), (GLsizei)verticesCount); it.first->setHasBeenDrawn(true); } diff --git a/source/client/world/ChunkMeshBuilder.cpp b/source/client/world/ChunkMeshBuilder.cpp index 7d96d453..c9c4356e 100644 --- a/source/client/world/ChunkMeshBuilder.cpp +++ b/source/client/world/ChunkMeshBuilder.cpp @@ -83,17 +83,22 @@ void ChunkMeshBuilder::update() { ClientChunk *chunk = (ClientChunk *)m_world.getChunk(job.chunkData.x, job.chunkData.y, job.chunkData.z); if (chunk) { + const gk::VertexBuffer &vbo = chunk->getVertexBuffer(); + + gk::VertexBuffer::bind(&vbo); + vbo.setData(job.totalVertexCount * sizeof(Vertex), nullptr, GL_DYNAMIC_DRAW); + + u64 offset = 0; for (u8 i = 0 ; i < ChunkMeshLayer::Count ; ++i) { job.vertices[i].shrink_to_fit(); - const gk::VertexBuffer &vbo = chunk->getVertexBuffer(i); - - gk::VertexBuffer::bind(&vbo); - vbo.setData(job.vertices[i].size() * sizeof(Vertex), job.vertices[i].data(), GL_DYNAMIC_DRAW); - gk::VertexBuffer::bind(nullptr); + vbo.updateData(offset * sizeof(Vertex), job.vertices[i].size() * sizeof(Vertex), job.vertices[i].data()); chunk->setVerticesCount(i, job.vertices[i].size()); + offset += job.vertices[i].size(); } + + gk::VertexBuffer::bind(nullptr); } it = m_futures.erase(it); @@ -307,6 +312,8 @@ inline void ChunkMeshBuilder::addCubeFace(s8f x, s8f y, s8f z, s8f f, ChunkMeshB addVertex(1); addVertex(2); } + + job.totalVertexCount += 6; } inline void ChunkMeshBuilder::addCross(s8f x, s8f y, s8f z, ChunkMeshBuildingJob &job, const BlockState &blockState) { @@ -371,6 +378,8 @@ inline void ChunkMeshBuilder::addCross(s8f x, s8f y, s8f z, ChunkMeshBuildingJob job.vertices[ChunkMeshLayer::Flora].emplace_back(vertices[3]); job.vertices[ChunkMeshLayer::Flora].emplace_back(vertices[1]); job.vertices[ChunkMeshLayer::Flora].emplace_back(vertices[2]); + + job.totalVertexCount += 6; } } diff --git a/source/client/world/ChunkMeshBuilder.hpp b/source/client/world/ChunkMeshBuilder.hpp index 1bf4556f..5a7076dc 100644 --- a/source/client/world/ChunkMeshBuilder.hpp +++ b/source/client/world/ChunkMeshBuilder.hpp @@ -97,6 +97,8 @@ struct ChunkMeshBuildingJob { VerticesArray vertices; const TextureAtlas *textureAtlas; + + u64 totalVertexCount = 0; }; class ClientWorld; diff --git a/source/client/world/ClientChunk.cpp b/source/client/world/ClientChunk.cpp index c745e9ca..baf06ace 100644 --- a/source/client/world/ClientChunk.cpp +++ b/source/client/world/ClientChunk.cpp @@ -38,14 +38,12 @@ u64 ClientChunk::chunkUpdateTime = 0; ClientChunk::ClientChunk(s32 x, s32 y, s32 z, const Dimension &dimension, ClientWorld &world) : Chunk(x, y, z, (World &)world), m_world(world), m_dimension(dimension) { - for (auto &vbo : m_vbo) { - vbo.layout().addAttribute(0, "coord3d", 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), reinterpret_cast(offsetof(Vertex, coord3d))); - vbo.layout().addAttribute(1, "texCoord", 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), reinterpret_cast(offsetof(Vertex, texCoord))); - vbo.layout().addAttribute(2, "color", 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), reinterpret_cast(offsetof(Vertex, color))); - vbo.layout().addAttribute(3, "normal", 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), reinterpret_cast(offsetof(Vertex, normal))); - vbo.layout().addAttribute(4, "lightValue", 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), reinterpret_cast(offsetof(Vertex, lightValue))); - vbo.layout().addAttribute(5, "ambientOcclusion", 1, GL_FLOAT, GL_FALSE, sizeof(Vertex), reinterpret_cast(offsetof(Vertex, ambientOcclusion))); - } + m_vbo.layout().addAttribute(0, "coord3d", 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), reinterpret_cast(offsetof(Vertex, coord3d))); + m_vbo.layout().addAttribute(1, "texCoord", 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), reinterpret_cast(offsetof(Vertex, texCoord))); + m_vbo.layout().addAttribute(2, "color", 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), reinterpret_cast(offsetof(Vertex, color))); + m_vbo.layout().addAttribute(3, "normal", 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), reinterpret_cast(offsetof(Vertex, normal))); + m_vbo.layout().addAttribute(4, "lightValue", 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), reinterpret_cast(offsetof(Vertex, lightValue))); + m_vbo.layout().addAttribute(5, "ambientOcclusion", 1, GL_FLOAT, GL_FALSE, sizeof(Vertex), reinterpret_cast(offsetof(Vertex, ambientOcclusion))); } void ClientChunk::update() { diff --git a/source/client/world/ClientChunk.hpp b/source/client/world/ClientChunk.hpp index 394135e1..55a088e9 100644 --- a/source/client/world/ClientChunk.hpp +++ b/source/client/world/ClientChunk.hpp @@ -27,6 +27,8 @@ #ifndef CLIENTCHUNK_HPP_ #define CLIENTCHUNK_HPP_ +#include + #include #include "Chunk.hpp" @@ -59,13 +61,12 @@ class ClientChunk : public Chunk { bool areAllNeighboursTooFar() const; - const gk::VertexBuffer &getVertexBuffer(u8 layer) { return m_vbo[layer]; } + const gk::VertexBuffer &getVertexBuffer() { return m_vbo; } + GLint getBufferOffset(u8 layer) const { return std::accumulate(m_verticesCount.begin(), m_verticesCount.begin() + layer, 0); } std::size_t getVerticesCount(u8 layer) const { return m_verticesCount[layer]; } void setVerticesCount(u8 layer, std::size_t count) { m_verticesCount[layer] = count; } - const gk::VertexBuffer &getVBO(u8 layer) const { return m_vbo[layer]; } - int debugTimesReceived = 0; // Only used by Minimap static u32 chunkUpdatesPerSec; @@ -77,7 +78,7 @@ class ClientChunk : public Chunk { const Dimension &m_dimension; - std::array m_vbo{}; + gk::VertexBuffer m_vbo{}; std::array m_verticesCount{}; bool m_isReadyForMeshing = false;