From 829ca638cb03e0ad9b39a9529e488b8a9abdf5f0 Mon Sep 17 00:00:00 2001 From: Isuru Samarathunga Date: Mon, 15 Sep 2025 20:28:22 +0530 Subject: [PATCH] Fixes --- Src/IAESandbox/imp/cpp/Game.cpp | 2 +- .../imp/cpp/Components/AtlasRenderer.cpp | 56 +++++++++------- Src/IAEngine/imp/cpp/IAEngine.cpp | 40 +++++++++-- Src/IAEngine/imp/cpp/Nodes/Node.cpp | 6 ++ Src/IAEngine/imp/cpp/Rendering/GPUTexture.cpp | 67 +++++++++++++++---- Src/IAEngine/imp/cpp/Scene.cpp | 6 ++ Src/IAEngine/imp/hpp/stb_image.h | 9 +++ .../inc/IAEngine/Components/AtlasRenderer.hpp | 18 +++-- Src/IAEngine/inc/IAEngine/IAEngine.hpp | 4 +- Src/IAEngine/inc/IAEngine/Nodes/Node.hpp | 2 + .../inc/IAEngine/Rendering/GPUTexture.hpp | 2 + Src/IAEngine/inc/IAEngine/Scene.hpp | 2 + Src/IAEngine/inc/IAEngine/Texture.hpp | 13 ++-- 13 files changed, 170 insertions(+), 57 deletions(-) diff --git a/Src/IAESandbox/imp/cpp/Game.cpp b/Src/IAESandbox/imp/cpp/Game.cpp index f7c7391..c8936bd 100644 --- a/Src/IAESandbox/imp/cpp/Game.cpp +++ b/Src/IAESandbox/imp/cpp/Game.cpp @@ -16,7 +16,7 @@ namespace ia::iae::game { scene = Engine::CreateScene(); scene->YSortingEnabled() = true; - Engine::ChangeScene(scene); + Engine::ChangeScene(scene.get()); g_player = MakeRefPtr(); { diff --git a/Src/IAEngine/imp/cpp/Components/AtlasRenderer.cpp b/Src/IAEngine/imp/cpp/Components/AtlasRenderer.cpp index 85d2909..580f5ec 100644 --- a/Src/IAEngine/imp/cpp/Components/AtlasRenderer.cpp +++ b/Src/IAEngine/imp/cpp/Components/AtlasRenderer.cpp @@ -24,23 +24,42 @@ namespace ia::iae { } - Handle AtlasRendererComponent::AddTexture(IN RefPtr texture) + AtlasRendererComponent::~AtlasRendererComponent() { - m_textures.pushBack(texture); - return m_textures.size() - 1; + m_bakedGPUTexture.reset(); } - VOID AtlasRendererComponent::SetGrid(IN CONST TileGrid &grid) + VOID AtlasRendererComponent::SetGrid(IN INT32 tileWidth, IN INT32 tileHeight, IN INT32 tileCountX, + IN INT32 tileCountY) { - m_tileGrid = grid; - m_tileGrid.m_tileTextures.resize(grid.TileCountX * grid.TileCountY); - for (auto &t : m_tileGrid.m_tileTextures) - t = INVALID_HANDLE; + m_tileGrid = {}; + m_tileGrid.TileWidth = tileWidth; + m_tileGrid.TileHeight = tileHeight; + m_tileGrid.TileCountX = tileCountX; + m_tileGrid.TileCountY = tileCountY; + m_tileGrid.m_tileTextures.resize(m_tileGrid.TileCountX * m_tileGrid.TileCountY); } - VOID AtlasRendererComponent::SetGridTileTexture(IN INT32 x, IN INT32 y, IN Handle textureHandle) + VOID AtlasRendererComponent::SetGridTileTexture(IN INT32 index, IN Texture texture) { - m_tileGrid.m_tileTextures[x + (y * m_tileGrid.TileCountX)] = textureHandle; + m_tileGrid.m_tileTextures[index] = texture; + } + + VOID AtlasRendererComponent::SetGridTileTexture(IN INT32 x, IN INT32 y, IN Texture texture) + { + m_tileGrid.m_tileTextures[x + (y * m_tileGrid.TileCountX)] = texture; + } + + VOID AtlasRendererComponent::BakeGrid() + { + CONST INT32 w = m_tileGrid.TileWidth * m_tileGrid.TileCountX, h = m_tileGrid.TileHeight * m_tileGrid.TileCountY; + Vector handles; + handles.resize(m_tileGrid.TileCountX * m_tileGrid.TileCountY); + for (SIZE_T i = 0; i < handles.size(); i++) + handles[i] = m_tileGrid.m_tileTextures[i].GetHandle(); + m_bakedGPUTexture = GPUTexture::GridCombine(handles.data(), m_tileGrid.TileCountX, m_tileGrid.TileCountY, + m_tileGrid.TileWidth, m_tileGrid.TileHeight); + m_bakedTexture = Texture(m_bakedGPUTexture->GetHandle(), w, h); } VOID AtlasRendererComponent::Update() @@ -49,18 +68,7 @@ namespace ia::iae VOID AtlasRendererComponent::Draw() { - glm::vec3 p{m_node->GetPosition().x, m_node->GetPosition().y, m_node->GetPosition().z}; - for (INT32 y = 0; y < m_tileGrid.TileCountY; y++) - { - for (INT32 x = 0; x < m_tileGrid.TileCountX; x++) - { - const auto t = m_tileGrid.m_tileTextures[x + (y * m_tileGrid.TileCountX)]; - if (t != INVALID_HANDLE) - m_textures[t]->Draw(m_node->SortOffset(), p + m_tileGrid.Position, {1.0f, 1.0f, 1.0f}, 0.0f, false, false, {1.0f, 1.0f, 1.0f, 1.0f}); - p.x += m_tileGrid.TileWidth; - } - p.x = m_node->GetPosition().x; - p.y += m_tileGrid.TileHeight; - } + m_bakedTexture.Draw(m_node->SortOffset(), m_node->GetPosition() + m_tileGrid.Position, {1.0f, 1.0f, 1.0f}, 0.0f, + false, false, {1.0f, 1.0f, 1.0f, 1.0f}); } -} // namespace ia::iae \ No newline at end of file +} // namespace ia::iae diff --git a/Src/IAEngine/imp/cpp/IAEngine.cpp b/Src/IAEngine/imp/cpp/IAEngine.cpp index 990898a..14c4dcd 100644 --- a/Src/IAEngine/imp/cpp/IAEngine.cpp +++ b/Src/IAEngine/imp/cpp/IAEngine.cpp @@ -41,8 +41,7 @@ namespace ia::iae SDL_Window *g_windowHandle{}; Vector> g_gpuTextureRefs; - RefPtr g_activeScene; - + Scene* g_activeScene; BOOL Engine::Initialize(IN CONST InitConfig &config) { @@ -55,7 +54,7 @@ namespace ia::iae } if (!(g_windowHandle = SDL_CreateWindow(config.GameName.c_str(), config.WindowWidth, config.WindowHeight, - SDL_WINDOW_RESIZABLE))) + SDL_WINDOW_RESIZABLE))) { IAE_LOG_ERROR("Couldn't create SDL3 window: ", SDL_GetError()); return false; @@ -140,14 +139,14 @@ namespace ia::iae g_activeScene->Draw(); } - VOID Engine::ChangeScene(IN RefPtr scene) + VOID Engine::ChangeScene(IN Scene* scene) { g_activeScene = scene; } - Scene* Engine::GetActiveScene() + Scene *Engine::GetActiveScene() { - return g_activeScene.get(); + return g_activeScene; } } // namespace ia::iae @@ -181,6 +180,35 @@ namespace ia::iae return Texture(t->GetHandle(), width, height); } + Vector Engine::CreateTextures(IN CONST Vector &encodedData, IN INT32 textureCount) + { + return CreateTextures(encodedData.data(), encodedData.size(), textureCount); + } + + Vector Engine::CreateTextures(IN PCUINT8 encodedData, IN SIZE_T encodedDataSize, IN INT32 textureCount) + { + SIZE_T offset{0}; + Vector result; + INT32 w, h, nrChannels; + for (INT32 i = 0; i < textureCount; i++) + { + SIZE_T readSize{}; + const auto pixels = stbi_load_from_memory(&encodedData[offset], encodedDataSize - offset, &w, &h, + &nrChannels, STBI_rgb_alpha, readSize); + if (!pixels) + THROW_INVALID_DATA("Failed to decode the provided image data"); + result.pushBack(CreateTexture((PCUINT8) pixels, w, h)); + STBI_FREE(pixels); + offset += readSize; + if (offset >= encodedDataSize) + { + IA_RELEASE_ASSERT(i == (textureCount - 1)); + break; + } + } + return result; + } + Sound Engine::CreateSound(IN PCUINT8 audioData, IN SIZE_T audioDataSize) { return Audio::CreateSound(audioData, audioDataSize); diff --git a/Src/IAEngine/imp/cpp/Nodes/Node.cpp b/Src/IAEngine/imp/cpp/Nodes/Node.cpp index cab9647..7a70f44 100644 --- a/Src/IAEngine/imp/cpp/Nodes/Node.cpp +++ b/Src/IAEngine/imp/cpp/Nodes/Node.cpp @@ -20,6 +20,12 @@ namespace ia::iae { + Node::~Node() + { + for (auto &c : m_components) + c.reset(); + } + VOID Node::OnAdded(IN Scene *scene) { m_scene = scene; diff --git a/Src/IAEngine/imp/cpp/Rendering/GPUTexture.cpp b/Src/IAEngine/imp/cpp/Rendering/GPUTexture.cpp index 4a786c0..bf6303f 100644 --- a/Src/IAEngine/imp/cpp/Rendering/GPUTexture.cpp +++ b/Src/IAEngine/imp/cpp/Rendering/GPUTexture.cpp @@ -28,16 +28,14 @@ namespace ia::iae { if (g_defaultSampler) return; - SDL_GPUSamplerCreateInfo createInfo{ - .min_filter = SDL_GPU_FILTER_LINEAR, - .mag_filter = SDL_GPU_FILTER_LINEAR, - .mipmap_mode = SDL_GPU_SAMPLERMIPMAPMODE_LINEAR, - .address_mode_u = SDL_GPU_SAMPLERADDRESSMODE_CLAMP_TO_EDGE, - .address_mode_v = SDL_GPU_SAMPLERADDRESSMODE_CLAMP_TO_EDGE, - .address_mode_w = SDL_GPU_SAMPLERADDRESSMODE_CLAMP_TO_EDGE, - .max_anisotropy = 1.0f, - .enable_anisotropy = true - }; + SDL_GPUSamplerCreateInfo createInfo{.min_filter = SDL_GPU_FILTER_LINEAR, + .mag_filter = SDL_GPU_FILTER_LINEAR, + .mipmap_mode = SDL_GPU_SAMPLERMIPMAPMODE_LINEAR, + .address_mode_u = SDL_GPU_SAMPLERADDRESSMODE_CLAMP_TO_EDGE, + .address_mode_v = SDL_GPU_SAMPLERADDRESSMODE_CLAMP_TO_EDGE, + .address_mode_w = SDL_GPU_SAMPLERADDRESSMODE_CLAMP_TO_EDGE, + .max_anisotropy = 1.0f, + .enable_anisotropy = true}; g_defaultSampler = SDL_CreateGPUSampler(g_gpuDevice, &createInfo); } @@ -59,8 +57,8 @@ namespace ia::iae SDL_GPUTextureCreateInfo createInfo{.type = SDL_GPU_TEXTURETYPE_2D, .format = SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UNORM, .usage = SDL_GPU_TEXTUREUSAGE_SAMPLER, - .width = (UINT32)width, - .height = (UINT32)height, + .width = (UINT32) width, + .height = (UINT32) height, .layer_count_or_depth = 1, .num_levels = 1}; @@ -72,7 +70,7 @@ namespace ia::iae } SDL_GPUTransferBufferCreateInfo stagingBufferCreateInfo{.usage = SDL_GPU_TRANSFERBUFFERUSAGE_UPLOAD, - .size = (UINT32)width * (UINT32)height * 4}; + .size = (UINT32) width * (UINT32) height * 4}; const auto stagingBuffer = SDL_CreateGPUTransferBuffer(g_gpuDevice, &stagingBufferCreateInfo); const auto mappedPtr = SDL_MapGPUTransferBuffer(g_gpuDevice, stagingBuffer, false); SDL_memcpy(mappedPtr, rgbaData, width * height * 4); @@ -81,7 +79,7 @@ namespace ia::iae const auto cmdBuffer = SDL_AcquireGPUCommandBuffer(g_gpuDevice); const auto copyPass = SDL_BeginGPUCopyPass(cmdBuffer); SDL_GPUTextureTransferInfo transferInfo{.transfer_buffer = stagingBuffer, .offset = 0}; - SDL_GPUTextureRegion region{.texture = handle, .w = (UINT32)width, .h = (UINT32)height, .d = 1}; + SDL_GPUTextureRegion region{.texture = handle, .w = (UINT32) width, .h = (UINT32) height, .d = 1}; SDL_UploadToGPUTexture(copyPass, &transferInfo, ®ion, false); SDL_EndGPUCopyPass(copyPass); SDL_SubmitGPUCommandBuffer(cmdBuffer); @@ -92,6 +90,47 @@ namespace ia::iae return res; } + RefPtr GPUTexture::GridCombine(IN Handle *handles, IN INT32 unitCountX, IN INT32 unitCountY, + IN INT32 unitSizeX, IN INT32 unitSizeY) + { + const auto res = MakeRefPtr(); + + SDL_GPUTextureCreateInfo createInfo{.type = SDL_GPU_TEXTURETYPE_2D, + .format = SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UNORM, + .usage = SDL_GPU_TEXTUREUSAGE_SAMPLER, + .width = (UINT32) unitCountX * unitSizeX, + .height = (UINT32) unitCountY * unitSizeY, + .layer_count_or_depth = 1, + .num_levels = 1}; + + SDL_GPUTexture *handle{}; + if (!(handle = SDL_CreateGPUTexture(g_gpuDevice, &createInfo))) + { + IAE_LOG_ERROR("Failed to create a SDL GPU Texture"); + return nullptr; + } + + const auto cmdBuffer = SDL_AcquireGPUCommandBuffer(g_gpuDevice); + const auto copyPass = SDL_BeginGPUCopyPass(cmdBuffer); + + for (INT32 y = 0; y < unitCountY; y++) + { + for (INT32 x = 0; x < unitCountX; x++) + { + SDL_GPUTextureLocation src{.texture = (SDL_GPUTexture *) handles[x + (y * unitCountX)], .x = 0, .y = 0}; + SDL_GPUTextureLocation dst{.texture = handle, .x = (UINT32)(x * unitSizeX), .y = (UINT32)(y * unitSizeY)}; + SDL_CopyGPUTextureToTexture(copyPass, &src, &dst, unitSizeX, unitSizeY, 1, false); + } + } + + SDL_EndGPUCopyPass(copyPass); + SDL_SubmitGPUCommandBuffer(cmdBuffer); + + res->m_handle = (Handle) handle; + + return res; + } + GPUTexture::~GPUTexture() { if (m_handle) diff --git a/Src/IAEngine/imp/cpp/Scene.cpp b/Src/IAEngine/imp/cpp/Scene.cpp index db81fde..b30dfe5 100644 --- a/Src/IAEngine/imp/cpp/Scene.cpp +++ b/Src/IAEngine/imp/cpp/Scene.cpp @@ -18,6 +18,12 @@ namespace ia::iae { + Scene::~Scene() + { + for (auto &n : m_nodes) + n.reset(); + } + VOID Scene::Draw() { for (auto &n : m_nodes) diff --git a/Src/IAEngine/imp/hpp/stb_image.h b/Src/IAEngine/imp/hpp/stb_image.h index d4b5c87..66b1bb7 100644 --- a/Src/IAEngine/imp/hpp/stb_image.h +++ b/Src/IAEngine/imp/hpp/stb_image.h @@ -1433,6 +1433,15 @@ STBIDEF stbi_uc *stbi_load_from_memory(stbi_uc const *buffer, int len, int *x, i return stbi__load_and_postprocess_8bit(&s,x,y,comp,req_comp); } +STBIDEF stbi_uc *stbi_load_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp, size_t& readSize) +{ + stbi__context s; + stbi__start_mem(&s,buffer,len); + const auto data = stbi__load_and_postprocess_8bit(&s,x,y,comp,req_comp); + readSize = s.img_buffer - s.img_buffer_original; + return data; +} + STBIDEF stbi_uc *stbi_load_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp, int req_comp) { stbi__context s; diff --git a/Src/IAEngine/inc/IAEngine/Components/AtlasRenderer.hpp b/Src/IAEngine/inc/IAEngine/Components/AtlasRenderer.hpp index 5380f08..f143a28 100644 --- a/Src/IAEngine/inc/IAEngine/Components/AtlasRenderer.hpp +++ b/Src/IAEngine/inc/IAEngine/Components/AtlasRenderer.hpp @@ -17,6 +17,7 @@ #pragma once #include +#include #include namespace ia::iae @@ -33,19 +34,21 @@ namespace ia::iae INT32 TileCountX{}; INT32 TileCountY{}; - Vector m_tileTextures{}; - + private: + Vector m_tileTextures{}; + friend class AtlasRendererComponent; }; public: AtlasRendererComponent(IN Node *node); + ~AtlasRendererComponent(); public: - Handle AddTexture(IN RefPtr texture); - - VOID SetGrid(IN CONST TileGrid &grid); - VOID SetGridTileTexture(IN INT32 x, IN INT32 y, IN Handle textureHandle); + VOID SetGrid(IN INT32 tileWidth, IN INT32 tileHeight, IN INT32 tileCountX, IN INT32 tileCountY); + VOID SetGridTileTexture(IN INT32 index, IN Texture texture); + VOID SetGridTileTexture(IN INT32 x, IN INT32 y, IN Texture texture); + VOID BakeGrid(); public: VOID Draw(); @@ -53,6 +56,7 @@ namespace ia::iae private: TileGrid m_tileGrid{}; - Vector> m_textures; + Texture m_bakedTexture{}; + RefPtr m_bakedGPUTexture{}; }; } // namespace ia::iae \ No newline at end of file diff --git a/Src/IAEngine/inc/IAEngine/IAEngine.hpp b/Src/IAEngine/inc/IAEngine/IAEngine.hpp index 7eac6b3..5859a77 100644 --- a/Src/IAEngine/inc/IAEngine/IAEngine.hpp +++ b/Src/IAEngine/inc/IAEngine/IAEngine.hpp @@ -47,7 +47,7 @@ namespace ia::iae STATIC VOID EndFrame(); STATIC BOOL ShouldClose(); - STATIC VOID ChangeScene(IN RefPtr scene); + STATIC VOID ChangeScene(IN Scene* scene); STATIC Scene* GetActiveScene(); public: @@ -56,6 +56,8 @@ namespace ia::iae STATIC Texture CreateTexture(IN CONST Vector &encodedData); STATIC Texture CreateTexture(IN PCUINT8 encodedData, IN SIZE_T encodedDataSize); STATIC Texture CreateTexture(IN PCUINT8 rgbaData, IN INT32 width, IN INT32 height); + STATIC Vector CreateTextures(IN CONST Vector &encodedData, IN INT32 textureCount); + STATIC Vector CreateTextures(IN PCUINT8 encodedData, IN SIZE_T encodedDataSize, IN INT32 textureCount); STATIC Sound CreateSound(IN CONST Vector &audioData); STATIC Sound CreateSound(IN PCUINT8 audioData, IN SIZE_T audioDataSize); diff --git a/Src/IAEngine/inc/IAEngine/Nodes/Node.hpp b/Src/IAEngine/inc/IAEngine/Nodes/Node.hpp index b4446db..d8ccc91 100644 --- a/Src/IAEngine/inc/IAEngine/Nodes/Node.hpp +++ b/Src/IAEngine/inc/IAEngine/Nodes/Node.hpp @@ -27,6 +27,8 @@ namespace ia::iae class Node : public Transform { public: + ~Node(); + VIRTUAL VOID OnAdded(IN Scene *scene); VIRTUAL VOID OnRemoved(); diff --git a/Src/IAEngine/inc/IAEngine/Rendering/GPUTexture.hpp b/Src/IAEngine/inc/IAEngine/Rendering/GPUTexture.hpp index 999f5bd..356cfce 100644 --- a/Src/IAEngine/inc/IAEngine/Rendering/GPUTexture.hpp +++ b/Src/IAEngine/inc/IAEngine/Rendering/GPUTexture.hpp @@ -32,6 +32,8 @@ namespace ia::iae STATIC RefPtr Create(IN PCUINT8 rgbaData, IN INT32 width, IN INT32 height); + STATIC RefPtr GridCombine(IN Handle* handles, IN INT32 unitCountX, IN INT32 unitCountY, IN INT32 unitSizeX, IN INT32 unitSizeY); + public: Handle GetHandle() CONST { diff --git a/Src/IAEngine/inc/IAEngine/Scene.hpp b/Src/IAEngine/inc/IAEngine/Scene.hpp index 2f3f3db..b35b321 100644 --- a/Src/IAEngine/inc/IAEngine/Scene.hpp +++ b/Src/IAEngine/inc/IAEngine/Scene.hpp @@ -23,6 +23,8 @@ namespace ia::iae class Scene { public: + ~Scene(); + VOID Draw(); VOID Update(); diff --git a/Src/IAEngine/inc/IAEngine/Texture.hpp b/Src/IAEngine/inc/IAEngine/Texture.hpp index 89abd4c..2d02b44 100644 --- a/Src/IAEngine/inc/IAEngine/Texture.hpp +++ b/Src/IAEngine/inc/IAEngine/Texture.hpp @@ -28,18 +28,23 @@ namespace ia::iae ~Texture(); public: - VOID Draw(IN FLOAT32 sortOffset, IN CONST glm::vec3 &position, IN CONST glm::vec3 &scale, IN FLOAT32 rotation, IN BOOL flipH, - IN BOOL flipV, IN CONST glm::vec4 &colorOverlay) CONST; + VOID Draw(IN FLOAT32 sortOffset, IN CONST glm::vec3 &position, IN CONST glm::vec3 &scale, IN FLOAT32 rotation, + IN BOOL flipH, IN BOOL flipV, IN CONST glm::vec4 &colorOverlay) CONST; public: + Handle GetHandle() CONST + { + return m_handle; + } + INT32 GetWidth() CONST { - return (INT32)m_size.x; + return (INT32) m_size.x; } INT32 GetHeight() CONST { - return (INT32)m_size.y; + return (INT32) m_size.y; } private: