feat: multiple index buffers per mesh support
This commit is contained in:
parent
6debc92ae5
commit
4a6ccf4847
@ -1,5 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include "MeshData.hpp"
|
#include "MeshData.hpp"
|
||||||
|
|
||||||
|
|
||||||
@ -8,25 +10,32 @@ struct MeshStats {
|
|||||||
static int drawCalls;
|
static int drawCalls;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct IndexBufferData {
|
||||||
|
const uint32_t* indices;
|
||||||
|
size_t indicesCount;
|
||||||
|
};
|
||||||
|
|
||||||
template <typename VertexStructure>
|
template <typename VertexStructure>
|
||||||
class Mesh {
|
class Mesh {
|
||||||
|
struct IndexBuffer {
|
||||||
|
unsigned int ibo;
|
||||||
|
size_t indexCount;
|
||||||
|
};
|
||||||
unsigned int vao;
|
unsigned int vao;
|
||||||
unsigned int vbo;
|
unsigned int vbo;
|
||||||
unsigned int ibo;
|
std::vector<IndexBuffer> ibos;
|
||||||
size_t vertexCount;
|
size_t vertexCount;
|
||||||
size_t indexCount;
|
|
||||||
public:
|
public:
|
||||||
explicit Mesh(const MeshData<VertexStructure>& data);
|
explicit Mesh(const MeshData<VertexStructure>& data);
|
||||||
|
|
||||||
Mesh(
|
Mesh(
|
||||||
const VertexStructure* vertexBuffer,
|
const VertexStructure* vertexBuffer,
|
||||||
size_t vertices,
|
size_t vertices,
|
||||||
const uint32_t* indexBuffer,
|
std::vector<IndexBufferData> indices
|
||||||
size_t indices
|
|
||||||
);
|
);
|
||||||
|
|
||||||
Mesh(const VertexStructure* vertexBuffer, size_t vertices)
|
Mesh(const VertexStructure* vertexBuffer, size_t vertices)
|
||||||
: Mesh<VertexStructure>(vertexBuffer, vertices, nullptr, 0) {};
|
: Mesh<VertexStructure>(vertexBuffer, vertices, {}) {};
|
||||||
|
|
||||||
~Mesh();
|
~Mesh();
|
||||||
|
|
||||||
@ -34,18 +43,21 @@ public:
|
|||||||
/// attributes
|
/// attributes
|
||||||
/// @param vertexBuffer vertex data buffer
|
/// @param vertexBuffer vertex data buffer
|
||||||
/// @param vertexCount number of vertices in new buffer
|
/// @param vertexCount number of vertices in new buffer
|
||||||
/// @param indexBuffer indices buffer
|
/// @param indices indices buffer
|
||||||
/// @param indexCount number of values in indices buffer
|
|
||||||
void reload(
|
void reload(
|
||||||
const VertexStructure* vertexBuffer,
|
const VertexStructure* vertexBuffer,
|
||||||
size_t vertexCount,
|
size_t vertexCount,
|
||||||
const uint32_t* indexBuffer = nullptr,
|
const std::vector<IndexBufferData>& indices
|
||||||
size_t indexCount = 0
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
void reload(const VertexStructure* vertexBuffer, size_t vertexCount) {
|
||||||
|
static const std::vector<IndexBufferData> indices {};
|
||||||
|
reload(vertexBuffer, vertexCount, indices);
|
||||||
|
}
|
||||||
|
|
||||||
/// @brief Draw mesh with specified primitives type
|
/// @brief Draw mesh with specified primitives type
|
||||||
/// @param primitive primitives type
|
/// @param iboIndex index of used element buffer
|
||||||
void draw(unsigned int primitive) const;
|
void draw(unsigned int primitive, int iboIndex = 0) const;
|
||||||
|
|
||||||
/// @brief Draw mesh as triangles
|
/// @brief Draw mesh as triangles
|
||||||
void draw() const;
|
void draw() const;
|
||||||
|
|||||||
@ -11,13 +11,21 @@ inline constexpr size_t calc_size(const VertexAttribute attrs[]) {
|
|||||||
return vertexSize;
|
return vertexSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename VertexStructure>
|
||||||
|
inline std::vector<IndexBufferData> convert_to_ibd(const MeshData<VertexStructure>& data) {
|
||||||
|
std::vector<IndexBufferData> indices;
|
||||||
|
for (const auto& buffer : data.indices) {
|
||||||
|
indices.push_back(IndexBufferData {buffer.data(), buffer.size()});
|
||||||
|
}
|
||||||
|
return indices;
|
||||||
|
}
|
||||||
|
|
||||||
template <typename VertexStructure>
|
template <typename VertexStructure>
|
||||||
Mesh<VertexStructure>::Mesh(const MeshData<VertexStructure>& data)
|
Mesh<VertexStructure>::Mesh(const MeshData<VertexStructure>& data)
|
||||||
: Mesh(
|
: Mesh(
|
||||||
data.vertices.data(),
|
data.vertices.data(),
|
||||||
data.vertices.size(),
|
data.vertices.size(),
|
||||||
data.indices.data(),
|
convert_to_ibd<VertexStructure>(data)
|
||||||
data.indices.size()
|
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -25,10 +33,9 @@ template <typename VertexStructure>
|
|||||||
Mesh<VertexStructure>::Mesh(
|
Mesh<VertexStructure>::Mesh(
|
||||||
const VertexStructure* vertexBuffer,
|
const VertexStructure* vertexBuffer,
|
||||||
size_t vertices,
|
size_t vertices,
|
||||||
const uint32_t* indexBuffer,
|
std::vector<IndexBufferData> indices
|
||||||
size_t indices
|
|
||||||
)
|
)
|
||||||
: vao(0), vbo(0), ibo(0), vertexCount(0), indexCount(0) {
|
: vao(0), vbo(0), ibos(), vertexCount(0) {
|
||||||
static_assert(
|
static_assert(
|
||||||
calc_size(VertexStructure::ATTRIBUTES) == sizeof(VertexStructure)
|
calc_size(VertexStructure::ATTRIBUTES) == sizeof(VertexStructure)
|
||||||
);
|
);
|
||||||
@ -39,8 +46,9 @@ Mesh<VertexStructure>::Mesh(
|
|||||||
glGenVertexArrays(1, &vao);
|
glGenVertexArrays(1, &vao);
|
||||||
glGenBuffers(1, &vbo);
|
glGenBuffers(1, &vbo);
|
||||||
|
|
||||||
reload(vertexBuffer, vertices, indexBuffer, indices);
|
reload(vertexBuffer, vertices, std::move(indices));
|
||||||
|
|
||||||
|
glBindVertexArray(vao);
|
||||||
// attributes
|
// attributes
|
||||||
int offset = 0;
|
int offset = 0;
|
||||||
for (int i = 0; attrs[i].count; i++) {
|
for (int i = 0; attrs[i].count; i++) {
|
||||||
@ -65,8 +73,8 @@ Mesh<VertexStructure>::~Mesh() {
|
|||||||
MeshStats::meshesCount--;
|
MeshStats::meshesCount--;
|
||||||
glDeleteVertexArrays(1, &vao);
|
glDeleteVertexArrays(1, &vao);
|
||||||
glDeleteBuffers(1, &vbo);
|
glDeleteBuffers(1, &vbo);
|
||||||
if (ibo != 0) {
|
for (int i = ibos.size() - 1; i >= 0; i--) {
|
||||||
glDeleteBuffers(1, &ibo);
|
glDeleteBuffers(1, &ibos[i].ibo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -74,11 +82,9 @@ template <typename VertexStructure>
|
|||||||
void Mesh<VertexStructure>::reload(
|
void Mesh<VertexStructure>::reload(
|
||||||
const VertexStructure* vertexBuffer,
|
const VertexStructure* vertexBuffer,
|
||||||
size_t vertexCount,
|
size_t vertexCount,
|
||||||
const uint32_t* indexBuffer,
|
const std::vector<IndexBufferData>& indices
|
||||||
size_t indexCount
|
|
||||||
) {
|
) {
|
||||||
this->vertexCount = vertexCount;
|
this->vertexCount = vertexCount;
|
||||||
this->indexCount = indexCount;
|
|
||||||
glBindVertexArray(vao);
|
glBindVertexArray(vao);
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, vbo);
|
glBindBuffer(GL_ARRAY_BUFFER, vbo);
|
||||||
if (vertexBuffer != nullptr && vertexCount != 0) {
|
if (vertexBuffer != nullptr && vertexCount != 0) {
|
||||||
@ -92,30 +98,47 @@ void Mesh<VertexStructure>::reload(
|
|||||||
glBufferData(GL_ARRAY_BUFFER, 0, {}, GL_STREAM_DRAW);
|
glBufferData(GL_ARRAY_BUFFER, 0, {}, GL_STREAM_DRAW);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (indexBuffer != nullptr && indexCount != 0) {
|
for (int i = indices.size(); i < ibos.size(); i++) {
|
||||||
if (ibo == 0) glGenBuffers(1, &ibo);
|
glDeleteBuffers(1, &ibos[i].ibo);
|
||||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 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(
|
glBufferData(
|
||||||
GL_ELEMENT_ARRAY_BUFFER,
|
GL_ELEMENT_ARRAY_BUFFER,
|
||||||
sizeof(uint32_t) * indexCount,
|
sizeof(uint32_t) * indexBuffer.indicesCount,
|
||||||
indexBuffer,
|
indexBuffer.indices,
|
||||||
GL_STATIC_DRAW
|
GL_STATIC_DRAW
|
||||||
);
|
);
|
||||||
} else if (ibo != 0) {
|
|
||||||
glDeleteBuffers(1, &ibo);
|
|
||||||
}
|
}
|
||||||
|
glBindVertexArray(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename VertexStructure>
|
template <typename VertexStructure>
|
||||||
void Mesh<VertexStructure>::draw(unsigned int primitive) const {
|
void Mesh<VertexStructure>::draw(unsigned int primitive, int iboIndex) const {
|
||||||
MeshStats::drawCalls++;
|
MeshStats::drawCalls++;
|
||||||
glBindVertexArray(vao);
|
|
||||||
if (ibo != 0) {
|
if (!ibos.empty()) {
|
||||||
glDrawElements(primitive, indexCount, GL_UNSIGNED_INT, nullptr);
|
if (iboIndex < ibos.size()) {
|
||||||
} else {
|
glBindVertexArray(vao);
|
||||||
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibos[
|
||||||
|
std::min(static_cast<size_t>(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);
|
glDrawArrays(primitive, 0, vertexCount);
|
||||||
|
glBindVertexArray(0);
|
||||||
}
|
}
|
||||||
glBindVertexArray(0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename VertexStructure>
|
template <typename VertexStructure>
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
|
||||||
#include "typedefs.hpp"
|
#include "typedefs.hpp"
|
||||||
@ -40,7 +41,7 @@ struct VertexAttribute {
|
|||||||
template<typename VertexStructure>
|
template<typename VertexStructure>
|
||||||
struct MeshData {
|
struct MeshData {
|
||||||
util::Buffer<VertexStructure> vertices;
|
util::Buffer<VertexStructure> vertices;
|
||||||
util::Buffer<uint32_t> indices;
|
std::vector<util::Buffer<uint32_t>> indices;
|
||||||
util::Buffer<VertexAttribute> attrs;
|
util::Buffer<VertexAttribute> attrs;
|
||||||
|
|
||||||
MeshData() = default;
|
MeshData() = default;
|
||||||
@ -50,7 +51,7 @@ struct MeshData {
|
|||||||
/// @param attrs vertex attribute sizes (must be null-terminated)
|
/// @param attrs vertex attribute sizes (must be null-terminated)
|
||||||
MeshData(
|
MeshData(
|
||||||
util::Buffer<VertexStructure> vertices,
|
util::Buffer<VertexStructure> vertices,
|
||||||
util::Buffer<uint32_t> indices,
|
std::vector<util::Buffer<uint32_t>> indices,
|
||||||
util::Buffer<VertexAttribute> attrs
|
util::Buffer<VertexAttribute> attrs
|
||||||
) : vertices(std::move(vertices)),
|
) : vertices(std::move(vertices)),
|
||||||
indices(std::move(indices)),
|
indices(std::move(indices)),
|
||||||
|
|||||||
@ -706,6 +706,7 @@ void BlocksRenderer::build(const Chunk* chunk, const Chunks* chunks) {
|
|||||||
vertexCount = 0;
|
vertexCount = 0;
|
||||||
vertexOffset = 0;
|
vertexOffset = 0;
|
||||||
indexCount = 0;
|
indexCount = 0;
|
||||||
|
denseRender = settings.graphics.denseRender.get();
|
||||||
|
|
||||||
render(voxels, beginEnds);
|
render(voxels, beginEnds);
|
||||||
}
|
}
|
||||||
@ -714,7 +715,7 @@ ChunkMeshData BlocksRenderer::createMesh() {
|
|||||||
return ChunkMeshData{
|
return ChunkMeshData{
|
||||||
MeshData(
|
MeshData(
|
||||||
util::Buffer(vertexBuffer.get(), vertexCount),
|
util::Buffer(vertexBuffer.get(), vertexCount),
|
||||||
util::Buffer(indexBuffer.get(), indexCount),
|
std::vector<util::Buffer<uint32_t>> {util::Buffer(indexBuffer.get(), indexCount)},
|
||||||
util::Buffer(
|
util::Buffer(
|
||||||
ChunkVertex::ATTRIBUTES, sizeof(ChunkVertex::ATTRIBUTES) / sizeof(VertexAttribute)
|
ChunkVertex::ATTRIBUTES, sizeof(ChunkVertex::ATTRIBUTES) / sizeof(VertexAttribute)
|
||||||
)
|
)
|
||||||
@ -727,7 +728,8 @@ ChunkMesh BlocksRenderer::render(const Chunk *chunk, const Chunks *chunks) {
|
|||||||
build(chunk, chunks);
|
build(chunk, chunks);
|
||||||
|
|
||||||
return ChunkMesh{std::make_unique<Mesh<ChunkVertex>>(
|
return ChunkMesh{std::make_unique<Mesh<ChunkVertex>>(
|
||||||
vertexBuffer.get(), vertexCount, indexBuffer.get(), indexCount
|
vertexBuffer.get(), vertexCount,
|
||||||
|
std::vector<IndexBufferData> {IndexBufferData {indexBuffer.get(), indexCount}}
|
||||||
), std::move(sortingMesh)};
|
), std::move(sortingMesh)};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -33,6 +33,7 @@ class BlocksRenderer {
|
|||||||
int voxelBufferPadding = 2;
|
int voxelBufferPadding = 2;
|
||||||
bool overflow = false;
|
bool overflow = false;
|
||||||
bool cancelled = false;
|
bool cancelled = false;
|
||||||
|
bool denseRender = false;
|
||||||
const Chunk* chunk = nullptr;
|
const Chunk* chunk = nullptr;
|
||||||
std::unique_ptr<VoxelsVolume> voxelsBuffer;
|
std::unique_ptr<VoxelsVolume> voxelsBuffer;
|
||||||
|
|
||||||
@ -137,7 +138,7 @@ class BlocksRenderer {
|
|||||||
}
|
}
|
||||||
if ((variant.culling == CullingMode::DISABLED ||
|
if ((variant.culling == CullingMode::DISABLED ||
|
||||||
(variant.culling == CullingMode::OPTIONAL &&
|
(variant.culling == CullingMode::OPTIONAL &&
|
||||||
settings.graphics.denseRender.get())) &&
|
denseRender)) &&
|
||||||
vox.id == def.rt.id) {
|
vox.id == def.rt.id) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -89,8 +89,7 @@ ChunksRenderer::ChunksRenderer(
|
|||||||
logger.info() << "created " << threadPool.getWorkersCount() << " workers";
|
logger.info() << "created " << threadPool.getWorkersCount() << " workers";
|
||||||
}
|
}
|
||||||
|
|
||||||
ChunksRenderer::~ChunksRenderer() {
|
ChunksRenderer::~ChunksRenderer() = default;
|
||||||
}
|
|
||||||
|
|
||||||
const Mesh<ChunkVertex>* ChunksRenderer::render(
|
const Mesh<ChunkVertex>* ChunksRenderer::render(
|
||||||
const std::shared_ptr<Chunk>& chunk, bool important
|
const std::shared_ptr<Chunk>& chunk, bool important
|
||||||
|
|||||||
@ -47,7 +47,7 @@ struct ChunkMeshData {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct ChunkMesh {
|
struct ChunkMesh {
|
||||||
std::unique_ptr<Mesh<ChunkVertex> > mesh;
|
std::unique_ptr<Mesh<ChunkVertex>> mesh;
|
||||||
SortingMeshData sortingMeshData;
|
SortingMeshData sortingMeshData;
|
||||||
std::unique_ptr<Mesh<ChunkVertex> > sortedMesh = nullptr;
|
std::unique_ptr<Mesh<ChunkVertex> > sortedMesh = nullptr;
|
||||||
};
|
};
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user