From 94fe5eeb5b5f6f7c73e69db435bd2d2f9c0c7b5b Mon Sep 17 00:00:00 2001 From: MihailRis Date: Sun, 23 Jun 2024 01:57:28 +0300 Subject: [PATCH] update ModelBatch semantics --- src/assets/assetload_funcs.cpp | 6 +-- src/frontend/debug_panel.cpp | 5 ++ src/graphics/core/Mesh.cpp | 2 + src/graphics/core/Mesh.hpp | 1 + src/graphics/render/ModelBatch.cpp | 72 ++++++++++++++++++--------- src/graphics/render/ModelBatch.hpp | 24 ++++++--- src/graphics/render/WorldRenderer.cpp | 22 +++++++- 7 files changed, 97 insertions(+), 35 deletions(-) diff --git a/src/assets/assetload_funcs.cpp b/src/assets/assetload_funcs.cpp index 4a85cb94..b7fe8ccf 100644 --- a/src/assets/assetload_funcs.cpp +++ b/src/assets/assetload_funcs.cpp @@ -122,9 +122,9 @@ assetload::postfunc assetload::font( ) { auto pages = std::make_shared>>(); for (size_t i = 0; i <= 4; i++) { - std::string name = filename + "_" + std::to_string(i) + ".png"; - name = paths->find(name).string(); - pages->push_back(imageio::read(name)); + std::string pagefile = filename + "_" + std::to_string(i) + ".png"; + pagefile = paths->find(pagefile).string(); + pages->push_back(imageio::read(pagefile)); } return [=](auto assets) { int res = pages->at(0)->getHeight() / 16; diff --git a/src/frontend/debug_panel.cpp b/src/frontend/debug_panel.cpp index d61e021f..b49abf89 100644 --- a/src/frontend/debug_panel.cpp +++ b/src/frontend/debug_panel.cpp @@ -62,6 +62,11 @@ std::shared_ptr create_debug_panel( panel->add(create_label([](){ return L"meshes: " + std::to_wstring(Mesh::meshesCount); })); + panel->add(create_label([](){ + int drawCalls = Mesh::drawCalls; + Mesh::drawCalls = 0; + return L"draw-calls: " + std::to_wstring(drawCalls); + })); panel->add(create_label([](){ return L"speakers: " + std::to_wstring(audio::count_speakers())+ L" streams: " + std::to_wstring(audio::count_streams()); diff --git a/src/graphics/core/Mesh.cpp b/src/graphics/core/Mesh.cpp index 45ba2878..ac4e2b14 100644 --- a/src/graphics/core/Mesh.cpp +++ b/src/graphics/core/Mesh.cpp @@ -2,6 +2,7 @@ #include int Mesh::meshesCount = 0; +int Mesh::drawCalls = 0; Mesh::Mesh(const float* vertexBuffer, size_t vertices, const int* indexBuffer, size_t indices, const vattr* attrs) : ibo(0), @@ -60,6 +61,7 @@ void Mesh::reload(const float* vertexBuffer, size_t vertices, const int* indexBu } void Mesh::draw(unsigned int primitive){ + drawCalls++; glBindVertexArray(vao); if (ibo != 0) { glDrawElements(primitive, indices, GL_UNSIGNED_INT, 0); diff --git a/src/graphics/core/Mesh.hpp b/src/graphics/core/Mesh.hpp index 541d396e..abff9d5e 100644 --- a/src/graphics/core/Mesh.hpp +++ b/src/graphics/core/Mesh.hpp @@ -37,6 +37,7 @@ public: /// @brief Total numbers of alive mesh objects static int meshesCount; + static int drawCalls; }; #endif // GRAPHICS_CORE_MESH_HPP_ diff --git a/src/graphics/render/ModelBatch.cpp b/src/graphics/render/ModelBatch.cpp index abbfc073..d314e78b 100644 --- a/src/graphics/render/ModelBatch.cpp +++ b/src/graphics/render/ModelBatch.cpp @@ -50,8 +50,8 @@ ModelBatch::ModelBatch(size_t capacity, Assets* assets, Chunks* chunks) ModelBatch::~ModelBatch() { } -void ModelBatch::draw(const model::Model* model) { - glm::vec3 gpos = combined * glm::vec4(glm::vec3(), 1.0f); +void ModelBatch::draw(const model::Mesh& mesh, const glm::mat4& matrix, const glm::mat3& rotation) { + glm::vec3 gpos = matrix * glm::vec4(glm::vec3(), 1.0f); light_t light = chunks->getLight(gpos.x, gpos.y, gpos.z); glm::vec4 lights ( Lightmap::extract(light, 0) / 15.0f, @@ -59,31 +59,44 @@ void ModelBatch::draw(const model::Model* model) { Lightmap::extract(light, 2) / 15.0f, Lightmap::extract(light, 3) / 15.0f ); - for (const auto& mesh : model->meshes) { - auto texture = assets->get(mesh.texture); - if (texture) { - texture->bind(); - } else { - blank->bind(); + setTexture(assets->get(mesh.texture)); + size_t vcount = mesh.vertices.size(); + const auto& vertexData = mesh.vertices.data(); + for (size_t i = 0; i < vcount / 3; i++) { + if (index + VERTEX_SIZE * 3 > capacity * VERTEX_SIZE) { + flush(); } - for (size_t i = 0; i < mesh.vertices.size() / 3; i++) { - if (index + VERTEX_SIZE * 3 > capacity) { - flush(); - } - for (size_t j = 0; j < 3; j++) { - const auto& vert = mesh.vertices[i * 3 + j]; - auto norm = rotation * vert.normal; - float d = glm::dot(norm, SUN_VECTOR); - d = 0.8f + d * 0.2f; - - auto color = lights * d; - vertex(vert.coord, vert.uv, color); - } + for (size_t j = 0; j < 3; j++) { + const auto& vert = vertexData[i * 3 + j]; + auto norm = rotation * vert.normal; + float d = glm::dot(norm, SUN_VECTOR); + d = 0.8f + d * 0.2f; + + auto color = lights * d; + vertex(matrix * glm::vec4(vert.coord, 1.0f), vert.uv, color); } - flush(); } } +void ModelBatch::draw(const model::Model* model) { + for (const auto& mesh : model->meshes) { + entries.push_back({combined, rotation, &mesh}); + } +} + +void ModelBatch::render() { + std::sort(entries.begin(), entries.end(), + [](const DrawEntry& a, const DrawEntry& b) { + return a.mesh->texture < b.mesh->texture; + } + ); + for (auto& entry : entries) { + draw(*entry.mesh, entry.matrix, entry.rotation); + } + flush(); + entries.clear(); +} + void ModelBatch::box(glm::vec3 pos, glm::vec3 size, glm::vec4 lights) { if (index + 36 < capacity*VERTEX_SIZE) { flush(); @@ -98,11 +111,24 @@ void ModelBatch::box(glm::vec3 pos, glm::vec3 size, glm::vec4 lights) { plane(pos-X*size, Z*size, Y*size, -X, lights); } +void ModelBatch::setTexture(Texture* texture) { + if (texture == nullptr) { + texture = blank.get(); + } + if (texture != this->texture) { + flush(); + } + this->texture = texture; +} + void ModelBatch::flush() { if (index == 0) { return; } - // blank->bind(); + if (texture == nullptr) { + texture = blank.get(); + } + texture->bind(); mesh->reload(buffer.get(), index / VERTEX_SIZE); mesh->draw(); index = 0; diff --git a/src/graphics/render/ModelBatch.hpp b/src/graphics/render/ModelBatch.hpp index 8b949227..ba6f1eed 100644 --- a/src/graphics/render/ModelBatch.hpp +++ b/src/graphics/render/ModelBatch.hpp @@ -11,12 +11,13 @@ class Chunks; class Assets; namespace model { + struct Mesh; struct Model; } class ModelBatch { - std::unique_ptr buffer; - size_t capacity; + std::unique_ptr const buffer; + size_t const capacity; size_t index; std::unique_ptr mesh; @@ -28,6 +29,7 @@ class ModelBatch { Assets* assets; Chunks* chunks; + Texture* texture = nullptr; static inline glm::vec3 SUN_VECTOR {0.411934f, 0.863868f, -0.279161f}; @@ -35,7 +37,6 @@ class ModelBatch { glm::vec3 pos, glm::vec2 uv, glm::vec4 light ) { float* buffer = this->buffer.get(); - pos = combined * glm::vec4(pos, 1.0f); buffer[index++] = pos.x; buffer[index++] = pos.y; buffer[index++] = pos.z; @@ -70,6 +71,18 @@ class ModelBatch { vertex(pos+right+up, {1,1}, color); vertex(pos-right+up, {0,1}, color); } + + void draw(const model::Mesh& mesh, const glm::mat4& matrix, const glm::mat3& rotation); + void box(glm::vec3 pos, glm::vec3 size, glm::vec4 lights); + void setTexture(Texture* texture); + void flush(); + + struct DrawEntry { + glm::mat4 matrix; + glm::mat3 rotation; + const model::Mesh* mesh; + }; + std::vector entries; public: ModelBatch(size_t capacity, Assets* assets, Chunks* chunks); ~ModelBatch(); @@ -80,12 +93,9 @@ public: void pushMatrix(glm::mat4 matrix); void popMatrix(); - - void box(glm::vec3 pos, glm::vec3 size, glm::vec4 lights); - void draw(const model::Model* model); - void flush(); + void render(); }; #endif // GRAPHICS_RENDER_MODEL_BATCH_HPP_ diff --git a/src/graphics/render/WorldRenderer.cpp b/src/graphics/render/WorldRenderer.cpp index 940cef92..ca90013d 100644 --- a/src/graphics/render/WorldRenderer.cpp +++ b/src/graphics/render/WorldRenderer.cpp @@ -50,7 +50,7 @@ WorldRenderer::WorldRenderer(Engine* engine, LevelFrontend* frontend, Player* pl player(player), frustumCulling(std::make_unique()), lineBatch(std::make_unique()), - modelBatch(std::make_unique(1000, engine->getAssets(), level->chunks.get())) + modelBatch(std::make_unique(20'000, engine->getAssets(), level->chunks.get())) { renderer = std::make_unique( level, @@ -195,7 +195,25 @@ void WorldRenderer::renderLevel( drawChunks(level->chunks.get(), camera, shader); shader->uniformMatrix("u_model", glm::mat4(1.0f)); - /// draw models here + if (auto model = assets->get("cube")) { + srand(0); + float timer = Window::time(); + for (size_t i = 0; i < 10000; i++) { + float x = (rand() % 5000)*0.1f; + float y = (rand() % 1000)*0.1f + 60; + float z = (rand() % 5000)*0.1f; + glm::vec3 coord(x, y, z); + int rot = rand() % 1000; + if (frustumCulling->IsBoxVisible(coord, coord)) { + modelBatch->translate(coord); + modelBatch->rotate(glm::vec3(0, 1, 0), timer*3+rot); + modelBatch->draw(model); + modelBatch->popMatrix(); + modelBatch->popMatrix(); + } + } + } + modelBatch->render(); skybox->unbind(); }