engine/src/application.cpp

204 lines
6.6 KiB
C++
Raw Normal View History

2023-05-01 13:13:35 +00:00
#include "application.h"
2022-09-13 18:25:18 +00:00
2023-04-29 14:22:25 +00:00
#include <filesystem>
#include <memory>
#include <stdexcept>
#include <string>
#include <thread>
2022-10-27 16:58:30 +00:00
2023-04-29 14:22:25 +00:00
#include <glm/mat4x4.hpp>
2023-05-01 13:13:35 +00:00
#include "gfx.h"
#include "gfx_device.h"
#include "input_manager.h"
#include "log.h"
2023-05-14 13:40:16 +00:00
#include "resources/font.h"
2023-05-01 13:13:35 +00:00
#include "resources/material.h"
#include "resources/mesh.h"
#include "resources/shader.h"
#include "resources/texture.h"
2023-08-31 09:51:12 +00:00
#include "systems/mesh_render_system.h"
#include "components/transform.h"
2023-05-01 13:13:35 +00:00
#include "scene.h"
#include "scene_manager.h"
#include "window.h"
2022-12-15 15:54:11 +00:00
#ifdef _MSC_VER
#include <windows.h>
#include <direct.h>
2023-04-29 14:22:25 +00:00
#define WIN_MAX_PATH 260
2022-12-15 15:54:11 +00:00
#endif
2023-03-13 17:10:46 +00:00
namespace engine {
2023-05-14 23:27:31 +00:00
static std::filesystem::path getResourcesPath() {
std::filesystem::path resourcesPath{};
2022-12-15 15:54:11 +00:00
#ifdef _MSC_VER
2023-07-04 16:08:28 +00:00
// get the path of the currently running process
2023-05-14 23:27:31 +00:00
CHAR exeDirBuf[MAX_PATH + 1];
GetModuleFileNameA(NULL, exeDirBuf, WIN_MAX_PATH + 1);
std::filesystem::path cwd = std::filesystem::path(exeDirBuf).parent_path();
(void)_chdir((const char*)std::filesystem::absolute(cwd).c_str());
2022-12-15 15:54:11 +00:00
#else
2023-05-14 23:27:31 +00:00
std::filesystem::path cwd = std::filesystem::current_path();
2022-12-15 15:54:11 +00:00
#endif
2023-05-14 23:27:31 +00:00
if (std::filesystem::is_directory(cwd / "res")) {
resourcesPath = cwd / "res";
} else {
resourcesPath = cwd.parent_path() / "share" / "sdltest";
}
if (std::filesystem::is_directory(resourcesPath) == false) {
resourcesPath = cwd.root_path() / "usr" / "local" / "share" / "sdltest";
}
if (std::filesystem::is_directory(resourcesPath) == false) {
throw std::runtime_error("Unable to determine resources location. CWD: " +
cwd.string());
}
return resourcesPath;
}
Application::Application(const char* appName, const char* appVersion,
gfx::GraphicsSettings graphicsSettings) {
window_ = std::make_unique<Window>(appName, true, false);
input_manager_ = std::make_unique<InputManager>(window_.get());
scene_manager_ = std::make_unique<SceneManager>(this);
// get base path for resources
resources_path_ = getResourcesPath();
// register resource managers
2023-08-29 21:10:05 +00:00
RegisterResourceManager<resources::Mesh>();
RegisterResourceManager<resources::Material>();
2023-05-14 23:27:31 +00:00
RegisterResourceManager<resources::Texture>();
RegisterResourceManager<resources::Shader>();
2023-08-29 21:10:05 +00:00
RegisterResourceManager<resources::Font>();
2023-05-14 23:27:31 +00:00
2023-08-29 17:06:04 +00:00
renderer_ = std::make_unique<Renderer>(
2023-05-14 23:27:31 +00:00
appName, appVersion, window_->GetHandle(), graphicsSettings);
/* default fonts */
{
auto monoFont = std::make_unique<resources::Font>(
GetResourcePath("engine/fonts/mono.ttf"));
GetResourceManager<resources::Font>()->AddPersistent("builtin.mono",
std::move(monoFont));
}
/* default shaders */
{
resources::Shader::VertexParams vertParams{};
vertParams.has_normal = true;
vertParams.has_uv0 = true;
2023-05-24 17:33:55 +00:00
resources::Shader::ShaderSettings shaderSettings{};
shaderSettings.vertexParams = vertParams;
shaderSettings.alpha_blending = false;
shaderSettings.cull_backface = true;
shaderSettings.write_z = true;
shaderSettings.render_order = 0;
2023-05-14 23:27:31 +00:00
auto texturedShader = std::make_unique<resources::Shader>(
2023-08-29 17:06:04 +00:00
renderer(), GetResourcePath("engine/shaders/standard.vert").c_str(),
2023-05-24 17:33:55 +00:00
GetResourcePath("engine/shaders/standard.frag").c_str(),
shaderSettings);
2023-05-14 23:27:31 +00:00
GetResourceManager<resources::Shader>()->AddPersistent(
"builtin.standard", std::move(texturedShader));
}
{
resources::Shader::VertexParams vertParams{};
vertParams.has_normal = true;
vertParams.has_uv0 = true;
2023-05-24 17:33:55 +00:00
resources::Shader::ShaderSettings shaderSettings{};
shaderSettings.vertexParams = vertParams;
shaderSettings.alpha_blending = false;
shaderSettings.cull_backface = true;
shaderSettings.write_z = true;
shaderSettings.render_order = 0;
2023-05-14 23:27:31 +00:00
auto skyboxShader = std::make_unique<resources::Shader>(
2023-08-29 17:06:04 +00:00
renderer(), GetResourcePath("engine/shaders/skybox.vert").c_str(),
2023-05-24 17:33:55 +00:00
GetResourcePath("engine/shaders/skybox.frag").c_str(), shaderSettings);
2023-05-14 23:27:31 +00:00
GetResourceManager<resources::Shader>()->AddPersistent(
"builtin.skybox", std::move(skyboxShader));
}
{
resources::Shader::VertexParams vertParams{};
vertParams.has_normal = true;
vertParams.has_uv0 = true;
2023-05-24 17:33:55 +00:00
resources::Shader::ShaderSettings shaderSettings{};
shaderSettings.vertexParams = vertParams;
shaderSettings.alpha_blending = true;
shaderSettings.cull_backface = true;
shaderSettings.write_z = false;
shaderSettings.render_order = 1;
2023-05-14 23:27:31 +00:00
auto quadShader = std::make_unique<resources::Shader>(
2023-08-29 17:06:04 +00:00
renderer(), GetResourcePath("engine/shaders/quad.vert").c_str(),
2023-05-24 17:33:55 +00:00
GetResourcePath("engine/shaders/quad.frag").c_str(), shaderSettings);
2023-05-14 23:27:31 +00:00
GetResourceManager<resources::Shader>()->AddPersistent(
"builtin.quad", std::move(quadShader));
}
/* default textures */
{
auto whiteTexture = std::make_unique<resources::Texture>(
2023-08-29 17:06:04 +00:00
renderer(), GetResourcePath("engine/textures/white.png"),
2023-05-14 23:27:31 +00:00
resources::Texture::Filtering::kOff);
GetResourceManager<resources::Texture>()->AddPersistent(
"builtin.white", std::move(whiteTexture));
}
}
2023-08-31 09:51:12 +00:00
Application::~Application() {}
2023-05-14 23:27:31 +00:00
void Application::GameLoop() {
2023-08-29 21:10:05 +00:00
LOG_DEBUG("Begin game loop...");
2023-05-14 23:27:31 +00:00
constexpr int FPS_LIMIT = 240;
constexpr auto FRAMETIME_LIMIT =
std::chrono::nanoseconds(1000000000 / FPS_LIMIT);
auto beginFrame = std::chrono::steady_clock::now();
auto endFrame = beginFrame + FRAMETIME_LIMIT;
auto lastTick = window_->GetNanos();
// single-threaded game loop
while (window_->IsRunning()) {
/* logic */
2023-08-31 09:51:12 +00:00
Scene* scene = scene_manager_->UpdateActiveScene(window_->dt());
2023-05-14 23:27:31 +00:00
uint64_t now = window_->GetNanos();
if (now - lastTick >= 1000000000LL * 5LL) [[unlikely]] {
lastTick = now;
LOG_INFO("fps: {}", window_->GetAvgFPS());
2023-08-31 09:51:12 +00:00
// renderer()->GetDevice()->LogPerformanceInfo();
2023-05-14 23:27:31 +00:00
window_->ResetAvgFPS();
2023-05-14 13:40:16 +00:00
}
2022-09-13 18:25:18 +00:00
/* render */
2023-08-31 09:51:12 +00:00
renderer_->PreRender(window()->GetWindowResized(), scene->GetComponent<TransformComponent>(scene->GetEntity("camera"))->world_matrix);
if (scene) {
2023-08-31 13:18:42 +00:00
auto mesh_render_system = scene->GetSystem<MeshRenderSystem>();
const RenderList* static_list = mesh_render_system->GetStaticRenderList();
const RenderList* dynamic_list = mesh_render_system->GetDynamicRenderList();
2023-09-02 18:14:12 +00:00
renderer_->Render(*static_list, *dynamic_list);
2023-08-31 09:51:12 +00:00
}
2023-05-14 23:27:31 +00:00
/* poll events */
window_->GetInputAndEvents();
/* fps limiter */
if (enable_frame_limiter_) {
std::this_thread::sleep_until(endFrame);
}
beginFrame = endFrame;
endFrame = beginFrame + FRAMETIME_LIMIT;
}
2023-08-31 09:51:12 +00:00
renderer_->GetDevice()->WaitIdle();
2022-09-13 18:25:18 +00:00
}
2023-05-14 23:27:31 +00:00
} // namespace engine