diff --git a/private/sdl_gpu_test/gui/ui_renderer.hpp b/private/sdl_gpu_test/gui/ui_renderer.hpp index 1be0512..334e1e3 100644 --- a/private/sdl_gpu_test/gui/ui_renderer.hpp +++ b/private/sdl_gpu_test/gui/ui_renderer.hpp @@ -67,7 +67,7 @@ class UIRenderer public: using primitive_id_t = std::uint64_t; - static constexpr std::uint64_t UNSET_PRIMITIVE_ID = 0; + static constexpr primitive_id_t UNSET_PRIMITIVE_ID = 0; private: Application* mApplication = nullptr; sdlpp::GPUBuffer mVertexBuffer; diff --git a/private/sdl_gpu_test/scene/mesh.cpp b/private/sdl_gpu_test/scene/mesh.cpp index 18ae6eb..99c4079 100644 --- a/private/sdl_gpu_test/scene/mesh.cpp +++ b/private/sdl_gpu_test/scene/mesh.cpp @@ -15,6 +15,7 @@ void MeshNode::setMesh(std::string resourcePath) if (mScene != nullptr) { updateMesh(); + updateSceneMesh(); } } @@ -25,6 +26,7 @@ void MeshNode::setTexture(std::string resourcePath) if (mScene != nullptr) { updateTexture(); + updateSceneMesh(); } } @@ -34,6 +36,7 @@ void MeshNode::handleEnteredScene() updateMesh(); updateTexture(); + updateSceneMesh(); } void MeshNode::updateMesh() @@ -59,4 +62,16 @@ void MeshNode::updateTexture() mTexture = mScene->getRenderer().getTexture(mTexturePath); } } + +void MeshNode::updateSceneMesh() +{ + if (mMeshId == SceneRenderer::UNSET_MESH_ID || !mScene->getRenderer().updateRenderListEntry(mMeshId, { + .mesh = mMesh, + .texture = mTexture, + .transform = mTransform + })) + { + mScene->getRenderer().addMeshToRenderList(mMesh, mTexture, mTransform, mMeshId); + } +} } diff --git a/private/sdl_gpu_test/scene/mesh.hpp b/private/sdl_gpu_test/scene/mesh.hpp index f4a94ac..4e5f849 100644 --- a/private/sdl_gpu_test/scene/mesh.hpp +++ b/private/sdl_gpu_test/scene/mesh.hpp @@ -25,6 +25,7 @@ private: std::shared_ptr mTexture; std::string mMeshPath; std::string mTexturePath; + SceneRenderer::mesh_id_t mMeshId = SceneRenderer::UNSET_MESH_ID; public: MeshNode(MeshNodeCreateArgs args); @@ -35,6 +36,7 @@ public: private: void updateMesh(); void updateTexture(); + void updateSceneMesh(); }; } // namespace sdl_gpu_test diff --git a/private/sdl_gpu_test/scene/scene.cpp b/private/sdl_gpu_test/scene/scene.cpp index 28fd78f..ed00490 100644 --- a/private/sdl_gpu_test/scene/scene.cpp +++ b/private/sdl_gpu_test/scene/scene.cpp @@ -38,5 +38,6 @@ void Scene::init(const SceneInitArgs& args) { MIJIN_ASSERT_FATAL(args.renderer != nullptr, "Missing parameter: renderer."); mRenderer = args.renderer; + mRootNode.enterScene(this, nullptr); } } diff --git a/private/sdl_gpu_test/scene/scene.hpp b/private/sdl_gpu_test/scene/scene.hpp index 3b5075a..ce326e2 100644 --- a/private/sdl_gpu_test/scene/scene.hpp +++ b/private/sdl_gpu_test/scene/scene.hpp @@ -42,6 +42,8 @@ public: } private: void enterScene(Scene* scene, SceneNode* parent); + + friend class Scene; }; struct SceneInitArgs diff --git a/private/sdl_gpu_test/scene/scene_renderer.cpp b/private/sdl_gpu_test/scene/scene_renderer.cpp index 3cd3d79..f43bd00 100644 --- a/private/sdl_gpu_test/scene/scene_renderer.cpp +++ b/private/sdl_gpu_test/scene/scene_renderer.cpp @@ -22,6 +22,7 @@ void SceneRenderer::init(Application& application) { mApplication = &application; + createPipeline(); mSampler.create(mApplication->getDevice(), {}); } @@ -61,13 +62,13 @@ std::shared_ptr SceneRenderer::getTexture(const std::string& resou mCachedTextures.erase(it); } - const Bitmap bitmap = loadBitmap(mApplication->getFileSystem().getPath(resourcePath)); - std::shared_ptr result = std::make_shared(); - result->texture.create(mApplication->getDevice(), { + sdlpp::GPUTextureCreateArgs textureArgs = + { .format = sdlpp::GPUTextureFormat::R8G8B8A8_UNORM_SRGB, .usage = {.sampler = true} - }); - mApplication->uploadTextureData(result->texture, bitmap); + }; + std::shared_ptr result = std::make_shared(); + result->texture = mApplication->loadTexture(resourcePath, textureArgs); mCachedTextures.emplace(resourcePath, result); return result; } @@ -117,6 +118,72 @@ void SceneRenderer::render(const SceneRendererRenderArgs& args) renderPass.end(); } +void SceneRenderer::addMeshToRenderList(std::shared_ptr mesh, std::shared_ptr texture, + const Transform3D& transform, mesh_id_t& inOutMeshId) +{ + if (inOutMeshId == UNSET_MESH_ID) + { + inOutMeshId = mNextMeshId; + ++mNextMeshId; + } + mRenderList.push_back({ + .mesh = std::move(mesh), + .texture = std::move(texture), + .transform = transform, + .meshId = inOutMeshId + }); +} + +bool SceneRenderer::removeMeshFromRenderList(SceneRenderer::mesh_id_t meshId) +{ + if (meshId == UNSET_MESH_ID) + { + return false; + } + + auto it = std::find_if(mRenderList.begin(), mRenderList.end(), [&](const RenderListEntry& entry) + { + return entry.meshId == meshId; + }); + if (it == mRenderList.end()) + { + return false; + } + mRenderList.erase(it); + return true; +} + +bool SceneRenderer::updateRenderListEntry(mesh_id_t meshId, const RenderListUpdate& update) +{ + if (meshId == UNSET_MESH_ID) + { + return false; + } + + auto it = std::find_if(mRenderList.begin(), mRenderList.end(), [&](const RenderListEntry& entry) + { + return entry.meshId == meshId; + }); + if (it == mRenderList.end()) + { + return false; + } + + if (update.mesh.has_value()) + { + it->mesh = *update.mesh; + } + if (update.texture.has_value()) + { + it->texture = *update.texture; + } + if (update.transform.has_value()) + { + it->transform = *update.transform; + } + return true; +} + void SceneRenderer::createPipeline() { // create shaders diff --git a/private/sdl_gpu_test/scene/scene_renderer.hpp b/private/sdl_gpu_test/scene/scene_renderer.hpp index 4ce11c8..f77a18f 100644 --- a/private/sdl_gpu_test/scene/scene_renderer.hpp +++ b/private/sdl_gpu_test/scene/scene_renderer.hpp @@ -4,6 +4,7 @@ #if !defined(SDL_GPU_TEST_PRIVATE_SDL_GPU_TEST_SCENE_SCENE_RENDERER_HPP_INCLUDED) #define SDL_GPU_TEST_PRIVATE_SDL_GPU_TEST_SCENE_SCENE_RENDERER_HPP_INCLUDED 1 +#include #include #include #include @@ -34,23 +35,33 @@ struct SceneRendererRenderArgs unsigned targetTextureHeight; }; +struct RenderListUpdate +{ + std::optional> mesh; + std::optional> texture; + std::optional transform; +}; + class SceneRenderer { public: - using mesh_idx_t = std::uint64_t; + using mesh_id_t = std::uint64_t; + + static constexpr mesh_id_t UNSET_MESH_ID = 0; private: struct RenderListEntry { std::shared_ptr mesh; std::shared_ptr texture; Transform3D transform; - mesh_idx_t meshIdx; + mesh_id_t meshId; }; Application* mApplication = nullptr; std::unordered_map> mCachedMeshes; std::unordered_map> mCachedTextures; std::vector mRenderList; + mesh_id_t mNextMeshId = 1; sdlpp::GPUGraphicsPipeline mPipeline; sdlpp::GPUSampler mSampler; @@ -63,6 +74,11 @@ public: [[nodiscard]] std::shared_ptr getTexture(const std::string& resourcePath); + void addMeshToRenderList(std::shared_ptr mesh, std::shared_ptr texture, + const Transform3D& transform, mesh_id_t& inOutMeshId); + bool removeMeshFromRenderList(mesh_id_t meshId); + bool updateRenderListEntry(mesh_id_t meshId, const RenderListUpdate& update); + void render(const SceneRendererRenderArgs& args); private: void createPipeline();