Compare commits

...

4 Commits

Author SHA1 Message Date
594180c5d3 Camera2D 2025-09-13 17:46:11 +05:30
3687a70aba Add GLM 2025-09-13 15:09:51 +05:30
62edc71750 Remove IAMath 2025-09-13 14:55:15 +05:30
50f3f14c47 Texture Rendering 2025-09-13 14:12:08 +05:30
47 changed files with 550 additions and 231 deletions

7
.gitmodules vendored
View File

@ -11,7 +11,6 @@
path = Dependencies/IACore path = Dependencies/IACore
url = https://git.iasoft.dev/dev0/IACore url = https://git.iasoft.dev/dev0/IACore
branch = main branch = main
[submodule "Dependencies/IAMath"] [submodule "Vendor/glm"]
path = Dependencies/IAMath path = Vendor/glm
url = https://git.iasoft.dev/dev0/IAMath url = https://github.com/g-truc/glm
branch = main

View File

@ -9,6 +9,7 @@
"tuple": "cpp", "tuple": "cpp",
"type_traits": "cpp", "type_traits": "cpp",
"xmemory": "cpp", "xmemory": "cpp",
"xtr1common": "cpp" "xtr1common": "cpp",
"chrono": "cpp"
} }
} }

View File

@ -9,10 +9,11 @@ set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
project(IAEngine) project(IAEngine)
add_compile_definitions("__IA_DEBUG=1")
add_subdirectory(Vendor/) add_subdirectory(Vendor/)
add_subdirectory(Dependencies/IACore) add_subdirectory(Dependencies/IACore)
add_subdirectory(Dependencies/IAMath)
add_subdirectory(Src/IAEngine) add_subdirectory(Src/IAEngine)
add_subdirectory(Src/IAESandbox) add_subdirectory(Src/IAESandbox)

1
Dependencies/IAMath vendored

Submodule Dependencies/IAMath deleted from 450d6b4ecc

View File

@ -3,6 +3,9 @@
#include <Ground.hpp> #include <Ground.hpp>
#include <IAEngine/ResourceManager.hpp> #include <IAEngine/ResourceManager.hpp>
#include <IAEngine/Rendering/Camera.hpp>
#include <IACore/File.hpp>
namespace ia::iae::game namespace ia::iae::game
{ {
@ -10,6 +13,8 @@ namespace ia::iae::game
ResourceManager* g_resourceManager{}; ResourceManager* g_resourceManager{};
RefPtr<Texture> g_tex;
VOID Game::Initialize() VOID Game::Initialize()
{ {
g_resourceManager = m_engine->RegisterResourceManager<ResourceManager>(); g_resourceManager = m_engine->RegisterResourceManager<ResourceManager>();
@ -18,15 +23,21 @@ namespace ia::iae::game
m_engine->ChangeScene(scene); m_engine->ChangeScene(scene);
iae::Renderer::AddDebugUIWindow("Debug Window", {100, 100}, {100, 200}, [](){}); iae::Renderer::AddDebugUIWindow("Debug Window", {100, 100}, {100, 200}, [](){});
const auto d = File::ReadToVector("Graphics/1.jpg");
g_tex = g_resourceManager->CreateTexture(d.data(), d.size());
} }
VOID Game::Terminate() VOID Game::Terminate()
{ {
g_tex.reset();
} }
VOID Game::Update() VOID Game::Update()
{ {
g_tex->Draw({200.0f, 150.0f, 0.0f}, {1.0f, 1.0f, 1.0f}, 0.0f, false, false, {1.0f, 1.0f, 1.0f, 1.0f});
iae::Renderer::GetCamera()->Position().x += 0.1f;
} }
} }

View File

@ -27,8 +27,8 @@ namespace ia::iae::game
m_spriteRenderer->AddAnimation({.ShouldLoop = true, .Keys = {keyFrame}}); m_spriteRenderer->AddAnimation({.ShouldLoop = true, .Keys = {keyFrame}});
m_spriteRenderer->BakeAnimations(); m_spriteRenderer->BakeAnimations();
m_id2 = Physics::CreateStaticBody({GetPosition().X + 300, GetPosition().Y + 25}); //m_id2 = Physics::CreateStaticBody({GetPosition().X + 300, GetPosition().Y + 25});
Physics::AddBoxCollider(m_id2, {600.0f, 50.0f}); //Physics::AddBoxCollider(m_id2, {600.0f, 50.0f});
} }
VOID Ground::OnRemoved() VOID Ground::OnRemoved()

View File

@ -28,8 +28,8 @@ namespace ia::iae::game
m_spriteRenderer->AddAnimation({.ShouldLoop = true, .Keys = {keyFrame}}); m_spriteRenderer->AddAnimation({.ShouldLoop = true, .Keys = {keyFrame}});
m_spriteRenderer->BakeAnimations(); m_spriteRenderer->BakeAnimations();
m_id = Physics::CreateDynamicBody({GetPosition().X + 20, GetPosition().Y + 20}); //m_id = Physics::CreateDynamicBody({GetPosition().X + 20, GetPosition().Y + 20});
Physics::AddBoxCollider(m_id, {40.0f, 40.0f}); //Physics::AddBoxCollider(m_id, {40.0f, 40.0f});
} }
VOID Player::OnRemoved() VOID Player::OnRemoved()
@ -46,6 +46,6 @@ namespace ia::iae::game
VOID Player::Update() VOID Player::Update()
{ {
Node::Update(); Node::Update();
SetLocalPosition(Physics::GetBodyPosition(m_id) - iam::Vec3f{20.0f, 20.0f, 0.0f}); SetLocalPosition(Physics::GetBodyPosition(m_id) - glm::vec3{20.0f, 20.0f, 0.0f});
} }
} // namespace ia::iae::game } // namespace ia::iae::game

View File

@ -6,13 +6,14 @@ set(IAEngine_Sources
imp/cpp/Input.cpp imp/cpp/Input.cpp
imp/cpp/Scene.cpp imp/cpp/Scene.cpp
imp/cpp/Random.cpp imp/cpp/Random.cpp
imp/cpp/Texture.cpp
imp/cpp/ResourceManager.cpp imp/cpp/ResourceManager.cpp
imp/cpp/Rendering/Camera.cpp imp/cpp/Rendering/Camera.cpp
imp/cpp/Rendering/Texture.cpp
imp/cpp/Rendering/Renderer.cpp imp/cpp/Rendering/Renderer.cpp
imp/cpp/Rendering/GPUBuffer.cpp imp/cpp/Rendering/GPUBuffer.cpp
imp/cpp/Rendering/GPUTexture.cpp
imp/cpp/Rendering/Mesh/Quad.cpp imp/cpp/Rendering/Mesh/Quad.cpp
@ -39,5 +40,5 @@ add_library(IAEngine STATIC ${IAEngine_Sources})
target_include_directories(IAEngine PUBLIC inc/) target_include_directories(IAEngine PUBLIC inc/)
target_include_directories(IAEngine PRIVATE imp/hpp) target_include_directories(IAEngine PRIVATE imp/hpp)
target_link_libraries(IAEngine PUBLIC IACore IAMath ImGui) target_link_libraries(IAEngine PUBLIC IACore ImGui glm::glm)
target_link_libraries(IAEngine PRIVATE SDL3::SDL3 SDL3_mixer::SDL3_mixer) target_link_libraries(IAEngine PRIVATE SDL3::SDL3 SDL3_mixer::SDL3_mixer)

View File

@ -49,7 +49,7 @@ namespace ia::iae
VOID AtlasRendererComponent::Draw() VOID AtlasRendererComponent::Draw()
{ {
iam::Vec3f p{m_node->GetPosition().X, m_node->GetPosition().Y, m_node->GetPosition().Z}; 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 y = 0; y < m_tileGrid.TileCountY; y++)
{ {
for (INT32 x = 0; x < m_tileGrid.TileCountX; x++) for (INT32 x = 0; x < m_tileGrid.TileCountX; x++)
@ -57,10 +57,10 @@ namespace ia::iae
const auto t = m_tileGrid.m_tileTextures[x + (y * m_tileGrid.TileCountX)]; const auto t = m_tileGrid.m_tileTextures[x + (y * m_tileGrid.TileCountX)];
if (t != INVALID_HANDLE) if (t != INVALID_HANDLE)
m_textures[t]->Draw(p + m_tileGrid.Position, {1.0f, 1.0f, 1.0f}, 0.0f, false, false, {1.0f, 1.0f, 1.0f, 1.0f}); m_textures[t]->Draw(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_tileGrid.TileWidth;
} }
p.X = m_node->GetPosition().X; p.x = m_node->GetPosition().x;
p.Y += m_tileGrid.TileHeight; p.y += m_tileGrid.TileHeight;
} }
} }
} // namespace ia::iae } // namespace ia::iae

