Files
Destrum/lightkeeper/src/Lightkeeper.cpp
T

190 lines
5.8 KiB
C++

#include "Lightkeeper.h"
#include <destrum/Components/CameraComponent.h>
#include <destrum/FS/AssetFS.h>
#include <destrum/Graphics/Managers/Renderer2D.h>
#include <destrum/Scene/Scene.h>
#include <components/FirstPersonController.h>
#include <components/Interactable.h>
#include <components/GameComponentRegistry.h>
LightKeeper::LightKeeper() : App()
{
}
LightKeeper::~LightKeeper()
{
if (!cleanedUp) {
try {
cleanup();
} catch (...) {
}
}
}
void LightKeeper::customInit()
{
RegisterGameComponents();
resources.init(gfxDevice);
renderer.init(gfxDevice, resources, m_params.renderSize);
const float aspectRatio = static_cast<float>(m_params.renderSize.x) / static_cast<float>(m_params.renderSize.y);
camera.setAspectRatio(aspectRatio);
camera.SetRotation(glm::radians(glm::vec2(90.f, 0.f)));
setupSkybox();
auto& scene = SceneManager::GetInstance().CreateScene("Main");
mainScene = BuildMainScene(scene, gfxDevice, resources);
debug2DTexture = resources.loadImageFromFile(
gfxDevice, AssetFS::GetInstance().GetFullPath("engine://textures/kobe.png"));
}
void LightKeeper::setupSkybox()
{
const auto skyboxPath = AssetFS::GetInstance().GetCookedPathForFile("engine://DJI_0001_stitch.jpg");
const auto vertShaderPath = AssetFS::GetInstance().GetCookedPathForFile("engine://shaders/cubemap.vert");
const auto fragShaderPath = AssetFS::GetInstance().GetCookedPathForFile("engine://shaders/cubemap.frag");
skyboxCubemap = std::make_unique<CubeMap>();
skyboxCubemap->LoadCubeMap(gfxDevice, resources, skyboxPath.generic_string());
skyboxCubemap->InitCubemapPipeline(gfxDevice, resources, vertShaderPath.generic_string(), fragShaderPath.generic_string());
skyboxCubemap->CreateCubeMap(gfxDevice, resources);
renderer.setSkyboxTexture(skyboxCubemap->GetCubeMapImageID());
}
void LightKeeper::customUpdate(float dt)
{
// LightKeeper owns a camera that hides App::camera; update this instance
// after SDL events have been consumed.
if (!isPlayerViewActive() && getSceneCamera() == nullptr)
{
camera.Update(dt);
}
SceneManager::GetInstance().Update(dt);
SceneManager::GetInstance().LateUpdate(dt);
updateDebugUi();
}
void LightKeeper::drawCrosshair()
{
if (!isPlayerViewActive()) {
return;
}
const bool focused = mainScene.playerController->GetFocusedInteractable() != nullptr;
const glm::vec4 color = focused ? glm::vec4{1.0f, 0.8f, 0.25f, 1.0f} : glm::vec4{1.0f, 1.0f, 1.0f, 0.8f};
const float armLength = focused ? 16.0f : 10.0f;
constexpr float thickness = 2.0f;
const VkExtent3D extent = renderer.getDrawImage().extent;
const glm::vec2 center{static_cast<float>(extent.width) * 0.5f, static_cast<float>(extent.height) * 0.5f};
auto& renderer2D = Renderer2D::GetInstance();
const float halfArm = armLength * 0.5f;
renderer2D.DrawLine(center - glm::vec2{halfArm, 0.0f}, center + glm::vec2{halfArm, 0.0f}, thickness, color);
renderer2D.DrawLine(center - glm::vec2{0.0f, halfArm}, center + glm::vec2{0.0f, halfArm}, thickness, color);
if (focused) {
renderer2D.DrawEllipseOutline(center, glm::vec2{14.0f}, thickness, color);
}
}
bool LightKeeper::isPlayerViewActive() const
{
return mainScene.playerController != nullptr && mainScene.playerController->IsMouseCaptured();
}
CameraComponent* LightKeeper::getSceneCamera() const
{
const auto& activeScenes = SceneManager::GetInstance().GetActiveScenes();
if (useFreeCamera || activeScenes.empty()) {
return nullptr;
}
return activeScenes.front()->GetCurrentCamera();
}
void LightKeeper::customDraw()
{
const auto cmd = gfxDevice.beginFrame();
if (cmd == VK_NULL_HANDLE) {
return;
}
renderer.beginDrawing(gfxDevice);
submitDebugDraws();
drawCrosshair();
if (isPlayerViewActive())
{
camera.SetRotation(mainScene.playerController->GetYaw(), mainScene.playerController->GetPitch());
camera.m_position = mainScene.playerController->GetEyePosition();
camera.CalculateViewMatrix();
camera.CalculateProjectionMatrix();
}
CameraComponent* sceneCamera = isPlayerViewActive() ? nullptr : getSceneCamera();
Camera& viewCamera = sceneCamera != nullptr ? sceneCamera->GetCamera(camera.GetAspectRatio()) : camera;
const SceneEnvironment& environment = SceneManager::GetInstance().GetCurrentScene().GetEnvironment();
const GameRenderer::SceneData sceneData{
.camera = viewCamera,
.ambientColor = environment.ambientColor,
.ambientIntensity = environment.ambientIntensity,
.fogColor = environment.fogColor,
.fogDensity = environment.fogDensity,
.skyboxRotation = environment.skyboxRotation,
};
const RenderContext ctx{
.renderer = renderer,
.camera = viewCamera,
.sceneData = sceneData,
};
SceneManager::GetInstance().Render(ctx);
renderer.endDrawing();
const auto& drawImage = renderer.getDrawImage();
renderer.draw(cmd, gfxDevice, viewCamera, sceneData);
gfxDevice.endFrame(
cmd, drawImage, {
.clearColor = {{0.f, 0.f, 0.5f, 1.f}},
.drawImageBlitRect = glm::ivec4{},
.imguiPass = &imguiPass,
});
}
void LightKeeper::customCleanup()
{
gfxDevice.waitIdle();
SceneManager::GetInstance().Destroy();
if (skyboxCubemap)
{
skyboxCubemap->cleanup(gfxDevice);
skyboxCubemap.reset();
}
renderer.cleanup(gfxDevice);
}
void LightKeeper::customFixedUpdate(float dt)
{
SceneManager::GetInstance().FixedUpdate(dt);
}
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);
}