/* * Copyright (C) 2024 Brett Terpstra * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include namespace blt::gfx { 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) { width_ = width; height_ = height; 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(type); glGenFramebuffers(1, &fboID); } void fbo_t::bind(draw_t type) const { glBindFramebuffer(static_cast(type), fboID); } void fbo_t::unbind() { glBindFramebuffer(GL_FRAMEBUFFER, 0); } 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(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(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); } void fbo_t::blitTexture(const fbo_t& draw, blt::i32 x1_offset, blt::i32 y1_offset, blt::i32 x2_offset, blt::i32 y2_offset) { 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].) } void fbo_t::blitDepth(fbo_t draw, blt::i32 x1_offset, blt::i32 y1_offset, blt::i32 x2_offset, blt::i32 y2_offset) { } 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; } }