From 977da197e22206d6583f042a77378e3523ab83c6 Mon Sep 17 00:00:00 2001 From: bailwillharr Date: Thu, 31 Aug 2023 14:18:42 +0100 Subject: [PATCH] Render dynamic meshes --- include/renderer.h | 6 +- include/systems/mesh_render_system.h | 16 ++-- src/application.cpp | 7 +- src/renderer.cpp | 70 +++++++++------- src/systems/mesh_render_system.cpp | 119 ++++++++++++++------------- test/src/game.cpp | 5 +- 6 files changed, 127 insertions(+), 96 deletions(-) diff --git a/include/renderer.h b/include/renderer.h index 34d4dec..dc0f7c1 100644 --- a/include/renderer.h +++ b/include/renderer.h @@ -33,7 +33,7 @@ class Renderer { void PreRender(bool window_is_resized, glm::mat4 camera_transform); // staticList can be nullptr to render nothing - void Render(const StaticRenderList* staticList); + void Render(const RenderList* static_list, const RenderList* dynamic_list); // getters @@ -88,6 +88,10 @@ class Renderer { const gfx::DescriptorSetLayout* material_set_layout; // set 2 float viewport_aspect_ratio_ = 1.0f; + + const gfx::Pipeline* last_bound_pipeline_ = nullptr; + + void DrawRenderList(gfx::DrawBuffer* draw_buffer, const RenderList& render_list); }; } // namespace engine diff --git a/include/systems/mesh_render_system.h b/include/systems/mesh_render_system.h index 11ac826..b644af9 100644 --- a/include/systems/mesh_render_system.h +++ b/include/systems/mesh_render_system.h @@ -9,7 +9,7 @@ namespace engine { -struct StaticRenderListEntry { +struct RenderListEntry { const gfx::Pipeline* pipeline; const gfx::Buffer* vertex_buffer; const gfx::Buffer* index_buffer; @@ -18,23 +18,29 @@ struct StaticRenderListEntry { uint32_t index_count; }; -using StaticRenderList = std::vector; +using RenderList = std::vector; class MeshRenderSystem : public System { public: MeshRenderSystem(Scene* scene); ~MeshRenderSystem(); - void RebuildRenderList(); - const StaticRenderList* GetStaticRenderList() const { return &static_render_list_; } + void RebuildStaticRenderList(); + const RenderList* GetStaticRenderList() const { return &static_render_list_; } + const RenderList* GetDynamicRenderList() const { return &dynamic_render_list_; } void OnComponentInsert(uint32_t entity) override; void OnUpdate(float ts) override; private: - StaticRenderList static_render_list_; + RenderList static_render_list_; + RenderList dynamic_render_list_; bool list_needs_rebuild_ = false; + // with_static_entities = false, build list of dynamic meshes + // with_static_entities = true, build list of static meshes + void BuildRenderList(RenderList& render_list, bool with_static_entities); + }; } // namespace engine diff --git a/src/application.cpp b/src/application.cpp index 464a0e9..b82ae75 100644 --- a/src/application.cpp +++ b/src/application.cpp @@ -179,11 +179,12 @@ void Application::GameLoop() { /* render */ renderer_->PreRender(window()->GetWindowResized(), scene->GetComponent(scene->GetEntity("camera"))->world_matrix); - const StaticRenderList* staticList = nullptr; if (scene) { - staticList = scene->GetSystem()->GetStaticRenderList(); + auto mesh_render_system = scene->GetSystem(); + const RenderList* static_list = mesh_render_system->GetStaticRenderList(); + const RenderList* dynamic_list = mesh_render_system->GetDynamicRenderList(); + renderer_->Render(static_list, dynamic_list); } - renderer_->Render(staticList); /* poll events */ window_->GetInputAndEvents(); diff --git a/src/renderer.cpp b/src/renderer.cpp index 88298f0..f3a9c02 100644 --- a/src/renderer.cpp +++ b/src/renderer.cpp @@ -90,40 +90,52 @@ void Renderer::PreRender(bool window_is_resized, glm::mat4 camera_transform) { &frame_uniform.uniform_buffer_data); } -void Renderer::Render(const StaticRenderList* staticList) { +void Renderer::Render(const RenderList* static_list, + const RenderList* dynamic_list) { + assert(static_list != nullptr); + assert(dynamic_list != nullptr); + + last_bound_pipeline_ = nullptr; + gfx::DrawBuffer* draw_buffer = device_->BeginRender(); - if (staticList && !staticList->empty()) { - const gfx::Pipeline* const first_pipeline = staticList->begin()->pipeline; - device_->CmdBindDescriptorSet(draw_buffer, first_pipeline, - global_uniform.set, 0); - device_->CmdBindDescriptorSet(draw_buffer, first_pipeline, - frame_uniform.set, 1); - - device_->CmdBindPipeline(draw_buffer, first_pipeline); - const gfx::Pipeline* last_bound_pipeline = first_pipeline; - - for (const auto& entry : *staticList) { - if (entry.pipeline != last_bound_pipeline) { - device_->CmdBindPipeline(draw_buffer, entry.pipeline); - last_bound_pipeline = entry.pipeline; - } - device_->CmdBindDescriptorSet(draw_buffer, entry.pipeline, - entry.base_colour_texture, 2); - device_->CmdPushConstants(draw_buffer, entry.pipeline, 0, - sizeof(entry.model_matrix), - &entry.model_matrix); - if (entry.vertex_buffer) { - device_->CmdBindVertexBuffer(draw_buffer, 0, entry.vertex_buffer); - } - if (entry.index_buffer) { - device_->CmdBindIndexBuffer(draw_buffer, entry.index_buffer); - } - device_->CmdDrawIndexed(draw_buffer, entry.index_count, 1, 0, 0, 0); - } + if (!static_list->empty()) { + DrawRenderList(draw_buffer, *static_list); + } + if (!dynamic_list->empty()) { + DrawRenderList(draw_buffer, *dynamic_list); } device_->FinishRender(draw_buffer); } +void Renderer::DrawRenderList(gfx::DrawBuffer* draw_buffer, + const RenderList& render_list) { + // if a pipeline hasn't been bound yet at all + if (last_bound_pipeline_ == nullptr) { + const gfx::Pipeline* first_pipeline = render_list.begin()->pipeline; + // these bindings persist between all pipelines + device_->CmdBindDescriptorSet(draw_buffer, first_pipeline, + global_uniform.set, 0); + device_->CmdBindDescriptorSet(draw_buffer, first_pipeline, + frame_uniform.set, 1); + device_->CmdBindPipeline(draw_buffer, first_pipeline); + last_bound_pipeline_ = first_pipeline; + } + + for (const auto& entry : render_list) { + if (entry.pipeline != last_bound_pipeline_) { + device_->CmdBindPipeline(draw_buffer, entry.pipeline); + last_bound_pipeline_ = entry.pipeline; + } + device_->CmdBindDescriptorSet(draw_buffer, entry.pipeline, + entry.base_colour_texture, 2); + device_->CmdPushConstants(draw_buffer, entry.pipeline, 0, + sizeof(entry.model_matrix), &entry.model_matrix); + device_->CmdBindVertexBuffer(draw_buffer, 0, entry.vertex_buffer); + device_->CmdBindIndexBuffer(draw_buffer, entry.index_buffer); + device_->CmdDrawIndexed(draw_buffer, entry.index_count, 1, 0, 0, 0); + } +} + } // namespace engine \ No newline at end of file diff --git a/src/systems/mesh_render_system.cpp b/src/systems/mesh_render_system.cpp index e30c5f3..bb56408 100644 --- a/src/systems/mesh_render_system.cpp +++ b/src/systems/mesh_render_system.cpp @@ -14,62 +14,8 @@ MeshRenderSystem::MeshRenderSystem(Scene* scene) MeshRenderSystem::~MeshRenderSystem() {} -void MeshRenderSystem::RebuildRenderList() { - static_render_list_.clear(); - static_render_list_.reserve(entities_.size()); - - std::unordered_map render_orders; - - for (uint32_t entity : entities_) { - auto transform = scene_->GetComponent(entity); - - if (transform->is_static == false) continue; - - auto renderable = scene_->GetComponent(entity); - - const gfx::Pipeline* pipeline = - renderable->material->GetShader()->GetPipeline(); - - static_render_list_.emplace_back(StaticRenderListEntry{ - .pipeline = pipeline, - .vertex_buffer = renderable->mesh->GetVB(), - .index_buffer = renderable->mesh->GetIB(), - .base_colour_texture = - renderable->material->texture_->GetDescriptorSet(), - .model_matrix = transform->world_matrix, - .index_count = renderable->mesh->GetCount()}); - - if (render_orders.contains(pipeline) == false) { - render_orders.emplace( - pipeline, renderable->material->GetShader()->GetRenderOrder()); - } - } - - // sort the meshes by pipeline - auto sort_by_pipeline = [&render_orders]( - const StaticRenderListEntry& e1, - const StaticRenderListEntry& e2) -> bool { - return (render_orders.at(e1.pipeline) < render_orders.at(e2.pipeline)); - }; - - std::sort(static_render_list_.begin(), static_render_list_.end(), - sort_by_pipeline); - -#ifndef NDEBUG - LOG_TRACE("\nPRINTING RENDER LIST:\n"); - for (const auto& entry : static_render_list_) { - LOG_TRACE("pipeline: {}", static_cast(entry.pipeline)); - LOG_TRACE("vertex_buffer: {}", - static_cast(entry.vertex_buffer)); - LOG_TRACE("index_buffer: {}", static_cast(entry.index_buffer)); - LOG_TRACE("base_color_texture: {}", - static_cast(entry.base_colour_texture)); - LOG_TRACE("transform position: {}, {}, {}", entry.model_matrix[3][0], - entry.model_matrix[3][1], entry.model_matrix[3][2]); - } - LOG_TRACE("\nRENDER LIST END\n"); -#endif - +void MeshRenderSystem::RebuildStaticRenderList() { + BuildRenderList(static_render_list_, true); list_needs_rebuild_ = false; } @@ -81,7 +27,66 @@ void MeshRenderSystem::OnComponentInsert(uint32_t entity) { void MeshRenderSystem::OnUpdate(float ts) { // do stuff (void)ts; - if (list_needs_rebuild_) RebuildRenderList(); + if (list_needs_rebuild_) { + RebuildStaticRenderList(); + } + BuildRenderList(dynamic_render_list_, false); +} + +void MeshRenderSystem::BuildRenderList(RenderList& render_list, + bool with_static_entities) { + render_list.clear(); + render_list.reserve(entities_.size()); + + std::unordered_map render_orders; + + for (uint32_t entity : entities_) { + auto transform = scene_->GetComponent(entity); + + if (transform->is_static != with_static_entities) continue; + + auto renderable = scene_->GetComponent(entity); + + const gfx::Pipeline* pipeline = + renderable->material->GetShader()->GetPipeline(); + + render_list.emplace_back( + RenderListEntry{.pipeline = pipeline, + .vertex_buffer = renderable->mesh->GetVB(), + .index_buffer = renderable->mesh->GetIB(), + .base_colour_texture = + renderable->material->texture_->GetDescriptorSet(), + .model_matrix = transform->world_matrix, + .index_count = renderable->mesh->GetCount()}); + + if (render_orders.contains(pipeline) == false) { + render_orders.emplace( + pipeline, renderable->material->GetShader()->GetRenderOrder()); + } + } + + // sort the meshes by pipeline + auto sort_by_pipeline = [&render_orders](const RenderListEntry& e1, + const RenderListEntry& e2) -> bool { + return (render_orders.at(e1.pipeline) < render_orders.at(e2.pipeline)); + }; + + std::sort(render_list.begin(), render_list.end(), sort_by_pipeline); + +#if 0 + LOG_TRACE("\nPRINTING RENDER LIST ({})\n", with_static_entities ? "STATIC" : "DYNAMIC"); + for (const auto& entry : render_list) { + LOG_TRACE("pipeline: {}", static_cast(entry.pipeline)); + LOG_TRACE("vertex_buffer: {}", + static_cast(entry.vertex_buffer)); + LOG_TRACE("index_buffer: {}", static_cast(entry.index_buffer)); + LOG_TRACE("base_color_texture: {}", + static_cast(entry.base_colour_texture)); + LOG_TRACE("transform position: {}, {}, {}", entry.model_matrix[3][0], + entry.model_matrix[3][1], entry.model_matrix[3][2]); + } + LOG_TRACE("\nRENDER LIST END\n"); +#endif } } // namespace engine diff --git a/test/src/game.cpp b/test/src/game.cpp index 7db7c9e..2da12ee 100644 --- a/test/src/game.cpp +++ b/test/src/game.cpp @@ -136,7 +136,7 @@ void PlayGame(GameSettings settings) { // app.GetResourcePath("models/test_scene.dae")); auto cobbleHouse = engine::util::LoadMeshFromFile( - my_scene, app.GetResourcePath("models/cobble_house/cobble_house.dae"), true); + my_scene, app.GetResourcePath("models/cobble_house/cobble_house.dae"), false); my_scene->GetComponent(cobbleHouse)->position += glm::vec3{33.0f, 0.1f, 35.0f}; auto cobbleCustom = @@ -148,6 +148,9 @@ void PlayGame(GameSettings settings) { static auto t = my_scene->GetComponent(cobbleHouse); t->rotation *= glm::angleAxis(ts, glm::vec3{0.0f, 0.0f, 1.0f}); + if (app.window()->GetKeyPress(engine::inputs::Key::K_F)) { + my_scene->GetSystem()->RebuildStaticRenderList(); + } }; /* some text */