View File

@ -20,8 +20,6 @@
#include <IAEngine/Time.hpp> #include <IAEngine/Time.hpp>
#include <IAMath/Lerp.hpp>
namespace ia::iae namespace ia::iae
{ {
SpriteRendererComponent::SpriteRendererComponent(IN Node *node) : IComponent(node) SpriteRendererComponent::SpriteRendererComponent(IN Node *node) : IComponent(node)
@ -71,7 +69,7 @@ namespace ia::iae
if(!animFrame.Texture) return; if(!animFrame.Texture) return;
animFrame.Texture->Draw( animFrame.Texture->Draw(
m_node->GetPosition() + animFrame.Position, m_node->GetScale() * animFrame.Scale, m_node->GetPosition() + animFrame.Position, m_node->GetScale() * animFrame.Scale,
m_node->GetRotation().Z + animFrame.Rotation.Z, m_isFlippedH, m_isFlippedV, animFrame.ColorOverlay); m_node->GetRotation().z + animFrame.Rotation.z, m_isFlippedH, m_isFlippedV, animFrame.ColorOverlay);
} }
VOID SpriteRendererComponent::UpdateAnimation() VOID SpriteRendererComponent::UpdateAnimation()
@ -86,10 +84,10 @@ namespace ia::iae
#define INTERP_PROPERTY(name) \ #define INTERP_PROPERTY(name) \
m_currentAnimationState.name = iam::Lerp(m_prevAnimationKeyFrame.name, m_nextAnimationKeyFrame.name, t); m_currentAnimationState.name = iam::Lerp(m_prevAnimationKeyFrame.name, m_nextAnimationKeyFrame.name, t);
INTERP_PROPERTY(Position); //INTERP_PROPERTY(Position); [IATODO]
INTERP_PROPERTY(Rotation); //INTERP_PROPERTY(Rotation);
INTERP_PROPERTY(Scale); //INTERP_PROPERTY(Scale);
INTERP_PROPERTY(ColorOverlay); //INTERP_PROPERTY(ColorOverlay);
#undef INTERP_PROPERTY #undef INTERP_PROPERTY
} }

View File

@ -33,6 +33,6 @@ namespace ia::iae
{ {
m_texture->Draw( m_texture->Draw(
m_node->GetPosition() + m_position, m_node->GetScale(), m_node->GetPosition() + m_position, m_node->GetScale(),
m_node->GetRotation().Z, false, false, iam::Vec4f{1.0f, 1.0f, 1.0f, 1.0f}); m_node->GetRotation().z, false, false, glm::vec4{1.0f, 1.0f, 1.0f, 1.0f});
} }
} // namespace ia::iae } // namespace ia::iae

View File

