Texture Rendering

This commit is contained in:
Isuru Samarathunga
2025-09-13 14:12:08 +05:30
parent 8a2baf6659
commit 50f3f14c47
25 changed files with 300 additions and 94 deletions

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,6 +9,8 @@ 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)

View File

@ -4,12 +4,16 @@
#include <IAEngine/ResourceManager.hpp> #include <IAEngine/ResourceManager.hpp>
#include <IACore/File.hpp>
namespace ia::iae::game namespace ia::iae::game
{ {
RefPtr<iae::Scene> scene; RefPtr<iae::Scene> scene;
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 +22,20 @@ 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({}, {}, {}, false, false, {});
} }
} }

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

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

@ -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

@ -28,7 +28,7 @@ namespace ia::iae
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] = {{iam::Vec3f{-1, 1, 0}, iam::Vec2f{0, 0}}, {iam::Vec3f{1, 1, 0}, iam::Vec2f{1, 0}},
{iam::Vec3f{1, -1, 0}, iam::Vec2f{1, 1}}, {iam::Vec3f{-1, 1, 0}, iam::Vec2f{0, 0}}, {iam::Vec3f{1, -1, 0}, iam::Vec2f{1, 1}}, {iam::Vec3f{-1, 1, 0}, iam::Vec2f{0, 0}},
{iam::Vec3f{1, -1, 0}, iam::Vec2f{1, 1}}, {iam::Vec3f{-1, -1, 0}, iam::Vec2f{0, 1}}}; {iam::Vec3f{1, -1, 0}, iam::Vec2f{1, 1}}, {iam::Vec3f{-1, -1, 0}, iam::Vec2f{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()
@ -39,6 +39,6 @@ namespace ia::iae
VOID QuadMesh::Draw(IN CONST iam::Vec3f &position, IN CONST iam::Vec3f &scale, IN FLOAT32 rotation) VOID QuadMesh::Draw(IN CONST iam::Vec3f &position, IN CONST iam::Vec3f &scale, IN FLOAT32 rotation)
{ {
Renderer::Draw((Handle)g_quadMeshVertexBuffer.get(), 6); Renderer::Draw(g_quadMeshVertexBuffer->GetHandle(), 6);
} }
} // namespace ia::iae } // namespace ia::iae

View File

@ -27,6 +27,8 @@ 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()
@ -34,7 +36,7 @@ namespace ia::iae
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, 0, 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, 0, 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(iam::Vec3f)}};
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

@ -16,6 +16,7 @@
#include <IAEngine/IAEngine.hpp> #include <IAEngine/IAEngine.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>
@ -87,6 +88,8 @@ 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();
@ -98,8 +101,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();
@ -172,6 +179,15 @@ namespace ia::iae
SDL_SubmitGPUCommandBuffer(g_cmdBuffer); SDL_SubmitGPUCommandBuffer(g_cmdBuffer);
} }
VOID Renderer::BindTexture(IN Handle handle, IN INT32 index)
{
SDL_GPUTextureSamplerBinding binding {
.texture = (SDL_GPUTexture*)handle,
.sampler = (SDL_GPUSampler*)GPUTexture::GetDefaultSampler()
};
SDL_BindGPUFragmentSamplers(g_renderPass, index, &binding, 1);
}
VOID Renderer::Draw(IN Handle vertexBufferHandle, IN INT32 vertexCount) VOID Renderer::Draw(IN Handle vertexBufferHandle, IN INT32 vertexCount)
{ {
SDL_GPUBufferBinding bindings[] = {{.buffer = (SDL_GPUBuffer *) vertexBufferHandle, .offset = 0}}; SDL_GPUBufferBinding bindings[] = {{.buffer = (SDL_GPUBuffer *) vertexBufferHandle, .offset = 0}};

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

@ -15,32 +15,26 @@
// 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/Texture.hpp> #include <IAEngine/Texture.hpp>
#include <SDL3/SDL.h> #include <IAEngine/Rendering/Renderer.hpp>
#include <IAEngine/Rendering/Mesh/Quad.hpp>
#define TEXTURE_HANDLE (SDL_Texture *) m_handle
namespace ia::iae namespace ia::iae
{ {
Texture::Texture() Texture::Texture(IN Handle handle,IN INT32 width, IN INT32 height):
m_handle(handle), m_size({(FLOAT32)width, (FLOAT32)height, 1.0f})
{ {
} }
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, 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 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}; Renderer::BindTexture(m_handle, 0);
//SDL_SetTextureColorModFloat(TEXTURE_HANDLE, colorOverlay.X, colorOverlay.Y, colorOverlay.Z); QuadMesh::Draw(position, m_size * scale, rotation);
//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 } // namespace ia::iae

View File

@ -5,7 +5,9 @@ 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;
void main() void main()
{ {
outColor = vec4(0, 1, 0, 1); outColor = texture(texSampler, inTexCoord);
} }

View File

@ -1,10 +1,13 @@
#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 inTexcCoord;
layout(location = 0) out vec2 outTexCoord; layout(location = 0) out vec2 outTexCoord;
void main() void main()
{ {
outTexCoord = vec2((gl_VertexIndex << 1) & 2, gl_VertexIndex & 2); gl_Position = vec4(inPosition, 1.0f);
gl_Position = vec4(outTexCoord * 2.0f - 1.0f, 0.0f, 1.0f); outTexCoord = inTexcCoord;
} }

File diff suppressed because one or more lines are too long

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
{ {

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
{ {

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
{ {

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

@ -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

@ -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

@ -44,6 +44,8 @@ namespace ia::iae
STATIC VOID BeginFrame(); STATIC VOID BeginFrame();
STATIC VOID EndFrame(); STATIC VOID EndFrame();
STATIC VOID BindTexture(IN Handle handle, IN INT32 index);
STATIC VOID Draw(IN Handle vertexBufferHandle, IN INT32 vertexCount); STATIC VOID Draw(IN Handle vertexBufferHandle, IN INT32 vertexCount);
STATIC VOID Draw(IN Handle vertexBufferHandle, IN Handle indexBufferHandle, IN INT32 indexCount); STATIC VOID Draw(IN Handle vertexBufferHandle, IN Handle indexBufferHandle, IN INT32 indexCount);

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 iam::Vec3f &position, IN CONST iam::Vec3f &scale, IN FLOAT32 rotation, IN BOOL flipH,
IN BOOL flipV, IN CONST iam::Vec4f &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 iam::Vec3f m_size;
PVOID m_handle{};
}; };
} // namespace ia::iae } // namespace ia::iae