From 561ea8cf8b9979636c1fbfe6f20fba5d12ed87dc Mon Sep 17 00:00:00 2001 From: Kai Blaschke Date: Sat, 9 Sep 2023 15:45:07 +0200 Subject: [PATCH] Added methods to Framebuffer class to add externally created texture attachments and remove existing ones. --- src/libprojectM/Renderer/Framebuffer.cpp | 84 ++++++++++++++++++++---- src/libprojectM/Renderer/Framebuffer.hpp | 46 ++++++++++++- 2 files changed, 117 insertions(+), 13 deletions(-) diff --git a/src/libprojectM/Renderer/Framebuffer.cpp b/src/libprojectM/Renderer/Framebuffer.cpp index 7478c47d5..7e0745da7 100644 --- a/src/libprojectM/Renderer/Framebuffer.cpp +++ b/src/libprojectM/Renderer/Framebuffer.cpp @@ -87,8 +87,8 @@ bool Framebuffer::SetSize(int width, int height) Bind(attachments.first); for (auto& texture : attachments.second) { - texture.second.SetSize(width, height); - glFramebufferTexture2D(GL_FRAMEBUFFER, texture.first, GL_TEXTURE_2D, texture.second.Texture()->TextureID(), 0); + texture.second->SetSize(width, height); + glFramebufferTexture2D(GL_FRAMEBUFFER, texture.first, GL_TEXTURE_2D, texture.second->Texture()->TextureID(), 0); } } glBindFramebuffer(GL_FRAMEBUFFER, 0); @@ -96,6 +96,39 @@ bool Framebuffer::SetSize(int width, int height) return true; } +void Framebuffer::SetAttachment(int framebufferIndex, int attachmentIndex, const std::shared_ptr& attachment) +{ + if (!attachment) + { + return; + } + + GLenum textureType; + Bind(framebufferIndex); + switch (attachment->Type()) + { + case TextureAttachment::AttachmentType::Color: + textureType = GL_COLOR_ATTACHMENT0 + attachmentIndex; + break; + case TextureAttachment::AttachmentType::Depth: + textureType = GL_DEPTH_ATTACHMENT; + break; + case TextureAttachment::AttachmentType::Stencil: + textureType = GL_STENCIL_ATTACHMENT; + break; + case TextureAttachment::AttachmentType::DepthStencil: + textureType = GL_DEPTH_STENCIL_ATTACHMENT; + break; + } + m_attachments.at(framebufferIndex).insert({textureType, attachment}); + if (m_width > 0 && m_height > 0) + { + glFramebufferTexture2D(GL_FRAMEBUFFER, textureType, GL_TEXTURE_2D, attachment->Texture()->TextureID(), 0); + } + UpdateDrawBuffers(framebufferIndex); + glBindFramebuffer(GL_FRAMEBUFFER, 0); +} + void Framebuffer::CreateColorAttachment(int framebufferIndex, int attachmentIndex) { CreateColorAttachment(framebufferIndex, attachmentIndex, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE); @@ -108,8 +141,8 @@ void Framebuffer::CreateColorAttachment(int framebufferIndex, int attachmentInde return; } - TextureAttachment textureAttachment{internalFormat, format, type, m_width, m_height }; - const auto texture = textureAttachment.Texture(); + auto textureAttachment = std::make_shared(internalFormat, format, type, m_width, m_height); + const auto texture = textureAttachment->Texture(); m_attachments.at(framebufferIndex).insert({GL_COLOR_ATTACHMENT0 + attachmentIndex, std::move(textureAttachment)}); Bind(framebufferIndex); @@ -121,6 +154,11 @@ void Framebuffer::CreateColorAttachment(int framebufferIndex, int attachmentInde glBindFramebuffer(GL_FRAMEBUFFER, 0); } +void Framebuffer::RemoveColorAttachment(int framebufferIndex, int attachmentIndex) +{ + RemoveAttachment(framebufferIndex, GL_COLOR_ATTACHMENT0 + attachmentIndex); +} + auto Framebuffer::GetColorAttachmentTexture(int framebufferIndex, int attachmentIndex) const -> std::shared_ptr { if (framebufferIndex < 0 || framebufferIndex >= static_cast(m_framebufferIds.size())) @@ -134,7 +172,7 @@ auto Framebuffer::GetColorAttachmentTexture(int framebufferIndex, int attachment return {}; } - return attachment.at(GL_COLOR_ATTACHMENT0 + attachmentIndex).Texture(); + return attachment.at(GL_COLOR_ATTACHMENT0 + attachmentIndex)->Texture(); } void Framebuffer::CreateDepthAttachment(int framebufferIndex) @@ -144,8 +182,8 @@ void Framebuffer::CreateDepthAttachment(int framebufferIndex) return; } - TextureAttachment textureAttachment{TextureAttachment::AttachmentType::Depth, m_width, m_height}; - const auto texture = textureAttachment.Texture(); + auto textureAttachment = std::make_shared(TextureAttachment::AttachmentType::Depth, m_width, m_height); + const auto texture = textureAttachment->Texture(); m_attachments.at(framebufferIndex).insert({GL_DEPTH_ATTACHMENT, std::move(textureAttachment)}); Bind(framebufferIndex); @@ -157,6 +195,11 @@ void Framebuffer::CreateDepthAttachment(int framebufferIndex) glBindFramebuffer(GL_FRAMEBUFFER, 0); } +void Framebuffer::RemoveDepthAttachment(int framebufferIndex) +{ + RemoveAttachment(framebufferIndex, GL_DEPTH_ATTACHMENT); +} + void Framebuffer::CreateStencilAttachment(int framebufferIndex) { if (framebufferIndex < 0 || framebufferIndex >= static_cast(m_framebufferIds.size())) @@ -164,8 +207,8 @@ void Framebuffer::CreateStencilAttachment(int framebufferIndex) return; } - TextureAttachment textureAttachment{TextureAttachment::AttachmentType::Stencil, m_width, m_height}; - const auto texture = textureAttachment.Texture(); + auto textureAttachment = std::make_shared(TextureAttachment::AttachmentType::Stencil, m_width, m_height); + const auto texture = textureAttachment->Texture(); m_attachments.at(framebufferIndex).insert({GL_STENCIL_ATTACHMENT, std::move(textureAttachment)}); Bind(framebufferIndex); @@ -177,6 +220,11 @@ void Framebuffer::CreateStencilAttachment(int framebufferIndex) glBindFramebuffer(GL_FRAMEBUFFER, 0); } +void Framebuffer::RemoveStencilAttachment(int framebufferIndex) +{ + RemoveAttachment(framebufferIndex, GL_STENCIL_ATTACHMENT); +} + void Framebuffer::CreateDepthStencilAttachment(int framebufferIndex) { if (framebufferIndex < 0 || framebufferIndex >= static_cast(m_framebufferIds.size())) @@ -184,8 +232,8 @@ void Framebuffer::CreateDepthStencilAttachment(int framebufferIndex) return; } - TextureAttachment textureAttachment{TextureAttachment::AttachmentType::DepthStencil, m_width, m_height}; - const auto texture = textureAttachment.Texture(); + auto textureAttachment = std::make_shared(TextureAttachment::AttachmentType::DepthStencil, m_width, m_height); + const auto texture = textureAttachment->Texture(); m_attachments.at(framebufferIndex).insert({GL_DEPTH_STENCIL_ATTACHMENT, std::move(textureAttachment)}); Bind(framebufferIndex); @@ -197,6 +245,11 @@ void Framebuffer::CreateDepthStencilAttachment(int framebufferIndex) glBindFramebuffer(GL_FRAMEBUFFER, 0); } +void Framebuffer::RemoveDepthStencilAttachment(int framebufferIndex) +{ + RemoveAttachment(framebufferIndex, GL_DEPTH_STENCIL_ATTACHMENT); +} + void Framebuffer::MaskDrawBuffer(int bufferIndex, bool masked) { // Invert the flag, as "true" means the color channel *will* be written. @@ -265,3 +318,12 @@ void Framebuffer::UpdateDrawBuffers(int framebufferIndex) glDrawBuffers(static_cast(buffers.size()), buffers.data()); } + +void Framebuffer::RemoveAttachment(int framebufferIndex, GLenum attachmentType) +{ + m_attachments.at(framebufferIndex).erase(attachmentType); + Bind(framebufferIndex); + glFramebufferTexture2D(GL_FRAMEBUFFER, attachmentType, GL_TEXTURE_2D, 0, 0); + UpdateDrawBuffers(framebufferIndex); + glBindFramebuffer(GL_FRAMEBUFFER, 0); +} diff --git a/src/libprojectM/Renderer/Framebuffer.hpp b/src/libprojectM/Renderer/Framebuffer.hpp index 9d304a192..931edd0bd 100644 --- a/src/libprojectM/Renderer/Framebuffer.hpp +++ b/src/libprojectM/Renderer/Framebuffer.hpp @@ -93,11 +93,20 @@ public: */ bool SetSize(int width, int height); + /** + * @brief Sets a texture attachment slot to the given object. + * @param framebufferIndex The framebuffer index. + * @param attachmentIndex The index of the color attachment, at least indices 0-7 are guaranteed + * to be available. Ignored for non-color attachments. + * @param attachment The attachment to add to the framebuffer. + */ + void SetAttachment(int framebufferIndex, int attachmentIndex, const std::shared_ptr& attachment); + /** * @brief Adds a new color attachment to the framebuffer. * The texture is always created in RGBA format. * @param framebufferIndex The framebuffer index. - * @param index The index of the attachment, at least indices 0-7 are guaranteed to be available. + * @param attachmentIndex The index of the attachment, at least indices 0-7 are guaranteed to be available. */ void CreateColorAttachment(int framebufferIndex, int attachmentIndex); @@ -112,6 +121,13 @@ public: void CreateColorAttachment(int framebufferIndex, int attachmentIndex, GLint internalFormat, GLenum format, GLenum type); + /** + * Removes the color attachment from the given slot, if there is any assigned. + * @param framebufferIndex The framebuffer index. + * @param attachmentIndex The index of the attachment to remove, at least indices 0-7 are guaranteed to be available. + */ + void RemoveColorAttachment(int framebufferIndex, int attachmentIndex); + /** * @brief Returns the texture ID of the given framebuffer and color attachment. * @param framebufferIndex The framebuffer index. @@ -126,21 +142,40 @@ public: */ void CreateDepthAttachment(int framebufferIndex); + /** + * @brief Removes the depth attachment from the given framebuffer, if there is any assigned. + * @param framebufferIndex The framebuffer index. + */ + void RemoveDepthAttachment(int framebufferIndex); + /** * @brief Adds a stencil buffer attachment to the framebuffer. * @param framebufferIndex The framebuffer index. */ void CreateStencilAttachment(int framebufferIndex); + /** + * @brief Removes the stencil attachment from the given framebuffer, if there is any assigned. + * @param framebufferIndex The framebuffer index. + */ + void RemoveStencilAttachment(int framebufferIndex); + /** * @brief Adds a depth stencil buffer attachment to the framebuffer. * @param framebufferIndex The framebuffer index. */ void CreateDepthStencilAttachment(int framebufferIndex); + /** + * @brief Removes the depth stencil attachment from the given framebuffer, if there is any assigned. + * @param framebufferIndex The framebuffer index. + */ + void RemoveDepthStencilAttachment(int framebufferIndex); + /** * @brief Sets the masked flag for a specific draw buffer. * This can be used to enable or disable rendering to specific color attachments. + * With GLES 3.1 and lower, this will always mask all buffers. * @param bufferIndex The index of the buffer to set the mask flag on. * @param masked true if the attachment should be masked, false if not. */ @@ -154,7 +189,14 @@ private: */ void UpdateDrawBuffers(int framebufferIndex); - using AttachmentsPerSlot = std::map; + /** + * @brief Removes the given attachment type from the framebuffer. + * @param framebufferIndex The framebuffer index. + * @param attachmentType The attachment type to remove. + */ + void RemoveAttachment(int framebufferIndex, GLenum attachmentType); + + using AttachmentsPerSlot = std::map>; std::vector m_framebufferIds{}; //!< The framebuffer IDs returned by OpenGL std::map m_attachments; //!< Framebuffer texture attachments.