From f4fb9b5e7d94d0c1d2f5a3e54fe618b5c2fd57e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sun, 1 Apr 2012 03:52:24 +0200 Subject: [PATCH] Classes for managing framebuffer. --- src/CMakeLists.txt | 2 + src/Framebuffer.cpp | 40 +++++ src/Framebuffer.h | 370 +++++++++++++++++++++++++++++++++++++++++++ src/Renderbuffer.cpp | 52 ++++++ src/Renderbuffer.h | 155 ++++++++++++++++++ 5 files changed, 619 insertions(+) create mode 100644 src/Framebuffer.cpp create mode 100644 src/Framebuffer.h create mode 100644 src/Renderbuffer.cpp create mode 100644 src/Renderbuffer.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index d19f11ebf..5eaaa6119 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -14,9 +14,11 @@ set(Magnum_SRCS BufferedImage.cpp Camera.cpp Image.cpp + Framebuffer.cpp IndexedMesh.cpp Light.cpp Mesh.cpp + Renderbuffer.cpp Scene.cpp Shader.cpp SizeTraits.cpp diff --git a/src/Framebuffer.cpp b/src/Framebuffer.cpp new file mode 100644 index 000000000..0770dcd76 --- /dev/null +++ b/src/Framebuffer.cpp @@ -0,0 +1,40 @@ +/* + Copyright © 2010, 2011, 2012 Vladimír Vondruš + + This file is part of Magnum. + + Magnum is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License version 3 + only, as published by the Free Software Foundation. + + Magnum 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 Lesser General Public License version 3 for more details. +*/ + +#include "Framebuffer.h" + +namespace Magnum { + +void Framebuffer::mapDefaultForDraw(std::initializer_list attachments) { + GLenum* _attachments = new GLenum[attachments.size()]; + for(auto it = attachments.begin(); it != attachments.end(); ++it) + _attachments[it-attachments.begin()] = static_cast(*it); + + bindDefault(Target::Draw); + glDrawBuffers(attachments.size(), _attachments); + delete[] _attachments; +} + +void Framebuffer::mapForDraw(std::initializer_list colorAttachments) { + GLenum* attachments = new GLenum[colorAttachments.size()]; + for(auto it = colorAttachments.begin(); it != colorAttachments.end(); ++it) + attachments[it-colorAttachments.begin()] = *it + GL_COLOR_ATTACHMENT0; + + bind(Target::Draw); + glDrawBuffers(colorAttachments.size(), attachments); + delete[] attachments; +} + +} diff --git a/src/Framebuffer.h b/src/Framebuffer.h new file mode 100644 index 000000000..b3690203b --- /dev/null +++ b/src/Framebuffer.h @@ -0,0 +1,370 @@ +#ifndef Magnum_Framebuffer_h +#define Magnum_Framebuffer_h +/* + Copyright © 2010, 2011, 2012 Vladimír Vondruš + + This file is part of Magnum. + + Magnum is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License version 3 + only, as published by the Free Software Foundation. + + Magnum 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 Lesser General Public License version 3 for more details. +*/ + +/** @file + * @brief Class Magnum::Framebuffer + */ + +#include "CubeMapTexture.h" +#include "Renderbuffer.h" + +namespace Magnum { + +/** +@brief Framebuffer +*/ +class MAGNUM_EXPORT Framebuffer { + Framebuffer(const Framebuffer& other) = delete; + Framebuffer(Framebuffer&& other) = delete; + Framebuffer& operator=(const Framebuffer& other) = delete; + Framebuffer& operator=(Framebuffer&& other) = delete; + + public: + /** @brief %Framebuffer target */ + enum class Target: GLenum { + Read = GL_READ_FRAMEBUFFER, /**< For reading only. */ + Draw = GL_DRAW_FRAMEBUFFER, /**< For drawing only. */ + ReadDraw = GL_FRAMEBUFFER /**< For both reading and drawing. */ + }; + + /** @brief Draw attachment for default framebuffer */ + enum class DefaultDrawAttachment: GLenum { + None = GL_NONE, /**< Don't use the output. */ + BackLeft = GL_BACK_LEFT, /**< Write output to back left framebuffer. */ + BackRight = GL_BACK_RIGHT, /**< Write output to back right framebuffer. */ + FrontLeft = GL_FRONT_LEFT, /**< Write output to front left framebuffer. */ + FrontRight = GL_FRONT_RIGHT /**< Write output to front right framebuffer. */ + }; + + /** @brief Read attachment for default framebuffer */ + enum class DefaultReadAttachment: GLenum { + FrontLeft = GL_FRONT_LEFT, /**< Read from front left framebuffer. */ + FrontRight = GL_FRONT_RIGHT, /**< Read from front right framebuffer. */ + BackLeft = GL_BACK_LEFT, /**< Read from back left framebuffer. */ + BackRight = GL_BACK_RIGHT, /**< Read from back right framebuffer. */ + Left = GL_LEFT, /**< Read from left framebuffers. */ + Right = GL_RIGHT, /**< Read from right framebuffers. */ + Front = GL_FRONT, /**< Read from front framebuffers. */ + Back = GL_BACK, /**< Read from back framebuffers. */ + FrontAndBack = GL_FRONT_AND_BACK /**< Read from front and back framebuffers. */ + }; + + /** @brief Attachment for depth/stencil part of fragment shader output */ + enum class DepthStencilAttachment: GLenum { + Depth = GL_DEPTH_ATTACHMENT, /**< Depth output only. */ + Stencil = GL_STENCIL_ATTACHMENT, /**< Stencil output only. */ + DepthStencil = GL_DEPTH_STENCIL_ATTACHMENT /**< Both depth and stencil output. */ + }; + + /** + * @brief Output mask for blitting + * + * Specifies which data are copied when performing blit operation + * using blit(). + */ + enum class BlitMask: GLbitfield { + Color = GL_COLOR_BUFFER_BIT, /**< Color only. */ + Depth = GL_DEPTH_BUFFER_BIT, /**< Depth value only. */ + Stencil = GL_STENCIL_BUFFER_BIT, /**< Stencil value only. */ + + /** Color and depth value. */ + ColorDepth = GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT, + + /** Color and stencil value. */ + ColorStencil = GL_COLOR_BUFFER_BIT|GL_STENCIL_BUFFER_BIT, + + /** Depth and stencil value */ + DepthStencil = GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT, + + /** Color, depth and stencil value. */ + ColorDepthStencil = GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT + }; + + /** + * @brief Bind default framebuffer to given target + * @param target %Target + */ + inline static void bindDefault(Target target) { + glBindFramebuffer(static_cast(target), 0); + } + + /** + * @brief Map given attachments of default framebuffer for drawing + * @param attachments Default attachments. If any value is + * DefaultAttachment::None, given output is not used. + * + * If used for mapping output of fragment shader, the order must be as + * specified by the shader (see AbstractShaderProgram documentation). + * If used for blit(), the order is not important. Each used attachment + * should have either renderbuffer or texture attached for writing to + * work properly. + * @see mapForDraw(), mapDefaultForRead() + */ + static void mapDefaultForDraw(std::initializer_list attachments); + + /** + * @brief Map given attachment of default framebuffer for reading + * @param attachment Default attachment + * + * Each used attachment should have either renderbuffer or texture + * attached to work properly. + * @see mapForRead(), mapDefaultForDraw() + */ + inline static void mapDefaultForRead(DefaultReadAttachment attachment) { + bindDefault(Target::Read); + glReadBuffer(static_cast(attachment)); + } + + /** + * @brief Copy block of pixels from read to draw framebuffer + * @param bottomLeft Bottom left coordinates of source rectangle + * @param topRight Top right coordinates of source rectangle + * @param destinationBottomLeft Bottom left coordinates of destination rectangle + * @param destinationTopRight Top right coordinates of destination + * rectangle + * @param blitMask Blit mask + * @param filter Interpolation applied if the image is + * stretched + * + * See mapForRead() / mapDefaultForRead() and mapForDraw() / + * mapDefaultForDraw() for binding particular framebuffer for reading + * and drawing. If multiple attachments are specified in mapForDraw() + * / mapDefaultForDraw(), the data are written to each of them. + */ + inline static void blit(const Math::Vector2& bottomLeft, const Math::Vector2& topRight, const Math::Vector2& destinationBottomLeft, const Math::Vector2& destinationTopRight, BlitMask blitMask, AbstractTexture::Filter filter) { + glBlitFramebuffer(bottomLeft.x(), bottomLeft.y(), topRight.x(), topRight.y(), destinationBottomLeft.x(), destinationBottomLeft.y(), destinationTopRight.x(), destinationTopRight.y(), static_cast(blitMask), static_cast(filter)); + } + + /** + * @brief Copy block of pixels from read to draw framebuffer + * @param bottomLeft Bottom left coordinates of source and + * destination rectangle + * @param topRight Top right coordinates of source and + * destination rectangle + * @param blitMask Blit mask + * + * Convenience function when source rectangle is the same as + * destination rectangle. As the image is copied pixel-by-pixel, + * no interpolation is needed and thus + * AbstractTexture::Filter::NearestNeighbor filtering is used by + * default. + */ + inline static void blit(const Math::Vector2& bottomLeft, const Math::Vector2& topRight, BlitMask blitMask) { + glBlitFramebuffer(bottomLeft.x(), bottomLeft.y(), topRight.x(), topRight.y(), bottomLeft.x(), bottomLeft.y(), topRight.x(), topRight.y(), static_cast(blitMask), static_cast(AbstractTexture::Filter::NearestNeighbor)); + } + + /** + * @brief Constructor + * + * Generates new OpenGL framebuffer. + */ + inline Framebuffer() { glGenFramebuffers(1, &framebuffer); } + + /** + * @brief Destructor + * + * Deletes associated OpenGL framebuffer. + */ + inline ~Framebuffer() { glDeleteFramebuffers(1, &framebuffer); } + + /** @brief Bind framebuffer */ + inline void bind(Target target) { + glBindFramebuffer(static_cast(target), framebuffer); + } + + /** + * @brief Map given color attachments of current framebuffer for drawing + * @param colorAttachments Color attachment IDs. If any value is -1, + * given output is not used. + * + * If used for mapping output of fragment shader, the order must be as + * specified by the shader (see AbstractShaderProgram documentation). + * If used for blit(), the order is not important. Each used attachment + * should have either renderbuffer or texture attached for writing to + * work properly. + * @see mapDefaultForDraw(), mapForRead() + */ + void mapForDraw(std::initializer_list colorAttachments); + + /** + * @brief Map given color attachment of current framebuffer for reading + * @param colorAttachment Color attachment ID + * + * The color attachment should have either renderbuffer or texture + * attached for reading to work properly. + * @see mapDefaultForRead(), mapForDraw() + */ + inline void mapForRead(unsigned int colorAttachment) { + bind(Target::Read); + glReadBuffer(GL_COLOR_ATTACHMENT0 + colorAttachment); + } + + /** + * @brief Attach renderbuffer to given framebuffer depth/stencil attachment + * @param target %Target + * @param depthStencilAttachment Depth/stencil attachment + * @param renderbuffer Renderbuffer + */ + inline void attachRenderbuffer(Target target, DepthStencilAttachment depthStencilAttachment, Renderbuffer* renderbuffer) { + /** @todo Check for internal format compatibility */ + bind(target); + glFramebufferRenderbuffer(static_cast(target), static_cast(depthStencilAttachment), GL_RENDERBUFFER, renderbuffer->id()); + } + + /** + * @brief Attach renderbuffer to given framebuffer color attachment + * @param target %Target + * @param colorAttachment Color attachment ID (number between 0 and 15) + * @param renderbuffer Renderbuffer + */ + inline void attachRenderbuffer(Target target, unsigned int colorAttachment, Renderbuffer* renderbuffer) { + /** @todo Check for internal format compatibility */ + bind(target); + glFramebufferRenderbuffer(static_cast(target), GL_COLOR_ATTACHMENT0 + colorAttachment, GL_RENDERBUFFER, renderbuffer->id()); + } + + /** + * @brief Attach 1D texture to given framebuffer depth/stencil attachment + * @param target %Target + * @param depthStencilAttachment Depth/stencil attachment + * @param texture 1D texture + * @param mipLevel Mip level + */ + inline void attachTexture1D(Target target, DepthStencilAttachment depthStencilAttachment, Texture1D* texture, GLint mipLevel) { + /** @todo Check for internal format compatibility */ + /** @todo Check for texture target compatibility */ + bind(target); + glFramebufferTexture1D(static_cast(target), static_cast(depthStencilAttachment), static_cast(texture->target()), texture->id(), mipLevel); + } + + /** + * @brief Attach 1D texture to given framebuffer color attachment + * @param target %Target + * @param colorAttachment Color attachment ID (number between 0 and 15) + * @param texture 1D texture + * @param mipLevel Mip level + */ + inline void attachTexture1D(Target target, unsigned int colorAttachment, Texture1D* texture, GLint mipLevel) { + /** @todo Check for internal format compatibility */ + /** @todo Check for texture target compatibility */ + bind(target); + glFramebufferTexture1D(static_cast(target), GL_COLOR_ATTACHMENT0 + colorAttachment, static_cast(texture->target()), texture->id(), mipLevel); + } + + /** + * @brief Attach 2D texture to given framebuffer depth/stencil attachment + * @param target %Target + * @param depthStencilAttachment Depth/stencil attachment + * @param texture 2D texture + * @param mipLevel Mip level. For rectangle textures it + * should be always 0. + * + * @see attachCubeMapTexture() + */ + inline void attachTexture2D(Target target, DepthStencilAttachment depthStencilAttachment, Texture2D* texture, GLint mipLevel) { + /** @todo Check for internal format compatibility */ + /** @todo Check for texture target compatibility */ + bind(target); + glFramebufferTexture2D(static_cast(target), static_cast(depthStencilAttachment), static_cast(texture->target()), texture->id(), mipLevel); + } + + /** + * @brief Attach 2D texture to given framebuffer color attachment + * @param target %Target + * @param colorAttachment Color attachment ID (number between 0 and 15) + * @param texture 2D texture + * @param mipLevel Mip level. For rectangle textures it + * should be always 0. + * + * @see attachCubeMapTexture() + */ + inline void attachTexture2D(Target target, unsigned int colorAttachment, Texture2D* texture, GLint mipLevel) { + /** @todo Check for internal format compatibility */ + /** @todo Check for texture target compatibility */ + bind(target); + glFramebufferTexture2D(static_cast(target), GL_COLOR_ATTACHMENT0 + colorAttachment, static_cast(texture->target()), texture->id(), mipLevel); + } + + /** + * @brief Attach cube map texture to given framebuffer depth/stencil attachment + * @param target %Target + * @param depthStencilAttachment Depth/stencil attachment + * @param texture Cube map texture + * @param coordinate Cube map coordinate + * @param mipLevel Mip level + * + * @see attachTexture2D() + */ + inline void attachCubeMapTexture(Target target, DepthStencilAttachment depthStencilAttachment, CubeMapTexture* texture, CubeMapTexture::Coordinate coordinate, GLint mipLevel) { + /** @todo Check for internal format compatibility */ + bind(target); + glFramebufferTexture2D(static_cast(target), static_cast(depthStencilAttachment), static_cast(coordinate), texture->id(), mipLevel); + } + + /** + * @brief Attach cube map texture to given framebuffer color attachment + * @param target %Target + * @param colorAttachment Color attachment ID (number between 0 and 15) + * @param texture Cube map texture + * @param coordinate Cube map coordinate + * @param mipLevel Mip level + * + * @see attachTexture2D() + */ + inline void attachCubeMapTexture(Target target, unsigned int colorAttachment, CubeMapTexture* texture, CubeMapTexture::Coordinate coordinate, GLint mipLevel) { + /** @todo Check for internal format compatibility */ + bind(target); + glFramebufferTexture2D(static_cast(target), GL_COLOR_ATTACHMENT0 + colorAttachment, static_cast(coordinate), texture->id(), mipLevel); + } + + /** + * @brief Attach 3D texture to given framebuffer depth/stencil attachment + * @param target %Target + * @param depthStencilAttachment Depth/stencil attachment + * @param texture 3D texture + * @param mipLevel Mip level + * @param layer Layer of 2D image within a 3D texture + */ + inline void attachTexture3D(Target target, DepthStencilAttachment depthStencilAttachment, Texture3D* texture, GLint mipLevel, GLint layer) { + /** @todo Check for internal format compatibility */ + /** @todo Check for texture target compatibility */ + bind(target); + glFramebufferTexture3D(static_cast(target), static_cast(depthStencilAttachment), static_cast(texture->target()), texture->id(), mipLevel, layer); + } + + /** + * @brief Attach 3D texture to given framebuffer color attachment + * @param target %Target + * @param colorAttachment Color attachment ID (number between 0 and 15) + * @param texture 3D texture + * @param mipLevel Mip level + * @param layer Layer of 2D image within a 3D texture. + */ + inline void attachTexture3D(Target target, unsigned int colorAttachment, Texture3D* texture, GLint mipLevel, GLint layer) { + /** @todo Check for internal format compatibility */ + /** @todo Check for texture target compatibility */ + bind(target); + glFramebufferTexture3D(static_cast(target), GL_COLOR_ATTACHMENT0 + colorAttachment, static_cast(texture->target()), texture->id(), mipLevel, layer); + } + + private: + GLuint framebuffer; +}; + +} + +#endif diff --git a/src/Renderbuffer.cpp b/src/Renderbuffer.cpp new file mode 100644 index 000000000..b0b2f30e6 --- /dev/null +++ b/src/Renderbuffer.cpp @@ -0,0 +1,52 @@ +/* + Copyright © 2010, 2011, 2012 Vladimír Vondruš + + This file is part of Magnum. + + Magnum is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License version 3 + only, as published by the Free Software Foundation. + + Magnum 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 Lesser General Public License version 3 for more details. +*/ + +#include "Renderbuffer.h" + +namespace Magnum { + +Renderbuffer::InternalFormat::InternalFormat(Components components, ComponentType type) { + #define internalFormatSwitch(c) switch(type) { \ + case ComponentType::UnsignedByte: \ + internalFormat = GL_##c##8UI; break; \ + case ComponentType::Byte: \ + internalFormat = GL_##c##8I; break; \ + case ComponentType::UnsignedShort: \ + internalFormat = GL_##c##16UI; break; \ + case ComponentType::Short: \ + internalFormat = GL_##c##16I; break; \ + case ComponentType::UnsignedInt: \ + internalFormat = GL_##c##32UI; break; \ + case ComponentType::Int: \ + internalFormat = GL_##c##32I; break; \ + case ComponentType::Half: \ + internalFormat = GL_##c##16F; break; \ + case ComponentType::Float: \ + internalFormat = GL_##c##32F; break; \ + case ComponentType::NormalizedUnsignedByte: \ + internalFormat = GL_##c##8; break; \ + case ComponentType::NormalizedUnsignedShort: \ + internalFormat = GL_##c##16; break; \ + } + if(components == Components::Red) + internalFormatSwitch(R) + else if(components == Components::RedGreen) + internalFormatSwitch(RG) + else if(components == Components::RGBA) + internalFormatSwitch(RGBA) + #undef internalFormatSwitch +} + +} diff --git a/src/Renderbuffer.h b/src/Renderbuffer.h new file mode 100644 index 000000000..ba77749d7 --- /dev/null +++ b/src/Renderbuffer.h @@ -0,0 +1,155 @@ +#ifndef Magnum_Renderbuffer_h +#define Magnum_Renderbuffer_h +/* + Copyright © 2010, 2011, 2012 Vladimír Vondruš + + This file is part of Magnum. + + Magnum is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License version 3 + only, as published by the Free Software Foundation. + + Magnum 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 Lesser General Public License version 3 for more details. +*/ + +/** @file + * @brief Class Magnum::Renderbuffer + */ + +#include "Magnum.h" + +namespace Magnum { + +/** +@brief Renderbuffer + +Attachable to Framebuffer as render target. +*/ +class Renderbuffer { + Renderbuffer(const Renderbuffer& other) = delete; + Renderbuffer(Renderbuffer&& other) = delete; + Renderbuffer& operator=(const Renderbuffer& other) = delete; + Renderbuffer& operator=(Renderbuffer&& other) = delete; + + public: + /** @{ @name Internal renderbuffer formats */ + + /** + * @copydoc AbstractTexture::Components + * + * Like AbstractTexture::Components, without three-component RGB. + */ + enum class Components { + Red, RedGreen, RGBA + }; + + /** + * @copydoc AbstractTexture::ComponentType + * + * Like AbstractTexture::ComponentType, without normalized signed + * types. + */ + enum class ComponentType { + UnsignedByte, Byte, UnsignedShort, Short, UnsignedInt, Int, Half, + Float, NormalizedUnsignedByte, NormalizedUnsignedShort + }; + + /** + * @copydoc AbstractTexture::Format + * + * Like AbstractTexture::Format without + * AbstractTexture::Format::RGB9Intensity5, three-component and + * compressed formats. + */ + enum class Format: GLenum { + Red = GL_RED, RedGreen = GL_RG, RGBA = GL_RGBA, BGRA = GL_BGRA, + SRGBA = GL_SRGB8_ALPHA8, + RGB10Alpha2 = GL_RGB10_A2, RGB10AlphaUnsigned2 = GL_RGB10_A2UI, + RGB5Alpha1 = GL_RGB5_A1, RGBA4 = GL_RGBA4, + RFloat11GFloat11BFloat10 = GL_R11F_G11F_B10F, + + #if defined(GL_RGB565) || defined(DOXYGEN_GENERATING_OUTPUT) + RGB565 = GL_RGB565, + #endif + + Depth = GL_DEPTH_COMPONENT, DepthStencil = GL_DEPTH_STENCIL, + Depth16 = GL_DEPTH_COMPONENT16, Depth24 = GL_DEPTH_COMPONENT24, + DepthFloat = GL_DEPTH_COMPONENT32F, + Depth24Stencil8 = GL_DEPTH24_STENCIL8, + DepthFloatStencil8 = GL_DEPTH32F_STENCIL8 + }; + + /** @copydoc AbstractTexture::InternalFormat */ + class InternalFormat { + public: + /** @copydoc AbstractTexture::InternalFormat::InternalFormat(AbstractTexture::Components, AbstractTexture::ComponentType) */ + InternalFormat(Components components, ComponentType type); + + /** @copydoc AbstractTexture::InternalFormat::InternalFormat(AbstractTexture::Format) */ + inline constexpr InternalFormat(Format format): internalFormat(static_cast(format)) {} + + /** @brief OpenGL internal format ID */ + /* doxygen: @copydoc AbstractTexture::InternalFormat::operator GLint() doesn't work */ + inline constexpr operator GLint() const { return internalFormat; } + + private: + GLint internalFormat; + }; + + /*@}*/ + + /** + * @brief Constructor + * + * Generates new OpenGL renderbuffer. + */ + Renderbuffer() { + glGenRenderbuffers(1, &renderbuffer); + } + + /** + * @brief Destructor + * + * Deletes associated OpenGL renderbuffer. + */ + ~Renderbuffer() { + glDeleteRenderbuffers(1, &renderbuffer); + } + + /** @brief OpenGL internal renderbuffer ID */ + inline GLuint id() const { return renderbuffer; } + + /** @brief Bind renderbuffer */ + inline void bind() { + glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer); + } + + /** + * @brief Set renderbuffer storage + * @param internalFormat Internal format + * @param size Renderbuffer size + */ + inline void setStorage(InternalFormat internalFormat, const Math::Vector2& size) { + bind(); + glRenderbufferStorage(GL_RENDERBUFFER, static_cast(internalFormat), size.x(), size.y()); + } + + private: + GLuint renderbuffer; +}; + +/** @copydoc operator|(AbstractTexture::Components, AbstractTexture::ComponentType) */ +inline Renderbuffer::InternalFormat operator|(Renderbuffer::Components components, Renderbuffer::ComponentType type) { + return Renderbuffer::InternalFormat(components, type); +} +/** @copydoc operator|(AbstractTexture::ComponentType, AbstractTexture::Components) */ +inline Renderbuffer::InternalFormat operator|(Renderbuffer::ComponentType type, Renderbuffer::Components components) { + return Renderbuffer::InternalFormat(components, type); +} + +} + +#endif