diff --git a/src/graphics/core/Mesh.hpp b/src/graphics/core/Mesh.hpp index 3d428322..48c02969 100644 --- a/src/graphics/core/Mesh.hpp +++ b/src/graphics/core/Mesh.hpp @@ -1,5 +1,7 @@ #pragma once +#include + #include "MeshData.hpp" @@ -8,25 +10,32 @@ struct MeshStats { static int drawCalls; }; +struct IndexBufferData { + const uint32_t* indices; + size_t indicesCount; +}; + template class Mesh { + struct IndexBuffer { + unsigned int ibo; + size_t indexCount; + }; unsigned int vao; unsigned int vbo; - unsigned int ibo; + std::vector ibos; size_t vertexCount; - size_t indexCount; public: explicit Mesh(const MeshData& data); Mesh( const VertexStructure* vertexBuffer, size_t vertices, - const uint32_t* indexBuffer, - size_t indices + std::vector indices ); Mesh(const VertexStructure* vertexBuffer, size_t vertices) - : Mesh(vertexBuffer, vertices, nullptr, 0) {}; + : Mesh(vertexBuffer, vertices, {}) {}; ~Mesh(); @@ -34,18 +43,21 @@ public: /// attributes /// @param vertexBuffer vertex data buffer /// @param vertexCount number of vertices in new buffer - /// @param indexBuffer indices buffer - /// @param indexCount number of values in indices buffer + /// @param indices indices buffer void reload( const VertexStructure* vertexBuffer, size_t vertexCount, - const uint32_t* indexBuffer = nullptr, - size_t indexCount = 0 + const std::vector& indices ); + void reload(const VertexStructure* vertexBuffer, size_t vertexCount) { + static const std::vector indices {}; + reload(vertexBuffer, vertexCount, indices); + } + /// @brief Draw mesh with specified primitives type - /// @param primitive primitives type - void draw(unsigned int primitive) const; + /// @param iboIndex index of used element buffer + void draw(unsigned int primitive, int iboIndex = 0) const; /// @brief Draw mesh as triangles void draw() const; diff --git a/src/graphics/core/Mesh.inl b/src/graphics/core/Mesh.inl index 390c2f9a..778baaf9 100644 --- a/src/graphics/core/Mesh.inl +++ b/src/graphics/core/Mesh.inl @@ -11,13 +11,21 @@ inline constexpr size_t calc_size(const VertexAttribute attrs[]) { return vertexSize; } +template +inline std::vector convert_to_ibd(const MeshData& data) { + std::vector indices; + for (const auto& buffer : data.indices) { + indices.push_back(IndexBufferData {buffer.data(), buffer.size()}); + } + return indices; +} + template Mesh::Mesh(const MeshData& data) : Mesh( data.vertices.data(), data.vertices.size(), - data.indices.data(), - data.indices.size() + convert_to_ibd(data) ) { } @@ -25,10 +33,9 @@ template Mesh::Mesh( const VertexStructure* vertexBuffer, size_t vertices, - const uint32_t* indexBuffer, - size_t indices + std::vector indices ) - : vao(0), vbo(0), ibo(0), vertexCount(0), indexCount(0) { + : vao(0), vbo(0), ibos(), vertexCount(0) { static_assert( calc_size(VertexStructure::ATTRIBUTES) == sizeof(VertexStructure) ); @@ -39,8 +46,9 @@ Mesh::Mesh( glGenVertexArrays(1, &vao); glGenBuffers(1, &vbo); - reload(vertexBuffer, vertices, indexBuffer, indices); + reload(vertexBuffer, vertices, std::move(indices)); + glBindVertexArray(vao); // attributes int offset = 0; for (int i = 0; attrs[i].count; i++) { @@ -65,8 +73,8 @@ Mesh::~Mesh() { MeshStats::meshesCount--; glDeleteVertexArrays(1, &vao); glDeleteBuffers(1, &vbo); - if (ibo != 0) { - glDeleteBuffers(1, &ibo); + for (int i = ibos.size() - 1; i >= 0; i--) { + glDeleteBuffers(1, &ibos[i].ibo); } } @@ -74,11 +82,9 @@ template void Mesh::reload( const VertexStructure* vertexBuffer, size_t vertexCount, - const uint32_t* indexBuffer, - size_t indexCount + const std::vector& indices ) { this->vertexCount = vertexCount; - this->indexCount = indexCount; glBindVertexArray(vao); glBindBuffer(GL_ARRAY_BUFFER, vbo); if (vertexBuffer != nullptr && vertexCount != 0) { @@ -92,30 +98,47 @@ void Mesh::reload( glBufferData(GL_ARRAY_BUFFER, 0, {}, GL_STREAM_DRAW); } - if (indexBuffer != nullptr && indexCount != 0) { - if (ibo == 0) glGenBuffers(1, &ibo); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo); + for (int i = indices.size(); i < ibos.size(); i++) { + glDeleteBuffers(1, &ibos[i].ibo); + } + ibos.clear(); + + for (int i = 0; i < indices.size(); i++) { + const auto& indexBuffer = indices[i]; + ibos.push_back(IndexBuffer {0, 0}); + glGenBuffers(1, &ibos[i].ibo); + ibos[i].indexCount = indexBuffer.indicesCount; + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibos[i].ibo); glBufferData( GL_ELEMENT_ARRAY_BUFFER, - sizeof(uint32_t) * indexCount, - indexBuffer, + sizeof(uint32_t) * indexBuffer.indicesCount, + indexBuffer.indices, GL_STATIC_DRAW ); - } else if (ibo != 0) { - glDeleteBuffers(1, &ibo); } + glBindVertexArray(0); } template -void Mesh::draw(unsigned int primitive) const { +void Mesh::draw(unsigned int primitive, int iboIndex) const { MeshStats::drawCalls++; - glBindVertexArray(vao); - if (ibo != 0) { - glDrawElements(primitive, indexCount, GL_UNSIGNED_INT, nullptr); - } else { + + if (!ibos.empty()) { + if (iboIndex < ibos.size()) { + glBindVertexArray(vao); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibos[ + std::min(static_cast(iboIndex), ibos.size()) + ].ibo); + glDrawElements( + primitive, ibos.at(0).indexCount, GL_UNSIGNED_INT, nullptr + ); + glBindVertexArray(0); + } + } else if (vertexCount > 0) { + glBindVertexArray(vao); glDrawArrays(primitive, 0, vertexCount); + glBindVertexArray(0); } - glBindVertexArray(0); } template diff --git a/src/graphics/core/MeshData.hpp b/src/graphics/core/MeshData.hpp index 82954b23..e9a0630c 100644 --- a/src/graphics/core/MeshData.hpp +++ b/src/graphics/core/MeshData.hpp @@ -1,5 +1,6 @@ #pragma once +#include #include #include "typedefs.hpp" @@ -40,7 +41,7 @@ struct VertexAttribute { template struct MeshData { util::Buffer vertices; - util::Buffer indices; + std::vector> indices; util::Buffer attrs; MeshData() = default; @@ -50,7 +51,7 @@ struct MeshData { /// @param attrs vertex attribute sizes (must be null-terminated) MeshData( util::Buffer vertices, - util::Buffer indices, + std::vector> indices, util::Buffer attrs ) : vertices(std::move(vertices)), indices(std::move(indices)), diff --git a/src/graphics/render/BlocksRenderer.cpp b/src/graphics/render/BlocksRenderer.cpp index ae9e5d99..45888543 100644 --- a/src/graphics/render/BlocksRenderer.cpp +++ b/src/graphics/render/BlocksRenderer.cpp @@ -706,6 +706,7 @@ void BlocksRenderer::build(const Chunk* chunk, const Chunks* chunks) { vertexCount = 0; vertexOffset = 0; indexCount = 0; + denseRender = settings.graphics.denseRender.get(); render(voxels, beginEnds); } @@ -714,7 +715,7 @@ ChunkMeshData BlocksRenderer::createMesh() { return ChunkMeshData{ MeshData( util::Buffer(vertexBuffer.get(), vertexCount), - util::Buffer(indexBuffer.get(), indexCount), + std::vector> {util::Buffer(indexBuffer.get(), indexCount)}, util::Buffer( ChunkVertex::ATTRIBUTES, sizeof(ChunkVertex::ATTRIBUTES) / sizeof(VertexAttribute) ) @@ -727,7 +728,8 @@ ChunkMesh BlocksRenderer::render(const Chunk *chunk, const Chunks *chunks) { build(chunk, chunks); return ChunkMesh{std::make_unique>( - vertexBuffer.get(), vertexCount, indexBuffer.get(), indexCount + vertexBuffer.get(), vertexCount, + std::vector {IndexBufferData {indexBuffer.get(), indexCount}} ), std::move(sortingMesh)}; } diff --git a/src/graphics/render/BlocksRenderer.hpp b/src/graphics/render/BlocksRenderer.hpp index 7d950ac4..6f1ff0d6 100644 --- a/src/graphics/render/BlocksRenderer.hpp +++ b/src/graphics/render/BlocksRenderer.hpp @@ -33,6 +33,7 @@ class BlocksRenderer { int voxelBufferPadding = 2; bool overflow = false; bool cancelled = false; + bool denseRender = false; const Chunk* chunk = nullptr; std::unique_ptr voxelsBuffer; @@ -137,7 +138,7 @@ class BlocksRenderer { } if ((variant.culling == CullingMode::DISABLED || (variant.culling == CullingMode::OPTIONAL && - settings.graphics.denseRender.get())) && + denseRender)) && vox.id == def.rt.id) { return true; } diff --git a/src/graphics/render/ChunksRenderer.cpp b/src/graphics/render/ChunksRenderer.cpp index 7238cb19..4f8bfc69 100644 --- a/src/graphics/render/ChunksRenderer.cpp +++ b/src/graphics/render/ChunksRenderer.cpp @@ -89,8 +89,7 @@ ChunksRenderer::ChunksRenderer( logger.info() << "created " << threadPool.getWorkersCount() << " workers"; } -ChunksRenderer::~ChunksRenderer() { -} +ChunksRenderer::~ChunksRenderer() = default; const Mesh* ChunksRenderer::render( const std::shared_ptr& chunk, bool important diff --git a/src/graphics/render/commons.hpp b/src/graphics/render/commons.hpp index 905e34cc..9e78d1f5 100644 --- a/src/graphics/render/commons.hpp +++ b/src/graphics/render/commons.hpp @@ -47,7 +47,7 @@ struct ChunkMeshData { }; struct ChunkMesh { - std::unique_ptr > mesh; + std::unique_ptr> mesh; SortingMeshData sortingMeshData; std::unique_ptr > sortedMesh = nullptr; };