@ -84,6 +84,8 @@ namespace ia::iae
{ {
IAE_LOG_INFO("Shutting down IAEngine"); IAE_LOG_INFO("Shutting down IAEngine");
m_resourceManager.reset();
Physics::Terminate(); Physics::Terminate();
Audio::Terminate(); Audio::Terminate();
Renderer::Terminate(); Renderer::Terminate();

View File

@ -22,27 +22,27 @@ namespace ia::iae
{ {
struct InputDirection struct InputDirection
{ {
iam::Vec2f Velocity{}; glm::vec2 Velocity{};
Input::DirectionalInput Direction{Input::DirectionalInput::NONE}; Input::DirectionalInput Direction{Input::DirectionalInput::NONE};
}; };
STATIC CONSTEXPR InputDirection INPUT_TO_DIRECTION_MAP[] = { STATIC CONSTEXPR InputDirection INPUT_TO_DIRECTION_MAP[] = {
{iam::Vec2f{0.0f, 0.0f}, Input::DirectionalInput::NONE}, /* 0 */ {glm::vec2{0.0f, 0.0f}, Input::DirectionalInput::NONE}, /* 0 */
{iam::Vec2f{1.0f, 0.0f}, Input::DirectionalInput::RIGHT}, /* D */ {glm::vec2{1.0f, 0.0f}, Input::DirectionalInput::RIGHT}, /* D */
{iam::Vec2f{-1.0f, 0.0f}, Input::DirectionalInput::LEFT}, /* A */ {glm::vec2{-1.0f, 0.0f}, Input::DirectionalInput::LEFT}, /* A */
{iam::Vec2f{0.0f, 0.0f}, Input::DirectionalInput::NONE}, /* A, D */ {glm::vec2{0.0f, 0.0f}, Input::DirectionalInput::NONE}, /* A, D */
{iam::Vec2f{0.0f, 1.0f}, Input::DirectionalInput::DOWN}, /* S */ {glm::vec2{0.0f, 1.0f}, Input::DirectionalInput::DOWN}, /* S */
{iam::Vec2f{1.0f, 1.0f}, Input::DirectionalInput::DOWN_RIGHT}, /* S, D */ {glm::vec2{1.0f, 1.0f}, Input::DirectionalInput::DOWN_RIGHT}, /* S, D */
{iam::Vec2f{-1.0f, 1.0f}, Input::DirectionalInput::DOWN_LEFT}, /* S, A */ {glm::vec2{-1.0f, 1.0f}, Input::DirectionalInput::DOWN_LEFT}, /* S, A */
{iam::Vec2f{0.0f, 0.0f}, Input::DirectionalInput::NONE}, /* S, A, D */ {glm::vec2{0.0f, 0.0f}, Input::DirectionalInput::NONE}, /* S, A, D */
{iam::Vec2f{0.0f, -1.0f}, Input::DirectionalInput::UP}, /* W */ {glm::vec2{0.0f, -1.0f}, Input::DirectionalInput::UP}, /* W */
{iam::Vec2f{1.0f, -1.0f}, Input::DirectionalInput::UP_RIGHT}, /* W, D */ {glm::vec2{1.0f, -1.0f}, Input::DirectionalInput::UP_RIGHT}, /* W, D */
{iam::Vec2f{-1.0f, -1.0f}, Input::DirectionalInput::UP_LEFT}, /* W, A */ {glm::vec2{-1.0f, -1.0f}, Input::DirectionalInput::UP_LEFT}, /* W, A */
{iam::Vec2f{0.0f, 0.0f}, Input::DirectionalInput::NONE}, /* W, A, D */ {glm::vec2{0.0f, 0.0f}, Input::DirectionalInput::NONE}, /* W, A, D */
{iam::Vec2f{0.0f, 0.0f}, Input::DirectionalInput::NONE}, /* W, S */ {glm::vec2{0.0f, 0.0f}, Input::DirectionalInput::NONE}, /* W, S */
{iam::Vec2f{0.0f, 0.0f}, Input::DirectionalInput::NONE}, /* W, S, D */ {glm::vec2{0.0f, 0.0f}, Input::DirectionalInput::NONE}, /* W, S, D */
{iam::Vec2f{0.0f, 0.0f}, Input::DirectionalInput::NONE}, /* W, S, A */ {glm::vec2{0.0f, 0.0f}, Input::DirectionalInput::NONE}, /* W, S, A */
{iam::Vec2f{0.0f, 0.0f}, Input::DirectionalInput::NONE}, /* W, S, A, D */ {glm::vec2{0.0f, 0.0f}, Input::DirectionalInput::NONE}, /* W, S, A, D */
}; };
BOOL Input::s_keys[256]; BOOL Input::s_keys[256];
@ -68,14 +68,14 @@ namespace ia::iae
memcpy(s_prevKeys, s_keys, sizeof(s_prevKeys)); memcpy(s_prevKeys, s_keys, sizeof(s_prevKeys));
} }
iam::Vec2f Input::GetDirectionalInput() glm::vec2 Input::GetDirectionalInput()
{ {
return INPUT_TO_DIRECTION_MAP[(IsKeyDown(Input::KEY_W) << 3) | (IsKeyDown(Input::KEY_S) << 2) | return INPUT_TO_DIRECTION_MAP[(IsKeyDown(Input::KEY_W) << 3) | (IsKeyDown(Input::KEY_S) << 2) |
(IsKeyDown(Input::KEY_A) << 1) | (IsKeyDown(Input::KEY_D) << 0)] (IsKeyDown(Input::KEY_A) << 1) | (IsKeyDown(Input::KEY_D) << 0)]
.Velocity; .Velocity;
} }
iam::Vec2f Input::GetDirectionalInput(OUT DirectionalInput &direction) glm::vec2 Input::GetDirectionalInput(OUT DirectionalInput &direction)
{ {
const auto dir = INPUT_TO_DIRECTION_MAP[(IsKeyDown(Input::KEY_W) << 3) | (IsKeyDown(Input::KEY_S) << 2) | const auto dir = INPUT_TO_DIRECTION_MAP[(IsKeyDown(Input::KEY_W) << 3) | (IsKeyDown(Input::KEY_S) << 2) |
(IsKeyDown(Input::KEY_A) << 1) | (IsKeyDown(Input::KEY_D) << 0)]; (IsKeyDown(Input::KEY_A) << 1) | (IsKeyDown(Input::KEY_D) << 0)];

View File

@ -39,12 +39,12 @@ namespace ia::iae
BOOL drew = false; BOOL drew = false;
for (auto &n : m_children) for (auto &n : m_children)
{ {
if (((INT32) n->GetPosition().Z) >= 0) if (((INT32) n->GetPosition().z) >= 0)
continue; continue;
n->Draw(); n->Draw();
} }
if(((INT32) GetPosition().Z) < 0) if(((INT32) GetPosition().z) < 0)
{ {
for (auto &c : m_components) for (auto &c : m_components)
c->Draw(); c->Draw();
@ -54,11 +54,11 @@ namespace ia::iae
{ {
for (auto &n : m_children) for (auto &n : m_children)
{ {
if (((INT32) n->GetPosition().Z) != i) if (((INT32) n->GetPosition().z) != i)
continue; continue;
n->Draw(); n->Draw();
} }
if (((INT32) GetPosition().Z) == i) if (((INT32) GetPosition().z) == i)
{ {
for (auto &c : m_components) for (auto &c : m_components)
c->Draw(); c->Draw();
@ -67,12 +67,12 @@ namespace ia::iae
for (auto &n : m_children) for (auto &n : m_children)
{ {
if (((INT32) n->GetPosition().Z) < 8) if (((INT32) n->GetPosition().z) < 8)
continue; continue;
n->Draw(); n->Draw();
} }
if(((INT32) GetPosition().Z) > 8) if(((INT32) GetPosition().z) > 8)
{ {
for (auto &c : m_components) for (auto &c : m_components)
c->Draw(); c->Draw();

View File

@ -32,21 +32,21 @@ namespace ia::iae
{ {
} }
Handle Physics::CreateStaticBody(IN iam::Vec3f position) Handle Physics::CreateStaticBody(IN glm::vec3 position)
{ {
return INVALID_HANDLE; return INVALID_HANDLE;
} }
Handle Physics::CreateDynamicBody(IN iam::Vec3f position) Handle Physics::CreateDynamicBody(IN glm::vec3 position)
{ {
return INVALID_HANDLE; return INVALID_HANDLE;
} }
VOID Physics::AddBoxCollider(IN Handle body, IN iam::Vec3f size) VOID Physics::AddBoxCollider(IN Handle body, IN glm::vec3 size)
{ {
} }
iam::Vec3f Physics::GetBodyPosition(IN Handle body) glm::vec3 Physics::GetBodyPosition(IN Handle body)
{ {
return {}; return {};
} }

View File

@ -13,3 +13,10 @@
// //
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>. // along with this program. If not, see <https://www.gnu.org/licenses/>.
#include <IAEngine/Rendering/Camera.hpp>
namespace ia::iae
{
}

View File

@ -21,64 +21,81 @@
namespace ia::iae namespace ia::iae
{ {
EXTERN SDL_GPUDevice *g_gpuDevice; EXTERN SDL_GPUDevice *g_gpuDevice;
UINT32 g_stagingBufferSize = 4096;
SDL_GPUTransferBuffer* g_stagingBuffer{};
RefPtr<GPUBuffer> GPUBuffer::Create(IN PCVOID data, IN UINT32 dataSize) UINT32 g_stagingBufferSize = 4096;
SDL_GPUTransferBuffer *g_stagingBuffer{};
RefPtr<GPUBuffer> GPUBuffer::Create(IN Usage usage, IN PCVOID data, IN UINT32 dataSize)
{ {
const auto res = MakeRefPtr<GPUBuffer>(); const auto res = MakeRefPtr<GPUBuffer>();
SDL_GPUBufferCreateInfo createInfo{ SDL_GPUBufferUsageFlags _usage{};
.usage = SDL_GPU_BUFFERUSAGE_VERTEX, switch (usage)
.size = dataSize {
}; case Usage::VERTEX:
SDL_GPUBuffer* handle{}; _usage = SDL_GPU_BUFFERUSAGE_VERTEX;
if(!(handle = SDL_CreateGPUBuffer(g_gpuDevice, &createInfo))) break;
case Usage::INDEX:
_usage = SDL_GPU_BUFFERUSAGE_INDEX;
break;
case Usage::STORAGE:
_usage = SDL_GPU_BUFFERUSAGE_GRAPHICS_STORAGE_READ;
break;
default:
THROW_INVALID_DATA("Invalid usage value for GPUBuffer");
break;
}
res->m_usage = usage;
SDL_GPUBufferCreateInfo createInfo{.usage = _usage, .size = dataSize};
SDL_GPUBuffer *handle{};
if (!(handle = SDL_CreateGPUBuffer(g_gpuDevice, &createInfo)))
{ {
IAE_LOG_ERROR("Couldn't create a SDL3 GPU Buffer: ", SDL_GetError()); IAE_LOG_ERROR("Couldn't create a SDL3 GPU Buffer: ", SDL_GetError());
return nullptr; return nullptr;
} }
if(data && dataSize) if (data && dataSize)
{ {
if(!EnsureStagingBufferSize((UINT32)dataSize)) if (!EnsureStagingBufferSize((UINT32) dataSize))
return nullptr; return nullptr;
res->m_size = dataSize;
const auto mappedPtr = SDL_MapGPUTransferBuffer(g_gpuDevice, g_stagingBuffer, false); const auto mappedPtr = SDL_MapGPUTransferBuffer(g_gpuDevice, g_stagingBuffer, false);
memcpy(mappedPtr, data, dataSize); memcpy(mappedPtr, data, dataSize);
SDL_UnmapGPUTransferBuffer(g_gpuDevice, g_stagingBuffer); SDL_UnmapGPUTransferBuffer(g_gpuDevice, g_stagingBuffer);
const auto cmdBuffer = SDL_AcquireGPUCommandBuffer(g_gpuDevice); const auto cmdBuffer = SDL_AcquireGPUCommandBuffer(g_gpuDevice);
const auto copyPass = SDL_BeginGPUCopyPass(cmdBuffer); const auto copyPass = SDL_BeginGPUCopyPass(cmdBuffer);
SDL_GPUTransferBufferLocation src{ SDL_GPUTransferBufferLocation src{.transfer_buffer = g_stagingBuffer, .offset = 0};
.transfer_buffer = g_stagingBuffer, SDL_GPUBufferRegion dst{.buffer = handle, .offset = 0, .size = dataSize};
.offset = 0
};
SDL_GPUBufferRegion dst{
.buffer = handle,
.offset = 0,
.size = dataSize
};
SDL_UploadToGPUBuffer(copyPass, &src, &dst, false); SDL_UploadToGPUBuffer(copyPass, &src, &dst, false);
SDL_EndGPUCopyPass(copyPass); SDL_EndGPUCopyPass(copyPass);
SDL_SubmitGPUCommandBuffer(cmdBuffer); SDL_SubmitGPUCommandBuffer(cmdBuffer);
} }
res->m_handle = (Handle)handle; res->m_handle = (Handle) handle;
return res; return res;
} }
GPUBuffer::~GPUBuffer()
{
if (m_handle)
SDL_ReleaseGPUBuffer(g_gpuDevice, (SDL_GPUBuffer *) m_handle);
}
BOOL GPUBuffer::InitializeStagingBuffer() BOOL GPUBuffer::InitializeStagingBuffer()
{ {
SDL_GPUTransferBufferCreateInfo createInfo{ SDL_GPUTransferBufferCreateInfo createInfo{.usage = SDL_GPU_TRANSFERBUFFERUSAGE_UPLOAD,
.usage = SDL_GPU_TRANSFERBUFFERUSAGE_UPLOAD, .size = g_stagingBufferSize};
.size = g_stagingBufferSize if (!(g_stagingBuffer = SDL_CreateGPUTransferBuffer(g_gpuDevice, &createInfo)))
};
if(!(g_stagingBuffer = SDL_CreateGPUTransferBuffer(g_gpuDevice, &createInfo)))
{ {
IAE_LOG_ERROR("Couldn't create a SDL3 GPU Staging Buffer: ", SDL_GetError()); IAE_LOG_ERROR("Couldn't create a SDL3 GPU Staging Buffer: ", SDL_GetError());
return false; return false;
@ -88,7 +105,7 @@ namespace ia::iae
VOID GPUBuffer::TerminateStagingBuffer() VOID GPUBuffer::TerminateStagingBuffer()
{ {
if(!g_stagingBuffer) if (!g_stagingBuffer)
return; return;
SDL_ReleaseGPUTransferBuffer(g_gpuDevice, g_stagingBuffer); SDL_ReleaseGPUTransferBuffer(g_gpuDevice, g_stagingBuffer);
@ -96,16 +113,14 @@ namespace ia::iae
BOOL GPUBuffer::EnsureStagingBufferSize(IN UINT32 size) BOOL GPUBuffer::EnsureStagingBufferSize(IN UINT32 size)
{ {
if(!g_stagingBuffer) if (!g_stagingBuffer)
return false; return false;
if(size <= g_stagingBufferSize) if (size <= g_stagingBufferSize)
return true; return true;
SDL_ReleaseGPUTransferBuffer(g_gpuDevice, g_stagingBuffer); SDL_ReleaseGPUTransferBuffer(g_gpuDevice, g_stagingBuffer);
SDL_GPUTransferBufferCreateInfo createInfo{ SDL_GPUTransferBufferCreateInfo createInfo{.usage = SDL_GPU_TRANSFERBUFFERUSAGE_UPLOAD,
.usage = SDL_GPU_TRANSFERBUFFERUSAGE_UPLOAD, .size = (g_stagingBufferSize = size)};
.size = (g_stagingBufferSize = size) if (!(g_stagingBuffer = SDL_CreateGPUTransferBuffer(g_gpuDevice, &createInfo)))
};
if(!(g_stagingBuffer = SDL_CreateGPUTransferBuffer(g_gpuDevice, &createInfo)))
{ {
IAE_LOG_ERROR("Couldn't create a SDL3 GPU Staging Buffer: ", SDL_GetError()); IAE_LOG_ERROR("Couldn't create a SDL3 GPU Staging Buffer: ", SDL_GetError());
return false; return false;

View File

@ -0,0 +1,98 @@
// IAEngine: 2D Game Engine by IA
// Copyright (C) 2025 IAS (ias@iasoft.dev)
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
#include <IAEngine/Rendering/GPUTexture.hpp>
#include <SDL3/SDL_gpu.h>
namespace ia::iae
{
EXTERN SDL_GPUDevice *g_gpuDevice;
SDL_GPUSampler *g_defaultSampler{};
VOID GPUTexture::Initialize()
{
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,
};
g_defaultSampler = SDL_CreateGPUSampler(g_gpuDevice, &createInfo);
}
VOID GPUTexture::Terminate()
{
if (g_defaultSampler)
SDL_ReleaseGPUSampler(g_gpuDevice, g_defaultSampler);
}
Handle GPUTexture::GetDefaultSampler()
{
return (Handle) g_defaultSampler;
}
RefPtr<GPUTexture> GPUTexture::Create(IN PCUINT8 rgbaData, IN INT32 width, IN INT32 height)
{
const auto res = MakeRefPtr<GPUTexture>();
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,
.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;
}
SDL_GPUTransferBufferCreateInfo stagingBufferCreateInfo{.usage = SDL_GPU_TRANSFERBUFFERUSAGE_UPLOAD,
.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);
SDL_UnmapGPUTransferBuffer(g_gpuDevice, stagingBuffer);
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_UploadToGPUTexture(copyPass, &transferInfo, &region, false);
SDL_EndGPUCopyPass(copyPass);
SDL_SubmitGPUCommandBuffer(cmdBuffer);
SDL_ReleaseGPUTransferBuffer(g_gpuDevice, stagingBuffer);
res->m_handle = (Handle) handle;
return res;
}
GPUTexture::~GPUTexture()
{
if (m_handle)
SDL_ReleaseGPUTexture(g_gpuDevice, (SDL_GPUTexture *) m_handle);
}
} // namespace ia::iae

View File

@ -25,10 +25,10 @@ namespace ia::iae
VOID QuadMesh::Initialize() VOID QuadMesh::Initialize()
{ {
Vertex_Mesh vertices[6] = {{iam::Vec3f{-1, 1, 0}, iam::Vec2f{0, 0}}, {iam::Vec3f{1, 1, 0}, iam::Vec2f{1, 0}}, Vertex_Mesh vertices[6] = {{glm::vec3{-1, 1, 0}, glm::vec2{0, 0}}, {glm::vec3{1, 1, 0}, glm::vec2{1, 0}},
{iam::Vec3f{1, -1, 0}, iam::Vec2f{1, 1}}, {iam::Vec3f{-1, 1, 0}, iam::Vec2f{0, 0}}, {glm::vec3{1, -1, 0}, glm::vec2{1, 1}}, {glm::vec3{-1, 1, 0}, glm::vec2{0, 0}},
{iam::Vec3f{1, -1, 0}, iam::Vec2f{1, 1}}, {iam::Vec3f{-1, -1, 0}, iam::Vec2f{0, 1}}}; {glm::vec3{1, -1, 0}, glm::vec2{1, 1}}, {glm::vec3{-1, -1, 0}, glm::vec2{0, 1}}};
g_quadMeshVertexBuffer = GPUBuffer::Create(&vertices, sizeof(vertices)); g_quadMeshVertexBuffer = GPUBuffer::Create(GPUBuffer::Usage::VERTEX, &vertices, sizeof(vertices));
} }
VOID QuadMesh::Terminate() VOID QuadMesh::Terminate()
@ -37,8 +37,8 @@ namespace ia::iae
g_quadMeshVertexBuffer.reset(); g_quadMeshVertexBuffer.reset();
} }
VOID QuadMesh::Draw(IN CONST iam::Vec3f &position, IN CONST iam::Vec3f &scale, IN FLOAT32 rotation) VOID QuadMesh::Draw(IN CONST glm::vec3 &position, IN CONST glm::vec3 &scale, IN FLOAT32 rotation)
{ {
Renderer::Draw((Handle)g_quadMeshVertexBuffer.get(), 6); Renderer::Draw(position, scale, rotation, g_quadMeshVertexBuffer->GetHandle(), 6);
} }
} // namespace ia::iae } // namespace ia::iae

View File

@ -27,14 +27,16 @@ namespace ia::iae
Pipeline_UnlitMesh::~Pipeline_UnlitMesh() Pipeline_UnlitMesh::~Pipeline_UnlitMesh()
{ {
if(m_handle)
SDL_ReleaseGPUGraphicsPipeline(g_gpuDevice, (SDL_GPUGraphicsPipeline*)m_handle);
} }
RefPtr<Pipeline_UnlitMesh> Pipeline_UnlitMesh::Create() RefPtr<Pipeline_UnlitMesh> Pipeline_UnlitMesh::Create()
{ {
const auto res = MakeRefPtr<Pipeline_UnlitMesh>(); const auto res = MakeRefPtr<Pipeline_UnlitMesh>();
const auto vertexShader = LoadShaderFromMemory(ShaderStage::VERTEX, SHADER_SOURCE_UNLITMESH_VERT, sizeof(SHADER_SOURCE_UNLITMESH_VERT), 0, 0, 0, 0); const auto vertexShader = LoadShaderFromMemory(ShaderStage::VERTEX, SHADER_SOURCE_UNLITMESH_VERT, sizeof(SHADER_SOURCE_UNLITMESH_VERT), 0, 3, 0, 0);
const auto pixelShader = LoadShaderFromMemory(ShaderStage::PIXEL, SHADER_SOURCE_UNLITMESH_FRAG, sizeof(SHADER_SOURCE_UNLITMESH_FRAG), 0, 0, 0, 0); const auto pixelShader = LoadShaderFromMemory(ShaderStage::PIXEL, SHADER_SOURCE_UNLITMESH_FRAG, sizeof(SHADER_SOURCE_UNLITMESH_FRAG), 1, 1, 0, 0);
SDL_GPUColorTargetDescription colorTargets[] = { SDL_GPUColorTargetDescription colorTargets[] = {
{.format = SDL_GetGPUSwapchainTextureFormat(g_gpuDevice, g_windowHandle)}}; {.format = SDL_GetGPUSwapchainTextureFormat(g_gpuDevice, g_windowHandle)}};
@ -49,7 +51,7 @@ namespace ia::iae
{.location = 1, {.location = 1,
.buffer_slot = 0, .buffer_slot = 0,
.format = SDL_GPU_VERTEXELEMENTFORMAT_FLOAT2, .format = SDL_GPU_VERTEXELEMENTFORMAT_FLOAT2,
.offset = sizeof(float) * 3}}; .offset = sizeof(glm::vec3)}};
SDL_GPUGraphicsPipelineCreateInfo createInfo = { SDL_GPUGraphicsPipelineCreateInfo createInfo = {
.vertex_shader = (SDL_GPUShader *) vertexShader, .vertex_shader = (SDL_GPUShader *) vertexShader,
.fragment_shader = (SDL_GPUShader *) pixelShader, .fragment_shader = (SDL_GPUShader *) pixelShader,

View File

@ -15,7 +15,9 @@
// along with this program. If not, see <https://www.gnu.org/licenses/>. // along with this program. If not, see <https://www.gnu.org/licenses/>.
#include <IAEngine/IAEngine.hpp> #include <IAEngine/IAEngine.hpp>
#include <IAEngine/Rendering/Camera.hpp>
#include <IAEngine/Rendering/GPUBuffer.hpp> #include <IAEngine/Rendering/GPUBuffer.hpp>
#include <IAEngine/Rendering/GPUTexture.hpp>
#include <IAEngine/Rendering/Mesh/Quad.hpp> #include <IAEngine/Rendering/Mesh/Quad.hpp>
#include <IAEngine/Rendering/Pipeline/UnlitMesh.hpp> #include <IAEngine/Rendering/Pipeline/UnlitMesh.hpp>
#include <IAEngine/Rendering/Renderer.hpp> #include <IAEngine/Rendering/Renderer.hpp>
@ -45,9 +47,16 @@ namespace ia::iae
RefPtr<Pipeline_UnlitMesh> g_pipelineUnlitMesh; RefPtr<Pipeline_UnlitMesh> g_pipelineUnlitMesh;
Camera2D g_camera{};
glm::mat4 matProjection{1.0f};
glm::mat4 matView{1.0f};
glm::mat4 matModel{1.0f};
BOOL Renderer::Initialize(IN Engine *engine) BOOL Renderer::Initialize(IN Engine *engine)
{ {
g_windowHandle = (SDL_Window *) engine->GetWindowHandle(); g_windowHandle = (SDL_Window *) engine->GetWindowHandle();
SDL_GetWindowSizeInPixels(g_windowHandle, &s_width, &s_height);
if (!(g_gpuDevice = SDL_CreateGPUDevice(SDL_GPU_SHADERFORMAT_SPIRV, engine->IsDebugMode, nullptr))) if (!(g_gpuDevice = SDL_CreateGPUDevice(SDL_GPU_SHADERFORMAT_SPIRV, engine->IsDebugMode, nullptr)))
{ {
@ -87,10 +96,14 @@ namespace ia::iae
if (!GPUBuffer::InitializeStagingBuffer()) if (!GPUBuffer::InitializeStagingBuffer())
return false; return false;
GPUTexture::Initialize();
g_pipelineUnlitMesh = Pipeline_UnlitMesh::Create(); g_pipelineUnlitMesh = Pipeline_UnlitMesh::Create();
QuadMesh::Initialize(); QuadMesh::Initialize();
matProjection = glm::orthoLH(0.0f, (FLOAT32) s_width, (FLOAT32) s_height, 0.0f, -0.1f, 100.0f);
return true; return true;
} }
@ -98,8 +111,12 @@ namespace ia::iae
{ {
SDL_WaitForGPUIdle(g_gpuDevice); SDL_WaitForGPUIdle(g_gpuDevice);
g_pipelineUnlitMesh.reset();
QuadMesh::Terminate(); QuadMesh::Terminate();
GPUTexture::Terminate();
GPUBuffer::TerminateStagingBuffer(); GPUBuffer::TerminateStagingBuffer();
ImGui_ImplSDL3_Shutdown(); ImGui_ImplSDL3_Shutdown();
@ -110,7 +127,7 @@ namespace ia::iae
SDL_DestroyGPUDevice(g_gpuDevice); SDL_DestroyGPUDevice(g_gpuDevice);
} }
VOID Renderer::AddDebugUIWindow(IN PCCHAR title, IN CONST iam::Vec2f &position, IN CONST iam::Vec2f &size, VOID Renderer::AddDebugUIWindow(IN PCCHAR title, IN CONST glm::vec2 &position, IN CONST glm::vec2 &size,
IN std::function<VOID()> contentDrawCallback) IN std::function<VOID()> contentDrawCallback)
{ {
s_debugUIWindows.pushBack(DebugUIWindow{title, position, size, contentDrawCallback}); s_debugUIWindows.pushBack(DebugUIWindow{title, position, size, contentDrawCallback});
@ -124,8 +141,8 @@ namespace ia::iae
for (const auto &w : s_debugUIWindows) for (const auto &w : s_debugUIWindows)
{ {
ImGui::Begin(w.Title); ImGui::Begin(w.Title);
ImGui::SetWindowPos({w.Position.X, w.Position.Y}); ImGui::SetWindowPos({w.Position.x, w.Position.y});
ImGui::SetWindowSize({w.Size.X, w.Size.Y}); ImGui::SetWindowSize({w.Size.x, w.Size.y});
w.ContentDrawCallback(); w.ContentDrawCallback();
ImGui::End(); ImGui::End();
} }
@ -160,6 +177,9 @@ namespace ia::iae
g_renderPass = SDL_BeginGPURenderPass(g_cmdBuffer, &colorTargetInfo, 1, NULL); g_renderPass = SDL_BeginGPURenderPass(g_cmdBuffer, &colorTargetInfo, 1, NULL);
g_pipelineUnlitMesh->Bind((Handle) g_renderPass); g_pipelineUnlitMesh->Bind((Handle) g_renderPass);
SDL_PushGPUVertexUniformData(g_cmdBuffer, 0, &matProjection, sizeof(matProjection));
matView = g_camera.GetViewMatrix();
SDL_PushGPUVertexUniformData(g_cmdBuffer, 1, &matView, sizeof(matView));
} }
VOID Renderer::EndFrame() VOID Renderer::EndFrame()
@ -172,19 +192,52 @@ namespace ia::iae
SDL_SubmitGPUCommandBuffer(g_cmdBuffer); SDL_SubmitGPUCommandBuffer(g_cmdBuffer);
} }
VOID Renderer::Draw(IN Handle vertexBufferHandle, IN INT32 vertexCount) VOID Renderer::BindTexture(IN Handle handle, IN BOOL flipV, IN BOOL flipH, IN CONST glm::vec4 &colorOverlay)
{ {
STATIC struct
{
glm::vec4 colorOverlay;
UINT32 flipV;
UINT32 flipH;
} textureState;
textureState = {colorOverlay, flipV, flipH};
SDL_GPUTextureSamplerBinding binding{.texture = (SDL_GPUTexture *) handle,
.sampler = (SDL_GPUSampler *) GPUTexture::GetDefaultSampler()};
SDL_BindGPUFragmentSamplers(g_renderPass, 0, &binding, 1);
SDL_PushGPUFragmentUniformData(g_cmdBuffer, 0, &textureState, sizeof(textureState));
}
VOID SetModelTransformMatrix(IN CONST glm::vec3 &position, IN CONST glm::vec3 &scale, IN FLOAT32 rotation)
{
matModel = glm::translate(glm::mat4(1.0f), position);
matModel = glm::rotate(matModel, rotation, glm::vec3(0.0f, 0.0f, 1.0f));
matModel = glm::scale(matModel, scale);
SDL_PushGPUVertexUniformData(g_cmdBuffer, 2, &matModel, sizeof(matModel));
}
VOID Renderer::Draw(IN CONST glm::vec3 &position, IN CONST glm::vec3 &scale, IN FLOAT32 rotation,
IN Handle vertexBufferHandle, IN INT32 vertexCount)
{
SetModelTransformMatrix(position, scale, rotation);
SDL_GPUBufferBinding bindings[] = {{.buffer = (SDL_GPUBuffer *) vertexBufferHandle, .offset = 0}}; SDL_GPUBufferBinding bindings[] = {{.buffer = (SDL_GPUBuffer *) vertexBufferHandle, .offset = 0}};
SDL_BindGPUVertexBuffers(g_renderPass, 0, bindings, 1); SDL_BindGPUVertexBuffers(g_renderPass, 0, bindings, 1);
SDL_DrawGPUPrimitives(g_renderPass, vertexCount, 1, 0, 0); SDL_DrawGPUPrimitives(g_renderPass, vertexCount, 1, 0, 0);
} }
VOID Renderer::Draw(IN Handle vertexBufferHandle, IN Handle indexBufferHandle, IN INT32 indexCount) VOID Renderer::Draw(IN CONST glm::vec3 &position, IN CONST glm::vec3 &scale, IN FLOAT32 rotation,
IN Handle vertexBufferHandle, IN Handle indexBufferHandle, IN INT32 indexCount)
{ {
SetModelTransformMatrix(position, scale, rotation);
SDL_GPUBufferBinding bindings[] = {{.buffer = (SDL_GPUBuffer *) vertexBufferHandle, .offset = 0}, SDL_GPUBufferBinding bindings[] = {{.buffer = (SDL_GPUBuffer *) vertexBufferHandle, .offset = 0},
{.buffer = (SDL_GPUBuffer *) indexBufferHandle, .offset = 0}}; {.buffer = (SDL_GPUBuffer *) indexBufferHandle, .offset = 0}};
SDL_BindGPUVertexBuffers(g_renderPass, 0, bindings, 1); SDL_BindGPUVertexBuffers(g_renderPass, 0, bindings, 1);
SDL_BindGPUIndexBuffer(g_renderPass, &bindings[1], SDL_GPU_INDEXELEMENTSIZE_32BIT); SDL_BindGPUIndexBuffer(g_renderPass, &bindings[1], SDL_GPU_INDEXELEMENTSIZE_32BIT);
SDL_DrawGPUIndexedPrimitives(g_renderPass, indexCount, 1, 0, 0, 0); SDL_DrawGPUIndexedPrimitives(g_renderPass, indexCount, 1, 0, 0, 0);
} }
Camera2D *Renderer::GetCamera()
{
return &g_camera;
}
} // namespace ia::iae } // namespace ia::iae

View File

@ -1,46 +0,0 @@
// IAEngine: 2D Game Engine by IA
// Copyright (C) 2025 IAS (ias@iasoft.dev)
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
#include <IAEngine/IAEngine.hpp>
#include <IAEngine/Rendering/Texture.hpp>
#include <SDL3/SDL.h>
#define TEXTURE_HANDLE (SDL_Texture *) m_handle
namespace ia::iae
{
Texture::Texture()
{
}
Texture::~Texture()
{
SDL_DestroyTexture(TEXTURE_HANDLE);
}
VOID Texture::Draw(IN CONST iam::Vec3f &position, IN CONST iam::Vec3f &scale, IN FLOAT32 rotation, IN BOOL flipH,
IN BOOL flipV, IN CONST iam::Vec4f &colorOverlay) CONST
{
// SDL_FRect rect{.x = position.X, .y = position.Y, .w = m_width * scale.X, .h = m_height * scale.Y};
//SDL_SetTextureColorModFloat(TEXTURE_HANDLE, colorOverlay.X, colorOverlay.Y, colorOverlay.Z);
//SDL_SetTextureAlphaModFloat(TEXTURE_HANDLE, colorOverlay.W);
//SDL_RenderTextureRotated((SDL_Renderer *) m_engine->GetRendererHandle(), TEXTURE_HANDLE, nullptr, &rect,
// rotation, nullptr,
// (SDL_FlipMode) (SDL_FLIP_NONE | (flipV ? SDL_FLIP_VERTICAL : SDL_FLIP_NONE) |
// (flipH ? SDL_FLIP_HORIZONTAL : SDL_FLIP_NONE)));
}
} // namespace ia::iae

View File

@ -15,6 +15,7 @@
// along with this program. If not, see <https://www.gnu.org/licenses/>. // along with this program. If not, see <https://www.gnu.org/licenses/>.
#include <IAEngine/IAEngine.hpp> #include <IAEngine/IAEngine.hpp>
#include <IAEngine/Rendering/GPUTexture.hpp>
#include <IAEngine/ResourceManager.hpp> #include <IAEngine/ResourceManager.hpp>
#include <SDL3/SDL.h> #include <SDL3/SDL.h>
@ -28,6 +29,12 @@ namespace ia::iae
{ {
} }
ResourceManager::~ResourceManager()
{
for(auto& t: m_textures)
t.reset();
}
RefPtr<Texture> ResourceManager::CreateTexture(IN CONST Span<CONST UINT8> &encodedData) RefPtr<Texture> ResourceManager::CreateTexture(IN CONST Span<CONST UINT8> &encodedData)
{ {
return CreateTexture(encodedData.data(), encodedData.size()); return CreateTexture(encodedData.data(), encodedData.size());
@ -46,20 +53,8 @@ namespace ia::iae
RefPtr<Texture> ResourceManager::CreateTexture(IN PCUINT8 rgbaData, IN INT32 width, IN INT32 height) RefPtr<Texture> ResourceManager::CreateTexture(IN PCUINT8 rgbaData, IN INT32 width, IN INT32 height)
{ {
//const auto result = MakeRefPtr<Texture>(m_engine); const auto t = GPUTexture::Create(rgbaData, width, height);
m_textures.pushBack(t);
//result->m_width = width; return MakeRefPtr<Texture>(t->GetHandle(), width, height);
//result->m_height = height;
//SDL_Surface *surface =
// SDL_CreateSurfaceFrom(width, height, SDL_PIXELFORMAT_RGBA32, (void *) rgbaData, width << 2);
//if (!surface)
// THROW_UNKNOWN("Failed to create SDL surface: ", SDL_GetError());
//result->m_handle = SDL_CreateTextureFromSurface((SDL_Renderer *) m_engine->GetRendererHandle(), surface);
//if (!result->m_handle)
// THROW_UNKNOWN("Failed to create SDL Texture: ", SDL_GetError());
//SDL_DestroySurface(surface);
return nullptr;
} }
} // namespace ia::iae } // namespace ia::iae

View File

@ -30,7 +30,7 @@ namespace ia::iae
{ {
for (auto &n : m_nodes) for (auto &n : m_nodes)
{ {
if (((INT32) n->GetPosition().Z) >= 0) if (((INT32) n->GetPosition().z) >= 0)
continue; continue;
n->Draw(); n->Draw();
} }
@ -39,7 +39,7 @@ namespace ia::iae
{ {
for (auto &n : m_nodes) for (auto &n : m_nodes)
{ {
if (((INT32) n->GetPosition().Z) != i) if (((INT32) n->GetPosition().z) != i)
continue; continue;
n->Draw(); n->Draw();
} }
@ -47,7 +47,7 @@ namespace ia::iae
for (auto &n : m_nodes) for (auto &n : m_nodes)
{ {
if (((INT32) n->GetPosition().Z) < 8) if (((INT32) n->GetPosition().z) < 8)
continue; continue;
n->Draw(); n->Draw();
} }

View File

@ -0,0 +1,40 @@
// IAEngine: 2D Game Engine by IA
// Copyright (C) 2025 IAS (ias@iasoft.dev)
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
#include <IAEngine/IAEngine.hpp>
#include <IAEngine/Texture.hpp>
#include <IAEngine/Rendering/Renderer.hpp>
#include <IAEngine/Rendering/Mesh/Quad.hpp>
namespace ia::iae
{
Texture::Texture(IN Handle handle,IN INT32 width, IN INT32 height):
m_handle(handle), m_size({(FLOAT32)width, (FLOAT32)height, 1.0f})
{
}
Texture::~Texture()
{
}
VOID Texture::Draw(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
{
Renderer::BindTexture(m_handle, flipV, flipH, colorOverlay);
QuadMesh::Draw(position, m_size * scale, rotation);
}
} // namespace ia::iae

View File

@ -5,7 +5,18 @@ layout(location = 0) in vec2 inTexCoord;
layout(location = 0) out vec4 outColor; layout(location = 0) out vec4 outColor;
layout(set = 2, binding = 0) uniform sampler2D texSampler;
layout(set = 3, binding = 0) uniform UniformBufferObject {
vec4 colorOverlay;
bool flipV;
bool flipH;
} ubo;
void main() void main()
{ {
outColor = vec4(0, 1, 0, 1); vec2 uv = inTexCoord;
uv.y = 1 - uv.y;
if(ubo.flipH) uv.x = 1 - uv.x;
if(ubo.flipV) uv.y = 1 - uv.y;
outColor = texture(texSampler, uv) * ubo.colorOverlay;
} }

View File

@ -1,10 +1,23 @@
#version 450 #version 450
#extension GL_ARB_separate_shader_objects : enable #extension GL_ARB_separate_shader_objects : enable
layout (location = 0) in vec3 inPosition;
layout (location = 1) in vec2 inTexCoord;
layout(location = 0) out vec2 outTexCoord; layout(location = 0) out vec2 outTexCoord;
layout(set = 1, binding = 0) uniform UBO_Vertex_PerScene {
mat4 projection;
} uboPerScene;
layout(set = 1, binding = 1) uniform UBO_Vertex_PerFrame {
mat4 view;
} uboPerFrame;
layout(set = 1, binding = 2) uniform UBO_Vertex_PerDraw {
mat4 model;
} uboPerDraw;
void main() void main()
{ {
outTexCoord = vec2((gl_VertexIndex << 1) & 2, gl_VertexIndex & 2); gl_Position = uboPerScene.projection * uboPerFrame.view * uboPerDraw.model * vec4(inPosition, 1.0f);
gl_Position = vec4(outTexCoord * 2.0f - 1.0f, 0.0f, 1.0f); outTexCoord = inTexCoord;
} }

File diff suppressed because one or more lines are too long

View File

@ -22,9 +22,15 @@
#include <IACore/String.hpp> #include <IACore/String.hpp>
#include <IACore/Exception.hpp> #include <IACore/Exception.hpp>
#include <IAMath/Vec.hpp> #include <glm/vec2.hpp>
#include <glm/vec3.hpp>
#include <glm/vec4.hpp>
#include <glm/mat4x4.hpp>
#include <glm/ext/matrix_transform.hpp> // glm::translate, glm::rotate, glm::scale
#include <glm/ext/matrix_clip_space.hpp> // glm::perspective
#include <glm/ext/scalar_constants.hpp> // glm::pi
#define IAE_LOG_TAG "IAE" #define IAE_LOG_TAG "[IAE]: "
#define IAE_LOG_INFO(...) ia::Logger::Info(IAE_LOG_TAG, __VA_ARGS__) #define IAE_LOG_INFO(...) ia::Logger::Info(IAE_LOG_TAG, __VA_ARGS__)
#define IAE_LOG_WARN(...) ia::Logger::Warn(IAE_LOG_TAG, __VA_ARGS__) #define IAE_LOG_WARN(...) ia::Logger::Warn(IAE_LOG_TAG, __VA_ARGS__)

View File

@ -17,7 +17,7 @@
#pragma once #pragma once
#include <IAEngine/Components/Component.hpp> #include <IAEngine/Components/Component.hpp>
#include <IAEngine/Rendering/Texture.hpp> #include <IAEngine/Texture.hpp>
namespace ia::iae namespace ia::iae
{ {
@ -26,7 +26,7 @@ namespace ia::iae
public: public:
struct TileGrid struct TileGrid
{ {
iam::Vec3f Position{}; glm::vec3 Position{};
INT32 TileWidth{}; INT32 TileWidth{};
INT32 TileHeight{}; INT32 TileHeight{};

View File

@ -17,7 +17,7 @@
#pragma once #pragma once
#include <IAEngine/Components/Component.hpp> #include <IAEngine/Components/Component.hpp>
#include <IAEngine/Rendering/Texture.hpp> #include <IAEngine/Texture.hpp>
namespace ia::iae namespace ia::iae
{ {
@ -27,10 +27,10 @@ namespace ia::iae
struct AnimationKeyFrame struct AnimationKeyFrame
{ {
INT32 Duration{100}; INT32 Duration{100};
iam::Vec3f Position{}; glm::vec3 Position{};
iam::Vec3f Rotation{}; glm::vec3 Rotation{};
iam::Vec3f Scale{1.0f, 1.0f, 1.0f}; glm::vec3 Scale{1.0f, 1.0f, 1.0f};
iam::Vec4f ColorOverlay{1.0f, 1.0f, 1.0f, 1.0f}; glm::vec4 ColorOverlay{1.0f, 1.0f, 1.0f, 1.0f};
BOOL ShouldInterpolate{}; BOOL ShouldInterpolate{};
RefPtr<Texture> Texture; RefPtr<Texture> Texture;
}; };

View File

@ -17,7 +17,7 @@
#pragma once #pragma once
#include <IAEngine/Components/Component.hpp> #include <IAEngine/Components/Component.hpp>
#include <IAEngine/Rendering/Texture.hpp> #include <IAEngine/Texture.hpp>
namespace ia::iae namespace ia::iae
{ {
@ -31,7 +31,7 @@ namespace ia::iae
return m_texture; return m_texture;
} }
iam::Vec3f &Position() glm::vec3 &Position()
{ {
return m_position; return m_position;
} }
@ -41,7 +41,7 @@ namespace ia::iae
VOID Update(); VOID Update();
private: private:
iam::Vec3f m_position; glm::vec3 m_position;
RefPtr<iae::Texture> m_texture; RefPtr<iae::Texture> m_texture;
}; };
} // namespace ia::iae } // namespace ia::iae

View File

@ -17,7 +17,7 @@
#pragma once #pragma once
#include <IAEngine/Nodes/Node.hpp> #include <IAEngine/Nodes/Node.hpp>
#include <IAEngine/Rendering/Texture.hpp> #include <IAEngine/Texture.hpp>
#include <IAEngine/Rendering/Renderer.hpp> #include <IAEngine/Rendering/Renderer.hpp>
#include <IAEngine/ResourceManager.hpp> #include <IAEngine/ResourceManager.hpp>
#include <IAEngine/Scene.hpp> #include <IAEngine/Scene.hpp>

View File

@ -285,8 +285,8 @@ namespace ia::iae
return s_prevKeys[key] && !s_keys[key]; return s_prevKeys[key] && !s_keys[key];
} }
STATIC iam::Vec2f GetDirectionalInput(); STATIC glm::vec2 GetDirectionalInput();
STATIC iam::Vec2f GetDirectionalInput(OUT DirectionalInput& direction); STATIC glm::vec2 GetDirectionalInput(OUT DirectionalInput& direction);
private: private:
STATIC BOOL s_keys[256]; STATIC BOOL s_keys[256];

View File

@ -18,7 +18,7 @@
#include <IAEngine/Components/Component.hpp> #include <IAEngine/Components/Component.hpp>
#include <IAEngine/Nodes/Transform.hpp> #include <IAEngine/Nodes/Transform.hpp>
#include <IAEngine/Rendering/Texture.hpp> #include <IAEngine/Texture.hpp>
namespace ia::iae namespace ia::iae
{ {

View File

@ -24,51 +24,51 @@ namespace ia::iae
class Transform class Transform
{ {
public: public:
VOID SetLocalPosition(IN CONST iam::Vec3f &v) VOID SetLocalPosition(IN CONST glm::vec3 &v)
{ {
m_local.Position = v; m_local.Position = v;
RecalculatePosition(); RecalculatePosition();
} }
VOID SetLocalScale(IN CONST iam::Vec3f &v) VOID SetLocalScale(IN CONST glm::vec3 &v)
{ {
m_local.Scale = v; m_local.Scale = v;
RecalculateScale(); RecalculateScale();
} }
VOID SetLocalRotation(IN CONST iam::Vec3f &v) VOID SetLocalRotation(IN CONST glm::vec3 &v)
{ {
m_local.Rotation = v; m_local.Rotation = v;
RecalculateRotation(); RecalculateRotation();
} }
public: public:
CONST iam::Vec3f &GetPosition() CONST CONST glm::vec3 &GetPosition() CONST
{ {
return m_global.Position; return m_global.Position;
} }
CONST iam::Vec3f &GetScale() CONST CONST glm::vec3 &GetScale() CONST
{ {
return m_global.Scale; return m_global.Scale;
} }
CONST iam::Vec3f &GetRotation() CONST CONST glm::vec3 &GetRotation() CONST
{ {
return m_global.Rotation; return m_global.Rotation;
} }
CONST iam::Vec3f &GetLocalPosition() CONST CONST glm::vec3 &GetLocalPosition() CONST
{ {
return m_local.Position; return m_local.Position;
} }
CONST iam::Vec3f &GetLocalScale() CONST CONST glm::vec3 &GetLocalScale() CONST
{ {
return m_local.Scale; return m_local.Scale;
} }
CONST iam::Vec3f &GetLocalRotation() CONST CONST glm::vec3 &GetLocalRotation() CONST
{ {
return m_local.Rotation; return m_local.Rotation;
} }
@ -80,21 +80,21 @@ namespace ia::iae
protected: protected:
VOID RecalculatePosition() VOID RecalculatePosition()
{ {
m_global.Position = (m_parent ? m_parent->GetPosition() : iam::Vec3f{}) + m_local.Position; m_global.Position = (m_parent ? m_parent->GetPosition() : glm::vec3{}) + m_local.Position;
for (auto &c : m_children) for (auto &c : m_children)
c->RecalculatePosition(); c->RecalculatePosition();
} }
VOID RecalculateRotation() VOID RecalculateRotation()
{ {
m_global.Rotation = (m_parent ? m_parent->GetRotation() : iam::Vec3f{}) + m_local.Rotation; m_global.Rotation = (m_parent ? m_parent->GetRotation() : glm::vec3{}) + m_local.Rotation;
for (auto &c : m_children) for (auto &c : m_children)
c->RecalculateRotation(); c->RecalculateRotation();
} }
VOID RecalculateScale() VOID RecalculateScale()
{ {
m_global.Scale = (m_parent ? m_parent->GetScale() : iam::Vec3f{}) + m_local.Scale; m_global.Scale = (m_parent ? m_parent->GetScale() : glm::vec3{}) + m_local.Scale;
for (auto &c : m_children) for (auto &c : m_children)
c->RecalculateScale(); c->RecalculateScale();
} }
@ -102,9 +102,9 @@ namespace ia::iae
private: private:
struct struct
{ {
iam::Vec3f Position{0.0f, 0.0f, 0.0f}; glm::vec3 Position{0.0f, 0.0f, 0.0f};
iam::Vec3f Rotation{0.0f, 0.0f, 0.0f}; glm::vec3 Rotation{0.0f, 0.0f, 0.0f};
iam::Vec3f Scale{1.0f, 1.0f, 1.0f}; glm::vec3 Scale{1.0f, 1.0f, 1.0f};
} m_local{}, m_global{}; } m_local{}, m_global{};
}; };
} // namespace ia::iae } // namespace ia::iae

View File

@ -28,10 +28,10 @@ namespace ia::iae
STATIC VOID Update(); STATIC VOID Update();
STATIC Handle CreateStaticBody(IN iam::Vec3f position); STATIC Handle CreateStaticBody(IN glm::vec3 position);
STATIC Handle CreateDynamicBody(IN iam::Vec3f position); STATIC Handle CreateDynamicBody(IN glm::vec3 position);
STATIC VOID AddBoxCollider(IN Handle body, IN iam::Vec3f size); STATIC VOID AddBoxCollider(IN Handle body, IN glm::vec3 size);
STATIC iam::Vec3f GetBodyPosition(IN Handle body); STATIC glm::vec3 GetBodyPosition(IN Handle body);
}; };
} }

View File

@ -0,0 +1,39 @@
// IAEngine: 2D Game Engine by IA
// Copyright (C) 2025 IAS (ias@iasoft.dev)
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
#pragma once
#include <IAEngine/Base.hpp>
namespace ia::iae
{
class Camera2D
{
public:
glm::vec2 &Position()
{
return m_position;
}
glm::mat4 GetViewMatrix()
{
return glm::lookAtLH(glm::vec3{m_position, -2.0f}, {m_position, 0.0f}, {0.0f, 1.0f, 0.0f});
}
private:
glm::vec2 m_position{};
};
} // namespace ia::iae

View File

@ -25,15 +25,33 @@ namespace ia::iae
class GPUBuffer class GPUBuffer
{ {
public: public:
STATIC RefPtr<GPUBuffer> Create(IN PCVOID data, IN UINT32 dataSize); enum class Usage
{
VERTEX,
INDEX,
STORAGE
};
public:
~GPUBuffer();
STATIC RefPtr<GPUBuffer> Create(IN Usage usage, IN PCVOID data, IN UINT32 dataSize);
public:
Handle GetHandle() CONST
{
return m_handle;
}
private: private:
Usage m_usage{};
UINT32 m_size{};
Handle m_handle{}; Handle m_handle{};
private: private:
STATIC BOOL InitializeStagingBuffer(); STATIC BOOL InitializeStagingBuffer();
STATIC VOID TerminateStagingBuffer(); STATIC VOID TerminateStagingBuffer();
STATIC BOOL EnsureStagingBufferSize(IN UINT32 size); STATIC BOOL EnsureStagingBufferSize(IN UINT32 size);
friend class Renderer; friend class Renderer;
}; };

View File

@ -0,0 +1,44 @@
// IAEngine: 2D Game Engine by IA
// Copyright (C) 2025 IAS (ias@iasoft.dev)
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
#pragma once
#include <IAEngine/Base.hpp>
namespace ia::iae
{
class GPUTexture
{
public:
STATIC VOID Initialize();
STATIC VOID Terminate();
STATIC Handle GetDefaultSampler();
public:
~GPUTexture();
STATIC RefPtr<GPUTexture> Create(IN PCUINT8 rgbaData, IN INT32 width, IN INT32 height);
public:
Handle GetHandle() CONST
{
return m_handle;
}
private:
Handle m_handle{};
};
} // namespace ia::iae

View File

@ -26,6 +26,6 @@ namespace ia::iae
STATIC VOID Initialize(); STATIC VOID Initialize();
STATIC VOID Terminate(); STATIC VOID Terminate();
STATIC VOID Draw(IN CONST iam::Vec3f &position, IN CONST iam::Vec3f &scale, IN FLOAT32 rotation); STATIC VOID Draw(IN CONST glm::vec3 &position, IN CONST glm::vec3 &scale, IN FLOAT32 rotation);
}; };
} // namespace ia::iae } // namespace ia::iae

View File

@ -21,14 +21,15 @@
namespace ia::iae namespace ia::iae
{ {
class Engine; class Engine;
class Camera2D;
class Renderer class Renderer
{ {
struct DebugUIWindow struct DebugUIWindow
{ {
PCCHAR Title{""}; PCCHAR Title{""};
iam::Vec2f Position{}; glm::vec2 Position{};
iam::Vec2f Size{}; glm::vec2 Size{};
std::function<VOID()> ContentDrawCallback{}; std::function<VOID()> ContentDrawCallback{};
}; };
@ -37,15 +38,19 @@ namespace ia::iae
STATIC VOID Terminate(); STATIC VOID Terminate();
public: public:
STATIC VOID AddDebugUIWindow(IN PCCHAR title, IN CONST iam::Vec2f &position, IN CONST iam::Vec2f &size, STATIC VOID AddDebugUIWindow(IN PCCHAR title, IN CONST glm::vec2 &position, IN CONST glm::vec2 &size,
IN std::function<VOID()> contentDrawCallback); IN std::function<VOID()> contentDrawCallback);
public: public:
STATIC VOID BeginFrame(); STATIC VOID BeginFrame();
STATIC VOID EndFrame(); STATIC VOID EndFrame();
STATIC VOID Draw(IN Handle vertexBufferHandle, IN INT32 vertexCount); STATIC VOID BindTexture(IN Handle handle, IN BOOL flipV, IN BOOL flipH, IN CONST glm::vec4& colorOverlay);
STATIC VOID Draw(IN Handle vertexBufferHandle, IN Handle indexBufferHandle, IN INT32 indexCount);
STATIC VOID Draw(IN CONST glm::vec3 &position, IN CONST glm::vec3 &scale, IN FLOAT32 rotation, IN Handle vertexBufferHandle, IN INT32 vertexCount);
STATIC VOID Draw(IN CONST glm::vec3 &position, IN CONST glm::vec3 &scale, IN FLOAT32 rotation, IN Handle vertexBufferHandle, IN Handle indexBufferHandle, IN INT32 indexCount);
STATIC Camera2D* GetCamera();
public: public:
STATIC INT32 Width() STATIC INT32 Width()

View File

@ -22,8 +22,8 @@ namespace ia::iae
{ {
struct Vertex_Mesh struct Vertex_Mesh
{ {
iam::Vec3f Position{}; glm::vec3 Position{};
iam::Vec2f UV{}; glm::vec2 UV{};
}; };

View File

@ -17,7 +17,7 @@
#pragma once #pragma once
#include <IAEngine/Audio.hpp> #include <IAEngine/Audio.hpp>
#include <IAEngine/Rendering/Texture.hpp> #include <IAEngine/Texture.hpp>
namespace ia::iae namespace ia::iae
{ {
@ -27,6 +27,7 @@ namespace ia::iae
{ {
public: public:
ResourceManager(IN Engine *engine); ResourceManager(IN Engine *engine);
~ResourceManager();
RefPtr<Texture> CreateTexture(IN CONST Span<CONST UINT8> &encodedData); RefPtr<Texture> CreateTexture(IN CONST Span<CONST UINT8> &encodedData);
RefPtr<Texture> CreateTexture(IN PCUINT8 encodedData, IN SIZE_T encodedDataSize); RefPtr<Texture> CreateTexture(IN PCUINT8 encodedData, IN SIZE_T encodedDataSize);
@ -45,6 +46,7 @@ namespace ia::iae
protected: protected:
Engine *CONST m_engine; Engine *CONST m_engine;
Vector<RefPtr<class GPUTexture>> m_textures;
friend class Engine; friend class Engine;
}; };

View File

@ -23,26 +23,26 @@ namespace ia::iae
class Texture class Texture
{ {
public: public:
Texture(); Texture(IN Handle handle, IN INT32 width, IN INT32 height);
~Texture(); ~Texture();
public: public:
VOID Draw(IN CONST iam::Vec3f& position, IN CONST iam::Vec3f& scale, IN FLOAT32 rotation, IN BOOL flipH, IN BOOL flipV, IN CONST iam::Vec4f& colorOverlay) CONST; VOID Draw(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: public:
INT32 GetWidth() CONST INT32 GetWidth() CONST
{ {
return m_width; return (INT32)m_size.x;
} }
INT32 GetHeight() CONST INT32 GetHeight() CONST
{ {
return m_height; return (INT32)m_size.y;
} }
private: private:
INT32 m_width; CONST Handle m_handle{};
INT32 m_height; CONST glm::vec3 m_size;
PVOID m_handle{};
}; };
} // namespace ia::iae } // namespace ia::iae

View File

@ -37,3 +37,7 @@ target_include_directories(
"imgui/backends" "imgui/backends"
) )
# -----------------------------------------------
# GLM
# -----------------------------------------------
add_subdirectory(glm/)

1
Vendor/glm vendored Submodule

Submodule Vendor/glm added at 2d4c4b4dd3