Debug Draw Base

This commit is contained in:
Isuru Samarathunga
2025-09-29 01:02:02 +05:30
parent 3c5792e975
commit fe88538e3c
13 changed files with 397 additions and 98 deletions

View File

@ -2,6 +2,7 @@
#include <IAEngine/Input.hpp> #include <IAEngine/Input.hpp>
#include <IAEngine/Rendering/Camera.hpp> #include <IAEngine/Rendering/Camera.hpp>
#include <IAEngine/Rendering/DebugDraw.hpp>
#include <IAEngine/Components/SpriteRenderer.hpp> #include <IAEngine/Components/SpriteRenderer.hpp>
#include <IACore/File.hpp> #include <IACore/File.hpp>
@ -57,6 +58,8 @@ namespace ia::iae::game
scene->AddNode(obstacle); scene->AddNode(obstacle);
Engine::ChangeScene(scene.get()); Engine::ChangeScene(scene.get());
DebugDraw::AddDebugUIWindow("Dsd", {100.0f, 100.0f}, {100.0f, 100.0f}, [](){});
} }
VOID Game::Terminate() VOID Game::Terminate()

View File

@ -13,9 +13,11 @@ set(IAEngine_Sources
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/GPUTexture.cpp
imp/cpp/Rendering/DebugDraw.cpp
imp/cpp/Rendering/Pipeline/Pipeline.cpp imp/cpp/Rendering/Pipeline/Pipeline.cpp
imp/cpp/Rendering/Pipeline/UnlitMesh.cpp imp/cpp/Rendering/Pipeline/UnlitMesh.cpp
imp/cpp/Rendering/Pipeline/PostProcess.cpp
imp/cpp/Physics/Physics.cpp imp/cpp/Physics/Physics.cpp

View File

@ -132,11 +132,12 @@ namespace ia::iae
VOID Engine::UpdateGame() VOID Engine::UpdateGame()
{ {
Physics::Update();
if B_LIKELY (g_activeScene) if B_LIKELY (g_activeScene)
g_activeScene->Update(); g_activeScene->Update();
UI::Update(); UI::Update();
Physics::Update();
} }
VOID Engine::RenderGame() VOID Engine::RenderGame()

View File

@ -0,0 +1,95 @@
// 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/Camera.hpp>
#include <IAEngine/Rendering/DebugDraw.hpp>
#include <IAEngine/Rendering/GPUBuffer.hpp>
#include <IAEngine/Rendering/GPUTexture.hpp>
#include <IAEngine/Rendering/Pipeline/UnlitMesh.hpp>
#include <IAEngine/Rendering/Renderer.hpp>
#include <SDL3/SDL_gpu.h>
#include <backends/imgui_impl_sdl3.h>
#include <backends/imgui_impl_sdlgpu3.h>
namespace ia::iae
{
EXTERN SDL_Window *g_windowHandle;
EXTERN SDL_GPUDevice *g_gpuDevice;
ImGuiIO g_imGUIIO{};
Vector<DebugDraw::DebugUIWindow> DebugDraw::s_debugUIWindows;
VOID DebugDraw::Initailize()
{
const auto mainScale = SDL_GetDisplayContentScale(SDL_GetPrimaryDisplay());
IMGUI_CHECKVERSION();
ImGui::CreateContext();
g_imGUIIO = ImGui::GetIO();
g_imGUIIO.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;
g_imGUIIO.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad;
ImGui::StyleColorsClassic();
ImGuiStyle &style = ImGui::GetStyle();
style.ScaleAllSizes(mainScale);
style.FontScaleDpi = mainScale;
ImGui_ImplSDLGPU3_InitInfo initInfo{.Device = g_gpuDevice,
.ColorTargetFormat =
SDL_GetGPUSwapchainTextureFormat(g_gpuDevice, g_windowHandle),
.PresentMode = SDL_GPU_PRESENTMODE_VSYNC};
ImGui_ImplSDL3_InitForSDLGPU(g_windowHandle);
ImGui_ImplSDLGPU3_Init(&initInfo);
}
VOID DebugDraw::Terminate()
{
ImGui_ImplSDL3_Shutdown();
ImGui_ImplSDLGPU3_Shutdown();
ImGui::DestroyContext();
}
VOID DebugDraw::Draw()
{
for (const auto &w : s_debugUIWindows)
{
ImGui::Begin(w.Title);
ImGui::SetWindowPos({w.Position.x, w.Position.y});
ImGui::SetWindowSize({w.Size.x, w.Size.y});
w.ContentDrawCallback();
ImGui::End();
}
}
VOID DebugDraw::DrawLine(IN CONST glm::vec2 &from, IN CONST glm::vec2 &to, IN CONST glm::vec4 &color)
{
}
VOID DebugDraw::DrawRect(IN CONST glm::vec2 &position, IN CONST glm::vec2 &size, IN CONST glm::vec4 &color)
{
}
VOID DebugDraw::AddDebugUIWindow(IN PCCHAR title, IN CONST glm::vec2 &position, IN CONST glm::vec2 &size,
IN std::function<VOID()> contentDrawCallback)
{
s_debugUIWindows.pushBack(DebugUIWindow{title, position, size, contentDrawCallback});
}
} // namespace ia::iae

View File

@ -0,0 +1,81 @@
// 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/Pipeline/PostProcess.hpp>
#include <SDL3/SDL_gpu.h>
#include <EmbeddedShaders.hpp>
namespace ia::iae
{
EXTERN SDL_GPUDevice *g_gpuDevice;
EXTERN SDL_Window *g_windowHandle;
Pipeline_PostProcess::~Pipeline_PostProcess()
{
if (m_handle)
SDL_ReleaseGPUGraphicsPipeline(g_gpuDevice, (SDL_GPUGraphicsPipeline *) m_handle);
}
RefPtr<Pipeline_PostProcess> Pipeline_PostProcess::Create()
{
const auto res = MakeRefPtr<Pipeline_PostProcess>();
const auto vertexShader = LoadShaderFromMemory(ShaderStage::VERTEX, SHADER_SOURCE_POSTPROCESS_VERT,
sizeof(SHADER_SOURCE_POSTPROCESS_VERT), 0, 0, 0, 0);
const auto pixelShader = LoadShaderFromMemory(ShaderStage::PIXEL, SHADER_SOURCE_POSTPROCESS_FRAG,
sizeof(SHADER_SOURCE_POSTPROCESS_FRAG), 2, 0, 0, 0);
SDL_GPUColorTargetDescription colorTargets[] = {{
.format = SDL_GetGPUSwapchainTextureFormat(g_gpuDevice, g_windowHandle),
}};
SDL_GPUGraphicsPipelineCreateInfo createInfo = {
.vertex_shader = (SDL_GPUShader *) vertexShader,
.fragment_shader = (SDL_GPUShader *) pixelShader,
.vertex_input_state = SDL_GPUVertexInputState{.vertex_buffer_descriptions = nullptr,
.num_vertex_buffers = 0,
.vertex_attributes = nullptr,
.num_vertex_attributes = 0},
.primitive_type = SDL_GPU_PRIMITIVETYPE_TRIANGLELIST,
.rasterizer_state = SDL_GPURasterizerState{.fill_mode = SDL_GPU_FILLMODE_FILL,
.cull_mode = SDL_GPU_CULLMODE_NONE,
.front_face = SDL_GPU_FRONTFACE_COUNTER_CLOCKWISE},
.target_info = {.color_target_descriptions = colorTargets,
.num_color_targets = sizeof(colorTargets) / sizeof(colorTargets[0]),
.has_depth_stencil_target = false},
};
SDL_GPUGraphicsPipeline *handle{};
if (!(handle = SDL_CreateGPUGraphicsPipeline(g_gpuDevice, &createInfo)))
{
IAE_LOG_ERROR("Failed to create a SDL graphics pipeline: ", SDL_GetError());
return nullptr;
}
UnloadShader(pixelShader);
UnloadShader(vertexShader);
res->m_handle = (Handle) handle;
return res;
}
VOID Pipeline_PostProcess::Bind(IN Handle renderPassHandle)
{
SDL_BindGPUGraphicsPipeline((SDL_GPURenderPass *) renderPassHandle, (SDL_GPUGraphicsPipeline *) m_handle);
}
} // namespace ia::iae

View File

@ -16,8 +16,10 @@
#include <IAEngine/IAEngine.hpp> #include <IAEngine/IAEngine.hpp>
#include <IAEngine/Rendering/Camera.hpp> #include <IAEngine/Rendering/Camera.hpp>
#include <IAEngine/Rendering/DebugDraw.hpp>
#include <IAEngine/Rendering/GPUBuffer.hpp> #include <IAEngine/Rendering/GPUBuffer.hpp>
#include <IAEngine/Rendering/GPUTexture.hpp> #include <IAEngine/Rendering/GPUTexture.hpp>
#include <IAEngine/Rendering/Pipeline/PostProcess.hpp>
#include <IAEngine/Rendering/Pipeline/UnlitMesh.hpp> #include <IAEngine/Rendering/Pipeline/UnlitMesh.hpp>
#include <IAEngine/Rendering/Renderer.hpp> #include <IAEngine/Rendering/Renderer.hpp>
@ -45,7 +47,7 @@ namespace ia::iae
SDL_Rect Scissor{0, 0, 0, 0}; SDL_Rect Scissor{0, 0, 0, 0};
}; };
Vector<Mesh*> g_meshes{}; Vector<Mesh *> g_meshes{};
RenderState g_renderState{}; RenderState g_renderState{};
} // namespace ia::iae } // namespace ia::iae
@ -55,21 +57,21 @@ namespace ia::iae
INT32 Renderer::s_width{}; INT32 Renderer::s_width{};
INT32 Renderer::s_height{}; INT32 Renderer::s_height{};
Vector<Renderer::DebugUIWindow> Renderer::s_debugUIWindows;
SDL_GPUDevice *g_gpuDevice{}; SDL_GPUDevice *g_gpuDevice{};
ImDrawData *g_imDrawData{};
// Render State // Render State
SDL_GPUCommandBuffer *g_cmdBuffer{}; SDL_GPUCommandBuffer *g_cmdBuffer{};
SDL_GPURenderPass *g_renderPass{}; SDL_GPURenderPass *g_renderPass{};
SDL_GPUTexture *g_swpChainTexture{}; SDL_GPUTexture *g_swpChainTexture{};
SDL_GPUTexture *g_depthBufferTexture{}; SDL_GPUTexture *g_depthBufferTexture{};
SDL_GPUTexture *g_sceneDrawBufferTexture{};
// ImGUI State SDL_GPUTexture *g_debugDrawBufferTexture{};
ImGuiIO g_imGUIIO{};
ImDrawData *g_imDrawData{};
RefPtr<Pipeline_UnlitMesh> g_pipelineUnlitMesh; RefPtr<Pipeline_UnlitMesh> g_pipelineUnlitMesh;
RefPtr<Pipeline_PostProcess> g_pipelinePostProcess;
Camera2D g_camera{}; Camera2D g_camera{};
@ -86,6 +88,9 @@ namespace ia::iae
Texture g_whiteFillTexture{}; Texture g_whiteFillTexture{};
Texture g_whiteStrokeTexture{}; Texture g_whiteStrokeTexture{};
SDL_GPUColorTargetInfo colorTargetInfo = {0};
SDL_GPUDepthStencilTargetInfo depthStencilTargetInfo = {0};
BOOL Renderer::Initialize() BOOL Renderer::Initialize()
{ {
SDL_GetWindowSizeInPixels(g_windowHandle, &s_width, &s_height); SDL_GetWindowSizeInPixels(g_windowHandle, &s_width, &s_height);
@ -104,30 +109,24 @@ namespace ia::iae
SDL_SetGPUSwapchainParameters(g_gpuDevice, g_windowHandle, SDL_GPU_SWAPCHAINCOMPOSITION_SDR, SDL_SetGPUSwapchainParameters(g_gpuDevice, g_windowHandle, SDL_GPU_SWAPCHAINCOMPOSITION_SDR,
SDL_GPU_PRESENTMODE_VSYNC); SDL_GPU_PRESENTMODE_VSYNC);
const auto mainScale = SDL_GetDisplayContentScale(SDL_GetPrimaryDisplay()); DebugDraw::Initailize();
IMGUI_CHECKVERSION();
ImGui::CreateContext();
g_imGUIIO = ImGui::GetIO();
g_imGUIIO.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;
g_imGUIIO.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad;
ImGui::StyleColorsClassic();
ImGuiStyle &style = ImGui::GetStyle();
style.ScaleAllSizes(mainScale);
style.FontScaleDpi = mainScale;
ImGui_ImplSDLGPU3_InitInfo initInfo{.Device = g_gpuDevice,
.ColorTargetFormat =
SDL_GetGPUSwapchainTextureFormat(g_gpuDevice, g_windowHandle),
.PresentMode = SDL_GPU_PRESENTMODE_VSYNC};
ImGui_ImplSDL3_InitForSDLGPU(g_windowHandle);
ImGui_ImplSDLGPU3_Init(&initInfo);
if (!GPUBuffer::InitializeStagingBuffer()) if (!GPUBuffer::InitializeStagingBuffer())
return false; return false;
{
SDL_GPUTextureCreateInfo createInfo{.type = SDL_GPU_TEXTURETYPE_2D,
.format = SDL_GetGPUSwapchainTextureFormat(g_gpuDevice, g_windowHandle),
.usage =
SDL_GPU_TEXTUREUSAGE_COLOR_TARGET | SDL_GPU_TEXTUREUSAGE_SAMPLER,
.width = (UINT32) s_width,
.height = (UINT32) s_height,
.layer_count_or_depth = 1,
.num_levels = 1,
.sample_count = SDL_GPU_SAMPLECOUNT_1};
g_sceneDrawBufferTexture = SDL_CreateGPUTexture(g_gpuDevice, &createInfo);
g_debugDrawBufferTexture = SDL_CreateGPUTexture(g_gpuDevice, &createInfo);
}
{ {
SDL_GPUTextureCreateInfo createInfo{.type = SDL_GPU_TEXTURETYPE_2D, SDL_GPUTextureCreateInfo createInfo{.type = SDL_GPU_TEXTURETYPE_2D,
.format = SDL_GPU_TEXTUREFORMAT_D16_UNORM, .format = SDL_GPU_TEXTUREFORMAT_D16_UNORM,
@ -143,6 +142,7 @@ namespace ia::iae
GPUTexture::Initialize(); GPUTexture::Initialize();
g_pipelineUnlitMesh = Pipeline_UnlitMesh::Create(); g_pipelineUnlitMesh = Pipeline_UnlitMesh::Create();
g_pipelinePostProcess = Pipeline_PostProcess::Create();
matProjection = glm::orthoLH(0.0f, (FLOAT32) s_width, (FLOAT32) s_height, 0.0f, -2097152.0f, 2097152.0f); matProjection = glm::orthoLH(0.0f, (FLOAT32) s_width, (FLOAT32) s_height, 0.0f, -2097152.0f, 2097152.0f);
@ -182,6 +182,18 @@ namespace ia::iae
}, },
{0, 1, 2, 2, 3, 0}); {0, 1, 2, 2, 3, 0});
colorTargetInfo.clear_color = SDL_FColor{0.33f, 0.33f, 0.33f, 1.0f};
colorTargetInfo.load_op = SDL_GPU_LOADOP_CLEAR;
colorTargetInfo.store_op = SDL_GPU_STOREOP_STORE;
depthStencilTargetInfo.cycle = true;
depthStencilTargetInfo.clear_depth = 0;
depthStencilTargetInfo.clear_stencil = 0;
depthStencilTargetInfo.load_op = SDL_GPU_LOADOP_CLEAR;
depthStencilTargetInfo.store_op = SDL_GPU_STOREOP_STORE;
depthStencilTargetInfo.stencil_load_op = SDL_GPU_LOADOP_CLEAR;
depthStencilTargetInfo.stencil_store_op = SDL_GPU_STOREOP_STORE;
return true; return true;
} }
@ -197,77 +209,32 @@ namespace ia::iae
} }
g_pipelineUnlitMesh.reset(); g_pipelineUnlitMesh.reset();
g_pipelinePostProcess.reset();
GPUTexture::Terminate(); GPUTexture::Terminate();
GPUBuffer::TerminateStagingBuffer(); GPUBuffer::TerminateStagingBuffer();
SDL_ReleaseGPUTexture(g_gpuDevice, g_depthBufferTexture); SDL_ReleaseGPUTexture(g_gpuDevice, g_depthBufferTexture);
SDL_ReleaseGPUTexture(g_gpuDevice, g_sceneDrawBufferTexture);
SDL_ReleaseGPUTexture(g_gpuDevice, g_debugDrawBufferTexture);
ImGui_ImplSDL3_Shutdown(); DebugDraw::Terminate();
ImGui_ImplSDLGPU3_Shutdown();
ImGui::DestroyContext();
SDL_ReleaseWindowFromGPUDevice(g_gpuDevice, g_windowHandle); SDL_ReleaseWindowFromGPUDevice(g_gpuDevice, g_windowHandle);
SDL_DestroyGPUDevice(g_gpuDevice); SDL_DestroyGPUDevice(g_gpuDevice);
} }
VOID Renderer::AddDebugUIWindow(IN PCCHAR title, IN CONST glm::vec2 &position, IN CONST glm::vec2 &size,
IN std::function<VOID()> contentDrawCallback)
{
s_debugUIWindows.pushBack(DebugUIWindow{title, position, size, contentDrawCallback});
}
VOID Renderer::BeginFrame() VOID Renderer::BeginFrame()
{ {
ImGui_ImplSDLGPU3_NewFrame();
ImGui_ImplSDL3_NewFrame();
ImGui::NewFrame();
for (const auto &w : s_debugUIWindows)
{
ImGui::Begin(w.Title);
ImGui::SetWindowPos({w.Position.x, w.Position.y});
ImGui::SetWindowSize({w.Size.x, w.Size.y});
w.ContentDrawCallback();
ImGui::End();
}
ImGui::Render();
if (!(g_cmdBuffer = SDL_AcquireGPUCommandBuffer(g_gpuDevice))) if (!(g_cmdBuffer = SDL_AcquireGPUCommandBuffer(g_gpuDevice)))
{ {
IAE_LOG_ERROR("Couldn't acquire SDL3 GPU command buffer: ", SDL_GetError()); IAE_LOG_ERROR("Couldn't acquire SDL3 GPU command buffer: ", SDL_GetError());
return; return;
} }
if (!SDL_WaitAndAcquireGPUSwapchainTexture(g_cmdBuffer, g_windowHandle, &g_swpChainTexture, (PUINT32) &s_width, colorTargetInfo.texture = g_sceneDrawBufferTexture;
(PUINT32) &s_height))
{
IAE_LOG_ERROR("Couldn't acquire SDL3 GPU Swapchain texture: ", SDL_GetError());
return;
}
if (!g_swpChainTexture)
return;
g_imDrawData = ImGui::GetDrawData();
ImGui_ImplSDLGPU3_PrepareDrawData(g_imDrawData, g_cmdBuffer);
SDL_GPUColorTargetInfo colorTargetInfo = {0};
colorTargetInfo.texture = g_swpChainTexture;
colorTargetInfo.clear_color = SDL_FColor{0.33f, 0.33f, 0.33f, 1.0f};
colorTargetInfo.load_op = SDL_GPU_LOADOP_CLEAR;
colorTargetInfo.store_op = SDL_GPU_STOREOP_STORE;
SDL_GPUDepthStencilTargetInfo depthStencilTargetInfo = {0};
depthStencilTargetInfo.texture = g_depthBufferTexture; depthStencilTargetInfo.texture = g_depthBufferTexture;
depthStencilTargetInfo.cycle = true;
depthStencilTargetInfo.clear_depth = 0;
depthStencilTargetInfo.clear_stencil = 0;
depthStencilTargetInfo.load_op = SDL_GPU_LOADOP_CLEAR;
depthStencilTargetInfo.store_op = SDL_GPU_STOREOP_STORE;
depthStencilTargetInfo.stencil_load_op = SDL_GPU_LOADOP_CLEAR;
depthStencilTargetInfo.stencil_store_op = SDL_GPU_STOREOP_STORE;
g_renderPass = SDL_BeginGPURenderPass(g_cmdBuffer, &colorTargetInfo, 1, &depthStencilTargetInfo); g_renderPass = SDL_BeginGPURenderPass(g_cmdBuffer, &colorTargetInfo, 1, &depthStencilTargetInfo);
@ -279,11 +246,48 @@ namespace ia::iae
VOID Renderer::EndFrame() VOID Renderer::EndFrame()
{ {
SDL_EndGPURenderPass(g_renderPass);
ImGui_ImplSDLGPU3_NewFrame();
ImGui_ImplSDL3_NewFrame();
ImGui::NewFrame();
DebugDraw::Draw();
ImGui::Render();
g_imDrawData = ImGui::GetDrawData();
ImGui_ImplSDLGPU3_PrepareDrawData(g_imDrawData, g_cmdBuffer);
colorTargetInfo.texture = g_debugDrawBufferTexture;
g_renderPass = SDL_BeginGPURenderPass(g_cmdBuffer, &colorTargetInfo, 1, nullptr);
ImGui_ImplSDLGPU3_RenderDrawData(g_imDrawData, g_cmdBuffer, g_renderPass);
SDL_EndGPURenderPass(g_renderPass);
if (!SDL_WaitAndAcquireGPUSwapchainTexture(g_cmdBuffer, g_windowHandle, &g_swpChainTexture, (PUINT32) &s_width,
(PUINT32) &s_height))
{
IAE_LOG_ERROR("Couldn't acquire SDL3 GPU Swapchain texture: ", SDL_GetError());
return;
}
if (!g_swpChainTexture) if (!g_swpChainTexture)
return; return;
ImGui_ImplSDLGPU3_RenderDrawData(g_imDrawData, g_cmdBuffer, g_renderPass); colorTargetInfo.texture = g_swpChainTexture;
g_renderPass = SDL_BeginGPURenderPass(g_cmdBuffer, &colorTargetInfo, 1, nullptr);
g_pipelinePostProcess->Bind((Handle) g_renderPass);
SDL_GPUTextureSamplerBinding textureBindings[2] = {
{
.texture = g_sceneDrawBufferTexture,
.sampler = (SDL_GPUSampler*)GPUTexture::GetDefaultSampler()
},
{
.texture = g_debugDrawBufferTexture,
.sampler = (SDL_GPUSampler*)GPUTexture::GetDefaultSampler()
},
};
SDL_BindGPUFragmentSamplers(g_renderPass, 0, textureBindings, 2);
SDL_DrawGPUPrimitives(g_renderPass, 6, 1, 0, 0);
SDL_EndGPURenderPass(g_renderPass); SDL_EndGPURenderPass(g_renderPass);
SDL_SubmitGPUCommandBuffer(g_cmdBuffer); SDL_SubmitGPUCommandBuffer(g_cmdBuffer);
} }
@ -336,7 +340,7 @@ namespace ia::iae
Handle Renderer::CreateMesh(IN CONST Vector<MeshVertex> &vertices, IN CONST Vector<INT32> &indices) Handle Renderer::CreateMesh(IN CONST Vector<MeshVertex> &vertices, IN CONST Vector<INT32> &indices)
{ {
const auto mesh = CreateUnmanagedMesh(vertices, indices); const auto mesh = CreateUnmanagedMesh(vertices, indices);
g_meshes.pushBack((Mesh*)mesh); g_meshes.pushBack((Mesh *) mesh);
return mesh; return mesh;
} }
@ -348,12 +352,12 @@ namespace ia::iae
mesh->IndexBuffer = GPUBuffer::Create(GPUBuffer::Usage::INDEX, indices.data(), mesh->IndexBuffer = GPUBuffer::Create(GPUBuffer::Usage::INDEX, indices.data(),
static_cast<UINT32>(indices.size() * sizeof(indices[0]))); static_cast<UINT32>(indices.size() * sizeof(indices[0])));
mesh->IndexCount = static_cast<UINT32>(indices.size()); mesh->IndexCount = static_cast<UINT32>(indices.size());
return (Handle)mesh; return (Handle) mesh;
} }
VOID Renderer::DestroyUnmanagedMesh(IN Handle handle) VOID Renderer::DestroyUnmanagedMesh(IN Handle handle)
{ {
delete ((Mesh*)handle); delete ((Mesh *) handle);
} }
VOID Renderer::Draw(IN Handle meshHandle, IN Handle textureHandle, IN CONST glm::vec2 &position, VOID Renderer::Draw(IN Handle meshHandle, IN Handle textureHandle, IN CONST glm::vec2 &position,
@ -402,7 +406,7 @@ namespace ia::iae
else else
SDL_SetGPUScissor(g_renderPass, &g_defaultScissor); SDL_SetGPUScissor(g_renderPass, &g_defaultScissor);
const auto mesh = (Mesh*)meshHandle; const auto mesh = (Mesh *) meshHandle;
SDL_GPUBufferBinding bufferBindings[] = { SDL_GPUBufferBinding bufferBindings[] = {
{.buffer = (SDL_GPUBuffer *) mesh->VertexBuffer->GetHandle(), .offset = 0}, {.buffer = (SDL_GPUBuffer *) mesh->VertexBuffer->GetHandle(), .offset = 0},
{.buffer = (SDL_GPUBuffer *) mesh->IndexBuffer->GetHandle(), .offset = 0}}; {.buffer = (SDL_GPUBuffer *) mesh->IndexBuffer->GetHandle(), .offset = 0}};

View File

@ -0,0 +1,23 @@
#version 450
#extension GL_ARB_separate_shader_objects : enable
layout(location = 0) in vec2 inTexCoord;
layout(set = 2, binding = 0) uniform sampler2D sceneDrawTexture;
layout(set = 2, binding = 1) uniform sampler2D debugDrawTexture;
layout(location = 0) out vec4 outColor;
vec4 overlay(vec4 background, vec4 foreground) {
return mix(
2.0 * background * foreground,
1.0 - 2.0 * (1.0 - background) * (1.0 - foreground),
step(0.5, background)
);
}
void main()
{
vec2 uv = vec2(inTexCoord.x, 1.0 - inTexCoord.y);
outColor = overlay(texture(debugDrawTexture, uv), texture(sceneDrawTexture, uv));
}

View File

@ -0,0 +1,10 @@
#version 450
#extension GL_ARB_separate_shader_objects : enable
layout(location = 0) out vec2 outTexCoord;
void main()
{
outTexCoord = vec2((gl_VertexIndex << 1) & 2, gl_VertexIndex & 2);
gl_Position = vec4(outTexCoord * 2.0f - 1.0f, 0.0f, 1.0f);
}

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,50 @@
// 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/Rendering/Types.hpp>
namespace ia::iae
{
class DebugDraw
{
struct DebugUIWindow
{
PCCHAR Title{""};
glm::vec2 Position{};
glm::vec2 Size{};
std::function<VOID()> ContentDrawCallback{};
};
public:
STATIC VOID DrawLine(IN CONST glm::vec2& from, IN CONST glm::vec2& to, IN CONST glm::vec4& color);
STATIC VOID DrawRect(IN CONST glm::vec2& position, IN CONST glm::vec2& size, IN CONST glm::vec4& color);
STATIC VOID AddDebugUIWindow(IN PCCHAR title, IN CONST glm::vec2 &position, IN CONST glm::vec2 &size,
IN std::function<VOID()> contentDrawCallback);
private:
STATIC VOID Initailize();
STATIC VOID Terminate();
STATIC VOID Draw();
STATIC Vector<DebugUIWindow> s_debugUIWindows;
friend class Renderer;
};
} // namespace ia::iae

View File

@ -0,0 +1,35 @@
// 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/Rendering/Pipeline/Pipeline.hpp>
namespace ia::iae
{
class Pipeline_PostProcess: public IPipeline
{
public:
~Pipeline_PostProcess();
STATIC RefPtr<Pipeline_PostProcess> Create();
VOID Bind(IN Handle renderPassHandle);
private:
Handle m_handle{INVALID_HANDLE};
};
}

View File

@ -24,14 +24,6 @@ namespace ia::iae
class Renderer class Renderer
{ {
struct DebugUIWindow
{
PCCHAR Title{""};
glm::vec2 Position{};
glm::vec2 Size{};
std::function<VOID()> ContentDrawCallback{};
};
public: public:
STATIC CONSTEXPR UINT8 MAX_LAYER_INDEX = 255; STATIC CONSTEXPR UINT8 MAX_LAYER_INDEX = 255;
@ -39,10 +31,6 @@ namespace ia::iae
STATIC BOOL Initialize(); STATIC BOOL Initialize();
STATIC VOID Terminate(); STATIC VOID Terminate();
public:
STATIC VOID AddDebugUIWindow(IN PCCHAR title, IN CONST glm::vec2 &position, IN CONST glm::vec2 &size,
IN std::function<VOID()> contentDrawCallback);
public: public:
STATIC VOID BeginFrame(); STATIC VOID BeginFrame();
STATIC VOID EndFrame(); STATIC VOID EndFrame();
@ -82,6 +70,5 @@ namespace ia::iae
private: private:
STATIC INT32 s_width; STATIC INT32 s_width;
STATIC INT32 s_height; STATIC INT32 s_height;
STATIC Vector<DebugUIWindow> s_debugUIWindows;
}; };
} // namespace ia::iae } // namespace ia::iae

View File

@ -34,7 +34,9 @@ SHADER_SOURCE_PATH = "Src/IAEngine/imp/glsl"
SHADER_SOURCE_FILES = [ SHADER_SOURCE_FILES = [
"UnlitMesh/UnlitMesh.vert", "UnlitMesh/UnlitMesh.vert",
"UnlitMesh/UnlitMesh.frag" "UnlitMesh/UnlitMesh.frag",
"PostProcessing/PostProcess.vert",
"PostProcessing/PostProcess.frag"
] ]
def file_to_source_array(arrayName, filePath): def file_to_source_array(arrayName, filePath):