diff --git a/include/renderer.h b/include/renderer.h index 69fec30..34d4dec 100644 --- a/include/renderer.h +++ b/include/renderer.h @@ -8,6 +8,7 @@ #include #include "gfx_device.h" +#include "systems/mesh_render_system.h" namespace engine { @@ -31,7 +32,8 @@ class Renderer { void PreRender(bool window_is_resized, glm::mat4 camera_transform); - void Render(); + // staticList can be nullptr to render nothing + void Render(const StaticRenderList* staticList); // getters diff --git a/include/scene_manager.h b/include/scene_manager.h index 298a6f2..e86ad78 100644 --- a/include/scene_manager.h +++ b/include/scene_manager.h @@ -21,7 +21,8 @@ class SceneManager { // creates an empty scene and sets it as active Scene* CreateEmptyScene(); - void UpdateActiveScene(float ts); +// returns active scene, nullptr if no scene active + Scene* UpdateActiveScene(float ts); Scene* GetActiveScene() { return scenes_.at(active_scene_index_).get(); } private: diff --git a/include/systems/mesh_render_system.h b/include/systems/mesh_render_system.h index 407182e..11ac826 100644 --- a/include/systems/mesh_render_system.h +++ b/include/systems/mesh_render_system.h @@ -9,7 +9,7 @@ namespace engine { -struct MeshRenderListEntry { +struct StaticRenderListEntry { const gfx::Pipeline* pipeline; const gfx::Buffer* vertex_buffer; const gfx::Buffer* index_buffer; @@ -18,18 +18,21 @@ struct MeshRenderListEntry { uint32_t index_count; }; +using StaticRenderList = std::vector; + class MeshRenderSystem : public System { public: MeshRenderSystem(Scene* scene); ~MeshRenderSystem(); void RebuildRenderList(); + const StaticRenderList* GetStaticRenderList() const { return &static_render_list_; } void OnComponentInsert(uint32_t entity) override; void OnUpdate(float ts) override; private: - std::vector static_render_list_; + StaticRenderList static_render_list_; bool list_needs_rebuild_ = false; }; diff --git a/include/util/model_loader.h b/include/util/model_loader.h index 0af7223..7728129 100644 --- a/include/util/model_loader.h +++ b/include/util/model_loader.h @@ -8,7 +8,7 @@ namespace engine { namespace util { -uint32_t LoadMeshFromFile(Scene* parent, const std::string& path); +uint32_t LoadMeshFromFile(Scene* parent, const std::string& path, bool is_static = false); } // namespace util } // namespace engine diff --git a/src/application.cpp b/src/application.cpp index 9e6abab..464a0e9 100644 --- a/src/application.cpp +++ b/src/application.cpp @@ -17,6 +17,8 @@ #include "resources/mesh.h" #include "resources/shader.h" #include "resources/texture.h" +#include "systems/mesh_render_system.h" +#include "components/transform.h" #include "scene.h" #include "scene_manager.h" #include "window.h" @@ -148,8 +150,7 @@ Application::Application(const char* appName, const char* appVersion, } } -Application::~Application() { -} +Application::~Application() {} void Application::GameLoop() { LOG_DEBUG("Begin game loop..."); @@ -165,19 +166,24 @@ void Application::GameLoop() { // single-threaded game loop while (window_->IsRunning()) { /* logic */ - scene_manager_->UpdateActiveScene(window_->dt()); + Scene* scene = scene_manager_->UpdateActiveScene(window_->dt()); uint64_t now = window_->GetNanos(); if (now - lastTick >= 1000000000LL * 5LL) [[unlikely]] { lastTick = now; LOG_INFO("fps: {}", window_->GetAvgFPS()); - //renderer()->GetDevice()->LogPerformanceInfo(); + // renderer()->GetDevice()->LogPerformanceInfo(); window_->ResetAvgFPS(); } /* render */ - renderer_->PreRender(window()->GetWindowResized(), glm::mat4{1.0f}); - renderer_->Render(); + renderer_->PreRender(window()->GetWindowResized(), scene->GetComponent(scene->GetEntity("camera"))->world_matrix); + + const StaticRenderList* staticList = nullptr; + if (scene) { + staticList = scene->GetSystem()->GetStaticRenderList(); + } + renderer_->Render(staticList); /* poll events */ window_->GetInputAndEvents(); @@ -190,7 +196,7 @@ void Application::GameLoop() { endFrame = beginFrame + FRAMETIME_LIMIT; } - renderer()->GetDevice()->WaitIdle(); + renderer_->GetDevice()->WaitIdle(); } } // namespace engine diff --git a/src/renderer.cpp b/src/renderer.cpp index e5c89c2..88298f0 100644 --- a/src/renderer.cpp +++ b/src/renderer.cpp @@ -90,10 +90,39 @@ void Renderer::PreRender(bool window_is_resized, glm::mat4 camera_transform) { &frame_uniform.uniform_buffer_data); } -void Renderer::Render() -{ +void Renderer::Render(const StaticRenderList* staticList) { 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); + } + } + device_->FinishRender(draw_buffer); } diff --git a/src/scene_manager.cpp b/src/scene_manager.cpp index 5421f26..6672f9a 100644 --- a/src/scene_manager.cpp +++ b/src/scene_manager.cpp @@ -22,12 +22,16 @@ namespace engine { return scenes_.back().get(); } - void SceneManager::UpdateActiveScene(float ts) + Scene* SceneManager::UpdateActiveScene(float ts) { if (active_scene_index_ >= 0) [[likely]] { assert((size_t)active_scene_index_ < scenes_.size()); - scenes_[active_scene_index_]->Update(ts); - } + Scene* activeScene = scenes_[active_scene_index_].get(); + activeScene->Update(ts); + return activeScene; + } else { + return nullptr; + } } } diff --git a/src/systems/mesh_render_system.cpp b/src/systems/mesh_render_system.cpp index 31bca17..e30c5f3 100644 --- a/src/systems/mesh_render_system.cpp +++ b/src/systems/mesh_render_system.cpp @@ -30,7 +30,7 @@ void MeshRenderSystem::RebuildRenderList() { const gfx::Pipeline* pipeline = renderable->material->GetShader()->GetPipeline(); - static_render_list_.emplace_back(MeshRenderListEntry{ + static_render_list_.emplace_back(StaticRenderListEntry{ .pipeline = pipeline, .vertex_buffer = renderable->mesh->GetVB(), .index_buffer = renderable->mesh->GetIB(), @@ -47,8 +47,8 @@ void MeshRenderSystem::RebuildRenderList() { // sort the meshes by pipeline auto sort_by_pipeline = [&render_orders]( - const MeshRenderListEntry& e1, - const MeshRenderListEntry& e2) -> bool { + const StaticRenderListEntry& e1, + const StaticRenderListEntry& e2) -> bool { return (render_orders.at(e1.pipeline) < render_orders.at(e2.pipeline)); }; @@ -74,6 +74,7 @@ void MeshRenderSystem::RebuildRenderList() { } void MeshRenderSystem::OnComponentInsert(uint32_t entity) { + (void)entity; list_needs_rebuild_ = true; } diff --git a/src/util/model_loader.cpp b/src/util/model_loader.cpp index efb801b..7ee772b 100644 --- a/src/util/model_loader.cpp +++ b/src/util/model_loader.cpp @@ -31,7 +31,7 @@ namespace engine::util { const std::map>& textures, const std::vector>& meshes, const std::vector& meshTextureIndices, - aiNode* parentNode, Scene* scene, uint32_t parentObj) + aiNode* parentNode, Scene* scene, uint32_t parentObj, bool is_static) { // convert to glm column major @@ -71,10 +71,12 @@ namespace engine::util { parentTransform->position = position; parentTransform->scale = scale; parentTransform->rotation = rotation; + parentTransform->is_static = is_static; for (uint32_t i = 0; i < parentNode->mNumMeshes; i++) { // create child node for each mesh auto child = scene->CreateEntity("_mesh" + std::to_string(i), parentObj); + scene->GetComponent(child)->is_static = is_static; auto childRenderer = scene->AddComponent(child); childRenderer->mesh = meshes[parentNode->mMeshes[i]]; childRenderer->material = std::make_shared(scene->app()->GetResource("builtin.standard")); @@ -92,12 +94,12 @@ namespace engine::util { meshTextureIndices, parentNode->mChildren[i], scene, - scene->CreateEntity("child" + std::to_string(i), parentObj) + scene->CreateEntity("child" + std::to_string(i), parentObj), is_static ); } } - uint32_t LoadMeshFromFile(Scene* parent, const std::string& path) + uint32_t LoadMeshFromFile(Scene* parent, const std::string& path, bool is_static) { Assimp::Importer importer; @@ -231,7 +233,7 @@ namespace engine::util { uint32_t obj = parent->CreateEntity(scene->GetShortFilename(path.c_str())); - buildGraph(textures, meshes, meshMaterialIndices, scene->mRootNode, parent, obj); + buildGraph(textures, meshes, meshMaterialIndices, scene->mRootNode, parent, obj, is_static); LOG_INFO("Loaded model: {}, meshes: {}, textures: {}", scene->GetShortFilename(path.c_str()), meshes.size(), textures.size()); diff --git a/test/src/game.cpp b/test/src/game.cpp index bf0d2c1..7db7c9e 100644 --- a/test/src/game.cpp +++ b/test/src/game.cpp @@ -53,7 +53,7 @@ void PlayGame(GameSettings settings) { engine::Application app(PROJECT_NAME, PROJECT_VERSION, graphics_settings); app.SetFrameLimiter(settings.enable_frame_limiter); - app.window()->SetRelativeMouseMode(false); + app.window()->SetRelativeMouseMode(true); ConfigureInputs(app.input_manager()); { @@ -79,14 +79,14 @@ void PlayGame(GameSettings settings) { } /* shared resources */ - /* auto grass_texture = std::make_shared( + auto grass_texture = std::make_shared( app.renderer(), app.GetResourcePath("textures/grass.jpg"), engine::resources::Texture::Filtering::kAnisotropic); auto space_texture = std::make_shared( app.renderer(), app.GetResourcePath("textures/space2.png"), engine::resources::Texture::Filtering::kAnisotropic); - */ + /* skybox */ { uint32_t skybox = my_scene->CreateEntity("skybox"); @@ -97,7 +97,7 @@ void PlayGame(GameSettings settings) { std::make_unique( app.GetResource("builtin.skybox")); skybox_renderable->material->texture_ = - app.GetResource("builtin.white"); + space_texture; skybox_renderable->mesh = GenCuboidMesh(app.renderer()->GetDevice(), 10.0f, 10.0f, 10.0f, 1.0f, true); @@ -122,7 +122,7 @@ void PlayGame(GameSettings settings) { std::make_shared( app.GetResource("builtin.standard")); floor_renderable->material->texture_ = - app.GetResource("builtin.white"); + grass_texture; floor_renderable->mesh = GenCuboidMesh(app.renderer()->GetDevice(), 100.0f, 0.1f, 100.0f, 100.0f); @@ -135,20 +135,20 @@ void PlayGame(GameSettings settings) { // engine::util::LoadMeshFromFile(my_scene, // app.GetResourcePath("models/test_scene.dae")); - //auto cobbleHouse = engine::util::LoadMeshFromFile( - // my_scene, app.GetResourcePath("models/cobble_house/cobble_house.dae")); - //my_scene->GetComponent(cobbleHouse)->position += - // glm::vec3{33.0f, 0.1f, 35.0f}; - //auto cobbleCustom = - // my_scene->AddComponent(cobbleHouse); - //cobbleCustom->onInit = [](void) { - // LOG_INFO("Cobble house spin component initialised!"); - //}; - //cobbleCustom->onUpdate = [&](float ts) { - // static auto t = - // my_scene->GetComponent(cobbleHouse); - // t->rotation *= glm::angleAxis(ts, glm::vec3{0.0f, 0.0f, 1.0f}); - //}; + auto cobbleHouse = engine::util::LoadMeshFromFile( + my_scene, app.GetResourcePath("models/cobble_house/cobble_house.dae"), true); + my_scene->GetComponent(cobbleHouse)->position += + glm::vec3{33.0f, 0.1f, 35.0f}; + auto cobbleCustom = + my_scene->AddComponent(cobbleHouse); + cobbleCustom->onInit = [](void) { + LOG_INFO("Cobble house spin component initialised!"); + }; + cobbleCustom->onUpdate = [&](float ts) { + static auto t = + my_scene->GetComponent(cobbleHouse); + t->rotation *= glm::angleAxis(ts, glm::vec3{0.0f, 0.0f, 1.0f}); + }; /* some text */ {