diff --git a/CMakeLists.txt b/CMakeLists.txt index 472b3d1..f651bee 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 3.25) -set(BLT_GRAPHICS_VERSION 0.9.15) +set(BLT_GRAPHICS_VERSION 0.9.16) set(BLT_GRAPHICS_TEST_VERSION 0.0.1) project(BLT_WITH_GRAPHICS VERSION ${BLT_GRAPHICS_VERSION}) diff --git a/include/blt/gfx/framebuffer.h b/include/blt/gfx/framebuffer.h index 19e1781..512a272 100644 --- a/include/blt/gfx/framebuffer.h +++ b/include/blt/gfx/framebuffer.h @@ -53,6 +53,7 @@ namespace blt::gfx void setStorage(GLuint storage_type, blt::i32 width, blt::i32 height); void updateStorage(blt::i32 width, blt::i32 height); + void updateStorageMultiSampled(blt::i32 width, blt::i32 height, blt::i32 samples); static void unbind(); @@ -83,6 +84,7 @@ namespace blt::gfx GLuint generic_bind_type = GL_FRAMEBUFFER; std::vector texture_buffers; std::vector render_buffers; + blt::i32 width_ = -1, height_ = -1; public: // default used for fbo binding void create(draw_t bind_type = draw_t::BOTH); @@ -97,8 +99,9 @@ namespace blt::gfx // this function takes ownership of the render buffer void attachRenderBuffer(rbo_t rbo, attachment_t attachment); - void blitTexture(const fbo_t& draw, blt::i32 x1_offset = 0, blt::i32 y1_offset = 0, blt::i32 x2_offset = 0, blt::i32 y2_offset = 0); - void blitDepth(fbo_t draw, blt::i32 x1_offset = 0, blt::i32 y1_offset = 0, blt::i32 x2_offset = 0, blt::i32 y2_offset = 0); + void blitTexture(const fbo_t& draw, blt::i32 srcX_off = 0, blt::i32 srcY_off = 0, blt::i32 destX_off = 0, blt::i32 destY_off = 0, GLuint filter = GL_NEAREST) const; + void blitToScreen(blt::i32 width, blt::i32 height) const; + void blitDepth(const fbo_t& draw, blt::i32 srcX_off = 0, blt::i32 srcY_off = 0, blt::i32 destX_off = 0, blt::i32 destY_off = 0, GLuint filter = GL_NEAREST) const; static bool validate(); diff --git a/include/blt/gfx/texture.h b/include/blt/gfx/texture.h index 29d2152..d290430 100644 --- a/include/blt/gfx/texture.h +++ b/include/blt/gfx/texture.h @@ -182,12 +182,12 @@ namespace blt::gfx } }; - struct texture_gl2D : public texture_gl + struct texture_gl2D_base : public texture_gl { public: - explicit texture_gl2D(const texture_data& data); + texture_gl2D_base(const texture_data& data, GLint type, GLint colorMode = GL_RGBA8); - texture_gl2D(int width, int height, GLint colorMode = GL_RGBA8); + texture_gl2D_base(int width, int height, GLint type, GLint colorMode = GL_RGBA8); void upload(void* data, GLint dataColorMode = GL_RGBA, int level = 0, int x_offset = 0, int y_offset = 0, int sub_width = -1, int sub_height = -1, GLint dataMode = GL_UNSIGNED_BYTE) const; @@ -207,6 +207,28 @@ namespace blt::gfx void resize(int width, int height); }; + struct texture_gl2D : public texture_gl2D_base + { + public: + explicit texture_gl2D(const texture_data& data, GLint colorMode = GL_RGBA8): texture_gl2D_base(data, GL_TEXTURE_2D, colorMode) + {} + + texture_gl2D(int width, int height, GLint colorMode = GL_RGBA8): texture_gl2D_base(width, height, GL_TEXTURE_2D, colorMode) + {} + }; + + struct texture_gl2D_multisample : public texture_gl2D_base + { + public: + explicit texture_gl2D_multisample(const texture_data& data, GLint colorMode = GL_RGBA8): + texture_gl2D_base(data, GL_TEXTURE_2D_MULTISAMPLE, colorMode) + {} + + texture_gl2D_multisample(int width, int height, GLint colorMode = GL_RGBA8): + texture_gl2D_base(width, height, GL_TEXTURE_2D_MULTISAMPLE, colorMode) + {} + }; + struct gl_texture2D_array : public texture_gl { protected: diff --git a/src/blt/gfx/framebuffer.cpp b/src/blt/gfx/framebuffer.cpp index 079c177..63765c3 100644 --- a/src/blt/gfx/framebuffer.cpp +++ b/src/blt/gfx/framebuffer.cpp @@ -15,6 +15,7 @@ * along with this program. If not, see . */ #include +#include "blt/std/assert.h" namespace blt::gfx { @@ -45,6 +46,13 @@ namespace blt::gfx glRenderbufferStorage(GL_RENDERBUFFER, storage_type, width, height); } + void rbo_t::updateStorageMultiSampled(blt::i32 width, blt::i32 height, blt::i32 samples) + { + width_ = width; + height_ = height; + glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples, storage_type, width, height); + } + void rbo_t::setStorage(GLuint s_type, blt::i32 width, blt::i32 height) { storage_type = s_type; @@ -93,19 +101,33 @@ namespace blt::gfx void fbo_t::attachTexture(blt::gfx::texture_gl* texture, attachment_t attachment, int level) { + if (width_ == -1) + { + width_ = texture->getWidth(); + height_ = texture->getHeight(); + } else + BLT_ASSERT_MSG(width_ == texture->getWidth() && height_ == texture->getHeight(), "Please ensure attached textures are the same size!"); texture_buffers.push_back(texture); glFramebufferTexture2D(generic_bind_type, static_cast(attachment), texture->getBindType(), texture->getTextureID(), level); } void fbo_t::attachRenderBuffer(rbo_t rbo, fbo_t::attachment_t attachment) { + if (width_ == -1) + { + width_ = rbo.width_; + height_ = rbo.height_; + } else + BLT_ASSERT_MSG(width_ == rbo.width_ && height_ == rbo.height_, "Please ensure attached renderbuffer is the same size!"); rbo.bind(); - glFramebufferRenderbuffer(generic_bind_type, static_cast(attachment), GL_RENDERBUFFER, rbo.rboID); render_buffers.push_back(rbo); + glFramebufferRenderbuffer(generic_bind_type, static_cast(attachment), GL_RENDERBUFFER, rbo.rboID); } void fbo_t::updateBuffersStorage(blt::i32 width, blt::i32 height) { + width_ = width; + height_ = height; for (auto& rbo : render_buffers) { rbo.bind(); @@ -116,21 +138,18 @@ namespace blt::gfx texture->updateSize(width, height); } - void fbo_t::blitTexture(const fbo_t& draw, blt::i32 x1_offset, blt::i32 y1_offset, blt::i32 x2_offset, blt::i32 y2_offset) + void fbo_t::blitTexture(const fbo_t& draw, blt::i32 srcX, blt::i32 srcY, blt::i32 destX, blt::i32 destY, GLuint filter) const { - if (texture_buffers.empty()) - { - BLT_ERROR("Trying to blit texture with no texture attached!"); - return; - } glBindFramebuffer(GL_READ_FRAMEBUFFER, fboID); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, draw.fboID); - //glBlitFramebuffer(x1_offset, y1_offset, texture_buffers[0].) + glBlitFramebuffer(srcX, srcY, width_, height_, destX, destY, draw.width_, draw.height_, GL_COLOR_BUFFER_BIT, filter); } - void fbo_t::blitDepth(fbo_t draw, blt::i32 x1_offset, blt::i32 y1_offset, blt::i32 x2_offset, blt::i32 y2_offset) + void fbo_t::blitDepth(const fbo_t& draw, blt::i32 srcX, blt::i32 srcY, blt::i32 destX, blt::i32 destY, GLuint filter) const { - + glBindFramebuffer(GL_READ_FRAMEBUFFER, fboID); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, draw.fboID); + glBlitFramebuffer(srcX, srcY, width_, height_, destX, destY, draw.width_, draw.height_, GL_DEPTH_BUFFER_BIT, filter); } fbo_t fbo_t::make_render_texture(blt::i32 width, blt::i32 height) @@ -156,4 +175,11 @@ namespace blt::gfx return fbo; } + + void fbo_t::blitToScreen(blt::i32 width, blt::i32 height) const + { + glBindFramebuffer(GL_READ_FRAMEBUFFER, fboID); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); + glBlitFramebuffer(0, 0, width_, height_, 0, 0, width, height, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, GL_NEAREST); + } } \ No newline at end of file diff --git a/src/blt/gfx/texture.cpp b/src/blt/gfx/texture.cpp index 22a1782..08dc737 100644 --- a/src/blt/gfx/texture.cpp +++ b/src/blt/gfx/texture.cpp @@ -95,7 +95,7 @@ void blt::gfx::texture_gl::setDefaults() const #endif } -void blt::gfx::texture_gl2D::upload(void* data, GLint dataColorMode, int level, int x_offset, int y_offset, int sub_width, int sub_height, +void blt::gfx::texture_gl2D_base::upload(void* data, GLint dataColorMode, int level, int x_offset, int y_offset, int sub_width, int sub_height, GLint dataMode) const { if (sub_width < 0) @@ -108,12 +108,12 @@ void blt::gfx::texture_gl2D::upload(void* data, GLint dataColorMode, int level, unbind(); } -void blt::gfx::texture_gl2D::upload(const blt::gfx::texture_data& file_data) const +void blt::gfx::texture_gl2D_base::upload(const blt::gfx::texture_data& file_data) const { upload((void*)file_data.data(), file_data.channels() == 4 ? GL_RGBA : GL_RGB, 0, 0, 0, file_data.width(), file_data.height()); } -void blt::gfx::texture_gl2D::resize(int width, int height) +void blt::gfx::texture_gl2D_base::resize(int width, int height) { m_width = width; m_height = height; @@ -122,7 +122,7 @@ void blt::gfx::texture_gl2D::resize(int width, int height) unbind(); } -blt::gfx::texture_gl2D::texture_gl2D(int width, int height, GLint colorMode): texture_gl(width, height, GL_TEXTURE_2D, colorMode) +blt::gfx::texture_gl2D_base::texture_gl2D_base(int width, int height, GLint type, GLint colorMode): texture_gl(width, height, type, colorMode) { bind(); setDefaults(); @@ -131,11 +131,11 @@ blt::gfx::texture_gl2D::texture_gl2D(int width, int height, GLint colorMode): te glTexStorage2D(textureBindType, MIPMAP_LEVELS, colorMode, width, height); } -blt::gfx::texture_gl2D::texture_gl2D(const blt::gfx::texture_data& data): texture_gl(data.width(), data.height(), GL_TEXTURE_2D, GL_RGBA8) +blt::gfx::texture_gl2D_base::texture_gl2D_base(const blt::gfx::texture_data& data, GLint type, GLint colorMode): texture_gl(data.width(), data.height(), type, colorMode) { bind(); setDefaults(); - glTexStorage2D(textureBindType, 4, GL_RGBA8, data.width(), data.height()); + glTexStorage2D(textureBindType, 4, colorMode, data.width(), data.height()); upload((void*) data.data(), data.channels() == 4 ? GL_RGBA : GL_RGB, 0, 0, 0, data.width(), data.height()); bind(); //glTexImage2D(textureBindType, 0, GL_RGBA, data.width(), data.height(), 0, data.channels() == 4 ? GL_RGBA : GL_RGB, GL_UNSIGNED_BYTE, (void*)data.data()); @@ -143,7 +143,7 @@ blt::gfx::texture_gl2D::texture_gl2D(const blt::gfx::texture_data& data): textur unbind(); } -void blt::gfx::texture_gl2D::upload(void* data, int width, int height, GLint dataColorMode, GLint dataMode) +void blt::gfx::texture_gl2D_base::upload(void* data, int width, int height, GLint dataColorMode, GLint dataMode) { bind(); glTexImage2D(textureBindType, 0, textureColorMode, width, height, 0, dataColorMode, dataMode, data);