We got GameObjects / Components and shit

This commit is contained in:
2026-01-10 06:09:50 +01:00
parent 10b00b0525
commit 0bfc5e0705
35 changed files with 1546 additions and 331 deletions

View File

@@ -2,12 +2,28 @@
#define LIGHTKEEPER_H
#include <destrum/App.h>
#include <destrum/Scene/SceneManager.h>
class LightKeeper : public App {
class LightKeeper final : public App {
public:
LightKeeper();
virtual ~LightKeeper();
void customInit() override;
void customUpdate(float dt) override;
void customDraw() override;
void customCleanup() override;
void onWindowResize(int newWidth, int newHeight) override;
private:
MeshCache meshCache;
MaterialCache materialCache;
GameRenderer renderer;
Camera camera{glm::vec3(0.f, 0.f, -5.f), glm::vec3(0, 1, 0)};
CPUMesh testMesh{};
MeshID testMeshID;
MaterialID testMaterialID;
};
#endif //LIGHTKEEPER_H

View File

@@ -1,4 +1,108 @@
#include "Lightkeeper.h"
LightKeeper::LightKeeper() {
#include <destrum/FS/AssetFS.h>
#include "glm/gtx/transform.hpp"
#include "spdlog/spdlog.h"
#include <destrum/Scene/Scene.h>
#include "destrum/Components/MeshRendererComponent.h"
#include "destrum/Components/Rotator.h"
#include "destrum/ObjectModel/GameObject.h"
LightKeeper::LightKeeper(): App(), renderer(meshCache, materialCache) {
}
LightKeeper::~LightKeeper() {
}
void LightKeeper::customInit() {
materialCache.init(gfxDevice);
renderer.init(gfxDevice, m_params.renderSize);
const float aspectRatio = static_cast<float>(m_params.renderSize.x) / static_cast<float>(m_params.renderSize.y);
camera.setAspectRatio(aspectRatio);
auto file = AssetFS::GetInstance().ReadBytes("engine://assetfstest.txt");
std::string fileStr(file.begin(), file.end());
spdlog::info("Read from assetfstest.txt: {}", fileStr);
testMesh.name = "Test Mesh";
testMesh.vertices = vertices;
testMesh.indices = indices;
testMeshID = meshCache.addMesh(gfxDevice, testMesh);
spdlog::info("TestMesh uploaded with id: {}", testMeshID);
const auto testimgpath = AssetFS::GetInstance().GetFullPath("engine://textures/kobe.png");
auto testimgID = gfxDevice.loadImageFromFile(testimgpath);
spdlog::info("Test image loaded with id: {}", testimgID);
testMaterialID = materialCache.addMaterial(gfxDevice, {
.baseColor = glm::vec3(1.f),
.diffuseTexture = testimgID,
});
spdlog::info("Test material created with id: {}", testMaterialID);
camera.SetRotation(glm::radians(glm::vec2(90.f, 0.f)));
auto& scene = SceneManager::GetInstance().CreateScene("Main");
auto testCube = std::make_shared<GameObject>("TestCube");
auto meshComp = testCube->AddComponent<MeshRendererComponent>();
meshComp->SetMeshID(testMeshID);
meshComp->SetMaterialID(testMaterialID);
testCube->AddComponent<Rotator>(10, 5);
scene.Add(testCube);
}
void LightKeeper::customUpdate(float dt) {
camera.Update(dt);
SceneManager::GetInstance().Update();
}
void LightKeeper::customDraw() {
renderer.beginDrawing(gfxDevice);
const RenderContext ctx{
.renderer = renderer,
.camera = camera,
.sceneData = {
.camera = camera,
.ambientColor = glm::vec3(0.1f),
.ambientIntensity = 0.5f,
.fogColor = glm::vec3(0.5f),
.fogDensity = 0.01f
}
};
SceneManager::GetInstance().Render(ctx);
renderer.endDrawing();
const auto cmd = gfxDevice.beginFrame();
const auto& drawImage = renderer.getDrawImage(gfxDevice);
renderer.draw(
cmd, gfxDevice, camera, GameRenderer::SceneData{
camera, glm::vec3(0.1f), 0.5f, glm::vec3(0.5f), 0.01f
});
gfxDevice.endFrame(
cmd, drawImage, {
.clearColor = {{0.f, 0.f, 0.5f, 1.f}},
.drawImageBlitRect = glm::ivec4{}
});
}
void LightKeeper::customCleanup() {
SceneManager::GetInstance().Destroy();
renderer.cleanup(gfxDevice.getDevice().device);
}
void LightKeeper::onWindowResize(int newWidth, int newHeight) {
renderer.resize(gfxDevice, glm::ivec2{newWidth, newHeight});
const float aspectRatio = static_cast<float>(newWidth) / static_cast<float>(newHeight);
camera.setAspectRatio(aspectRatio);
}

View File

@@ -23,6 +23,7 @@ int main(int argc, char* argv[]) {
.exeDir = exeDir,
});
app.run();
app.cleanup();
SDL_Quit();
return 0;

View File

@@ -1,213 +0,0 @@
#include <SDL.h>
#include <SDL_vulkan.h>
#include <vulkan/vulkan.h>
#include <VkBootstrap.h>
#include <vk_mem_alloc.h>
#include <vector>
#include <iostream>
#include <stdexcept>
#include <volk.h>
const int MAX_FRAMES_IN_FLIGHT = 2;
struct FrameData {
VkSemaphore imageAvailable;
VkSemaphore renderFinished;
VkFence inFlight;
VkCommandBuffer commandBuffer;
};
SDL_Window* window = nullptr;
VkInstance instance;
vkb::PhysicalDevice physicalDevice;
VkDevice device;
vkb::Device vkbDevice;
VkQueue graphicsQueue;
VkQueue presentQueue;
VkSurfaceKHR surface;
VkSwapchainKHR swapchain;
std::vector<VkImage> swapchainImages;
std::vector<VkImageView> swapchainImageViews;
VkCommandPool commandPool;
FrameData frames[MAX_FRAMES_IN_FLIGHT];
std::vector<VkFence> imagesInFlight;
size_t currentFrame = 0;
VkFormat swapchainImageFormat;
VkExtent2D swapchainExtent;
// --- Helper: allocate command buffer ---
VkCommandBuffer allocateCommandBuffer(VkDevice device, VkCommandPool pool) {
VkCommandBufferAllocateInfo allocInfo{};
allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
allocInfo.commandPool = pool;
allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
allocInfo.commandBufferCount = 1;
VkCommandBuffer cmd;
vkAllocateCommandBuffers(device, &allocInfo, &cmd);
return cmd;
}
// --- Helper: record command buffer with dynamic rendering ---
void recordCommandBuffer(VkCommandBuffer cmd, VkImage image) {
VkCommandBufferBeginInfo beginInfo{};
beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
vkBeginCommandBuffer(cmd, &beginInfo);
VkRenderingAttachmentInfo colorAttachment{};
colorAttachment.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO;
colorAttachment.imageView = VK_NULL_HANDLE; // placeholder, normally swapchainImageViews[i]
colorAttachment.imageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
VkClearValue clearColor{ {{0.1f, 0.2f, 0.3f, 1.0f}} };
colorAttachment.clearValue = clearColor;
colorAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
colorAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
VkRenderingInfo renderingInfo{};
renderingInfo.sType = VK_STRUCTURE_TYPE_RENDERING_INFO;
renderingInfo.renderArea.offset = {0, 0};
renderingInfo.renderArea.extent = {800, 600};
renderingInfo.layerCount = 1;
renderingInfo.colorAttachmentCount = 1;
renderingInfo.pColorAttachments = &colorAttachment;
vkCmdBeginRendering(cmd, &renderingInfo);
// No draw calls, just clear
vkCmdEndRendering(cmd);
vkEndCommandBuffer(cmd);
}
int SDL_main(int argc, char* argv[]) {
// --- SDL Window ---
if (SDL_Init(SDL_INIT_VIDEO) != 0)
throw std::runtime_error("SDL_Init failed");
window = SDL_CreateWindow("Vulkan SDL Dynamic Rendering",
SDL_WINDOWPOS_CENTERED,
SDL_WINDOWPOS_CENTERED,
800, 600,
SDL_WINDOW_VULKAN);
// --- Vulkan instance ---
volkInitialize();
vkb::InstanceBuilder builder;
auto instRet = builder.set_app_name("SDL Dynamic Rendering")
.request_validation_layers(true)
.build();
if (!instRet) throw std::runtime_error("Failed to create instance");
instance = instRet.value().instance;
if (!SDL_Vulkan_CreateSurface(window, instance, &surface))
throw std::runtime_error("Failed to create Vulkan surface");
// --- Physical device & logical device ---
vkb::PhysicalDeviceSelector selector{instRet.value()};
auto physRet = selector.set_minimum_version(1,2).set_surface(surface).require_dedicated_transfer_queue().select();
if (!physRet) throw std::runtime_error("Failed to select physical device");
physicalDevice = physRet.value();
vkb::DeviceBuilder deviceBuilder{physicalDevice};
auto devRet = deviceBuilder.build();
if (!devRet) throw std::runtime_error("Failed to create device");
device = devRet.value().device;
vkbDevice = devRet.value();
graphicsQueue = devRet.value().get_queue(vkb::QueueType::graphics).value();
presentQueue = devRet.value().get_queue(vkb::QueueType::present).value();
// --- Swapchain ---
vkb::SwapchainBuilder swapchainBuilder{vkbDevice};
auto swapRet = swapchainBuilder.set_desired_format(VkSurfaceFormatKHR{
.format = VK_FORMAT_B8G8R8A8_SRGB,
.colorSpace = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR,
})
.set_desired_present_mode(VK_PRESENT_MODE_FIFO_KHR)
.set_desired_extent(800,600)
.build();
if (!swapRet) throw std::runtime_error("Failed to create swapchain");
swapchain = swapRet.value().swapchain;
swapchainImages = swapRet.value().get_images().value();
swapchainImageFormat = swapRet.value().image_format;
swapchainExtent = swapRet.value().extent;
// --- Command pool ---
VkCommandPoolCreateInfo poolInfo{};
poolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
poolInfo.queueFamilyIndex = vkbDevice.get_queue_index(vkb::QueueType::graphics).value();
poolInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
vkCreateCommandPool(device, &poolInfo, nullptr, &commandPool);
// --- Frames ---
imagesInFlight.resize(swapchainImages.size(), VK_NULL_HANDLE);
for (int i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) {
VkSemaphoreCreateInfo semInfo{};
semInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
vkCreateSemaphore(device, &semInfo, nullptr, &frames[i].imageAvailable);
vkCreateSemaphore(device, &semInfo, nullptr, &frames[i].renderFinished);
VkFenceCreateInfo fenceInfo{};
fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
fenceInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT;
vkCreateFence(device, &fenceInfo, nullptr, &frames[i].inFlight);
frames[i].commandBuffer = allocateCommandBuffer(device, commandPool);
}
// --- Main loop ---
bool running = true;
while (running) {
SDL_Event event;
while (SDL_PollEvent(&event)) {
if (event.type == SDL_QUIT) running = false;
}
FrameData& frame = frames[currentFrame];
vkWaitForFences(device, 1, &frame.inFlight, VK_TRUE, UINT64_MAX);
uint32_t imageIndex;
vkAcquireNextImageKHR(device, swapchain, UINT64_MAX, frame.imageAvailable, VK_NULL_HANDLE, &imageIndex);
if (imagesInFlight[imageIndex] != VK_NULL_HANDLE)
vkWaitForFences(device, 1, &imagesInFlight[imageIndex], VK_TRUE, UINT64_MAX);
imagesInFlight[imageIndex] = frame.inFlight;
vkResetFences(device, 1, &frame.inFlight);
vkResetCommandBuffer(frame.commandBuffer, 0);
recordCommandBuffer(frame.commandBuffer, swapchainImages[imageIndex]);
VkSubmitInfo submitInfo{};
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
VkSemaphore waitSemaphores[] = { frame.imageAvailable };
VkPipelineStageFlags waitStages[] = { VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT };
submitInfo.waitSemaphoreCount = 1;
submitInfo.pWaitSemaphores = waitSemaphores;
submitInfo.pWaitDstStageMask = waitStages;
submitInfo.commandBufferCount = 1;
submitInfo.pCommandBuffers = &frame.commandBuffer;
VkSemaphore signalSemaphores[] = { frame.renderFinished };
submitInfo.signalSemaphoreCount = 1;
submitInfo.pSignalSemaphores = signalSemaphores;
vkQueueSubmit(graphicsQueue, 1, &submitInfo, frame.inFlight);
VkPresentInfoKHR presentInfo{};
presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
presentInfo.waitSemaphoreCount = 1;
presentInfo.pWaitSemaphores = signalSemaphores;
presentInfo.swapchainCount = 1;
presentInfo.pSwapchains = &swapchain;
presentInfo.pImageIndices = &imageIndex;
vkQueuePresentKHR(presentQueue, &presentInfo);
currentFrame = (currentFrame + 1) % MAX_FRAMES_IN_FLIGHT;
}
vkDeviceWaitIdle(device);
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}