190 lines
5.8 KiB
C++
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);
|
|
}
|