@@ -25,7 +25,8 @@ elseif (APPLE)
|
||||
target_compile_options(inferno PRIVATE -O1)
|
||||
endif()
|
||||
else()
|
||||
target_compile_options(inferno PRIVATE -std=c++17)
|
||||
target_compile_options(inferno PRIVATE -std=c++20)
|
||||
target_compile_options(inferno PRIVATE -m64)
|
||||
if (CMAKE_BUILD_TYPE MATCHES "Debug")
|
||||
target_compile_options(inferno PRIVATE -O1)
|
||||
target_compile_options(inferno PRIVATE -Wall)
|
||||
|
||||
@@ -8,7 +8,10 @@
|
||||
|
||||
namespace inferno::graphics {
|
||||
|
||||
struct _CameraImpl;
|
||||
typedef struct _CameraImpl {
|
||||
bool DidUpdate;
|
||||
std::mutex CamMutex;
|
||||
} _CameraImpl;
|
||||
|
||||
typedef struct Viewport {
|
||||
glm::ivec2 Raster;
|
||||
@@ -20,7 +23,7 @@ typedef struct Camera {
|
||||
glm::mat4 ProjectionMatrix;
|
||||
glm::mat4 LookMatrix;
|
||||
|
||||
std::shared_ptr<Viewport> Views;
|
||||
Viewport Views;
|
||||
|
||||
float MouseSensitivity = 0.4f;
|
||||
float Speed = 0.1f;
|
||||
@@ -30,33 +33,35 @@ typedef struct Camera {
|
||||
glm::vec3 Position = {};
|
||||
glm::vec3 LookDirection = {};
|
||||
|
||||
std::unique_ptr<_CameraImpl> _impl;
|
||||
_CameraImpl* _impl;
|
||||
} Camera;
|
||||
|
||||
std::unique_ptr<Camera> camera_create();
|
||||
void camera_cleanup(std::unique_ptr<Camera>& camera);
|
||||
Camera* camera_create();
|
||||
void camera_cleanup(Camera* camera);
|
||||
|
||||
void camera_update(std::unique_ptr<Camera>& camera);
|
||||
bool camera_did_update(std::unique_ptr<Camera>& camera);
|
||||
void camera_new_frame(std::unique_ptr<Camera>& camera);
|
||||
void camera_update(Camera* camera);
|
||||
bool camera_did_update(Camera* camera);
|
||||
void camera_new_frame(Camera* camera);
|
||||
|
||||
glm::mat4 camera_get_view(std::unique_ptr<Camera>& camera);
|
||||
glm::mat4 camera_get_projection(std::unique_ptr<Camera>& camera);
|
||||
glm::mat4 camera_get_look(std::unique_ptr<Camera>& camera);
|
||||
glm::mat4 camera_get_view(Camera* camera);
|
||||
glm::mat4 camera_get_projection(Camera* camera);
|
||||
glm::mat4 camera_get_look(Camera* camera);
|
||||
|
||||
void raster_set_viewport(std::unique_ptr<Camera>& camera, glm::ivec2 viewport);
|
||||
glm::ivec2 raster_get_viewport(std::unique_ptr<Camera>& camera);
|
||||
void raster_set_viewport(Camera* camera, glm::ivec2 viewport);
|
||||
glm::ivec2 raster_get_viewport(Camera* camera);
|
||||
|
||||
void ray_set_viewport(std::unique_ptr<Camera>& camera, glm::ivec2 viewport);
|
||||
glm::ivec2 ray_get_viewport(std::unique_ptr<Camera>& camera);
|
||||
void ray_set_viewport(Camera* camera, glm::ivec2 viewport);
|
||||
glm::ivec2 ray_get_viewport(Camera* camera);
|
||||
|
||||
void camera_move(std::unique_ptr<Camera>& camera, uint8_t movement_delta);
|
||||
void camera_mouse_move(std::unique_ptr<Camera>& camera, glm::vec2 mouse_delta);
|
||||
void camera_move(Camera* camera, uint8_t movement_delta);
|
||||
void camera_mouse_move(Camera* camera, glm::vec2 mouse_delta);
|
||||
|
||||
void camera_set_position(std::unique_ptr<Camera>& camera, glm::vec3 position);
|
||||
void camera_set_euler_look(std::unique_ptr<Camera>& camera, float roll,
|
||||
void camera_set_position(Camera* camera, glm::vec3 position);
|
||||
void camera_set_euler_look(Camera* camera, float roll,
|
||||
float pitch, float yaw);
|
||||
void camera_set_look(std::unique_ptr<Camera>& camera,
|
||||
void camera_set_look(Camera* camera,
|
||||
glm::vec3 look_direction);
|
||||
|
||||
glm::vec3 camera_get_position(Camera* camera);
|
||||
|
||||
} // namespace inferno::graphics
|
||||
|
||||
@@ -1,185 +0,0 @@
|
||||
#include "hart_directory.hpp"
|
||||
|
||||
#include "inferno_hart.hpp"
|
||||
|
||||
#include <yolo/yolo.hpp>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
using namespace inferno;
|
||||
|
||||
HARTModuleDirectory::HARTModuleDirectory()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
HARTModuleDirectory::~HARTModuleDirectory()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
std::vector<HARTModuleDirectory::discoveryEntry> HARTModuleDirectory::discoverModules(std::filesystem::path folder, bool recurse)
|
||||
{
|
||||
if (!std::filesystem::exists(folder)) return { };
|
||||
if (!std::filesystem::is_directory(folder))
|
||||
{
|
||||
return { this->registerModule(folder) };
|
||||
}
|
||||
|
||||
std::error_code err;
|
||||
if (recurse)
|
||||
{
|
||||
for (const auto& file : std::filesystem::recursive_directory_iterator(folder, err))
|
||||
{
|
||||
if (file.path().extension() == HART_EXTENSION)
|
||||
{
|
||||
this->registerModule(file);
|
||||
}
|
||||
}
|
||||
} else
|
||||
{
|
||||
for (const auto& file : std::filesystem::directory_iterator(folder, err))
|
||||
{
|
||||
if (file.path().extension() == HART_EXTENSION)
|
||||
{
|
||||
this->registerModule(file);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return { };
|
||||
}
|
||||
|
||||
HARTModuleDirectory::discoveryEntry HARTModuleDirectory::registerModule(std::filesystem::path file)
|
||||
{
|
||||
yolo::info("Registering module at {}", file.c_str());
|
||||
|
||||
discoveryEntry entry;
|
||||
entry.Location = file;
|
||||
|
||||
#ifdef _WIN32
|
||||
entry.Handle = LoadLibraryA(file.c_str());
|
||||
if (entry.Handle == NULL)
|
||||
{
|
||||
yolo::error("Cannot load module at {}.", file.c_str());
|
||||
entry.Handle = NULL; entry.DidLink = false;
|
||||
return entry;
|
||||
}
|
||||
HART_CREDIT_F credit = (HART_CREDIT_F)GetProcAddress(entry.Handle, "_CREDIT");
|
||||
entry.InitCallback = (HART_INIT_F)GetProcAddress(entry.Handle, "_GET");
|
||||
entry.DestroyCallback = (HART_DESTROY_F)GetProcAddress(entry.Handle, "_DESTROY");
|
||||
#else // UNIX-Like
|
||||
entry.Handle = dlopen(file.c_str(), RTLD_NOW | RTLD_LOCAL);
|
||||
if (entry.Handle == NULL)
|
||||
{
|
||||
yolo::error("Cannot load module at ", dlerror());
|
||||
entry.Handle = NULL; entry.DidLink = false;
|
||||
return entry;
|
||||
}
|
||||
HART_CREDIT_F credit = (HART_CREDIT_F)dlsym(entry.Handle, "_CREDIT");
|
||||
entry.InitCallback = (HART_INIT_F)dlsym(entry.Handle, "_GET");
|
||||
entry.DestroyCallback = (HART_DESTROY_F)dlsym(entry.Handle, "_DESTROY");
|
||||
#endif
|
||||
|
||||
if (credit == NULL)
|
||||
{
|
||||
yolo::error("Cannot load module at {}... No credit...", file.c_str());
|
||||
entry.Handle = NULL; entry.DidLink = false;
|
||||
return entry;
|
||||
}
|
||||
if (entry.InitCallback == NULL)
|
||||
{
|
||||
yolo::error("Cannot load module at {}... No get...", file.c_str());
|
||||
entry.Handle = NULL; entry.DidLink = false;
|
||||
return entry;
|
||||
}
|
||||
if (entry.DestroyCallback == NULL)
|
||||
{
|
||||
yolo::error("Cannot load module at {}... No destroy...", file.c_str());
|
||||
entry.Handle = NULL; entry.DidLink = false;
|
||||
return entry;
|
||||
}
|
||||
|
||||
entry.Credit = (ModuleCredit*)credit();
|
||||
|
||||
yolo::info("Module {} v{}.{}.{} by {}", entry.Credit->ModuleName,
|
||||
entry.Credit->VersionMajor,
|
||||
entry.Credit->VersionMinor,
|
||||
entry.Credit->VersionBuild,
|
||||
entry.Credit->AuthorName);
|
||||
|
||||
entry.DidLink = true;
|
||||
mEntries[entry.Credit->ModuleName] = { entry, nullptr };
|
||||
|
||||
if (mEntries.size() == 1)
|
||||
{
|
||||
// this is the first, make it active - or else
|
||||
mActiveModule = entry.Credit->ModuleName;
|
||||
this->load(mActiveModule);
|
||||
}
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
||||
std::vector<std::string> HARTModuleDirectory::getModules()
|
||||
{
|
||||
std::vector<std::string> keys;
|
||||
for(auto kv : mEntries)
|
||||
{
|
||||
keys.push_back(kv.first);
|
||||
}
|
||||
return keys;
|
||||
}
|
||||
|
||||
void HARTModuleDirectory::setActive(std::string moduleName)
|
||||
{
|
||||
if (moduleName == mActiveModule) return;
|
||||
this->destroy(mActiveModule);
|
||||
mActiveModule = moduleName;
|
||||
this->load(mActiveModule);
|
||||
}
|
||||
|
||||
void HARTModuleDirectory::setActiveIndex(int index)
|
||||
{
|
||||
std::vector<std::string> keys = this->getModules();
|
||||
this->setActive(keys[index]);
|
||||
}
|
||||
|
||||
HARTModule* HARTModuleDirectory::getActiveModule()
|
||||
{
|
||||
return mEntries[mActiveModule].Module;
|
||||
}
|
||||
|
||||
std::string HARTModuleDirectory::getActive()
|
||||
{
|
||||
return mActiveModule;
|
||||
}
|
||||
|
||||
int HARTModuleDirectory::getActiveIndex()
|
||||
{
|
||||
std::vector<std::string> keys = this->getModules();
|
||||
for (int i = 0; i < keys.size(); i++)
|
||||
{
|
||||
if (keys[i] == mActiveModule) return i;
|
||||
}
|
||||
return -1; // this should never happen
|
||||
}
|
||||
|
||||
ModuleCredit* HARTModuleDirectory::getActiveCredit()
|
||||
{
|
||||
return mEntries[mActiveModule].Discovery.Credit;
|
||||
}
|
||||
|
||||
void HARTModuleDirectory::load(std::string moduleName)
|
||||
{
|
||||
HARTModule* mod = (HARTModule*)mEntries[moduleName].Discovery.InitCallback();
|
||||
mEntries[moduleName].Module = mod;
|
||||
mEntries[moduleName].Active = true;
|
||||
}
|
||||
|
||||
void HARTModuleDirectory::destroy(std::string moduleName)
|
||||
{
|
||||
mEntries[moduleName].Discovery.DestroyCallback(mEntries[moduleName].Module);
|
||||
mEntries[moduleName].Module = nullptr;
|
||||
mEntries[moduleName].Active = false;
|
||||
}
|
||||
@@ -1,71 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
// INFERNO-HART Modules
|
||||
// _GET returns derived HARTModule
|
||||
// _DESTROY returns void but takes derived HARTModule
|
||||
// _CREDIT returns ModuleCredit
|
||||
|
||||
// THIS IS SHARED DO __NOT__ REINCLUDE libhart/thirdparty
|
||||
#include <inferno_hart.hpp>
|
||||
|
||||
#include <filesystem>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <unordered_map>
|
||||
|
||||
namespace inferno {
|
||||
|
||||
class HARTModule;
|
||||
struct ModuleCredit;
|
||||
|
||||
class HARTModuleDirectory
|
||||
{
|
||||
public:
|
||||
HARTModuleDirectory();
|
||||
~HARTModuleDirectory();
|
||||
|
||||
struct discoveryEntry
|
||||
{
|
||||
std::filesystem::path Location;
|
||||
bool DidLink = false;
|
||||
#ifdef _WIN32
|
||||
HMODULE Handle;
|
||||
#else // UNIX-Like
|
||||
void* Handle;
|
||||
#endif
|
||||
ModuleCredit* Credit;
|
||||
HART_INIT_F InitCallback;
|
||||
HART_DESTROY_F DestroyCallback;
|
||||
};
|
||||
|
||||
struct moduleEntry
|
||||
{
|
||||
discoveryEntry Discovery;
|
||||
HARTModule* Module;
|
||||
bool Active;
|
||||
};
|
||||
|
||||
// This can take a file or a directory, and inside the directory discover recursively or not
|
||||
std::vector<discoveryEntry> discoverModules(std::filesystem::path path, bool recurse = false);
|
||||
discoveryEntry registerModule(std::filesystem::path file);
|
||||
|
||||
std::vector<std::string> getModules();
|
||||
|
||||
void setActive(std::string moduleName);
|
||||
void setActiveIndex(int index);
|
||||
|
||||
HARTModule* getActiveModule();
|
||||
std::string getActive();
|
||||
int getActiveIndex();
|
||||
ModuleCredit* getActiveCredit();
|
||||
|
||||
void load(std::string moduleName);
|
||||
void destroy(std::string moduleName);
|
||||
|
||||
private:
|
||||
std::string mActiveModule;
|
||||
std::unordered_map<std::string, moduleEntry> mEntries;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -1,83 +0,0 @@
|
||||
#include "hart_module.hpp"
|
||||
|
||||
#include <renderer/ray_source.hpp>
|
||||
#include <renderer/renderer.hpp>
|
||||
|
||||
#include <scene/scene.hpp>
|
||||
#include <scene/mesh.hpp>
|
||||
|
||||
#include <yolo/yolo.hpp>
|
||||
|
||||
#include <vector>
|
||||
|
||||
using namespace inferno;
|
||||
|
||||
HHM::HHM()
|
||||
: mDirectory()
|
||||
{
|
||||
mDirectory.discoverModules("./hart/", true);
|
||||
}
|
||||
|
||||
HHM::~HHM()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
HARTModuleDirectory* HHM::getModuleDirectory()
|
||||
{
|
||||
return &mDirectory;
|
||||
}
|
||||
|
||||
HARTModule::EModuleState HHM::getModuleState()
|
||||
{
|
||||
HARTModule* mod = mDirectory.getActiveModule();
|
||||
return mod->getState();
|
||||
}
|
||||
|
||||
void HHM::newScene(Scene* scene)
|
||||
{
|
||||
HARTModule* mod = mDirectory.getActiveModule();
|
||||
std::vector<Mesh*> meshs = scene->getRenderables();
|
||||
// TODO: This may not be the way i want to approach it
|
||||
// as submitTris should take maybe a mesh ID and then the mesh data
|
||||
// as it is now, submitTris assumes it's getting the whole scene
|
||||
// which would involve a lot of mesh copying (avoid!) if i were to chain them
|
||||
for (auto* mesh : meshs) {
|
||||
void* verticies; void* normals; void* indicies;
|
||||
int vertexCount = mesh->getVerticies(&verticies, &normals);
|
||||
int indexCount = mesh->getIndicies(&indicies);
|
||||
yolo::debug("Mesh for module ready... {} {}", verticies, normals);
|
||||
mod->submitTris(verticies, normals, vertexCount, indicies, indexCount);
|
||||
}
|
||||
}
|
||||
|
||||
void HHM::notifySceneUpdate()
|
||||
{
|
||||
HARTModule* mod = mDirectory.getActiveModule();
|
||||
mod->updateTris();
|
||||
}
|
||||
|
||||
void rayHitCallback(void* hhm, HitInfo* hit)
|
||||
{
|
||||
((HHM*)hhm)->rayReturn(hit);
|
||||
}
|
||||
|
||||
void HHM::rayReturn(HitInfo* hit)
|
||||
{
|
||||
Renderer->computeHit(hit);
|
||||
}
|
||||
|
||||
void HHM::bounce(Ray* newRay)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void HHM::startTrace(RayField sourceScatter)
|
||||
{
|
||||
// TODO: Signal start
|
||||
HARTModule* mod = mDirectory.getActiveModule();
|
||||
mod->passContext((void*)this, &rayHitCallback);
|
||||
yolo::debug("SubmitQueue {}", sourceScatter.size());
|
||||
mod->submitQueue(sourceScatter);
|
||||
mod->start();
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
// the HHM (Hamlin Hamlin McGill) aka the Head HART Module keeps track of the module
|
||||
// and gives the renderer a cleaner interface to talk to a HART Module
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <graphics.hpp>
|
||||
#include "hart_directory.hpp"
|
||||
|
||||
namespace inferno {
|
||||
|
||||
class Scene;
|
||||
class Ray;
|
||||
class HitInfo;
|
||||
class HARTModule;
|
||||
class RayRenderer;
|
||||
|
||||
class HHM
|
||||
{
|
||||
public:
|
||||
HHM();
|
||||
~HHM();
|
||||
|
||||
HARTModuleDirectory* getModuleDirectory();
|
||||
HARTModule::EModuleState getModuleState();
|
||||
|
||||
void newScene(Scene* scene);
|
||||
void notifySceneUpdate();
|
||||
|
||||
void rayReturn(HitInfo* hit);
|
||||
void bounce(Ray* newRay);
|
||||
|
||||
void startTrace(RayField sourceScatter);
|
||||
|
||||
RayRenderer* Renderer;
|
||||
|
||||
private:
|
||||
HARTModuleDirectory mDirectory;
|
||||
};
|
||||
|
||||
}
|
||||
138
src/inferno.cpp
138
src/inferno.cpp
@@ -2,19 +2,16 @@
|
||||
|
||||
#include <version.hpp>
|
||||
// #include "gui/layout.hpp"
|
||||
#include "imgui/imgui.h"
|
||||
#include "scene/scene.hpp"
|
||||
#include "window.hpp"
|
||||
|
||||
// #include "hart_module.hpp"
|
||||
// #include "hart_directory.hpp"
|
||||
|
||||
// #include "preview_renderer/renderer.hpp"
|
||||
// #include "preview_renderer/shader.hpp"
|
||||
// #include "renderer/dispatcher.hpp"
|
||||
// #include "renderer/renderer.hpp"
|
||||
#include "preview_renderer/renderer.hpp"
|
||||
#include "preview_renderer/shader.hpp"
|
||||
#include "scene/camera.hpp"
|
||||
// #include "scene/scene.hpp"
|
||||
// #include "scene/material.hpp"
|
||||
// #include "scene/mesh.hpp"
|
||||
#include "scene/material.hpp"
|
||||
#include "scene/mesh.hpp"
|
||||
#include "scene/scene.hpp"
|
||||
|
||||
#include <yolo/yolo.hpp>
|
||||
|
||||
@@ -25,24 +22,45 @@
|
||||
|
||||
namespace inferno {
|
||||
|
||||
std::unique_ptr<InfernoApp> inferno_create()
|
||||
InfernoApp* inferno_create()
|
||||
{
|
||||
// MOTD
|
||||
yolo::info("INFERNO HART v" INFERNO_VERSION);
|
||||
|
||||
std::unique_ptr<InfernoApp> app = std::make_unique<InfernoApp>();
|
||||
app->Input = std::make_unique<InfernoInput>();
|
||||
InfernoApp* app = new InfernoApp;
|
||||
app->Input = new InfernoInput;
|
||||
app->Scene = scene::scene_create();
|
||||
|
||||
// Create window
|
||||
graphics::window_create("Inferno v" INFERNO_VERSION, 1280, 720);
|
||||
|
||||
// setup the scene
|
||||
scene::Material* basicMaterial = new scene::Material("basic");
|
||||
graphics::Shader* basicShader = graphics::shader_create();
|
||||
graphics::shader_load(basicShader, "res/shaders/basic.glsl");
|
||||
graphics::shader_link(basicShader);
|
||||
basicMaterial->setGlShader(basicShader);
|
||||
|
||||
scene::Mesh* mesh = new scene::Mesh;
|
||||
// mesh->loadOBJ("res/cornell-box.obj");
|
||||
mesh->loadOBJ("res/sponza.obj");
|
||||
mesh->ready();
|
||||
mesh->setMaterial(basicMaterial);
|
||||
|
||||
scene::SceneObject* object = scene::scene_object_create();
|
||||
scene::scene_object_add_mesh(object, mesh);
|
||||
|
||||
scene::scene_add_object(app->Scene, object);
|
||||
|
||||
app->PreviewRenderer = graphics::preview_create();
|
||||
|
||||
return app;
|
||||
}
|
||||
|
||||
void inferno_cleanup(std::unique_ptr<InfernoApp>& app)
|
||||
void inferno_cleanup(InfernoApp* app)
|
||||
{
|
||||
graphics::window_cleanup();
|
||||
app.reset();
|
||||
delete app;
|
||||
}
|
||||
|
||||
static void inferno_gui_help_marker(const char* desc)
|
||||
@@ -57,7 +75,7 @@ static void inferno_gui_help_marker(const char* desc)
|
||||
}
|
||||
}
|
||||
|
||||
void inferno_preset_gui(std::unique_ptr<InfernoApp>& app)
|
||||
void inferno_preset_gui(InfernoApp* app)
|
||||
{
|
||||
ImGuiID dockspace_id = ImGui::GetID("main");
|
||||
|
||||
@@ -65,7 +83,7 @@ void inferno_preset_gui(std::unique_ptr<InfernoApp>& app)
|
||||
ImGui::DockBuilderAddNode(dockspace_id, ImGuiDockNodeFlags_DockSpace); // Add empty node
|
||||
ImGui::DockBuilderSetNodeSize(dockspace_id, { 1000, 1000 });
|
||||
|
||||
ImGuiID dock_main_id = dockspace_id; // This variable will track the document node, however we are not using it here as we aren't docking anything into it.
|
||||
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);
|
||||
@@ -74,7 +92,7 @@ void inferno_preset_gui(std::unique_ptr<InfernoApp>& app)
|
||||
yolo::info("LAYOUT SET TO DEFAULT");
|
||||
}
|
||||
|
||||
void inferno_move_input(std::unique_ptr<InfernoApp>& app)
|
||||
void inferno_move_input(InfernoApp* app)
|
||||
{
|
||||
static GLFWcursor* cursor = glfwCreateStandardCursor(GLFW_HAND_CURSOR);
|
||||
glfwSetCursor(graphics::window_get_glfw_window(), cursor);
|
||||
@@ -113,15 +131,14 @@ void inferno_move_input(std::unique_ptr<InfernoApp>& app)
|
||||
app->Input->MovementDelta |= 0b00000100;
|
||||
}
|
||||
|
||||
void inferno_stop_move_input(std::unique_ptr<InfernoApp>& app)
|
||||
void inferno_stop_move_input(InfernoApp* app)
|
||||
{
|
||||
app->Input->MovementDelta = 0x0;
|
||||
app->Input->MouseDelta = { 0.0f, 0.0f };
|
||||
}
|
||||
|
||||
int inferno_run(std::unique_ptr<InfernoApp>& app)
|
||||
int inferno_run(InfernoApp* app)
|
||||
{
|
||||
|
||||
while (true) {
|
||||
if (!graphics::window_new_frame())
|
||||
break;
|
||||
@@ -134,6 +151,11 @@ int inferno_run(std::unique_ptr<InfernoApp>& app)
|
||||
}
|
||||
ImGui::DockSpace(dockspace_id, ImVec2(0.0f, 0.0f), dockspace_flags);
|
||||
|
||||
if (glm::length(app->Input->MouseDelta) > 0.0f)
|
||||
graphics::camera_mouse_move(app->Scene->Camera, app->Input->MouseDelta);
|
||||
if (app->Input->MovementDelta != 0b00000000)
|
||||
graphics::camera_move(app->Scene->Camera, app->Input->MovementDelta);
|
||||
|
||||
// Menu Bar
|
||||
static bool showPreview = true;
|
||||
static bool showRenderSettings = true;
|
||||
@@ -162,22 +184,78 @@ int inferno_run(std::unique_ptr<InfernoApp>& app)
|
||||
} else {
|
||||
inferno_stop_move_input(app);
|
||||
}
|
||||
if (glm::length(app->Input->MouseDelta) > 0.0f)
|
||||
graphics::camera_mouse_move(app->Camera, app->Input->MouseDelta);
|
||||
if (app->Input->MovementDelta != 0b00000000)
|
||||
graphics::camera_move(app->Camera, app->Input->MovementDelta);
|
||||
|
||||
graphics::raster_set_viewport(app->Camera, { ImGui::GetWindowSize().x, ImGui::GetWindowSize().y });
|
||||
mRasterRenderer->setTargetSize({ ImGui::GetWindowSize().x, ImGui::GetWindowSize().y });
|
||||
mRasterRenderer->prepare();
|
||||
mRasterRenderer->draw();
|
||||
graphics::raster_set_viewport(scene::scene_get_camera(app->Scene),
|
||||
{ ImGui::GetWindowSize().x, ImGui::GetWindowSize().y });
|
||||
graphics::preview_draw(app->PreviewRenderer, app->Scene);
|
||||
|
||||
ImGui::Image((ImTextureID)mRasterRenderer->getRenderedTexture(), inderno { mRasterRenderer->getTargetSize().x, mRasterRenderer->getTargetSize().y },
|
||||
ImTextureID texture = (ImTextureID)graphics::preview_get_rendered_texture(app->PreviewRenderer);
|
||||
ImGui::Image(
|
||||
texture,
|
||||
{ ImGui::GetWindowSize().x, ImGui::GetWindowSize().y },
|
||||
ImVec2(0, 1), ImVec2(1, 0));
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
if (showRenderSettings && ImGui::Begin("Inferno HART")) {
|
||||
if (ImGui::TreeNode("Camera")) {
|
||||
ImGui::PushItemWidth(100);
|
||||
ImGui::Text("Camera Position X,Y,Z");
|
||||
|
||||
graphics::Camera* camera = scene::scene_get_camera(app->Scene);
|
||||
|
||||
bool positionUpdated = false;
|
||||
ImGui::DragFloat("X", &camera->Position.x, 0.01f, -FLT_MAX, FLT_MAX, "%.2f", ImGuiSliderFlags_None);
|
||||
ImGui::SameLine();
|
||||
if (ImGui::IsItemEdited())
|
||||
positionUpdated = true;
|
||||
ImGui::DragFloat("Y", &camera->Position.y, 0.01f, -FLT_MAX, FLT_MAX, "%.2f", ImGuiSliderFlags_None);
|
||||
ImGui::SameLine();
|
||||
if (ImGui::IsItemEdited())
|
||||
positionUpdated = true;
|
||||
ImGui::DragFloat("Z", &camera->Position.z, 0.01f, -FLT_MAX, FLT_MAX, "%.2f", ImGuiSliderFlags_None);
|
||||
if (ImGui::IsItemEdited())
|
||||
positionUpdated = true;
|
||||
if (positionUpdated)
|
||||
graphics::camera_set_position(camera, graphics::camera_get_position(camera));
|
||||
|
||||
bool viewUpdated = false;
|
||||
ImGui::Text("Camera Look Yaw, Pitch, Roll");
|
||||
ImGui::DragFloat("Yaw", &camera->Yaw, 0.01f, -FLT_MAX, FLT_MAX, "%.2f", ImGuiSliderFlags_None);
|
||||
ImGui::SameLine();
|
||||
if (ImGui::IsItemEdited())
|
||||
viewUpdated = true;
|
||||
ImGui::DragFloat("Pitch", &camera->Pitch, 0.01f, -FLT_MAX, FLT_MAX, "%.2f", ImGuiSliderFlags_None);
|
||||
ImGui::SameLine();
|
||||
if (ImGui::IsItemEdited())
|
||||
viewUpdated = true;
|
||||
ImGui::DragFloat("Roll", &camera->Roll, 0.01f, -FLT_MAX, FLT_MAX, "%.2f", ImGuiSliderFlags_None);
|
||||
if (ImGui::IsItemEdited())
|
||||
viewUpdated = true;
|
||||
|
||||
ImGui::PopItemWidth();
|
||||
ImGui::PushItemWidth(300);
|
||||
|
||||
ImGui::Text("Camera Zoom");
|
||||
ImGui::DragFloat("Zoom", &camera->FOV, -0.1f, 0.01f, 180.0f, "%.2f", ImGuiSliderFlags_None);
|
||||
ImGui::SameLine();
|
||||
if (ImGui::IsItemEdited())
|
||||
viewUpdated = true;
|
||||
if (viewUpdated)
|
||||
graphics::camera_update(camera);
|
||||
|
||||
ImGui::PopItemWidth();
|
||||
ImGui::TreePop();
|
||||
}
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
if (showDemoWindow) {
|
||||
ImGui::ShowDemoWindow();
|
||||
}
|
||||
|
||||
// clang-format off
|
||||
GLenum err;
|
||||
while((err = glGetError()) != GL_NO_ERROR) {
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#include "graphics.hpp"
|
||||
#include "scene/scene.hpp"
|
||||
#include "scene/camera.hpp"
|
||||
// #include "renderer/renderer.hpp"
|
||||
#include "preview_renderer/renderer.hpp"
|
||||
|
||||
#include <memory>
|
||||
|
||||
@@ -10,21 +14,27 @@ namespace graphics {
|
||||
struct Camera;
|
||||
}
|
||||
|
||||
namespace scene {
|
||||
struct Scene;
|
||||
}
|
||||
|
||||
typedef struct InfernoInput {
|
||||
glm::vec2 MouseDelta;
|
||||
uint8_t MovementDelta;
|
||||
glm::vec2 MouseDelta = {0.0f, 0.0f};
|
||||
uint8_t MovementDelta = 0;
|
||||
} InfernoInput;
|
||||
|
||||
typedef struct InfernoApp {
|
||||
std::unique_ptr<InfernoInput> Input;
|
||||
std::unique_ptr<graphics::Camera> Camera;
|
||||
InfernoInput* Input;
|
||||
scene::Scene* Scene;
|
||||
graphics::PreviewRenderer* PreviewRenderer;
|
||||
// graphics::RayRenderer* RayRenderer;
|
||||
} InfernoApp;
|
||||
|
||||
std::unique_ptr<InfernoApp> inferno_create();
|
||||
void inferno_cleanup(std::unique_ptr<InfernoApp>& app);
|
||||
void inferno_preset_gui(std::unique_ptr<InfernoApp>& app);
|
||||
void inferno_move_input(std::unique_ptr<InfernoApp>& app);
|
||||
void inferno_stop_move_input(std::unique_ptr<InfernoApp>& app);
|
||||
int inferno_run(std::unique_ptr<InfernoApp>& app);
|
||||
InfernoApp* inferno_create();
|
||||
void inferno_cleanup(InfernoApp* app);
|
||||
void inferno_preset_gui(InfernoApp* app);
|
||||
void inferno_move_input(InfernoApp* app);
|
||||
void inferno_stop_move_input(InfernoApp* app);
|
||||
int inferno_run(InfernoApp* app);
|
||||
|
||||
}
|
||||
} // namespace inferno
|
||||
|
||||
@@ -5,6 +5,6 @@
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
std::unique_ptr<inferno::InfernoApp> inferno = inferno::inferno_create();
|
||||
auto inferno = inferno::inferno_create();
|
||||
return inferno::inferno_run(inferno);
|
||||
}
|
||||
|
||||
@@ -1,19 +1,24 @@
|
||||
#include "renderer.hpp"
|
||||
|
||||
#include "scene/object.hpp"
|
||||
#include "shader.hpp"
|
||||
|
||||
#include <yolo/yolo.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <scene/camera.hpp>
|
||||
#include <scene/material.hpp>
|
||||
#include <scene/mesh.hpp>
|
||||
#include <scene/object.hpp>
|
||||
#include <scene/scene.hpp>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
namespace inferno::graphics {
|
||||
|
||||
std::unique_ptr<PreviewRenderer> preview_create()
|
||||
PreviewRenderer* preview_create()
|
||||
{
|
||||
std::unique_ptr<PreviewRenderer> renderer = std::make_unique<PreviewRenderer>();
|
||||
PreviewRenderer* renderer = new PreviewRenderer;
|
||||
|
||||
glGenFramebuffers(1, &renderer->RenderTarget);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, renderer->RenderTarget);
|
||||
@@ -44,18 +49,23 @@ std::unique_ptr<PreviewRenderer> preview_create()
|
||||
return renderer;
|
||||
}
|
||||
|
||||
void preview_cleanup(std::unique_ptr<PreviewRenderer>& renderer)
|
||||
void preview_cleanup(PreviewRenderer* renderer)
|
||||
{
|
||||
}
|
||||
|
||||
void preview_set_scene(std::unique_ptr<PreviewRenderer>& renderer, std::shared_ptr<Scene> scene)
|
||||
void preview_set_viewport(PreviewRenderer* renderer, Viewport* viewport)
|
||||
{
|
||||
renderer->CurrentScene = scene;
|
||||
}
|
||||
|
||||
void preview_set_viewport(std::unique_ptr<PreviewRenderer>& renderer, std::shared_ptr<const Viewport> viewport)
|
||||
GLuint preview_get_rendered_texture(PreviewRenderer* renderer)
|
||||
{
|
||||
renderer->RenderTargetSize = viewport;
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, renderer->RenderTarget);
|
||||
return renderer->RenderTargetTexture;
|
||||
}
|
||||
|
||||
void preview_draw(PreviewRenderer* renderer, scene::Scene* scene)
|
||||
{
|
||||
const glm::ivec2& viewport = graphics::raster_get_viewport(scene::scene_get_camera(scene));
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, renderer->RenderTarget);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, renderer->RenderTargetTexture);
|
||||
@@ -63,8 +73,8 @@ void preview_set_viewport(std::unique_ptr<PreviewRenderer>& renderer, std::share
|
||||
GL_TEXTURE_2D,
|
||||
0,
|
||||
GL_RGB,
|
||||
viewport->Raster.x,
|
||||
viewport->Raster.y,
|
||||
viewport.x,
|
||||
viewport.y,
|
||||
0,
|
||||
GL_RGB,
|
||||
GL_UNSIGNED_BYTE,
|
||||
@@ -74,61 +84,55 @@ void preview_set_viewport(std::unique_ptr<PreviewRenderer>& renderer, std::share
|
||||
glTexImage2D(GL_TEXTURE_2D,
|
||||
0,
|
||||
GL_DEPTH24_STENCIL8,
|
||||
viewport->Raster.x,
|
||||
viewport->Raster.y,
|
||||
viewport.x,
|
||||
viewport.y,
|
||||
0,
|
||||
GL_DEPTH_COMPONENT,
|
||||
GL_FLOAT,
|
||||
NULL);
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
}
|
||||
|
||||
const glm::ivec2& preview_get_viewport(std::unique_ptr<PreviewRenderer>& renderer)
|
||||
{
|
||||
return renderer->RenderTargetSize->Raster;
|
||||
}
|
||||
// clear
|
||||
|
||||
GLuint preview_get_rendered_texture(std::unique_ptr<PreviewRenderer>& renderer)
|
||||
{
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, renderer->RenderTarget);
|
||||
return renderer->RenderTargetTexture;
|
||||
}
|
||||
|
||||
void preview_prepare(std::unique_ptr<PreviewRenderer>& renderer)
|
||||
{
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, renderer->RenderTarget);
|
||||
glClearColor(0.1, 0.1, 0.1, 1.0);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
}
|
||||
|
||||
void preview_draw(std::unique_ptr<PreviewRenderer>& renderer)
|
||||
{
|
||||
// draw
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, renderer->RenderTarget);
|
||||
glViewport(0,
|
||||
0,
|
||||
renderer->RenderTargetSize->Raster.x,
|
||||
renderer->RenderTargetSize->Raster.y);
|
||||
renderer->Viewport.x,
|
||||
renderer->Viewport.y);
|
||||
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
|
||||
for (Mesh* m : renderer->CurrentScene->getRenderables()) {
|
||||
// m->getMaterial()->getGlShader()->use();
|
||||
// GLint uniTrans = glGetUniformLocation(m->getMaterial()->getGlShader()->getProgram(), "model");
|
||||
// glUniformMatrix4fv(uniTrans, 1, GL_FALSE, glm::value_ptr(glm::mat4(1.0f)));
|
||||
for (scene::SceneObject* o : scene::scene_get_renderables(scene)) {
|
||||
for (scene::Mesh* m : scene::scene_object_get_meshs(o)) {
|
||||
graphics::Shader* shader = m->getMaterial()->getGlShader();
|
||||
graphics::shader_use(shader);
|
||||
|
||||
// GLint uniView = glGetUniformLocation(m->getMaterial()->getGlShader()->getProgram(), "view");
|
||||
// glUniformMatrix4fv(uniView, 1, GL_FALSE, glm::value_ptr(renderer->CurrentScene->getCamera()->getViewMatrix()));
|
||||
auto viewMatrix = graphics::camera_get_view(scene::scene_get_camera(scene));
|
||||
auto projMatrix = graphics::camera_get_projection(scene::scene_get_camera(scene));
|
||||
|
||||
// GLint uniProj = glGetUniformLocation(m->getMaterial()->getGlShader()->getProgram(), "proj");
|
||||
// glUniformMatrix4fv(uniProj, 1, GL_FALSE, glm::value_ptr(renderer->CurrentScene->getCamera()->getProjectionMatrix()));
|
||||
GLint uniTrans = glGetUniformLocation(graphics::shader_get_program(shader), "model");
|
||||
glUniformMatrix4fv(uniTrans, 1, GL_FALSE, glm::value_ptr(glm::mat4(1.0f)));
|
||||
|
||||
GLint uniView = glGetUniformLocation(graphics::shader_get_program(shader), "view");
|
||||
glUniformMatrix4fv(uniView, 1, GL_FALSE, glm::value_ptr(viewMatrix));
|
||||
|
||||
GLint uniProj = glGetUniformLocation(graphics::shader_get_program(shader), "proj");
|
||||
glUniformMatrix4fv(uniProj, 1, GL_FALSE, glm::value_ptr(projMatrix));
|
||||
|
||||
glBindVertexArray(m->getVAO());
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m->getEBO());
|
||||
|
||||
glDrawElements(GL_TRIANGLES, m->getIndexCount() * sizeof(uint32_t), GL_UNSIGNED_INT, 0);
|
||||
}
|
||||
}
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
}
|
||||
|
||||
@@ -13,22 +13,18 @@ namespace inferno::graphics {
|
||||
struct Viewport;
|
||||
|
||||
typedef struct PreviewRenderer {
|
||||
glm::ivec2 Viewport;
|
||||
|
||||
GLuint RenderTarget = 0;
|
||||
GLuint RenderTargetTexture = 0;
|
||||
GLuint RenderTargetDepthTexture = 0;
|
||||
std::shared_ptr<scene::Scene> CurrentScene;
|
||||
std::shared_ptr<const Viewport> RenderTargetSize;
|
||||
} PreviewRenderer;
|
||||
|
||||
std::unique_ptr<PreviewRenderer> preview_create();
|
||||
void preview_cleanup(std::unique_ptr<PreviewRenderer>& renderer);
|
||||
PreviewRenderer* preview_create();
|
||||
void preview_cleanup(PreviewRenderer* renderer);
|
||||
|
||||
void preview_set_scene(std::unique_ptr<PreviewRenderer>& renderer, std::shared_ptr<scene::Scene> scene);
|
||||
void preview_set_viewport(std::unique_ptr<PreviewRenderer>& renderer, std::shared_ptr<const Viewport> viewports);
|
||||
const glm::ivec2& preview_get_viewport(std::unique_ptr<PreviewRenderer>& renderer);
|
||||
GLuint preview_get_rendered_texture(std::unique_ptr<PreviewRenderer>& renderer);
|
||||
GLuint preview_get_rendered_texture(PreviewRenderer* renderer);
|
||||
|
||||
void preview_prepare(std::unique_ptr<PreviewRenderer>& renderer);
|
||||
void preview_draw(std::unique_ptr<PreviewRenderer>& renderer);
|
||||
void preview_draw(PreviewRenderer* renderer, scene::Scene* scene);
|
||||
|
||||
} // namespace inferno::graphics
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
|
||||
using namespace inferno::graphics;
|
||||
namespace inferno::graphics {
|
||||
|
||||
static std::unordered_map<GLuint, int> shader2Index = {
|
||||
{ GL_VERTEX_SHADER, 0 },
|
||||
@@ -25,7 +25,7 @@ std::string textFromFile(const std::filesystem::path& path)
|
||||
std::istreambuf_iterator<char>());
|
||||
}
|
||||
|
||||
std::vector<const ShaderPreprocessorDefinition*> getKeys(std::unique_ptr<Shader>& shader, std::string key)
|
||||
std::vector<const ShaderPreprocessorDefinition*> getKeys(Shader* shader, std::string key)
|
||||
{
|
||||
std::vector<const ShaderPreprocessorDefinition*> ret;
|
||||
for (const auto& p : shader->PreprocessorDefinitions)
|
||||
@@ -56,9 +56,9 @@ bool checkShader(GLuint uid)
|
||||
return true;
|
||||
}
|
||||
|
||||
std::unique_ptr<Shader> shader_create()
|
||||
Shader* shader_create()
|
||||
{
|
||||
std::unique_ptr<Shader> shader = std::make_unique<Shader>();
|
||||
Shader* shader = new Shader;
|
||||
|
||||
shader->Program = 0;
|
||||
shader->Shaders[0] = GL_NONE;
|
||||
@@ -68,7 +68,7 @@ std::unique_ptr<Shader> shader_create()
|
||||
return shader;
|
||||
}
|
||||
|
||||
void shader_cleanup(std::unique_ptr<Shader>& shader)
|
||||
void shader_cleanup(Shader* shader)
|
||||
{
|
||||
for (int i = 0; i < 3; i++) {
|
||||
if (shader->Shaders[i] == GL_NONE)
|
||||
@@ -79,7 +79,7 @@ void shader_cleanup(std::unique_ptr<Shader>& shader)
|
||||
glDeleteProgram(shader->Program);
|
||||
}
|
||||
|
||||
void shader_load(std::unique_ptr<Shader>& shader, std::filesystem::path path)
|
||||
void shader_load(Shader* shader, std::filesystem::path path)
|
||||
{
|
||||
|
||||
assert(std::filesystem::exists(path));
|
||||
@@ -132,7 +132,7 @@ void shader_load(std::unique_ptr<Shader>& shader, std::filesystem::path path)
|
||||
}
|
||||
}
|
||||
|
||||
void shader_link(std::unique_ptr<Shader>& shader)
|
||||
void shader_link(Shader* shader)
|
||||
{
|
||||
shader->Program = glCreateProgram();
|
||||
|
||||
@@ -150,32 +150,39 @@ void shader_link(std::unique_ptr<Shader>& shader)
|
||||
glLinkProgram(shader->Program);
|
||||
}
|
||||
|
||||
void shader_add_attribute(std::unique_ptr<Shader>& shader, const std::string& attribute)
|
||||
GLuint shader_get_program(Shader* shader)
|
||||
{
|
||||
return shader->Program;
|
||||
}
|
||||
|
||||
void shader_add_attribute(Shader* shader, const std::string& attribute)
|
||||
{
|
||||
shader->Attributes[attribute] = glGetAttribLocation(shader->Program, attribute.c_str());
|
||||
}
|
||||
|
||||
void shader_add_uniform(std::unique_ptr<Shader>& shader, const std::string& uniform)
|
||||
void shader_add_uniform(Shader* shader, const std::string& uniform)
|
||||
{
|
||||
shader->Uniforms[uniform] = glGetUniformLocation(shader->Program, uniform.c_str());
|
||||
}
|
||||
|
||||
GLuint shader_get_attribute(std::unique_ptr<Shader>& shader, const std::string& attribute)
|
||||
GLuint shader_get_attribute(Shader* shader, const std::string& attribute)
|
||||
{
|
||||
return shader->Attributes[attribute];
|
||||
}
|
||||
|
||||
GLuint shader_get_uniform(std::unique_ptr<Shader>& shader, const std::string& uniform)
|
||||
GLuint shader_get_uniform(Shader* shader, const std::string& uniform)
|
||||
{
|
||||
return shader->Uniforms[uniform];
|
||||
}
|
||||
|
||||
void shader_use(std::unique_ptr<Shader>& shader)
|
||||
void shader_use(Shader* shader)
|
||||
{
|
||||
glUseProgram(shader->Program);
|
||||
}
|
||||
|
||||
void shader_unuse(std::unique_ptr<Shader>& shader)
|
||||
void shader_unuse(Shader* shader)
|
||||
{
|
||||
glUseProgram(0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -24,18 +24,21 @@ typedef struct Shader {
|
||||
std::vector<ShaderPreprocessorDefinition> PreprocessorDefinitions;
|
||||
} Shader;
|
||||
|
||||
std::unique_ptr<Shader> shader_create();
|
||||
void shader_cleanup(std::unique_ptr<Shader>& shader);
|
||||
Shader* shader_create();
|
||||
void shader_cleanup(Shader* shader);
|
||||
|
||||
void shader_load(Shader* shader, std::filesystem::path path);
|
||||
void shader_link(Shader* shader);
|
||||
|
||||
GLuint shader_get_program(Shader* shader);
|
||||
|
||||
void shader_load(std::unique_ptr<Shader>& shader, std::filesystem::path path);
|
||||
void shader_link(std::unique_ptr<Shader>& shader);
|
||||
// TODO: Implement shader_reload
|
||||
void shader_add_attribute(std::unique_ptr<Shader>& shader, const std::string& attribute);
|
||||
void shader_add_uniform(std::unique_ptr<Shader>& shader, const std::string& uniform);
|
||||
GLuint shader_get_attribute(std::unique_ptr<Shader>& shader, const std::string& attribute);
|
||||
GLuint shader_get_uniform(std::unique_ptr<Shader>& shader, const std::string& uniform);
|
||||
void shader_add_attribute(Shader* shader, const std::string& attribute);
|
||||
void shader_add_uniform(Shader* shader, const std::string& uniform);
|
||||
GLuint shader_get_attribute(Shader* shader, const std::string& attribute);
|
||||
GLuint shader_get_uniform(Shader* shader, const std::string& uniform);
|
||||
|
||||
void shader_use(std::unique_ptr<Shader>& shader);
|
||||
void shader_unuse(std::unique_ptr<Shader>& shader);
|
||||
void shader_use(Shader* shader);
|
||||
void shader_unuse(Shader* shader);
|
||||
|
||||
}
|
||||
|
||||
@@ -1,75 +0,0 @@
|
||||
#include "dispatcher.hpp"
|
||||
|
||||
#include "hart_module.hpp"
|
||||
#include "renderer.hpp"
|
||||
|
||||
#include <mutex>
|
||||
#include <chrono>
|
||||
|
||||
using namespace inferno;
|
||||
|
||||
RenderDispatcher::RenderDispatcher()
|
||||
: mRenderWorker{}
|
||||
{
|
||||
mHHM = new HHM();
|
||||
mRenderer = new RayRenderer(mHHM);
|
||||
mHHM->Renderer = mRenderer;
|
||||
}
|
||||
|
||||
RenderDispatcher::~RenderDispatcher()
|
||||
{
|
||||
mDoWork = false;
|
||||
mJoin = true;
|
||||
mRenderWorker.join();
|
||||
}
|
||||
|
||||
RayRenderer* RenderDispatcher::getRenderer()
|
||||
{
|
||||
return mRenderer;
|
||||
}
|
||||
|
||||
HHM* RenderDispatcher::getTopModule()
|
||||
{
|
||||
return mHHM;
|
||||
}
|
||||
|
||||
void renderWorker(RayRenderer* renderer, std::atomic<bool>* doWork, std::atomic<bool>* join)
|
||||
{
|
||||
while (!*join)
|
||||
{
|
||||
if (!*doWork) {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||
continue; // stall
|
||||
}
|
||||
renderer->prepare();
|
||||
renderer->draw();
|
||||
}
|
||||
}
|
||||
|
||||
void RenderDispatcher::startProgression()
|
||||
{
|
||||
if (!mRenderWorker.joinable())
|
||||
{
|
||||
mRenderWorker = std::thread{ &renderWorker, this->mRenderer, &mDoWork, &mJoin };
|
||||
}
|
||||
mDoWork = true;
|
||||
}
|
||||
|
||||
void RenderDispatcher::stopProgression()
|
||||
{
|
||||
mDoWork = false;
|
||||
}
|
||||
|
||||
bool RenderDispatcher::progressionStatus()
|
||||
{
|
||||
return mDoWork;
|
||||
}
|
||||
|
||||
GLuint RenderDispatcher::getLatestTexture()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mRenderer->_RenderData);
|
||||
glBindTexture(GL_TEXTURE_2D, mRenderer->mRenderTargetTexture);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, mRenderer->mRenderTargetSize.x, mRenderer->mRenderTargetSize.y, 0, GL_RGBA, GL_FLOAT, mRenderer->mTarget);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
return mRenderer->mRenderTargetTexture;
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <graphics.hpp>
|
||||
|
||||
#include <thread>
|
||||
#include <mutex>
|
||||
#include <atomic>
|
||||
|
||||
namespace inferno {
|
||||
|
||||
// Thread dispatcher keeps track of the thread that calls the
|
||||
// copy function because OpenGL is a nightmare
|
||||
|
||||
class HHM;
|
||||
class Scene;
|
||||
class RayRenderer;
|
||||
|
||||
class RenderDispatcher
|
||||
{
|
||||
public:
|
||||
RenderDispatcher();
|
||||
~RenderDispatcher();
|
||||
|
||||
RayRenderer* getRenderer();
|
||||
HHM* getTopModule();
|
||||
|
||||
void startProgression();
|
||||
void stopProgression();
|
||||
bool progressionStatus();
|
||||
GLuint getLatestTexture();
|
||||
|
||||
private:
|
||||
HHM* mHHM;
|
||||
RayRenderer* mRenderer;
|
||||
|
||||
private:
|
||||
std::thread mRenderWorker;
|
||||
std::atomic<bool> mDoWork = false;
|
||||
std::atomic<bool> mJoin = false;
|
||||
};
|
||||
|
||||
}
|
||||
@@ -1,70 +1,70 @@
|
||||
#include "ray_source.hpp"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include <maths.hpp>
|
||||
|
||||
#include <scene/camera.hpp>
|
||||
|
||||
#include <tracing/ray.hpp>
|
||||
|
||||
using namespace inferno;
|
||||
|
||||
RaySource::RaySource(Camera* camera)
|
||||
: mReferenceCamera(camera)
|
||||
{
|
||||
this->generate();
|
||||
}
|
||||
|
||||
RaySource::~RaySource()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void RaySource::generate()
|
||||
{
|
||||
// #include "ray_source.hpp"
|
||||
//
|
||||
// #include <iostream>
|
||||
//
|
||||
// #include <maths.hpp>
|
||||
//
|
||||
// #include <scene/camera.hpp>
|
||||
//
|
||||
// #include <tracing/ray.hpp>
|
||||
//
|
||||
// using namespace inferno;
|
||||
//
|
||||
// RaySource::RaySource(Camera* camera)
|
||||
// : mReferenceCamera(camera)
|
||||
// {
|
||||
// this->generate();
|
||||
// }
|
||||
//
|
||||
// RaySource::~RaySource()
|
||||
// {
|
||||
//
|
||||
// }
|
||||
//
|
||||
// void RaySource::generate()
|
||||
// {
|
||||
// // const float aspect = mReferenceCamera->getRayViewport().x / mReferenceCamera->getRayViewport().y;
|
||||
// // float scale = tan(mReferenceCamera->FOV / 2.0f * helpers::PI / 180.0f);
|
||||
// }
|
||||
//
|
||||
// ReferencedRayField RaySource::getInitialRays(bool MSAA)
|
||||
// {
|
||||
// if (mReferenceCamera->didUpdate())
|
||||
// {
|
||||
// this->generate();
|
||||
// }
|
||||
//
|
||||
// RayField field;
|
||||
// field.reserve(mReferenceCamera->getRayViewport().x * mReferenceCamera->getRayViewport().y);
|
||||
//
|
||||
// const float aspect = mReferenceCamera->getRayViewport().x / mReferenceCamera->getRayViewport().y;
|
||||
// float scale = tan(mReferenceCamera->FOV / 2.0f * helpers::PI / 180.0f);
|
||||
}
|
||||
|
||||
ReferencedRayField RaySource::getInitialRays(bool MSAA)
|
||||
{
|
||||
if (mReferenceCamera->didUpdate())
|
||||
{
|
||||
this->generate();
|
||||
}
|
||||
|
||||
RayField field;
|
||||
field.reserve(mReferenceCamera->getRayViewport().x * mReferenceCamera->getRayViewport().y);
|
||||
|
||||
const float aspect = mReferenceCamera->getRayViewport().x / mReferenceCamera->getRayViewport().y;
|
||||
float scale = tan(mReferenceCamera->FOV / 2.0f * helpers::PI / 180.0f);
|
||||
|
||||
glm::mat4 cameraToWorld = mReferenceCamera->getCameraLook();
|
||||
glm::vec3 origin = mReferenceCamera->Position;
|
||||
|
||||
std::unordered_map<uint32_t, glm::ivec2> reference;
|
||||
|
||||
uint32_t i = 0;
|
||||
for (int x = 0; x < mReferenceCamera->getRayViewport().x; x++)
|
||||
for (int y = 0; y < mReferenceCamera->getRayViewport().y; y++)
|
||||
{
|
||||
float Px = (2.0f * ((x + 0.5f) / mReferenceCamera->getRayViewport().x) - 1.0f) * scale * aspect;
|
||||
float Py = (2.0f * ((y + 0.5f) / mReferenceCamera->getRayViewport().y) - 1.0f) * scale;
|
||||
|
||||
Ray* ray = new Ray{};
|
||||
|
||||
glm::vec4 dir4 = glm::vec4(Px, Py, -1.0f, 1.0f) * cameraToWorld;
|
||||
glm::vec3 dir3 = glm::vec3(dir4) / dir4.w;
|
||||
ray->Direction = glm::normalize(dir3);
|
||||
|
||||
ray->Origin = origin;
|
||||
ray->Reference = i;
|
||||
reference[i] = {x, y};
|
||||
|
||||
field.push_back(ray);
|
||||
i++;
|
||||
}
|
||||
|
||||
return { field, reference };
|
||||
}
|
||||
//
|
||||
// glm::mat4 cameraToWorld = mReferenceCamera->getCameraLook();
|
||||
// glm::vec3 origin = mReferenceCamera->Position;
|
||||
//
|
||||
// std::unordered_map<uint32_t, glm::ivec2> reference;
|
||||
//
|
||||
// uint32_t i = 0;
|
||||
// for (int x = 0; x < mReferenceCamera->getRayViewport().x; x++)
|
||||
// for (int y = 0; y < mReferenceCamera->getRayViewport().y; y++)
|
||||
// {
|
||||
// float Px = (2.0f * ((x + 0.5f) / mReferenceCamera->getRayViewport().x) - 1.0f) * scale * aspect;
|
||||
// float Py = (2.0f * ((y + 0.5f) / mReferenceCamera->getRayViewport().y) - 1.0f) * scale;
|
||||
//
|
||||
// Ray* ray = new Ray{};
|
||||
//
|
||||
// glm::vec4 dir4 = glm::vec4(Px, Py, -1.0f, 1.0f) * cameraToWorld;
|
||||
// glm::vec3 dir3 = glm::vec3(dir4) / dir4.w;
|
||||
// ray->Direction = glm::normalize(dir3);
|
||||
//
|
||||
// ray->Origin = origin;
|
||||
// ray->Reference = i;
|
||||
// reference[i] = {x, y};
|
||||
//
|
||||
// field.push_back(ray);
|
||||
// i++;
|
||||
// }
|
||||
//
|
||||
// return { field, reference };
|
||||
// }
|
||||
|
||||
@@ -1,33 +1,33 @@
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include <unordered_map>
|
||||
|
||||
#include <graphics.hpp>
|
||||
|
||||
#include <tracing/ray.hpp>
|
||||
|
||||
namespace inferno {
|
||||
|
||||
class Camera;
|
||||
|
||||
struct ReferencedRayField {
|
||||
RayField Field;
|
||||
std::unordered_map<uint32_t, glm::ivec2> Reference;
|
||||
};
|
||||
|
||||
|
||||
class RaySource
|
||||
{
|
||||
public:
|
||||
RaySource(Camera* camera);
|
||||
~RaySource();
|
||||
|
||||
void generate();
|
||||
ReferencedRayField getInitialRays(bool MSAA);
|
||||
|
||||
private:
|
||||
Camera* mReferenceCamera;
|
||||
};
|
||||
|
||||
}
|
||||
// #pragma once
|
||||
//
|
||||
// #include <vector>
|
||||
// #include <unordered_map>
|
||||
//
|
||||
// #include <graphics.hpp>
|
||||
//
|
||||
// #include <tracing/ray.hpp>
|
||||
//
|
||||
// namespace inferno {
|
||||
//
|
||||
// class Camera;
|
||||
//
|
||||
// struct ReferencedRayField {
|
||||
// RayField Field;
|
||||
// std::unordered_map<uint32_t, glm::ivec2> Reference;
|
||||
// };
|
||||
//
|
||||
//
|
||||
// class RaySource
|
||||
// {
|
||||
// public:
|
||||
// RaySource(Camera* camera);
|
||||
// ~RaySource();
|
||||
//
|
||||
// void generate();
|
||||
// ReferencedRayField getInitialRays(bool MSAA);
|
||||
//
|
||||
// private:
|
||||
// Camera* mReferenceCamera;
|
||||
// };
|
||||
//
|
||||
// }
|
||||
|
||||
@@ -1,144 +1,143 @@
|
||||
#include "renderer.hpp"
|
||||
|
||||
#include <graphics.hpp>
|
||||
|
||||
#include <scene/camera.hpp>
|
||||
#include <scene/scene.hpp>
|
||||
#include <scene/mesh.hpp>
|
||||
#include <tracing/ray.hpp>
|
||||
#include <tracing/hit.hpp>
|
||||
|
||||
#include "hart_module.hpp"
|
||||
#include "ray_source.hpp"
|
||||
|
||||
#include <yolo/yolo.hpp>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
namespace inferno::graphics {
|
||||
|
||||
std::unique_ptr<RayRenderer> rayr_create(glm::ivec2 viewport, HHM* accelIface)
|
||||
{
|
||||
std::unique_ptr<RayRenderer> renderer = std::make_unique<RayRenderer>();
|
||||
renderer->RenderTargetSize = viewport;
|
||||
renderer->RenderData = new glm::fvec4[renderer->RenderTargetSize.x * renderer->RenderTargetSize.y];
|
||||
|
||||
glGenTextures(1, &renderer->RenderTargetTexture);
|
||||
glBindTexture(GL_TEXTURE_2D, renderer->RenderTargetTexture);
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
|
||||
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, renderer->RenderTargetSize.x, renderer->RenderTargetSize.y, 0, GL_RGBA, GL_FLOAT, renderer->RenderData);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
return renderer;
|
||||
}
|
||||
|
||||
void rayr_cleanup(std::unique_ptr<RayRenderer>& renderer)
|
||||
{
|
||||
delete[] renderer->RenderData;
|
||||
}
|
||||
|
||||
void rayr_set_scene(std::unique_ptr<RayRenderer>& renderer, std::shared_ptr<scene::Scene> scene)
|
||||
{
|
||||
renderer->CurrentScene = scene;
|
||||
if (renderer->RaySource != nullptr)
|
||||
{
|
||||
delete renderer->RaySource;
|
||||
}
|
||||
// renderer->RaySource = new RaySource(scene->getCamera());
|
||||
// the scene will be sent to the module on prepare
|
||||
// as it did update during initialisation
|
||||
|
||||
// mIface->newScene(scene);
|
||||
}
|
||||
|
||||
void rayr_set_viewport(std::unique_ptr<RayRenderer> &renderer, glm::ivec2 size)
|
||||
{
|
||||
renderer->RenderTargetSize = size;
|
||||
}
|
||||
|
||||
glm::ivec2 rayr_get_viewport(std::unique_ptr<RayRenderer> &renderer)
|
||||
{
|
||||
return renderer->RenderTargetSize;
|
||||
}
|
||||
|
||||
GLuint rayr_get_rendered_texture(std::unique_ptr<RayRenderer> &renderer)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(renderer->RenderDataMutex);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
glBindTexture(GL_TEXTURE_2D, renderer->RenderTargetTexture);
|
||||
return renderer->RenderTargetTexture;
|
||||
}
|
||||
|
||||
glm::fvec4* rayr_get_render_data(std::unique_ptr<RayRenderer> &renderer)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(renderer->RenderDataMutex);
|
||||
return renderer->RenderData;
|
||||
}
|
||||
|
||||
void rayr_prepare(std::unique_ptr<RayRenderer> &renderer)
|
||||
{
|
||||
assert(renderer->CurrentScene != nullptr);
|
||||
// here, scene_did_update takes a unique_ptr, but we have a shared_ptr
|
||||
// so we need to call unique() to get the unique_ptr but that will error
|
||||
// with non-const ltype so we need to const_cast it
|
||||
if (scene::scene_did_update(renderer->CurrentScene))
|
||||
{
|
||||
yolo::debug("New Scene!");
|
||||
// renderer->AccelerationInterface->newScene(renderer->CurrentScene);
|
||||
}
|
||||
}
|
||||
|
||||
void rayr_draw(std::unique_ptr<RayRenderer> &renderer)
|
||||
{
|
||||
scene::scene_frame_tick(renderer->CurrentScene);
|
||||
// TODO: Rays should definately be bump allocated if possible, this is KBs of
|
||||
// ray data and nothing else being reallocated every frame for no reason
|
||||
ReferencedRayField startRays = mRaySource->getInitialRays(true);
|
||||
|
||||
for (int x = 0; x < mRenderTargetSize.x; x++)
|
||||
for (int y = 0; y < mRenderTargetSize.y; y++)
|
||||
{
|
||||
mTarget[y * mRenderTargetSize.x + x] = { 0.1f, 0.1f, 0.1f, 1.0f };
|
||||
}
|
||||
mCurrentRefTable = &startRays.Reference;
|
||||
|
||||
// before we start we now want to check that it hasn't been force-stopped
|
||||
mIface->startTrace(startRays.Field);
|
||||
|
||||
yolo::info("Sample complete");
|
||||
|
||||
for (auto* ray : startRays.Field)
|
||||
{
|
||||
delete ray;
|
||||
}
|
||||
}
|
||||
|
||||
void RayRenderer::computeHit(HitInfo* info)
|
||||
{
|
||||
static float mind = 100000.0f;
|
||||
static float maxd = 0.0f;
|
||||
// TODO: Make sure signal is started
|
||||
if (!(*mCurrentRefTable).count(info->Caller->Reference))
|
||||
{
|
||||
yolo::warn("Why is the ray not in the map?!");
|
||||
return;
|
||||
}
|
||||
glm::ivec2 pos = (*mCurrentRefTable)[info->Caller->Reference];
|
||||
float d = info->Distance;
|
||||
if (d < mind) mind = d;
|
||||
if (d > maxd) maxd = d;
|
||||
float n = (d - mind) / (maxd - mind);
|
||||
mTarget[pos.y * mRenderTargetSize.x + pos.x] = { n, n, n, 1.0f};
|
||||
}
|
||||
void mHaultWait();
|
||||
std::unordered_map<uint32_t, glm::ivec2>* mCurrentRefTable;
|
||||
|
||||
|
||||
}
|
||||
// #include "renderer.hpp"
|
||||
//
|
||||
// #include <graphics.hpp>
|
||||
//
|
||||
// #include <scene/camera.hpp>
|
||||
// #include <scene/scene.hpp>
|
||||
// #include <scene/mesh.hpp>
|
||||
// #include <tracing/ray.hpp>
|
||||
// #include <tracing/hit.hpp>
|
||||
//
|
||||
// #include "ray_source.hpp"
|
||||
//
|
||||
// #include <yolo/yolo.hpp>
|
||||
//
|
||||
// #include <iostream>
|
||||
//
|
||||
// namespace inferno::graphics {
|
||||
//
|
||||
// RayRenderer* rayr_create(glm::ivec2 viewport, HHM* accelIface)
|
||||
// {
|
||||
// RayRenderer* renderer = new RayRenderer;
|
||||
// renderer->RenderTargetSize = viewport;
|
||||
// renderer->RenderData = new glm::fvec4[renderer->RenderTargetSize.x * renderer->RenderTargetSize.y];
|
||||
//
|
||||
// glGenTextures(1, &renderer->RenderTargetTexture);
|
||||
// glBindTexture(GL_TEXTURE_2D, renderer->RenderTargetTexture);
|
||||
//
|
||||
// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
//
|
||||
// glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
|
||||
// glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, renderer->RenderTargetSize.x, renderer->RenderTargetSize.y, 0, GL_RGBA, GL_FLOAT, renderer->RenderData);
|
||||
//
|
||||
// glBindTexture(GL_TEXTURE_2D, 0);
|
||||
//
|
||||
// return renderer;
|
||||
// }
|
||||
//
|
||||
// void rayr_cleanup(RayRenderer* renderer)
|
||||
// {
|
||||
// delete[] renderer->RenderData;
|
||||
// }
|
||||
//
|
||||
// void rayr_set_scene(RayRenderer* renderer, std::shared_ptr<scene::Scene> scene)
|
||||
// {
|
||||
// renderer->CurrentScene = scene;
|
||||
// if (renderer->RaySource != nullptr)
|
||||
// {
|
||||
// delete renderer->RaySource;
|
||||
// }
|
||||
// // renderer->RaySource = new RaySource(scene->getCamera());
|
||||
// // the scene will be sent to the module on prepare
|
||||
// // as it did update during initialisation
|
||||
//
|
||||
// // mIface->newScene(scene);
|
||||
// }
|
||||
//
|
||||
// void rayr_set_viewport(RayRenderer* &renderer, glm::ivec2 size)
|
||||
// {
|
||||
// renderer->RenderTargetSize = size;
|
||||
// }
|
||||
//
|
||||
// glm::ivec2 rayr_get_viewport(RayRenderer* &renderer)
|
||||
// {
|
||||
// return renderer->RenderTargetSize;
|
||||
// }
|
||||
//
|
||||
// GLuint rayr_get_rendered_texture(RayRenderer* &renderer)
|
||||
// {
|
||||
// std::lock_guard<std::mutex> lock(renderer->RenderDataMutex);
|
||||
// glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
// glBindTexture(GL_TEXTURE_2D, renderer->RenderTargetTexture);
|
||||
// return renderer->RenderTargetTexture;
|
||||
// }
|
||||
//
|
||||
// glm::fvec4* rayr_get_render_data(RayRenderer* &renderer)
|
||||
// {
|
||||
// std::lock_guard<std::mutex> lock(renderer->RenderDataMutex);
|
||||
// return renderer->RenderData;
|
||||
// }
|
||||
//
|
||||
// void rayr_prepare(RayRenderer* &renderer)
|
||||
// {
|
||||
// assert(renderer->CurrentScene != nullptr);
|
||||
// // here, scene_did_update takes a unique_ptr, but we have a shared_ptr
|
||||
// // so we need to call unique() to get the unique_ptr but that will error
|
||||
// // with non-const ltype so we need to const_cast it
|
||||
// if (scene::scene_did_update(renderer->CurrentScene))
|
||||
// {
|
||||
// yolo::debug("New Scene!");
|
||||
// // renderer->AccelerationInterface->newScene(renderer->CurrentScene);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// void rayr_draw(RayRenderer* &renderer)
|
||||
// {
|
||||
// scene::scene_frame_tick(renderer->CurrentScene);
|
||||
// // TODO: Rays should definately be bump allocated if possible, this is KBs of
|
||||
// // ray data and nothing else being reallocated every frame for no reason
|
||||
// ReferencedRayField startRays = mRaySource->getInitialRays(true);
|
||||
//
|
||||
// for (int x = 0; x < mRenderTargetSize.x; x++)
|
||||
// for (int y = 0; y < mRenderTargetSize.y; y++)
|
||||
// {
|
||||
// mTarget[y * mRenderTargetSize.x + x] = { 0.1f, 0.1f, 0.1f, 1.0f };
|
||||
// }
|
||||
// mCurrentRefTable = &startRays.Reference;
|
||||
//
|
||||
// // before we start we now want to check that it hasn't been force-stopped
|
||||
// mIface->startTrace(startRays.Field);
|
||||
//
|
||||
// yolo::info("Sample complete");
|
||||
//
|
||||
// for (auto* ray : startRays.Field)
|
||||
// {
|
||||
// delete ray;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// void RayRenderer::computeHit(HitInfo* info)
|
||||
// {
|
||||
// static float mind = 100000.0f;
|
||||
// static float maxd = 0.0f;
|
||||
// // TODO: Make sure signal is started
|
||||
// if (!(*mCurrentRefTable).count(info->Caller->Reference))
|
||||
// {
|
||||
// yolo::warn("Why is the ray not in the map?!");
|
||||
// return;
|
||||
// }
|
||||
// glm::ivec2 pos = (*mCurrentRefTable)[info->Caller->Reference];
|
||||
// float d = info->Distance;
|
||||
// if (d < mind) mind = d;
|
||||
// if (d > maxd) maxd = d;
|
||||
// float n = (d - mind) / (maxd - mind);
|
||||
// mTarget[pos.y * mRenderTargetSize.x + pos.x] = { n, n, n, 1.0f};
|
||||
// }
|
||||
// void mHaultWait();
|
||||
// std::unordered_map<uint32_t, glm::ivec2>* mCurrentRefTable;
|
||||
//
|
||||
//
|
||||
// }
|
||||
|
||||
@@ -20,33 +20,26 @@ class RaySource;
|
||||
class RenderDispatcher;
|
||||
|
||||
typedef struct RayRenderer {
|
||||
glm::ivec2* Viewport;
|
||||
|
||||
// TODO: Can this be direct 2 GPU?
|
||||
glm::fvec4* RenderData = nullptr;
|
||||
GLuint RenderTargetTexture = 0;
|
||||
|
||||
// TODO: Put this inside an internal struct
|
||||
std::mutex RenderDataMutex;
|
||||
std::condition_variable RenderPause;
|
||||
// TODO: End
|
||||
|
||||
std::unique_ptr<scene::Scene> CurrentScene;
|
||||
// std::shared_ptr<const Viewport> RenderTargetSize;
|
||||
glm::ivec2 RenderTargetSize;
|
||||
|
||||
HHM* AccelerationInterface = nullptr;
|
||||
RenderDispatcher* Dispatcher = nullptr;
|
||||
// Internal stuffs
|
||||
RaySource* RaySource = nullptr;
|
||||
} RayRenderer;
|
||||
|
||||
std::unique_ptr<RayRenderer> rayr_create(glm::ivec2 viewport, HHM* accelIface);
|
||||
void rayr_cleanup(std::unique_ptr<RayRenderer>& renderer);
|
||||
void rayr_set_scene(std::unique_ptr<RayRenderer>& renderer, std::unique_ptr<scene::Scene> scene);
|
||||
void rayr_set_viewport(std::unique_ptr<RayRenderer>& renderer, glm::ivec2 size);
|
||||
glm::ivec2 rayr_get_viewport(std::unique_ptr<RayRenderer>& renderer);
|
||||
GLuint rayr_get_rendered_texture(std::unique_ptr<RayRenderer>& renderer);
|
||||
glm::fvec4* rayr_get_render_data(std::unique_ptr<RayRenderer>& renderer);
|
||||
void rayr_prepare(std::unique_ptr<RayRenderer>& renderer);
|
||||
void rayr_draw(std::unique_ptr<RayRenderer>& renderer);
|
||||
RayRenderer* rayr_create(glm::ivec2 viewport, HHM* accelIface);
|
||||
void rayr_cleanup(RayRenderer* renderer);
|
||||
|
||||
void rayr_set_viewport(RayRenderer* renderer, glm::ivec2 size);
|
||||
|
||||
GLuint rayr_get_rendered_texture(RayRenderer* renderer);
|
||||
glm::fvec4* rayr_get_render_data(RayRenderer* renderer);
|
||||
|
||||
void rayr_draw(RayRenderer* renderer, scene::Scene* scene);
|
||||
|
||||
void raryr_compute_hit(HitInfo* info);
|
||||
|
||||
}
|
||||
} // namespace inferno::graphics
|
||||
|
||||
@@ -2,19 +2,14 @@
|
||||
|
||||
namespace inferno::graphics {
|
||||
|
||||
typedef struct _CameraImpl {
|
||||
|
||||
bool DidUpdate;
|
||||
std::mutex CamMutex;
|
||||
} _CameraImpl;
|
||||
|
||||
std::unique_ptr<Camera> camera_create()
|
||||
Camera* camera_create()
|
||||
{
|
||||
std::unique_ptr<Camera> camera = std::make_unique<Camera>();
|
||||
camera->_impl = std::make_unique<_CameraImpl>();
|
||||
camera->Views = std::make_shared<Viewports>();
|
||||
camera->Views->Raster = glm::ivec2(800, 600);
|
||||
camera->Views->Ray = glm::ivec2(800, 600);
|
||||
Camera* camera = new Camera;
|
||||
camera->_impl = new _CameraImpl;
|
||||
|
||||
camera->Views = Viewports();
|
||||
camera->Views.Raster = glm::ivec2(800, 600);
|
||||
camera->Views.Ray = glm::ivec2(800, 600);
|
||||
|
||||
camera->ProjectionMatrix = glm::perspective(
|
||||
glm::radians(camera->FOV),
|
||||
@@ -34,13 +29,13 @@ std::unique_ptr<Camera> camera_create()
|
||||
return camera;
|
||||
}
|
||||
|
||||
void camera_cleanup(std::unique_ptr<Camera>& camera)
|
||||
void camera_cleanup(Camera* camera)
|
||||
{
|
||||
camera->_impl.reset();
|
||||
camera.reset();
|
||||
delete camera->_impl;
|
||||
delete camera;
|
||||
}
|
||||
|
||||
void camera_update(std::unique_ptr<Camera>& camera)
|
||||
void camera_update(Camera* camera)
|
||||
{
|
||||
glm::mat4 matRoll = glm::mat4(1.0f);
|
||||
glm::mat4 matPitch = glm::mat4(1.0f);
|
||||
@@ -61,7 +56,7 @@ void camera_update(std::unique_ptr<Camera>& camera)
|
||||
camera->ViewMatrix = rotate * translate;
|
||||
camera->ProjectionMatrix = glm::perspective(
|
||||
glm::radians(camera->FOV),
|
||||
static_cast<float>(camera->Views->Raster.x) / static_cast<float>(camera->Views->Raster.y),
|
||||
static_cast<float>(camera->Views.Raster.x) / static_cast<float>(camera->Views.Raster.y),
|
||||
0.1f,
|
||||
1000.0f);
|
||||
|
||||
@@ -75,40 +70,40 @@ void camera_update(std::unique_ptr<Camera>& camera)
|
||||
camera->_impl->DidUpdate = true;
|
||||
}
|
||||
|
||||
bool camera_did_update(std::unique_ptr<Camera>& camera)
|
||||
bool camera_did_update(Camera* camera)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(camera->_impl->CamMutex);
|
||||
return camera->_impl->DidUpdate;
|
||||
}
|
||||
|
||||
void camera_new_frame(std::unique_ptr<Camera>& camera)
|
||||
void camera_new_frame(Camera* camera)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(camera->_impl->CamMutex);
|
||||
camera->_impl->DidUpdate = false;
|
||||
}
|
||||
|
||||
glm::mat4 camera_get_view(std::unique_ptr<Camera>& camera)
|
||||
glm::mat4 camera_get_view(Camera* camera)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(camera->_impl->CamMutex);
|
||||
return camera->ViewMatrix;
|
||||
}
|
||||
|
||||
glm::mat4 camera_get_projection(std::unique_ptr<Camera>& camera)
|
||||
glm::mat4 camera_get_projection(Camera* camera)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(camera->_impl->CamMutex);
|
||||
return camera->ProjectionMatrix;
|
||||
}
|
||||
|
||||
glm::mat4 camera_get_look(std::unique_ptr<Camera>& camera)
|
||||
glm::mat4 camera_get_look(Camera* camera)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(camera->_impl->CamMutex);
|
||||
return camera->LookMatrix;
|
||||
}
|
||||
|
||||
void raster_set_viewport(std::unique_ptr<Camera>& camera, glm::ivec2 viewport)
|
||||
void raster_set_viewport(Camera* camera, glm::ivec2 viewport)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(camera->_impl->CamMutex);
|
||||
camera->Views->Raster = viewport;
|
||||
camera->Views.Raster = viewport;
|
||||
camera->ProjectionMatrix = glm::perspective(
|
||||
glm::radians(camera->FOV),
|
||||
static_cast<float>(viewport.x) / static_cast<float>(viewport.y),
|
||||
@@ -116,25 +111,25 @@ void raster_set_viewport(std::unique_ptr<Camera>& camera, glm::ivec2 viewport)
|
||||
1000.0f);
|
||||
}
|
||||
|
||||
glm::ivec2 raster_get_viewport(std::unique_ptr<Camera>& camera)
|
||||
glm::ivec2 raster_get_viewport(Camera* camera)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(camera->_impl->CamMutex);
|
||||
return camera->Views->Raster;
|
||||
return camera->Views.Raster;
|
||||
}
|
||||
|
||||
void ray_set_viewport(std::unique_ptr<Camera>& camera, glm::ivec2 viewport)
|
||||
void ray_set_viewport(Camera* camera, glm::ivec2 viewport)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(camera->_impl->CamMutex);
|
||||
camera->Views->Ray = viewport;
|
||||
camera->Views.Ray = viewport;
|
||||
}
|
||||
|
||||
glm::ivec2 ray_get_viewport(std::unique_ptr<Camera>& camera)
|
||||
glm::ivec2 ray_get_viewport(Camera* camera)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(camera->_impl->CamMutex);
|
||||
return camera->Views->Ray;
|
||||
return camera->Views.Ray;
|
||||
}
|
||||
|
||||
void camera_move(std::unique_ptr<Camera>& camera, uint8_t movement_delta)
|
||||
void camera_move(Camera* camera, uint8_t movement_delta)
|
||||
{
|
||||
if (movement_delta == 0)
|
||||
return;
|
||||
@@ -186,7 +181,7 @@ void camera_move(std::unique_ptr<Camera>& camera, uint8_t movement_delta)
|
||||
camera_update(camera);
|
||||
}
|
||||
|
||||
void camera_mouse_move(std::unique_ptr<Camera>& camera, glm::vec2 mouse_delta)
|
||||
void camera_mouse_move(Camera* camera, glm::vec2 mouse_delta)
|
||||
{
|
||||
if (glm::length(mouse_delta) == 0)
|
||||
return;
|
||||
@@ -199,13 +194,13 @@ void camera_mouse_move(std::unique_ptr<Camera>& camera, glm::vec2 mouse_delta)
|
||||
camera_update(camera);
|
||||
}
|
||||
|
||||
void camera_set_position(std::unique_ptr<Camera>& camera, glm::vec3 position)
|
||||
void camera_set_position(Camera* camera, glm::vec3 position)
|
||||
{
|
||||
camera->Position = position;
|
||||
camera_update(camera);
|
||||
}
|
||||
|
||||
void camera_set_euler_look(std::unique_ptr<Camera>& camera, float roll, float pitch, float yaw)
|
||||
void camera_set_euler_look(Camera* camera, float roll, float pitch, float yaw)
|
||||
{
|
||||
camera->Roll = roll;
|
||||
camera->Pitch = pitch;
|
||||
@@ -217,7 +212,7 @@ void camera_set_euler_look(std::unique_ptr<Camera>& camera, float roll, float pi
|
||||
camera_update(camera);
|
||||
}
|
||||
|
||||
void camera_set_look(std::unique_ptr<Camera>& camera, glm::vec3 look_direction)
|
||||
void camera_set_look(Camera* camera, glm::vec3 look_direction)
|
||||
{
|
||||
camera->LookDirection = look_direction;
|
||||
camera->Pitch = asin(-look_direction.y);
|
||||
@@ -226,4 +221,9 @@ void camera_set_look(std::unique_ptr<Camera>& camera, glm::vec3 look_direction)
|
||||
camera_update(camera);
|
||||
}
|
||||
|
||||
glm::vec3 camera_get_position(Camera* camera)
|
||||
{
|
||||
return camera->Position;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
#include "preview_renderer/shader.hpp"
|
||||
|
||||
using namespace inferno;
|
||||
namespace inferno::scene {
|
||||
|
||||
Material::Material(std::string name)
|
||||
: mName(name)
|
||||
@@ -15,12 +15,13 @@ Material::~Material()
|
||||
|
||||
}
|
||||
|
||||
//void Material::setGlShader(Shader* shader)
|
||||
//{
|
||||
//mGlShader = shader;
|
||||
//}
|
||||
void Material::setGlShader(graphics::Shader* shader)
|
||||
{
|
||||
mGlShader = shader;
|
||||
}
|
||||
|
||||
//Shader* Material::getGlShader()
|
||||
//{
|
||||
//return mGlShader;
|
||||
//}
|
||||
graphics::Shader* Material::getGlShader()
|
||||
{
|
||||
return mGlShader;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,9 +4,12 @@
|
||||
|
||||
#include <hart_graphics.hpp>
|
||||
|
||||
namespace inferno {
|
||||
namespace inferno::graphics {
|
||||
class Shader;
|
||||
};
|
||||
|
||||
namespace inferno::scene {
|
||||
|
||||
//class Shader;
|
||||
class HitInfo;
|
||||
|
||||
class Material {
|
||||
@@ -15,14 +18,14 @@ public:
|
||||
~Material();
|
||||
|
||||
std::string getName();
|
||||
//void setGlShader(Shader* shader);
|
||||
//Shader* getGlShader();
|
||||
void setGlShader(graphics::Shader* shader);
|
||||
graphics::Shader* getGlShader();
|
||||
|
||||
glm::vec3 sample(HitInfo* hit);
|
||||
|
||||
private:
|
||||
std::string mName;
|
||||
//Shader* mGlShader;
|
||||
graphics::Shader* mGlShader;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
#include <iostream>
|
||||
|
||||
using namespace inferno;
|
||||
namespace inferno::scene {
|
||||
|
||||
Mesh::Mesh()
|
||||
{
|
||||
@@ -116,3 +116,5 @@ GLuint Mesh::getEBO()
|
||||
{
|
||||
return mEBO;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include <filesystem>
|
||||
|
||||
#include <hart_graphics.hpp>
|
||||
|
||||
namespace inferno {
|
||||
namespace inferno::scene {
|
||||
|
||||
class ObjLoader;
|
||||
class Material;
|
||||
|
||||
// TODO: This should be procedural like everything else
|
||||
struct Vert
|
||||
{
|
||||
glm::vec3 Position;
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
#include "object.hpp"
|
||||
|
||||
#include "mesh.hpp"
|
||||
|
||||
namespace inferno::scene {
|
||||
|
||||
SceneObject* scene_object_create()
|
||||
{
|
||||
SceneObject* object = new SceneObject;
|
||||
return object;
|
||||
}
|
||||
|
||||
void scene_object_cleanup(SceneObject* object)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void scene_object_add_mesh(SceneObject* object, Mesh* mesh)
|
||||
{
|
||||
object->Meshs.push_back(mesh);
|
||||
}
|
||||
|
||||
std::vector<Mesh*>& scene_object_get_meshs(SceneObject* object)
|
||||
{
|
||||
return object->Meshs;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -1,19 +1,20 @@
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
namespace inferno {
|
||||
namespace inferno::scene {
|
||||
|
||||
class Mesh;
|
||||
|
||||
class Object
|
||||
{
|
||||
public:
|
||||
Object();
|
||||
~Object();
|
||||
typedef struct SceneObject {
|
||||
std::vector<Mesh*> Meshs;
|
||||
} SceneObject;
|
||||
|
||||
private:
|
||||
std::vector<Mesh*> mMeshs;
|
||||
};
|
||||
SceneObject* scene_object_create();
|
||||
void scene_object_cleanup(SceneObject* object);
|
||||
|
||||
}
|
||||
void scene_object_add_mesh(SceneObject* object, Mesh* mesh);
|
||||
std::vector<Mesh*>& scene_object_get_meshs(SceneObject* object);
|
||||
|
||||
} // namespace inferno::scene
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
#include <assert.h>
|
||||
#include <map>
|
||||
|
||||
using namespace inferno;
|
||||
namespace inferno::scene {
|
||||
|
||||
struct FaceVert
|
||||
{
|
||||
@@ -263,3 +263,5 @@ const float* ObjLoader::getTexCoords(int multiTexCoordLayer)
|
||||
assert(multiTexCoordLayer < mTexCoordLayers);
|
||||
return (const float*)&mTexCoords[0];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
#include <hart_graphics.hpp>
|
||||
|
||||
namespace inferno {
|
||||
namespace inferno::scene {
|
||||
|
||||
struct Face
|
||||
{
|
||||
|
||||
@@ -1,55 +1,61 @@
|
||||
#include "scene.hpp"
|
||||
|
||||
#include <yolo/yolo.hpp>
|
||||
|
||||
#include <memory>
|
||||
#include <scene/camera.hpp>
|
||||
#include <scene/mesh.hpp>
|
||||
#include <scene/object.hpp>
|
||||
|
||||
namespace inferno::scene {
|
||||
|
||||
std::unique_ptr<Scene> scene_create()
|
||||
Scene* scene_create()
|
||||
{
|
||||
std::unique_ptr<Scene> scene = std::make_unique<Scene>();
|
||||
scene->Camera = std::make_shared<graphics::Camera>();
|
||||
Scene* scene = new Scene;
|
||||
scene->Objects = std::vector<SceneObject*>();
|
||||
scene->Camera = graphics::camera_create();
|
||||
yolo::debug("Created scene {} and camera {}", scene, scene->Camera);
|
||||
return scene;
|
||||
}
|
||||
|
||||
void scene_cleanup(std::unique_ptr<Scene>& scene)
|
||||
void scene_cleanup(Scene* scene)
|
||||
{
|
||||
}
|
||||
|
||||
void scene_set_camera(std::unique_ptr<Scene>& scene, std::shared_ptr<graphics::Camera> camera)
|
||||
void scene_add_object(Scene* scene, SceneObject* object)
|
||||
{
|
||||
scene->Camera = camera;
|
||||
yolo::debug("Using scene {}", scene);
|
||||
yolo::debug("Adding object to scene, no Objects: {}, adding to pool of: {}", object->Meshs.size(), scene->Objects.size());
|
||||
yolo::debug("Object Mesh 0 is {}", object->Meshs[0]);
|
||||
scene->Objects.push_back(object);
|
||||
scene->DidUpdate = true;
|
||||
}
|
||||
|
||||
void scene_add_object(std::unique_ptr<Scene>& scene, std::unique_ptr<SceneObject> object)
|
||||
graphics::Camera* scene_get_camera(Scene* scene)
|
||||
{
|
||||
scene->Objects.push_back(std::move(object));
|
||||
scene->DidUpdate = true;
|
||||
return scene->Camera;
|
||||
}
|
||||
|
||||
std::vector<std::unique_ptr<SceneObject>>& scene_get_renderables(std::unique_ptr<Scene>& scene)
|
||||
std::vector<SceneObject*>& scene_get_renderables(Scene* scene)
|
||||
{
|
||||
return scene->Objects;
|
||||
}
|
||||
|
||||
bool scene_did_update(std::unique_ptr<Scene>& scene)
|
||||
bool scene_did_update(Scene* scene)
|
||||
{
|
||||
return scene->DidUpdate;
|
||||
}
|
||||
|
||||
void scene_frame_tick(std::unique_ptr<Scene>& scene)
|
||||
void scene_frame_tick(Scene* scene)
|
||||
{
|
||||
scene->DidUpdate = false;
|
||||
}
|
||||
|
||||
void scene_tick(std::unique_ptr<Scene>& scene)
|
||||
void scene_tick(Scene* scene)
|
||||
{
|
||||
for (auto& object : scene->Objects) {
|
||||
// object->tick();
|
||||
// Shit here like animation idk
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "scene/object.hpp"
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
@@ -13,19 +15,22 @@ class SceneObject;
|
||||
class Mesh;
|
||||
|
||||
typedef struct Scene {
|
||||
std::shared_ptr<graphics::Camera> Camera;
|
||||
std::vector<std::unique_ptr<SceneObject>> Objects;
|
||||
std::vector<SceneObject*> Objects;
|
||||
graphics::Camera* Camera;
|
||||
bool DidUpdate = false;
|
||||
} Scene;
|
||||
|
||||
std::unique_ptr<Scene> scene_create();
|
||||
void scene_cleanup(std::unique_ptr<Scene>& scene);
|
||||
void scene_set_camera(std::unique_ptr<Scene>& scene, std::shared_ptr<graphics::Camera> camera);
|
||||
void scene_add_object(std::unique_ptr<Scene>& scene, std::unique_ptr<SceneObject> object);
|
||||
std::unique_ptr<graphics::Camera>& scene_get_camera(std::unique_ptr<Scene>& scene);
|
||||
std::vector<std::unique_ptr<SceneObject>>& scene_get_renderables(std::unique_ptr<Scene>& scene);
|
||||
bool scene_did_update(std::unique_ptr<Scene>& scene);
|
||||
void scene_frame_tick(std::unique_ptr<Scene>& scene);
|
||||
void scene_tick(std::unique_ptr<Scene>& scene);
|
||||
Scene* scene_create();
|
||||
void scene_cleanup(Scene* scene);
|
||||
|
||||
}
|
||||
void scene_add_object(Scene* scene, SceneObject* object);
|
||||
|
||||
graphics::Camera* scene_get_camera(Scene* scene);
|
||||
std::vector<SceneObject*>& scene_get_renderables(Scene* scene);
|
||||
|
||||
bool scene_did_update(Scene* scene);
|
||||
|
||||
void scene_frame_tick(Scene* scene);
|
||||
void scene_tick(Scene* scene);
|
||||
|
||||
} // namespace inferno::scene
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
#pragma once
|
||||
|
||||
#define INFERNO_VERSION "3.0.1_alpha"
|
||||
#define INFERNO_VERSION "3.0.13_alpha"
|
||||
|
||||
@@ -60,6 +60,10 @@ void setupGLFW(std::string title)
|
||||
glfwMakeContextCurrent(Window);
|
||||
gladLoadGLLoader((GLADloadproc)glfwGetProcAddress);
|
||||
glfwSwapInterval(1); // Enable vsync
|
||||
yolo::info("GLFW {} initialized", glfwGetVersionString());
|
||||
yolo::info("OpenGL {} initialized", glGetString(GL_VERSION));
|
||||
yolo::info("GLSL {} initialized", glGetString(GL_SHADING_LANGUAGE_VERSION));
|
||||
yolo::info("INFERNO HART Running on ", glGetString(GL_RENDERER));
|
||||
}
|
||||
|
||||
void setupImGui()
|
||||
|
||||
Reference in New Issue
Block a user