Files
inferno-hart/src/inferno.cpp
2023-12-03 22:55:25 +00:00

350 lines
12 KiB
C++

#include "inferno.hpp"
#include <cstdint>
#include <graphics.hpp>
#include <version.hpp>
#include "graphics/rendertarget.hpp"
#include "gui/gui.hpp"
// #include "renderer/renderer.hpp"
// #include "scene/scene.hpp"
#include "graphics/buffer.hpp"
#include "graphics/device.hpp"
#include "graphics/pipeline.hpp"
#include "graphics/shader.hpp"
#include "graphics/swapchain.hpp"
#include "graphics/vkrenderer.hpp"
#include "window.hpp"
// #include "preview_renderer/debug.hpp"
// #include "preview_renderer/renderer.hpp"
#include "scene/camera.hpp"
// #include "scene/material.hpp"
#include "scene/mesh.hpp"
#include "scene/scene.hpp"
#include <yolo/yolo.hpp>
#include <chrono>
#include <numeric>
namespace inferno {
InfernoTimer* inferno_timer_create()
{
InfernoTimer* timer = new InfernoTimer;
// lazy init
inferno_timer_start(timer);
inferno_timer_end(timer);
return timer;
}
void inferno_timer_cleanup(InfernoTimer* timer) { delete timer; }
void inferno_timer_rolling_average(InfernoTimer* timer, int count)
{
if (timer->Times.size() > count)
timer->Times.erase(timer->Times.begin());
timer->RollingAverage = std::accumulate(timer->Times.begin(), timer->Times.end(),
std::chrono::duration<double>(0.0))
/ count;
}
void inferno_timer_start(InfernoTimer* timer)
{
timer->StartTime = std::chrono::high_resolution_clock::now();
}
void inferno_timer_end(InfernoTimer* timer)
{
timer->EndTime = std::chrono::high_resolution_clock::now();
timer->Time = timer->EndTime - timer->StartTime;
timer->Times.push_back(timer->Time);
inferno_timer_rolling_average(timer, 1000);
}
void inferno_timer_print(InfernoTimer* timer, bool time)
{
if (time)
yolo::info("Time: {}s", timer->Time.count());
yolo::info("Average time: {}ms", timer->RollingAverage.count() * 1000.0);
}
std::chrono::duration<double> inferno_timer_get_time(InfernoTimer* timer)
{
return timer->Time;
}
std::chrono::duration<double> inferno_timer_get_average(InfernoTimer* timer)
{
return timer->RollingAverage;
}
InfernoApp* inferno_create()
{
// MOTD
yolo::info("INFERNO HART v" INFERNO_VERSION);
InfernoApp* app = new InfernoApp;
app->Input = new InfernoInput;
app->Scene = scene::scene_create();
app->MainTimer = inferno_timer_create();
graphics::camera_set_position(app->Scene->Camera, { 0.0f, 1.0f, 3.1f });
// Create window
graphics::window_create("Inferno v" INFERNO_VERSION, 1920, 1080);
app->Device = graphics::device_create();
app->Renderer = graphics::renderer_create(app->Device);
graphics::renderer_configure_gui(app->Renderer);
graphics::renderer_configure_command_buffer(app->Renderer);
app->PreviewRenderer = graphics::preview_create(app->Renderer);
graphics::renderer_submit_repeat(
app->Renderer,
[](graphics::VulkanRenderer* renderer, VkCommandBuffer* commandBuffer) {
gui::imgui_new_frame();
},
false);
graphics::renderer_submit_repeat(
app->Renderer,
[&](graphics::VulkanRenderer* renderer, VkCommandBuffer* commandBuffer) {
graphics::renderer_begin_pass(renderer,
{ 0, 0, (uint32_t)graphics::window_get_size().x,
(uint32_t)graphics::window_get_size().y });
gui::imgui_render_frame(*commandBuffer);
graphics::renderer_end_pass(renderer);
},
true);
scene::Mesh* mesh = scene::mesh_create(app->Device);
scene::mesh_load_obj(mesh, "res/cornell-box.obj");
scene::mesh_ready(mesh);
scene::SceneObject* object = scene::scene_object_create();
scene::scene_object_add_mesh(object, mesh);
scene::scene_add_object(app->Scene, object);
scene::Mesh* lucy = scene::mesh_create(app->Device);
scene::mesh_load_obj(lucy, "res/lucy.obj");
scene::mesh_ready(lucy);
scene::SceneObject* lucyObject = scene::scene_object_create();
scene::scene_object_add_mesh(lucyObject, lucy);
scene::scene_add_object(app->Scene, lucyObject);
// app->PreviewRenderer = graphics::preview_create();
// graphics::preview_set_viewport(app->PreviewRenderer, app->Scene->Camera);
// app->RayRenderer = graphics::rayr_create(app->Scene);
// graphics::rayr_set_viewport(app->RayRenderer, app->Scene->Camera);
return app;
}
void inferno_cleanup(InfernoApp* app)
{
graphics::window_cleanup();
delete app;
}
static void inferno_gui_help_marker(const char* desc)
{
ImGui::TextDisabled("(?)");
if (ImGui::IsItemHovered(ImGuiHoveredFlags_DelayShort)) {
ImGui::BeginTooltip();
ImGui::PushTextWrapPos(ImGui::GetFontSize() * 35.0f);
ImGui::TextUnformatted(desc);
ImGui::PopTextWrapPos();
ImGui::EndTooltip();
}
}
void inferno_preset_gui(InfernoApp* app)
{
ImGuiID dockspace_id = ImGui::GetID("main");
ImGui::DockBuilderRemoveNode(dockspace_id); // Clear out existing layout
ImGui::DockBuilderAddNode(dockspace_id, ImGuiDockNodeFlags_DockSpace); // Add empty
// node ImGui::DockBuilderSetNodeSize(dockspace_id, { 1000, 1000 });
ImGuiID dock_main_id = dockspace_id;
ImGuiID dock_left = ImGui::DockBuilderSplitNode(
dock_main_id, ImGuiDir_Left, 0.5f, NULL, &dock_main_id);
ImGui::DockBuilderDockWindow("Preview", dock_left);
ImGui::DockBuilderDockWindow("Render", dock_main_id);
ImGui::DockBuilderFinish(dockspace_id);
yolo::info("LAYOUT SET TO DEFAULT");
}
void inferno_move_input(InfernoApp* app, std::chrono::duration<double> deltaTime)
{
static GLFWcursor* cursor = glfwCreateStandardCursor(GLFW_HAND_CURSOR);
glfwSetCursor(graphics::window_get_glfw_window(), cursor);
// KBD & MOUSE
// pan only get on hold
static glm::dvec2 lastMousePos;
static int firstClick = 0;
if (glfwGetMouseButton(graphics::window_get_glfw_window(), GLFW_MOUSE_BUTTON_1)
== GLFW_PRESS) {
firstClick++;
if (firstClick == 1) {
glfwGetCursorPos(
graphics::window_get_glfw_window(), &lastMousePos.x, &lastMousePos.y);
}
glm::dvec2 tempMousePos = { 0.0f, 0.0f };
glfwGetCursorPos(
graphics::window_get_glfw_window(), &tempMousePos.x, &tempMousePos.y);
app->Input->MouseDelta = lastMousePos - tempMousePos;
lastMousePos = tempMousePos;
} else {
firstClick = 0;
app->Input->MouseDelta = { 0.0f, 0.0f };
lastMousePos = { 0.0f, 0.0f };
}
app->Input->MovementDelta = 0b00000000;
if (glfwGetKey(graphics::window_get_glfw_window(), GLFW_KEY_W) == GLFW_PRESS)
app->Input->MovementDelta |= 0b10000000;
if (glfwGetKey(graphics::window_get_glfw_window(), GLFW_KEY_A) == GLFW_PRESS)
app->Input->MovementDelta |= 0b01000000;
if (glfwGetKey(graphics::window_get_glfw_window(), GLFW_KEY_S) == GLFW_PRESS)
app->Input->MovementDelta |= 0b00100000;
if (glfwGetKey(graphics::window_get_glfw_window(), GLFW_KEY_D) == GLFW_PRESS)
app->Input->MovementDelta |= 0b00010000;
if (glfwGetKey(graphics::window_get_glfw_window(), GLFW_KEY_SPACE) == GLFW_PRESS)
app->Input->MovementDelta |= 0b00001000;
if (glfwGetKey(graphics::window_get_glfw_window(), GLFW_KEY_LEFT_SHIFT) == GLFW_PRESS)
app->Input->MovementDelta |= 0b00000100;
}
void inferno_stop_move_input(InfernoApp* app)
{
app->Input->MovementDelta = 0x0;
app->Input->MouseDelta = { 0.0f, 0.0f };
}
bool inferno_pre(InfernoApp* app)
{
inferno_timer_start(app->MainTimer);
app->FrameCount++;
if (app->FrameCount % 100 == 0) {
yolo::info(
"Average FPS: {}", 1.0 / inferno_timer_get_time(app->MainTimer).count());
inferno_timer_print(app->MainTimer, false);
}
if (!graphics::renderer_begin_frame(app->Renderer))
return false;
return true;
}
void inferno_end(InfernoApp* app)
{
graphics::renderer_draw_frame(app->Renderer);
graphics::window_render();
inferno_timer_end(app->MainTimer);
}
int inferno_run(InfernoApp* app)
{
while (graphics::window_new_frame()) {
if (!inferno_pre(app))
continue;
if (glm::length(app->Input->MouseDelta) > 0.0f)
graphics::camera_mouse_move(app->Scene->Camera, app->Input->MouseDelta,
inferno_timer_get_time(app->MainTimer).count());
if (app->Input->MovementDelta != 0b00000000)
graphics::camera_move(app->Scene->Camera, app->Input->MovementDelta,
inferno_timer_get_time(app->MainTimer).count());
// Menu Bar
static bool showPreview = true;
static bool showRenderSettings = true;
static bool showDemoWindow = false;
if (ImGui::BeginMenuBar()) {
if (ImGui::BeginMenu("Menu")) {
ImGui::EndMenu();
}
if (ImGui::BeginMenu("View")) {
ImGui::Checkbox("Show Preview", &showPreview);
ImGui::SameLine();
inferno_gui_help_marker("Show the preview window");
ImGui::Checkbox("Show Settings", &showRenderSettings);
ImGui::SameLine();
inferno_gui_help_marker("Show the Inferno HART settings window");
ImGui::Checkbox("Show Demo", &showDemoWindow);
ImGui::EndMenu();
}
ImGui::EndMenuBar();
}
if (showRenderSettings && ImGui::Begin("Inferno HART")) {
if (ImGui::TreeNode("Camera")) {
graphics::camera_draw_ui(scene::scene_get_camera(app->Scene));
ImGui::TreePop();
}
if (ImGui::TreeNode("Preview Render")) {
ImGui::Checkbox("Show Preview", &showPreview);
// graphics::preview_draw_ui(app->PreviewRenderer);
if (ImGui::TreeNode("Debug Overlay")) {
// graphics::debug_draw_ui();
ImGui::TreePop();
}
ImGui::TreePop();
}
if (ImGui::TreeNode("RayTraced Render")) {
// graphics::rayr_draw_ui(app->RayRenderer);
ImGui::TreePop();
}
ImGui::End();
}
if (showPreview
&& ImGui::Begin("Preview", nullptr, ImGuiWindowFlags_NoScrollbar)) {
if (ImGui::IsWindowHovered()) {
inferno_move_input(app, inferno_timer_get_time(app->MainTimer));
} else {
inferno_stop_move_input(app);
}
graphics::camera_raster_set_viewport(scene::scene_get_camera(app->Scene),
{ ImGui::GetWindowSize().x, ImGui::GetWindowSize().y });
graphics::preview_set_viewport(app->PreviewRenderer, app->Scene->Camera);
graphics::preview_draw(app->PreviewRenderer, app->Scene);
ImTextureID texture
= (ImTextureID)graphics::preview_get_target(app->PreviewRenderer)
->DescriptorSet;
ImGui::Image(texture, { ImGui::GetWindowSize().x, ImGui::GetWindowSize().y },
ImVec2(0, 1), ImVec2(1, 0));
ImGui::End();
}
if (ImGui::Begin("Render")) {
// graphics::rayr_draw(app->RayRenderer);
// ImTextureID texture
// = (ImTextureID)graphics::rayr_get_rendered_texture(app->RayRenderer);
// ImGui::Image(texture, { ImGui::GetWindowSize().x, ImGui::GetWindowSize().y
// },
// ImVec2(0, 1), ImVec2(1, 0));
ImGui::End();
}
if (showDemoWindow) {
ImGui::ShowDemoWindow();
}
inferno_end(app);
}
return 1;
}
} // namespace inferno