post processing

main
Brett 2024-05-03 22:14:48 -04:00
parent 622b706618
commit ecae5287cc
11 changed files with 342 additions and 127 deletions

View File

@ -1,6 +1,6 @@
cmake_minimum_required(VERSION 3.25) cmake_minimum_required(VERSION 3.25)
set(BLT_GRAPHICS_VERSION 0.13.2) set(BLT_GRAPHICS_VERSION 0.13.3)
set(BLT_GRAPHICS_TEST_VERSION 0.0.1) set(BLT_GRAPHICS_TEST_VERSION 0.0.1)
project(BLT_WITH_GRAPHICS VERSION ${BLT_GRAPHICS_VERSION}) project(BLT_WITH_GRAPHICS VERSION ${BLT_GRAPHICS_VERSION})

View File

@ -123,6 +123,8 @@ namespace blt::gfx
static void unbind(); static void unbind();
static void bindScreen(draw_t type);
void destroy(); void destroy();
[[nodiscard]] i32 getHeight() const [[nodiscard]] i32 getHeight() const

View File

@ -23,6 +23,7 @@
#include "blt/gfx/shader.h" #include "blt/gfx/shader.h"
#include "blt/gfx/framebuffer.h" #include "blt/gfx/framebuffer.h"
#include "blt/gfx/renderer/resource_manager.h" #include "blt/gfx/renderer/resource_manager.h"
#include "blt/gfx/renderer/postprocess.h"
#include <blt/std/hashmap.h> #include <blt/std/hashmap.h>
#include <blt/std/memory_util.h> #include <blt/std/memory_util.h>
#include <blt/math/vectors.h> #include <blt/math/vectors.h>
@ -148,7 +149,7 @@ namespace blt::gfx
class batch_renderer_2d class batch_renderer_2d
{ {
private: private:
frame_buffer_t draw_buffer; pp_engine_t engine;
template<typename T> template<typename T>
struct render_object_t struct render_object_t

View File

@ -28,56 +28,74 @@
namespace blt::gfx namespace blt::gfx
{ {
namespace detail class pp_engine_t;
{
class pp_link;
class pp_iterator;
class pp_link
{
public:
private:
};
class pp_iterator
{
public:
private:
};
}
class pp_step class pp_step_t;
class pp_step_t
{ {
public: public:
virtual void create(i32 width, i32 height) = 0; virtual void create() = 0;
virtual void draw(i32 width, i32 height) = 0; virtual void draw() = 0;
frame_buffer_t& getBuffer() frame_buffer_t& getBuffer()
{ {
return draw_buffer; return draw_buffer;
} }
shader_t& getShader()
{
return *shader;
}
virtual ~pp_step_t() = default;
protected: protected:
frame_buffer_t draw_buffer; frame_buffer_t draw_buffer;
std::unique_ptr<shader_t> shader;
}; };
class pp_engine class pp_render_target_t : public pp_step_t
{
public:
void create() override;
void draw() override;
};
class pp_to_screen_step_t : public pp_step_t
{
public:
void create() override;
void draw() override;
};
class pp_engine_t
{ {
public: public:
void create(); void create();
void render(i32 width, i32 height); void bind();
void render();
void cleanup();
void addStep(std::unique_ptr<pp_step_t> step)
{
steps.emplace_back(std::move(step));
}
static std::unique_ptr<shader_t> createShader(std::string_view fragment);
private: private:
std::vector<std::unique_ptr<pp_step>> steps; std::vector<std::unique_ptr<pp_step_t>> steps;
shader_t screen_shader; std::unique_ptr<vertex_array_t> screen_vao;
#ifdef __EMSCRIPTEN__
std::unique_ptr<pp_to_screen_step_t> to_screen;
#endif
}; };
} }

View File

@ -0,0 +1,32 @@
#ifdef __cplusplus
#include <string>
const std::string shader_postprocess_vert = R"("
#version 300 es
precision mediump float;
layout (location = 0) in vec3 vertex;
layout (location = 1) in vec2 uv_in;
out vec2 pos;
out vec2 uv;
layout (std140) uniform GlobalMatrices
{
mat4 projection;
mat4 ortho;
mat4 view;
mat4 pvm;
mat4 ovm;
};
uniform mat4 model;
uniform float z_index;
void main() {
gl_Position = ovm * model * vec4(vertex.xy, z_index, 1.0);
pos = vertex.xy;
uv = uv_in;
}
")";
#endif

View File

@ -0,0 +1,22 @@
#ifdef __cplusplus
#include <string>
const std::string shader_pp_to_screen_frag = R"("
#version 300 es
precision mediump float;
out vec4 FragColor;
in vec2 uv;
in vec2 pos;
uniform sampler2D tex;
vec4 linear_iter(vec4 i, vec4 p, float factor){
return (i + p) * factor;
}
void main() {
FragColor = texture(tex, uv);
}
")";
#endif

View File

@ -9,6 +9,7 @@
#define BLT_WITH_GRAPHICS_TEMPLATE_WINDOW_H #define BLT_WITH_GRAPHICS_TEMPLATE_WINDOW_H
#include <blt/gfx/gl_includes.h> #include <blt/gfx/gl_includes.h>
#include <blt/std/types.h>
#include <GLFW/glfw3.h> #include <GLFW/glfw3.h>
#include <functional> #include <functional>
#include <cstdint> #include <cstdint>
@ -19,11 +20,11 @@ namespace blt::gfx
{ {
struct window_context struct window_context
{ {
std::int32_t GL_MAJOR = 4; i32 GL_MAJOR = 4;
std::int32_t GL_MINOR = 6; i32 GL_MINOR = 6;
std::int32_t DOUBLE_BUFFER = GLFW_TRUE; i32 DOUBLE_BUFFER = GLFW_TRUE;
std::int32_t GL_PROFILE = GLFW_OPENGL_CORE_PROFILE; i32 GL_PROFILE = GLFW_OPENGL_CORE_PROFILE;
std::int32_t SAMPLES = 8; i32 SAMPLES = 8;
}; };
struct window_data struct window_data
@ -39,9 +40,9 @@ namespace blt::gfx
window_context context{}; window_context context{};
std::int32_t sync_interval = 0; std::int32_t sync_interval = 0;
window_data(std::string title, std::function<void(const window_data&)> init, std::function<void(const window_data&)> update, window_data(std::string_view title, std::function<void(const window_data&)> init, std::function<void(const window_data&)> update,
std::int32_t width = 640, std::int32_t height = 480): init(std::move(init)), update(std::move(update)), i32 width = 640, i32 height = 480): init(std::move(init)), update(std::move(update)),
title(std::move(title)), width(width), height(height) title(title), width(width), height(height)
{} {}
inline void call_init() const inline void call_init() const
@ -128,7 +129,11 @@ namespace blt::gfx
double getFrameDeltaMilliseconds(); double getFrameDeltaMilliseconds();
std::int64_t getFrameDelta(); i64 getFrameDelta();
i32 getWindowWidth();
i32 getWindowHeight();
void cleanup(); void cleanup();

View File

@ -279,9 +279,14 @@ namespace blt::gfx
fbo.attachRenderBuffer(depth_rbo, attachment_t::DEPTH_STENCIL); fbo.attachRenderBuffer(depth_rbo, attachment_t::DEPTH_STENCIL);
if (!frame_buffer_t::validate()) if (!frame_buffer_t::validate())
BLT_ERROR("Failed to create multi-sampled render texture framebuffer!"); BLT_ERROR("Failed to create render texture framebuffer!");
frame_buffer_t::unbind(); frame_buffer_t::unbind();
return fbo; return fbo;
} }
void frame_buffer_t::bindScreen(frame_buffer_t::draw_t type)
{
glBindFramebuffer(static_cast<i32>(type), 0);
}
} }

