framebuffers
parent
321379fb12
commit
e9e3622963
|
@ -1,6 +1,6 @@
|
|||
cmake_minimum_required(VERSION 3.25)
|
||||
|
||||
set(BLT_GRAPHICS_VERSION 0.9.13)
|
||||
set(BLT_GRAPHICS_VERSION 0.9.14)
|
||||
set(BLT_GRAPHICS_TEST_VERSION 0.0.1)
|
||||
|
||||
project(BLT_WITH_GRAPHICS VERSION ${BLT_GRAPHICS_VERSION})
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
# BLT-With-Graphics-Template
|
||||
|
||||
BLT + Graphics + Emscripten
|
||||
BLT + Graphics + Emscripten
|
||||
|
||||
TODO: some of the API is inconsistent.
|
||||
|
||||
Textures bind themselves but FBOs do not.
|
||||
|
||||
make more use of factory functions
|
|
@ -25,7 +25,7 @@ blt::gfx::resource_manager resources;
|
|||
blt::gfx::batch_renderer_2d renderer_2d(resources);
|
||||
blt::gfx::first_person_camera camera;
|
||||
|
||||
void init(blt::gfx::window_context& context)
|
||||
void init(const blt::gfx::window_context& context)
|
||||
{
|
||||
using namespace blt::gfx;
|
||||
|
||||
|
@ -35,7 +35,7 @@ void init(blt::gfx::window_context& context)
|
|||
renderer_2d.create();
|
||||
}
|
||||
|
||||
void update(blt::gfx::window_context& context, std::int32_t width, std::int32_t height)
|
||||
void update(const blt::gfx::window_context& context, std::int32_t width, std::int32_t height)
|
||||
{
|
||||
global_matrices.update_perspectives(width, height, 90, 0.1, 2000);
|
||||
|
||||
|
|
|
@ -20,31 +20,94 @@
|
|||
#define BLT_WITH_GRAPHICS_FRAMEBUFFER_H
|
||||
|
||||
#include "blt/gfx/gl_includes.h"
|
||||
#include <blt/gfx/texture.h>
|
||||
#include <vector>
|
||||
#include "blt/std/types.h"
|
||||
|
||||
namespace blt::gfx
|
||||
{
|
||||
|
||||
#define C(num) COLOR##num = GL_COLOR_ATTACHMENT##num,
|
||||
|
||||
#define COLOR_LIST \
|
||||
C(0) C(1) C(2) C(3) C(4) C(5) C(6) C(7) C(8) C(9) C(10) C(11) C(12) C(13) C(14) C(15) C(16) \
|
||||
C(17) C(18) C(19) C(20) C(21) C(22) C(23) C(24) C(25) C(26) C(27) C(28) C(29) C(30) C(31)
|
||||
|
||||
class fbo_t;
|
||||
|
||||
class rbo_t
|
||||
{
|
||||
friend fbo_t;
|
||||
private:
|
||||
GLuint rboID;
|
||||
GLuint storage_type;
|
||||
public:
|
||||
rbo_t(): rboID(0), storage_type(0)
|
||||
{}
|
||||
|
||||
void create();
|
||||
|
||||
void bind() const;
|
||||
|
||||
void setStorage(GLuint storage_type, blt::i32 width, blt::i32 height);
|
||||
|
||||
void updateStorage(blt::i32 width, blt::i32 height) const;
|
||||
|
||||
static void unbind();
|
||||
|
||||
void destroy();
|
||||
|
||||
static rbo_t make_render_buffer(GLuint storage_type, blt::i32 width, blt::i32 height);
|
||||
};
|
||||
|
||||
class fbo_t
|
||||
{
|
||||
public:
|
||||
enum class fbo_draw_t : GLuint
|
||||
enum class draw_t : GLuint
|
||||
{
|
||||
DRAW = GL_DRAW_FRAMEBUFFER,
|
||||
READ = GL_READ_FRAMEBUFFER,
|
||||
BOTH = GL_FRAMEBUFFER
|
||||
};
|
||||
enum class attachment_t : GLuint
|
||||
{
|
||||
COLOR_LIST
|
||||
DEPTH_STENCIL = GL_DEPTH_STENCIL_ATTACHMENT,
|
||||
DEPTH = GL_DEPTH_ATTACHMENT,
|
||||
STENCIL = GL_STENCIL_ATTACHMENT
|
||||
};
|
||||
|
||||
private:
|
||||
GLuint fboID;
|
||||
GLuint fboID = 0;
|
||||
GLuint generic_bind_type = GL_FRAMEBUFFER;
|
||||
std::vector<blt::gfx::texture_gl*> texture_buffers;
|
||||
std::vector<rbo_t> render_buffers;
|
||||
public:
|
||||
void create();
|
||||
// default used for fbo binding
|
||||
void create(draw_t bind_type = draw_t::BOTH);
|
||||
|
||||
void bind(fbo_draw_t type = fbo_draw_t::BOTH) const;
|
||||
void bind(draw_t type = draw_t::BOTH) const;
|
||||
|
||||
bool validate();
|
||||
// this function takes ownership of the pointer.
|
||||
void attachTexture(blt::gfx::texture_gl* texture, attachment_t attachment, int level = 0);
|
||||
|
||||
void updateBuffersStorage(blt::i32 width, blt::i32 height);
|
||||
|
||||
// this function takes ownership of the render buffer
|
||||
void attachRenderBuffer(rbo_t rbo, attachment_t attachment);
|
||||
|
||||
static bool validate();
|
||||
|
||||
static void unbind();
|
||||
|
||||
void destroy();
|
||||
|
||||
public:
|
||||
static fbo_t make_render_texture(blt::i32 width, blt::i32 height);
|
||||
};
|
||||
|
||||
#undef C
|
||||
#undef COLOR_LIST
|
||||
}
|
||||
|
||||
#endif //BLT_WITH_GRAPHICS_FRAMEBUFFER_H
|
||||
|
|
|
@ -227,7 +227,7 @@ namespace blt::gfx
|
|||
glBindVertexArray(0);
|
||||
}
|
||||
|
||||
static inline std::shared_ptr<vbo_t_owner> createSharedVBO(const vbo_t& vbo)
|
||||
static inline static_dynamic_array::vbo_type createSharedVBO(const vbo_t& vbo)
|
||||
{
|
||||
return std::make_shared<vbo_t_owner>(vbo);
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include <string>
|
||||
#include <vector>
|
||||
#include <utility>
|
||||
#include "blt/std/types.h"
|
||||
|
||||
namespace blt::gfx
|
||||
{
|
||||
|
@ -157,6 +158,14 @@ namespace blt::gfx
|
|||
return textureID;
|
||||
}
|
||||
|
||||
[[nodiscard]] inline GLint getBindType() const
|
||||
{
|
||||
return textureBindType;
|
||||
}
|
||||
|
||||
virtual void updateSize(blt::i32, blt::i32)
|
||||
{}
|
||||
|
||||
virtual ~texture_gl()
|
||||
{
|
||||
glDeleteTextures(1, &textureID);
|
||||
|
@ -177,10 +186,15 @@ namespace blt::gfx
|
|||
|
||||
void upload(const texture_data& file_data) const;
|
||||
|
||||
inline void updateSize(blt::i32 width, blt::i32 height) final
|
||||
{
|
||||
resize(width, height);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resizes the internal memory for the texture but does NOT resize the texture image stored
|
||||
*/
|
||||
inline void resize(int width, int height);
|
||||
void resize(int width, int height);
|
||||
};
|
||||
|
||||
struct gl_texture2D_array : public texture_gl
|
||||
|
|
|
@ -31,14 +31,14 @@ namespace blt::gfx
|
|||
std::string title;
|
||||
std::int32_t width;
|
||||
std::int32_t height;
|
||||
std::function<void(window_context&)> init;
|
||||
std::function<void(window_context&, std::int32_t, std::int32_t)> update;
|
||||
std::function<void(const window_context&)> init;
|
||||
std::function<void(const window_context&, std::int32_t, std::int32_t)> update;
|
||||
|
||||
window_context context{};
|
||||
std::int32_t sync_interval = 0;
|
||||
|
||||
window_data(std::string title, std::function<void(window_context&)> init,
|
||||
std::function<void(window_context&, std::int32_t, std::int32_t)> update, std::int32_t width = 640,
|
||||
window_data(std::string title, std::function<void(const window_context&)> init,
|
||||
std::function<void(const window_context&, std::int32_t, std::int32_t)> update, std::int32_t width = 640,
|
||||
std::int32_t height = 480):
|
||||
title(std::move(title)), width(width), height(height), init(std::move(init)), update(std::move(update))
|
||||
{}
|
||||
|
|
|
@ -18,13 +18,54 @@
|
|||
|
||||
namespace blt::gfx
|
||||
{
|
||||
|
||||
void fbo_t::create()
|
||||
void rbo_t::create()
|
||||
{
|
||||
glGenRenderbuffers(1, &rboID);
|
||||
}
|
||||
|
||||
void rbo_t::bind() const
|
||||
{
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, rboID);
|
||||
}
|
||||
|
||||
void rbo_t::unbind()
|
||||
{
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, 0);
|
||||
}
|
||||
|
||||
void rbo_t::destroy()
|
||||
{
|
||||
glDeleteRenderbuffers(1, &rboID);
|
||||
}
|
||||
|
||||
void rbo_t::updateStorage(blt::i32 width, blt::i32 height) const
|
||||
{
|
||||
glRenderbufferStorage(GL_RENDERBUFFER, storage_type, width, height);
|
||||
}
|
||||
|
||||
void rbo_t::setStorage(GLuint s_type, blt::i32 width, blt::i32 height)
|
||||
{
|
||||
storage_type = s_type;
|
||||
updateStorage(width, height);
|
||||
}
|
||||
|
||||
rbo_t rbo_t::make_render_buffer(GLuint storage_type, blt::i32 width, blt::i32 height)
|
||||
{
|
||||
rbo_t rbo{};
|
||||
rbo.create();
|
||||
rbo.bind();
|
||||
rbo.setStorage(storage_type, width, height);
|
||||
rbo_t::unbind();
|
||||
return rbo;
|
||||
}
|
||||
|
||||
void fbo_t::create(fbo_t::draw_t type)
|
||||
{
|
||||
generic_bind_type = static_cast<GLuint>(type);
|
||||
glGenFramebuffers(1, &fboID);
|
||||
}
|
||||
|
||||
void fbo_t::bind(fbo_draw_t type) const
|
||||
void fbo_t::bind(draw_t type) const
|
||||
{
|
||||
glBindFramebuffer(static_cast<GLuint>(type), fboID);
|
||||
}
|
||||
|
@ -36,11 +77,64 @@ namespace blt::gfx
|
|||
|
||||
void fbo_t::destroy()
|
||||
{
|
||||
|
||||
glDeleteFramebuffers(1, &fboID);
|
||||
for (auto& v : render_buffers)
|
||||
v.destroy();
|
||||
for (auto* texture : texture_buffers)
|
||||
delete texture;
|
||||
}
|
||||
|
||||
bool fbo_t::validate()
|
||||
{
|
||||
return glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE;
|
||||
}
|
||||
|
||||
void fbo_t::attachTexture(blt::gfx::texture_gl* texture, attachment_t attachment, int level)
|
||||
{
|
||||
texture_buffers.push_back(texture);
|
||||
glFramebufferTexture2D(generic_bind_type, static_cast<GLuint>(attachment), texture->getBindType(), texture->getTextureID(), level);
|
||||
}
|
||||
|
||||
void fbo_t::attachRenderBuffer(rbo_t rbo, fbo_t::attachment_t attachment)
|
||||
{
|
||||
rbo.bind();
|
||||
glFramebufferRenderbuffer(generic_bind_type, static_cast<GLuint>(attachment), GL_RENDERBUFFER, rbo.rboID);
|
||||
render_buffers.push_back(rbo);
|
||||
}
|
||||
|
||||
void fbo_t::updateBuffersStorage(blt::i32 width, blt::i32 height)
|
||||
{
|
||||
for (auto& rbo : render_buffers)
|
||||
{
|
||||
rbo.bind();
|
||||
rbo.updateStorage(width, height);
|
||||
}
|
||||
|
||||
for (auto& texture : texture_buffers)
|
||||
texture->updateSize(width, height);
|
||||
}
|
||||
|
||||
fbo_t fbo_t::make_render_texture(blt::i32 width, blt::i32 height)
|
||||
{
|
||||
fbo_t fbo;
|
||||
|
||||
fbo.create();
|
||||
fbo.bind();
|
||||
|
||||
auto* texture = new texture_gl2D(width, height);
|
||||
fbo.attachTexture(texture, attachment_t::COLOR0);
|
||||
|
||||
rbo_t depth_rbo;
|
||||
depth_rbo.create();
|
||||
depth_rbo.bind();
|
||||
depth_rbo.setStorage(GL_DEPTH24_STENCIL8, width, height);
|
||||
|
||||
fbo.attachRenderBuffer(depth_rbo, attachment_t::DEPTH_STENCIL);
|
||||
|
||||
if (!fbo_t::validate())
|
||||
BLT_ERROR("Failed to create render texture framebuffer!");
|
||||
fbo_t::unbind();
|
||||
|
||||
return fbo;
|
||||
}
|
||||
}
|
|
@ -43,8 +43,7 @@ namespace blt::gfx
|
|||
size_ = next_size;
|
||||
}
|
||||
|
||||
static_dynamic_array::static_dynamic_array()
|
||||
{}
|
||||
static_dynamic_array::static_dynamic_array() = default;
|
||||
|
||||
static_dynamic_array::vbo_type& static_dynamic_array::operator[](size_t index)
|
||||
{
|
||||
|
|
|
@ -143,7 +143,7 @@ namespace blt::gfx
|
|||
|
||||
void loop(void* arg)
|
||||
{
|
||||
const auto& data = *((const window_data*) arg);
|
||||
const auto& data = *((window_data*) arg);
|
||||
/* -- Get the current framebuffer size, update the global width/height state, along with OpenGL viewport -- */
|
||||
glfwGetFramebufferSize(window_state.window, &window_state.width, &window_state.height);
|
||||
glViewport(0, 0, window_state.width, window_state.height);
|
||||
|
@ -156,7 +156,7 @@ namespace blt::gfx
|
|||
ImGui::NewFrame();
|
||||
|
||||
/* -- Call user update function -- */
|
||||
data.update(window_state.width, window_state.height);
|
||||
data.update(data.context, window_state.width, window_state.height);
|
||||
|
||||
/* -- Render the ImGUI frame -- */
|
||||
ImGui::Render();
|
||||
|
@ -209,7 +209,7 @@ namespace blt::gfx
|
|||
glEnable(GL_MULTISAMPLE);
|
||||
|
||||
/* -- Call User Provided post-window-init function -- */
|
||||
data.init();
|
||||
data.init(data.context);
|
||||
|
||||
#ifdef __EMSCRIPTEN__
|
||||
/*
|
||||
|
|
Loading…
Reference in New Issue