#include #include #include #include #include "glm/gtx/transform.hpp" #include "spdlog/spdlog.h" App::App(): renderer{meshCache} { } void App::init(const AppParams& params) { m_params = params; AssetFS::GetInstance().Init(params.exeDir); // AssetFS::GetInstance().Mount("engine", params.exeDir / "assets" / "engine"); // AssetFS::GetInstance().Mount("game", params.exeDir / "assets" / "game"); window = SDL_CreateWindow( params.windowTitle.c_str(), // pos SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, // size params.windowSize.x, params.windowSize.y, SDL_WINDOW_VULKAN); SDL_SetWindowResizable(window, SDL_TRUE); if (!window) { spdlog::error("Failed to create window. SDL Error: {}", SDL_GetError()); std::exit(1); } gfxDevice.init(window, params.appName, false); renderer.init(gfxDevice, params.renderSize); //Read whole file 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); float aspectRatio = static_cast(params.renderSize.x) / static_cast(params.renderSize.y); camera.setAspectRatio(aspectRatio); //Look 90 deg to the right camera.SetRotation(glm::radians(glm::vec2(90.f, 0.f))); inputManager.Init(); } void App::run() { const float FPS = 30.f; const float dt = 1.f / FPS; auto prevTime = std::chrono::high_resolution_clock::now(); float accumulator = dt; // so that we get at least 1 update before render isRunning = true; while (isRunning) { const auto newTime = std::chrono::high_resolution_clock::now(); frameTime = std::chrono::duration(newTime - prevTime).count(); if (frameTime > 0.07f && frameTime < 5.f) { // if >=5.f - debugging? spdlog::warn("Frame drop detected, time: {:.4f}s", frameTime); } accumulator += frameTime; prevTime = newTime; float newFPS = 1.f / frameTime; if (newFPS == std::numeric_limits::infinity()) { // can happen when frameTime == 0 newFPS = 0; } avgFPS = std::lerp(avgFPS, newFPS, 0.1f); if (accumulator > 10 * dt) { // game stopped for debug accumulator = dt; } while (accumulator >= dt) { inputManager.BeginFrame(); SDL_Event event; while (SDL_PollEvent(&event)) { if (event.type == SDL_QUIT) { isRunning = false; return; } if (event.type == SDL_WINDOWEVENT) { switch (event.window.event) { case SDL_WINDOWEVENT_SIZE_CHANGED: /* fallthrough */ case SDL_WINDOWEVENT_RESIZED: m_params.windowSize = {event.window.data1, event.window.data2}; break; } } inputManager.ProcessEvent(event); if (inputManager.IsKeyDown(SDL_SCANCODE_W)) { camera.m_position += camera.GetForward() * dt * 5.f; } if (inputManager.IsKeyDown(SDL_SCANCODE_S)) { camera.m_position -= camera.GetForward() * dt * 5.f; } if (inputManager.IsKeyDown(SDL_SCANCODE_A)) { camera.m_position -= camera.GetRight() * dt * 5.f; } if (inputManager.IsKeyDown(SDL_SCANCODE_D)) { camera.m_position += camera.GetRight() * dt * 5.f; } // rotation if (inputManager.IsKeyDown(SDL_SCANCODE_LEFT)) { camera.SetRotation(camera.GetYaw() - glm::radians(90.f) * dt, camera.GetPitch()); } if (inputManager.IsKeyDown(SDL_SCANCODE_RIGHT)) { camera.SetRotation(camera.GetYaw() + glm::radians(90.f) * dt, camera.GetPitch()); } if (inputManager.IsKeyDown(SDL_SCANCODE_UP)) { camera.SetRotation(camera.GetYaw(), camera.GetPitch() + glm::radians(90.f) * dt); } if (inputManager.IsKeyDown(SDL_SCANCODE_DOWN)) { camera.SetRotation(camera.GetYaw(), camera.GetPitch() - glm::radians(90.f) * dt); } camera.Update(dt); } if (gfxDevice.needsSwapchainRecreate()) { spdlog::info("Recreating swapchain to size: {}x{}", m_params.windowSize.x, m_params.windowSize.y); gfxDevice.recreateSwapchain(m_params.windowSize.x, m_params.windowSize.y); renderer.resize(gfxDevice, { m_params.windowSize.x, m_params.windowSize.y }); float aspectRatio = float(m_params.windowSize.x) / float(m_params.windowSize.y); camera.setAspectRatio(aspectRatio); } accumulator -= dt; } if (!gfxDevice.needsSwapchainRecreate()) { glm::mat4 objMatrix = glm::mat4(1.f); objMatrix = glm::translate(objMatrix, glm::vec3(0.f, -3.0f, 0.f)); renderer.beginDrawing(gfxDevice); renderer.drawMesh(testMeshID, glm::mat4(1.f), 0); renderer.drawMesh(testMeshID, objMatrix, 0); renderer.endDrawing(); 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{}} ); } if (frameLimit) { // Delay to not overload the CPU const auto now = std::chrono::high_resolution_clock::now(); const auto frameTime = std::chrono::duration(now - prevTime).count(); if (dt > frameTime) { SDL_Delay(static_cast(dt - frameTime)); } } } } void App::cleanup() { }