View File

@ -89,20 +89,23 @@ namespace blt::gfx
point_shader->bindAttribute(0, "vertex"); point_shader->bindAttribute(0, "vertex");
point_shader->bindAttribute(1, "uv_in"); point_shader->bindAttribute(1, "uv_in");
draw_buffer.create(); engine.addStep(std::make_unique<pp_render_target_t>());
draw_buffer.bind(); engine.create();
auto* texture = new texture_gl2D(1440, 720); // draw_buffer.create();
draw_buffer.attachTexture(texture, frame_buffer_t::attachment_t::COLOR0); // draw_buffer.bind();
auto* mask = new texture_gl2D(1440, 720); //
draw_buffer.attachTexture(mask, frame_buffer_t::attachment_t::COLOR1); // auto* texture = new texture_gl2D(1440, 720);
// draw_buffer.attachTexture(texture, frame_buffer_t::attachment_t::COLOR0);
render_buffer_t depth_rbo = render_buffer_t::make_render_buffer(GL_DEPTH24_STENCIL8, 1440, 720); // auto* mask = new texture_gl2D(1440, 720);
draw_buffer.attachRenderBuffer(depth_rbo, frame_buffer_t::attachment_t::DEPTH_STENCIL); // draw_buffer.attachTexture(mask, frame_buffer_t::attachment_t::COLOR1);
//
if (!frame_buffer_t::validate()) // render_buffer_t depth_rbo = render_buffer_t::make_render_buffer(GL_DEPTH24_STENCIL8, 1440, 720);
BLT_ERROR("Failed to create render framebuffer!"); // draw_buffer.attachRenderBuffer(depth_rbo, frame_buffer_t::attachment_t::DEPTH_STENCIL);
frame_buffer_t::unbind(); //
// if (!frame_buffer_t::validate())
// BLT_ERROR("Failed to create render framebuffer!");
// frame_buffer_t::unbind();
} }
void batch_renderer_2d::drawRectangleInternal(const std::string_view texture, const rectangle2d_t& rectangle, const f32 z_index) void batch_renderer_2d::drawRectangleInternal(const std::string_view texture, const rectangle2d_t& rectangle, const f32 z_index)
@ -161,6 +164,7 @@ namespace blt::gfx
void batch_renderer_2d::cleanup() void batch_renderer_2d::cleanup()
{ {
engine.cleanup();
delete square_vao; delete square_vao;
delete square_shader; delete square_shader;
delete point_shader; delete point_shader;
@ -168,8 +172,8 @@ namespace blt::gfx
void batch_renderer_2d::render(i32 width, i32 height, const bool transparency) void batch_renderer_2d::render(i32 width, i32 height, const bool transparency)
{ {
draw_buffer.bind(); //draw_buffer.bind();
draw_buffer.updateBuffersStorage(width, height); //draw_buffer.updateBuffersStorage(width, height);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
if (transparency) if (transparency)
{ {
@ -179,6 +183,7 @@ namespace blt::gfx
glEnable(GL_DEPTH_TEST); glEnable(GL_DEPTH_TEST);
glActiveTexture(GL_TEXTURE0); glActiveTexture(GL_TEXTURE0);
engine.bind();
draw_objects(); draw_objects();
glDisable(GL_DEPTH_TEST); glDisable(GL_DEPTH_TEST);
@ -186,8 +191,9 @@ namespace blt::gfx
glDisable(GL_BLEND); glDisable(GL_BLEND);
render_reset(); render_reset();
draw_buffer.blitToScreen(width, height);
frame_buffer_t::unbind(); frame_buffer_t::unbind();
engine.render();
} }
void batch_renderer_2d::draw_objects() void batch_renderer_2d::draw_objects()

View File

@ -15,17 +15,115 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
#include <blt/gfx/renderer/post_process.h> #include <blt/gfx/window.h>
#include <blt/gfx/renderer/postprocess.h>
#include <blt/gfx/renderer/shaders/postprocess.vert>
#include <blt/gfx/renderer/shaders/pp_to_screen.frag>
#include <blt/std/ranges.h>
float full_screen_vertices[20] = {
1.0f, 1.0f, 0.0f, 1.0f, 1.0f,
1.0f, -1.0f, 0.0f, 1.0f, 0.0f,
-1.0f, -1.0f, 0.0f, 0.0f, 0.0f,
-1.0f, 1.0f, 0.0f, 0.0f, 1.0f
};
const unsigned int full_screen_indices[6] = {
0, 1, 3,
1, 2, 3
};
namespace blt::gfx namespace blt::gfx
{ {
void pp_engine::create() void pp_engine_t::create()
{ {
{
vertex_buffer_t vertices_vbo;
element_buffer_t indices_vbo;
vertices_vbo.create();
indices_vbo.create();
vertices_vbo.allocate(sizeof(full_screen_vertices), full_screen_vertices);
indices_vbo.allocate(sizeof(full_screen_indices), full_screen_indices);
screen_vao = std::make_unique<vertex_array_t>();
const auto tb = screen_vao->bindVBO(vertices_vbo, 0, 3, GL_FLOAT, 5 * sizeof(float), 0);
screen_vao->bindVBO(tb, 1, 2, GL_FLOAT, 5 * sizeof(float), 3 * sizeof(float));
screen_vao->bindElement(indices_vbo);
}
#ifdef __EMSCRIPTEN__
to_screen = std::make_unique<pp_to_screen_step_t>();
#endif
for (auto& step : steps)
step->create();
} }
void pp_engine::render(i32 width, i32 height) void pp_engine_t::render()
{ {
screen_vao->bind();
for (const auto& [index, step] : blt::enumerate(steps))
{
if (index == 0)
{
continue;
} else
steps[index - 1]->getBuffer().bind(frame_buffer_t::draw_t::READ);
step->draw();
step->getBuffer().bind(frame_buffer_t::draw_t::DRAW);
step->getShader().bind();
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
}
frame_buffer_t::unbind();
#ifdef __EMSCRIPTEN__
to_screen->getShader().bind();
steps.back()->getBuffer().bind(frame_buffer_t::draw_t::READ);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
#else
steps.back()->getBuffer().blitToScreen(getWindowWidth(), getWindowHeight());
#endif
}
void pp_engine_t::cleanup()
{
screen_vao = nullptr;
for (auto& v : steps)
v = nullptr;
steps.clear();
}
std::unique_ptr<shader_t> pp_engine_t::createShader(std::string_view fragment)
{
auto shader = std::make_unique<shader_t>(shader_postprocess_vert, std::string(fragment));
shader->bindAttribute(0, "vertex");
shader->bindAttribute(1, "uv_in");
return shader;
}
void pp_engine_t::bind()
{
steps.front()->draw();
steps.front()->getBuffer().bind(frame_buffer_t::draw_t::DRAW);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
}
void pp_to_screen_step_t::create()
{
shader = pp_engine_t::createShader(shader_pp_to_screen_frag);
}
void pp_to_screen_step_t::draw()
{}
void pp_render_target_t::create()
{
shader = pp_engine_t::createShader(shader_pp_to_screen_frag);
draw_buffer = frame_buffer_t::make_render_target(getWindowWidth(), getWindowHeight());
}
void pp_render_target_t::draw()
{
draw_buffer.updateBuffersStorage(getWindowWidth(), getWindowHeight());
} }
} }

View File

@ -46,7 +46,7 @@ namespace blt::gfx
double nanoDelta = 0; double nanoDelta = 0;
double millisDelta = 0; double millisDelta = 0;
} window_state; } window_state;
void create_callbacks() void create_callbacks()
{ {
/* Setup keyboard callback */ /* Setup keyboard callback */
@ -68,7 +68,7 @@ namespace blt::gfx
window_state.inputManager.key(key) = state; window_state.inputManager.key(key) = state;
window_state.inputManager.key_pressed = true; window_state.inputManager.key_pressed = true;
}); });
/* Setup mouse button callback */ /* Setup mouse button callback */
glfwSetMouseButtonCallback(window_state.window, [](GLFWwindow*, int button, int action, int) { glfwSetMouseButtonCallback(window_state.window, [](GLFWwindow*, int button, int action, int) {
if (button < 0) if (button < 0)
@ -86,40 +86,40 @@ namespace blt::gfx
window_state.inputManager.mouse(button) = state; window_state.inputManager.mouse(button) = state;
window_state.inputManager.mouse_pressed = true; window_state.inputManager.mouse_pressed = true;
}); });
/* Setup mouse cursor callback */ /* Setup mouse cursor callback */
glfwSetCursorPosCallback(window_state.window, [](GLFWwindow*, double x, double y) { glfwSetCursorPosCallback(window_state.window, [](GLFWwindow*, double x, double y) {
window_state.inputManager.updateMousePos(x, y); window_state.inputManager.updateMousePos(x, y);
window_state.inputManager.mouse_moved = true; window_state.inputManager.mouse_moved = true;
}); });
/* Setup mouse scroll callback */ /* Setup mouse scroll callback */
glfwSetScrollCallback(window_state.window, [](GLFWwindow*, double, double s) { window_state.inputManager.updateScroll(s); }); glfwSetScrollCallback(window_state.window, [](GLFWwindow*, double, double s) { window_state.inputManager.updateScroll(s); });
/* Setup drop input callback */ /* Setup drop input callback */
glfwSetDropCallback(window_state.window, [](GLFWwindow*, int count, const char** paths) { glfwSetDropCallback(window_state.window, [](GLFWwindow*, int count, const char** paths) {
for (int i = 0; i < count; i++) for (int i = 0; i < count; i++)
window_state.pendingPaths.emplace(paths[i]); window_state.pendingPaths.emplace(paths[i]);
}); });
} }
void setup_ImGUI() void setup_ImGUI()
{ {
const char* glsl_version = "#version 100"; const char* glsl_version = "#version 100";
// Setup Dear ImGui context // Setup Dear ImGui context
IMGUI_CHECKVERSION(); IMGUI_CHECKVERSION();
ImGui::CreateContext(); ImGui::CreateContext();
ImGuiIO& io = ImGui::GetIO(); ImGuiIO& io = ImGui::GetIO();
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls
// Setup Dear ImGui style // Setup Dear ImGui style
ImGui::StyleColorsDark(); ImGui::StyleColorsDark();
//ImGui::Spectrum::StyleColorsSpectrum(); //ImGui::Spectrum::StyleColorsSpectrum();
ImGui::Spectrum::LoadFont(); ImGui::Spectrum::LoadFont();
ImGui::SetupImGuiStyle(true, 1.0); ImGui::SetupImGuiStyle(true, 1.0);
// Setup FA // Setup FA
ImFontConfig config; ImFontConfig config;
config.MergeMode = true; config.MergeMode = true;
@ -131,9 +131,9 @@ namespace blt::gfx
io.Fonts->AddFontFromMemoryCompressedTTF(fontAwesomeBrands_compressed_data, static_cast<int>(fontAwesomeBrands_compressed_size), 13.0, io.Fonts->AddFontFromMemoryCompressedTTF(fontAwesomeBrands_compressed_data, static_cast<int>(fontAwesomeBrands_compressed_size), 13.0,
&config, &config,
icon_ranges); icon_ranges);
//ImGui::StyleColorsLight(); //ImGui::StyleColorsLight();
// Setup Platform/Renderer backends // Setup Platform/Renderer backends
ImGui_ImplGlfw_InitForOpenGL(window_state.window, true); ImGui_ImplGlfw_InitForOpenGL(window_state.window, true);
#ifdef __EMSCRIPTEN__ #ifdef __EMSCRIPTEN__
@ -145,7 +145,7 @@ namespace blt::gfx
io.IniFilename = nullptr; io.IniFilename = nullptr;
#endif #endif
} }
void loop(void* arg) void loop(void* arg)
{ {
auto& data = *((window_data*) arg); auto& data = *((window_data*) arg);
@ -156,24 +156,24 @@ namespace blt::gfx
data.height = window_state.height; data.height = window_state.height;
// TODO: user option for this // TODO: user option for this
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
/* -- Begin the next ImGUI frame -- */ /* -- Begin the next ImGUI frame -- */
ImGui_ImplOpenGL3_NewFrame(); ImGui_ImplOpenGL3_NewFrame();
ImGui_ImplGlfw_NewFrame(); ImGui_ImplGlfw_NewFrame();
ImGui::NewFrame(); ImGui::NewFrame();
/* -- Call user update function -- */ /* -- Call user update function -- */
data.call_update(); data.call_update();
/* -- Render the ImGUI frame -- */ /* -- Render the ImGUI frame -- */
ImGui::Render(); ImGui::Render();
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData()); ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
/* -- Update GLFW state -- */ /* -- Update GLFW state -- */
window_state.inputManager.clear(); window_state.inputManager.clear();
glfwSwapBuffers(window_state.window); glfwSwapBuffers(window_state.window);
glfwPollEvents(); glfwPollEvents();
/* -- Update Frame Timing Information -- */ /* -- Update Frame Timing Information -- */
const auto current_time = system::nanoTime(); const auto current_time = system::nanoTime();
window_state.deltaTime = current_time - window_state.lastTime; window_state.deltaTime = current_time - window_state.lastTime;
@ -183,7 +183,7 @@ namespace blt::gfx
} }
#ifdef __EMSCRIPTEN__ #ifdef __EMSCRIPTEN__
EM_BOOL emscripten_resize_callback(int, const EmscriptenUiEvent* event, void* data) EM_BOOL emscripten_resize_callback(int, const EmscriptenUiEvent* event, void* data)
{ {
int width = event->documentBodyClientWidth; int width = event->documentBodyClientWidth;
@ -203,7 +203,7 @@ namespace blt::gfx
}); });
#endif #endif
void init(window_data data) void init(window_data data)
{ {
#ifdef __EMSCRIPTEN__ #ifdef __EMSCRIPTEN__
@ -217,28 +217,28 @@ namespace blt::gfx
/* -- Set up Error Callback -- */ /* -- Set up Error Callback -- */
glfwSetErrorCallback(error_callback); glfwSetErrorCallback(error_callback);
BLT_ASSERT(glfwInit() && "Unable to init GLFW. Aborting."); BLT_ASSERT(glfwInit() && "Unable to init GLFW. Aborting.");
/* -- Set up Window Context -- */ /* -- Set up Window Context -- */
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, data.context.GL_MAJOR); glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, data.context.GL_MAJOR);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, data.context.GL_MINOR); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, data.context.GL_MINOR);
glfwWindowHint(GLFW_DOUBLEBUFFER, data.context.DOUBLE_BUFFER); glfwWindowHint(GLFW_DOUBLEBUFFER, data.context.DOUBLE_BUFFER);
glfwWindowHint(GLFW_OPENGL_PROFILE, data.context.GL_PROFILE); glfwWindowHint(GLFW_OPENGL_PROFILE, data.context.GL_PROFILE);
glfwWindowHint(GLFW_SAMPLES, data.context.SAMPLES); glfwWindowHint(GLFW_SAMPLES, data.context.SAMPLES);
/* -- Create the Window -- */ /* -- Create the Window -- */
window_state.window = glfwCreateWindow(data.width, data.height, data.title.c_str(), nullptr, nullptr); window_state.window = glfwCreateWindow(data.width, data.height, data.title.c_str(), nullptr, nullptr);
BLT_ASSERT(window_state.window && "Unable to create GLFW window."); BLT_ASSERT(window_state.window && "Unable to create GLFW window.");
/* -- Set Window Specifics + OpenGL -- */ /* -- Set Window Specifics + OpenGL -- */
glfwMakeContextCurrent(window_state.window); glfwMakeContextCurrent(window_state.window);
#ifndef __EMSCRIPTEN__ #ifndef __EMSCRIPTEN__
glfwSwapInterval(data.sync_interval); glfwSwapInterval(data.sync_interval);
gladLoadGL(glfwGetProcAddress); gladLoadGL(glfwGetProcAddress);
#endif #endif
/* -- Set up our local callbacks, ImGUI will then call these -- */ /* -- Set up our local callbacks, ImGUI will then call these -- */
create_callbacks(); create_callbacks();
/* -- Set up ImGUI -- */ /* -- Set up ImGUI -- */
setup_ImGUI(); setup_ImGUI();
@ -246,7 +246,10 @@ namespace blt::gfx
if (data.context.SAMPLES > 0) if (data.context.SAMPLES > 0)
glEnable(GL_MULTISAMPLE); glEnable(GL_MULTISAMPLE);
#endif #endif
window_state.width = data.width;
window_state.height = data.height;
/* -- Call User Provided post-window-init function -- */ /* -- Call User Provided post-window-init function -- */
data.call_init(); data.call_init();
@ -264,31 +267,38 @@ namespace blt::gfx
loop((void*) &data); loop((void*) &data);
#endif #endif
} }
void cleanup() void cleanup()
{ {
ImGui_ImplOpenGL3_Shutdown(); ImGui_ImplOpenGL3_Shutdown();
ImGui_ImplGlfw_Shutdown(); ImGui_ImplGlfw_Shutdown();
ImGui::DestroyContext(); ImGui::DestroyContext();
glfwDestroyWindow(window_state.window); glfwDestroyWindow(window_state.window);
glfwTerminate(); glfwTerminate();
} }
double getMouseX() { return window_state.inputManager.mouseX; } double getMouseX()
{ return window_state.inputManager.mouseX; }
double getMouseY() { return window_state.inputManager.mouseY; }
double getMouseY()
double getMouseDX() { return window_state.inputManager.deltaX; } { return window_state.inputManager.mouseY; }
double getMouseDY() { return window_state.inputManager.deltaY; } double getMouseDX()
{ return window_state.inputManager.deltaX; }
void lockCursor() { glfwSetInputMode(window_state.window, GLFW_CURSOR, GLFW_CURSOR_DISABLED); }
double getMouseDY()
void unlockCursor() { glfwSetInputMode(window_state.window, GLFW_CURSOR, GLFW_CURSOR_NORMAL); } { return window_state.inputManager.deltaY; }
bool isCursorLocked() { return glfwGetInputMode(window_state.window, GLFW_CURSOR) == GLFW_CURSOR_DISABLED; } void lockCursor()
{ glfwSetInputMode(window_state.window, GLFW_CURSOR, GLFW_CURSOR_DISABLED); }
void unlockCursor()
{ glfwSetInputMode(window_state.window, GLFW_CURSOR, GLFW_CURSOR_NORMAL); }
bool isCursorLocked()
{ return glfwGetInputMode(window_state.window, GLFW_CURSOR) == GLFW_CURSOR_DISABLED; }
bool isCursorInWindow() bool isCursorInWindow()
{ {
#ifdef __EMSCRIPTEN__ #ifdef __EMSCRIPTEN__
@ -298,7 +308,7 @@ namespace blt::gfx
return glfwGetWindowAttrib(window_state.window, GLFW_HOVERED); return glfwGetWindowAttrib(window_state.window, GLFW_HOVERED);
#endif #endif
} }
void setRawInput(bool state) void setRawInput(bool state)
{ {
#ifdef __EMSCRIPTEN__ #ifdef __EMSCRIPTEN__
@ -308,7 +318,7 @@ namespace blt::gfx
glfwSetInputMode(window_state.window, GLFW_RAW_MOUSE_MOTION, state ? GLFW_TRUE : GLFW_FALSE); glfwSetInputMode(window_state.window, GLFW_RAW_MOUSE_MOTION, state ? GLFW_TRUE : GLFW_FALSE);
#endif #endif
} }
bool isRawInput() bool isRawInput()
{ {
#ifdef __EMSCRIPTEN__ #ifdef __EMSCRIPTEN__
@ -317,27 +327,43 @@ namespace blt::gfx
return glfwGetInputMode(window_state.window, GLFW_RAW_MOUSE_MOTION); return glfwGetInputMode(window_state.window, GLFW_RAW_MOUSE_MOTION);
#endif #endif
} }
void setClipboard(const std::string& str) { glfwSetClipboardString(window_state.window, str.c_str()); } void setClipboard(const std::string& str)
{ glfwSetClipboardString(window_state.window, str.c_str()); }
std::string getClipboard() { return glfwGetClipboardString(window_state.window); }
std::string getClipboard()
bool isMousePressed(int button) { return window_state.inputManager.isMousePressed(button); } { return glfwGetClipboardString(window_state.window); }
bool isKeyPressed(int key) { return window_state.inputManager.isKeyPressed(key); } bool isMousePressed(int button)
{ return window_state.inputManager.isMousePressed(button); }
double getFrameDeltaSeconds() { return window_state.nanoDelta; }
bool isKeyPressed(int key)
double getFrameDeltaMilliseconds() { return window_state.millisDelta; } { return window_state.inputManager.isKeyPressed(key); }
std::int64_t getFrameDelta() { return window_state.deltaTime; } double getFrameDeltaSeconds()
{ return window_state.nanoDelta; }
bool mouseMovedLastFrame() { return window_state.inputManager.mouse_moved; }
double getFrameDeltaMilliseconds()
bool mousePressedLastFrame() { return window_state.inputManager.mouse_pressed; } { return window_state.millisDelta; }
bool keyPressedLastFrame() { return window_state.inputManager.key_pressed; } i64 getFrameDelta()
{ return window_state.deltaTime; }
bool mouseMovedLastFrame()
{ return window_state.inputManager.mouse_moved; }
bool mousePressedLastFrame()
{ return window_state.inputManager.mouse_pressed; }
bool keyPressedLastFrame()
{ return window_state.inputManager.key_pressed; }
i32 getWindowHeight()
{ return window_state.height; }
i32 getWindowWidth()
{ return window_state.width; }
window_data& window_data::setWindowSize(int32_t new_width, int32_t new_height) window_data& window_data::setWindowSize(int32_t new_width, int32_t new_height)
{ {
width = new_width; width = new_width;