diff --git a/src/Camera.cpp b/src/Camera.cpp index c37bc0559..32c44787e 100644 --- a/src/Camera.cpp +++ b/src/Camera.cpp @@ -14,27 +14,13 @@ */ #include "Camera.h" +#include "Framebuffer.h" #include "Scene.h" using namespace std; namespace Magnum { -GLbitfield Camera::clearMask = GL_COLOR_BUFFER_BIT; - -void Camera::setFeature(Feature feature, bool enabled) { - /* Enable or disable the feature */ - enabled ? glEnable(static_cast(feature)) : glDisable(static_cast(feature)); - - /* Update clear mask, if needed */ - GLbitfield clearMaskChange; - if(feature == Feature::DepthTest) clearMaskChange = GL_DEPTH_BUFFER_BIT; - else if(feature == Feature::StencilTest) clearMaskChange = GL_STENCIL_BUFFER_BIT; - else return; - - enabled ? clearMask |= clearMaskChange : clearMask &= ~clearMaskChange; -} - Camera::Camera(Object* parent): Object(parent), _aspectRatioPolicy(AspectRatioPolicy::Extend) {} void Camera::setOrthographic(GLfloat size, GLfloat near, GLfloat far) { @@ -78,7 +64,7 @@ void Camera::setPerspective(GLfloat fov, GLfloat near, GLfloat far) { } void Camera::setViewport(const Math::Vector2& size) { - glViewport(0, 0, size.x(), size.y()); + Framebuffer::setViewport({0, 0}, size); _viewport = size; fixAspectRatio(); @@ -119,7 +105,7 @@ void Camera::draw() { Scene* s = scene(); CORRADE_ASSERT(s, "Camera: cannot draw without camera attached to scene", ) - clear(); + Framebuffer::clear(); /* Recursively draw child objects */ drawChildren(s, cameraMatrix()); diff --git a/src/Camera.h b/src/Camera.h index e3907996a..833993e96 100644 --- a/src/Camera.h +++ b/src/Camera.h @@ -33,30 +33,6 @@ namespace Magnum { */ class MAGNUM_EXPORT Camera: public Object { public: - /** - * @brief Features - * - * If not specified otherwise, all features are disabled by default. - * @see setFeature() - */ - enum class Feature: GLenum { - AlphaBlending = GL_BLEND, /**< Alpha blending */ - - #ifndef MAGNUM_TARGET_GLES - /** - * Depth clamping. If enabled, ignores near and far clipping plane. - * @requires_gl - * @requires_gl32 Extension @extension{ARB,depth_clamp} - */ - DepthClamp = GL_DEPTH_CLAMP, - #endif - - DepthTest = GL_DEPTH_TEST, /**< Depth test */ - StencilTest = GL_STENCIL_TEST, /**< Stencil test */ - Dithering = GL_DITHER, /**< Dithering (enabled by default) */ - FaceCulling = GL_CULL_FACE /**< Back face culling */ - }; - /** * @brief Aspect ratio policy * @@ -68,42 +44,6 @@ class MAGNUM_EXPORT Camera: public Object { Clip /**< Clip on smaller side of view */ }; - /** @brief Set feature */ - static void setFeature(Feature feature, bool enabled); - - /** - * @brief Set clear color - * - * Initial value is `{0.0f, 0.0f, 0.0f, 1.0f}`. - */ - inline static void setClearColor(const Vector4& color) { - glClearColor(color.r(), color.g(), color.b(), color.a()); - } - - #ifndef MAGNUM_TARGET_GLES - /** - * @brief Set clear depth - * - * Initial value is `1.0`. - * @requires_gl See setClearDepth(GLfloat), which is supported in OpenGL ES. - */ - inline static void setClearDepth(GLdouble depth) { glClearDepth(depth); } - #endif - - /** - * @overload - * - * @requires_gl41 Extension @extension{ARB,ES2_compatibility} - */ - inline static void setClearDepth(GLfloat depth) { glClearDepthf(depth); } - - /** - * @brief Set clear stencil - * - * Initial value is `0`. - */ - inline static void setClearStencil(GLint stencil) { glClearStencil(stencil); } - /** * @brief Constructor * @param parent Parent object @@ -171,30 +111,22 @@ class MAGNUM_EXPORT Camera: public Object { * @brief Set viewport size * * Call when window size changes. + * + * Calls Framebuffer::setViewport() and stores viewport size + * internally. */ virtual void setViewport(const Math::Vector2& size); /** * @brief Draw the scene * - * Calls clear() and draws the scene using drawChildren(). + * Calls Framebuffer::clear() and draws the scene using drawChildren(). */ virtual void draw(); using Object::draw; /* Don't hide Object's draw() */ protected: - /** - * @brief Clear framebuffer - * - * Clears color buffer, depth and stencil buffer in currently active - * framebuffer. If depth or stencil test is not enabled, it doesn't - * clear these buffers. - * - * @see setFeature() - */ - inline static void clear() { glClear(clearMask); } - /** * Recalculates camera matrix. */ @@ -208,8 +140,6 @@ class MAGNUM_EXPORT Camera: public Object { void drawChildren(Object* object, const Matrix4& transformationMatrix); private: - static GLbitfield clearMask; - Matrix4 rawProjectionMatrix; Matrix4 _projectionMatrix; Matrix4 _cameraMatrix; diff --git a/src/Framebuffer.cpp b/src/Framebuffer.cpp index e6117caec..864a70d80 100644 --- a/src/Framebuffer.cpp +++ b/src/Framebuffer.cpp @@ -17,6 +17,25 @@ namespace Magnum { +Framebuffer::ClearMask Framebuffer::clearMask = Framebuffer::Clear::Color; + +void Framebuffer::setFeature(Feature feature, bool enabled) { + /* Enable or disable the feature */ + enabled ? glEnable(static_cast(feature)) : glDisable(static_cast(feature)); + + /* Update clear mask, if needed */ + ClearMask clearMaskChange; + if(feature == Feature::DepthTest) clearMaskChange = Clear::Color; + else if(feature == Feature::StencilTest) clearMaskChange = Clear::Stencil; + else return; + + enabled ? clearMask |= clearMaskChange : clearMask &= ~clearMaskChange; +} + +void Framebuffer::setViewport(const Math::Vector2& position, const Math::Vector2& size) { + glViewport(position.x(), position.y(), size.x(), size.y()); +} + #ifndef MAGNUM_TARGET_GLES void Framebuffer::mapDefaultForDraw(std::initializer_list attachments) { GLenum* _attachments = new GLenum[attachments.size()]; diff --git a/src/Framebuffer.h b/src/Framebuffer.h index e609d322f..f1a382567 100644 --- a/src/Framebuffer.h +++ b/src/Framebuffer.h @@ -30,7 +30,8 @@ namespace Magnum { /** @ingroup textures @brief %Framebuffer -@requires_gl30 Extension @extension{EXT,framebuffer_object} +Provides operations with framebuffers (configuring, clearing, blitting...) and +creation and attaching of named framebuffers. */ class MAGNUM_EXPORT Framebuffer { Framebuffer(const Framebuffer& other) = delete; @@ -39,10 +40,48 @@ class MAGNUM_EXPORT Framebuffer { Framebuffer& operator=(Framebuffer&& other) = delete; public: + /** + * @brief Features + * + * If not specified otherwise, all features are disabled by default. + * @see setFeature() + */ + enum class Feature: GLenum { + AlphaBlending = GL_BLEND, /**< Alpha blending */ + + #ifndef MAGNUM_TARGET_GLES + /** + * Depth clamping. If enabled, ignores near and far clipping plane. + * @requires_gl + * @requires_gl32 Extension @extension{ARB,depth_clamp} + */ + DepthClamp = GL_DEPTH_CLAMP, + #endif + + DepthTest = GL_DEPTH_TEST, /**< Depth test */ + StencilTest = GL_STENCIL_TEST, /**< Stencil test */ + Dithering = GL_DITHER, /**< Dithering (enabled by default) */ + FaceCulling = GL_CULL_FACE /**< Back face culling */ + }; + + /** + * @brief Mask for clearing + * + * @see ClearMask, clear(), clear(ClearMask) + */ + enum class Clear: GLbitfield { + Color = GL_COLOR_BUFFER_BIT, /**< Color */ + Depth = GL_DEPTH_BUFFER_BIT, /**< Depth value */ + Stencil = GL_STENCIL_BUFFER_BIT /**< Stencil value */ + }; + + typedef Set ClearMask; /**< @brief Mask for clearing */ + /** * @brief %Framebuffer target * * @see bind(), bindDefault() + * @requires_gl30 Extension @extension{EXT,framebuffer_object} */ enum class Target: GLenum { #ifndef MAGNUM_TARGET_GLES @@ -70,6 +109,7 @@ class MAGNUM_EXPORT Framebuffer { * * @see mapDefaultForDraw() * @requires_gl + * @requires_gl30 Extension @extension{EXT,framebuffer_object} */ enum class DefaultDrawAttachment: GLenum { None = GL_NONE, /**< Don't use the output. */ @@ -84,6 +124,7 @@ class MAGNUM_EXPORT Framebuffer { * * @see mapDefaultForRead() * @requires_gl + * @requires_gl30 Extension @extension{EXT,framebuffer_object} */ enum class DefaultReadAttachment: GLenum { FrontLeft = GL_FRONT_LEFT, /**< Read from front left framebuffer. */ @@ -106,6 +147,7 @@ class MAGNUM_EXPORT Framebuffer { * attachTexture2D(Target, DepthStencilAttachment, Texture2D*, GLint), * attachCubeMapTexture(Target, DepthStencilAttachment, CubeMapTexture*, CubeMapTexture::Coordinate, GLint), * attachTexture3D(Target, DepthStencilAttachment, Texture3D*, GLint) + * @requires_gl30 Extension @extension{EXT,framebuffer_object} */ enum class DepthStencilAttachment: GLenum { Depth = GL_DEPTH_ATTACHMENT, /**< Depth output only. */ @@ -127,6 +169,7 @@ class MAGNUM_EXPORT Framebuffer { * Specifies which data are copied when performing blit operation * using blit(). * @see BlitMask + * @requires_gl30 Extension @extension{EXT,framebuffer_object} */ enum class Blit: GLbitfield { Color = GL_COLOR_BUFFER_BIT, /**< Color */ @@ -134,11 +177,79 @@ class MAGNUM_EXPORT Framebuffer { Stencil = GL_STENCIL_BUFFER_BIT /**< Stencil value */ }; - typedef Set BlitMask; /**< @brief Output mask for blitting */ + /** + * @brief Output mask for blitting + * @requires_gl30 Extension @extension{EXT,framebuffer_object} + */ + typedef Set BlitMask; + + /** @brief Set feature */ + static void setFeature(Feature feature, bool enabled); + + /** + * @brief Set clear color + * + * Initial value is `{0.0f, 0.0f, 0.0f, 1.0f}`. + */ + inline static void setClearColor(const Vector4& color) { + glClearColor(color.r(), color.g(), color.b(), color.a()); + } + + /** + * @brief Clear framebuffer + * + * Clears color buffer, depth and stencil buffer in currently active + * framebuffer. If depth or stencil test is not enabled, it doesn't + * clear these buffers. + * + * @see setFeature(), clear(ClearMask) + */ + inline static void clear() { glClear(static_cast(clearMask)); } + + /** + * @brief Clear specified buffers in framebuffer + * + * @see clear() + */ + inline static void clear(ClearMask mask) { glClear(static_cast(mask)); } + + #ifndef MAGNUM_TARGET_GLES + /** + * @brief Set clear depth + * + * Initial value is `1.0`. + * @requires_gl See setClearDepth(GLfloat), which is supported in OpenGL ES. + */ + inline static void setClearDepth(GLdouble depth) { glClearDepth(depth); } + #endif + + /** + * @overload + * + * @requires_gl41 Extension @extension{ARB,ES2_compatibility} + */ + inline static void setClearDepth(GLfloat depth) { glClearDepthf(depth); } + + /** + * @brief Set clear stencil + * + * Initial value is `0`. + */ + inline static void setClearStencil(GLint stencil) { glClearStencil(stencil); } + + /** + * @brief Set viewport size + * + * Call when window size changes. + * @see Camera::setViewport() + */ + static void setViewport(const Math::Vector2& position, const Math::Vector2& size); /** * @brief Bind default framebuffer to given target * @param target %Target + * + * @requires_gl30 Extension @extension{EXT,framebuffer_object} */ inline static void bindDefault(Target target) { glBindFramebuffer(static_cast(target), 0); @@ -157,6 +268,7 @@ class MAGNUM_EXPORT Framebuffer { * work properly. * @see mapForDraw(), mapDefaultForRead() * @requires_gl + * @requires_gl30 Extension @extension{EXT,framebuffer_object} */ static void mapDefaultForDraw(std::initializer_list attachments); @@ -168,6 +280,7 @@ class MAGNUM_EXPORT Framebuffer { * attached to work properly. * @see mapForRead(), mapDefaultForDraw() * @requires_gl + * @requires_gl30 Extension @extension{EXT,framebuffer_object} */ inline static void mapDefaultForRead(DefaultReadAttachment attachment) { bindDefault(Target::Read); @@ -226,6 +339,8 @@ class MAGNUM_EXPORT Framebuffer { * @param components Color components * @param type Data type * @param image %Image where to put the data + * + * @requires_gl30 Extension @extension{EXT,framebuffer_object} */ static void read(const Math::Vector2& offset, const Math::Vector2& dimensions, AbstractImage::Components components, AbstractImage::ComponentType type, Image2D* image); @@ -240,6 +355,7 @@ class MAGNUM_EXPORT Framebuffer { * @param usage %Buffer usage * * @requires_gl + * @requires_gl30 Extension @extension{EXT,framebuffer_object} */ static void read(const Math::Vector2& offset, const Math::Vector2& dimensions, AbstractImage::Components components, AbstractImage::ComponentType type, BufferedImage2D* image, Buffer::Usage usage); #endif @@ -248,6 +364,7 @@ class MAGNUM_EXPORT Framebuffer { * @brief Constructor * * Generates new OpenGL framebuffer. + * @requires_gl30 Extension @extension{EXT,framebuffer_object} */ inline Framebuffer() { glGenFramebuffers(1, &framebuffer); } @@ -255,10 +372,15 @@ class MAGNUM_EXPORT Framebuffer { * @brief Destructor * * Deletes associated OpenGL framebuffer. + * @requires_gl30 Extension @extension{EXT,framebuffer_object} */ inline ~Framebuffer() { glDeleteFramebuffers(1, &framebuffer); } - /** @brief Bind framebuffer */ + /** + * @brief Bind framebuffer + * + * @requires_gl30 Extension @extension{EXT,framebuffer_object} + */ inline void bind(Target target) { glBindFramebuffer(static_cast(target), framebuffer); } @@ -276,6 +398,7 @@ class MAGNUM_EXPORT Framebuffer { * work properly. * @see mapDefaultForDraw(), mapForRead() * @requires_gl + * @requires_gl30 Extension @extension{EXT,framebuffer_object} */ void mapForDraw(std::initializer_list colorAttachments); @@ -287,6 +410,7 @@ class MAGNUM_EXPORT Framebuffer { * attached for reading to work properly. * @see mapDefaultForRead(), mapForDraw() * @requires_gl + * @requires_gl30 Extension @extension{EXT,framebuffer_object} */ inline void mapForRead(unsigned int colorAttachment) { bind(Target::Read); @@ -299,6 +423,8 @@ class MAGNUM_EXPORT Framebuffer { * @param target %Target * @param depthStencilAttachment Depth/stencil attachment * @param renderbuffer Renderbuffer + * + * @requires_gl30 Extension @extension{EXT,framebuffer_object} */ inline void attachRenderbuffer(Target target, DepthStencilAttachment depthStencilAttachment, Renderbuffer* renderbuffer) { /** @todo Check for internal format compatibility */ @@ -311,6 +437,8 @@ class MAGNUM_EXPORT Framebuffer { * @param target %Target * @param colorAttachment Color attachment ID (number between 0 and 15) * @param renderbuffer Renderbuffer + * + * @requires_gl30 Extension @extension{EXT,framebuffer_object} */ inline void attachRenderbuffer(Target target, unsigned int colorAttachment, Renderbuffer* renderbuffer) { /** @todo Check for internal format compatibility */ @@ -327,6 +455,7 @@ class MAGNUM_EXPORT Framebuffer { * @param mipLevel Mip level * * @requires_gl + * @requires_gl30 Extension @extension{EXT,framebuffer_object} */ inline void attachTexture1D(Target target, DepthStencilAttachment depthStencilAttachment, Texture1D* texture, GLint mipLevel) { /** @todo Check for internal format compatibility */ @@ -343,6 +472,7 @@ class MAGNUM_EXPORT Framebuffer { * @param mipLevel Mip level * * @requires_gl + * @requires_gl30 Extension @extension{EXT,framebuffer_object} */ inline void attachTexture1D(Target target, unsigned int colorAttachment, Texture1D* texture, GLint mipLevel) { /** @todo Check for internal format compatibility */ @@ -361,6 +491,7 @@ class MAGNUM_EXPORT Framebuffer { * should be always 0. * * @see attachCubeMapTexture() + * @requires_gl30 Extension @extension{EXT,framebuffer_object} */ inline void attachTexture2D(Target target, DepthStencilAttachment depthStencilAttachment, Texture2D* texture, GLint mipLevel) { /** @todo Check for internal format compatibility */ @@ -378,6 +509,7 @@ class MAGNUM_EXPORT Framebuffer { * should be always 0. * * @see attachCubeMapTexture() + * @requires_gl30 Extension @extension{EXT,framebuffer_object} */ inline void attachTexture2D(Target target, unsigned int colorAttachment, Texture2D* texture, GLint mipLevel) { /** @todo Check for internal format compatibility */ @@ -395,6 +527,7 @@ class MAGNUM_EXPORT Framebuffer { * @param mipLevel Mip level * * @see attachTexture2D() + * @requires_gl30 Extension @extension{EXT,framebuffer_object} */ inline void attachCubeMapTexture(Target target, DepthStencilAttachment depthStencilAttachment, CubeMapTexture* texture, CubeMapTexture::Coordinate coordinate, GLint mipLevel) { /** @todo Check for internal format compatibility */ @@ -411,6 +544,7 @@ class MAGNUM_EXPORT Framebuffer { * @param mipLevel Mip level * * @see attachTexture2D() + * @requires_gl30 Extension @extension{EXT,framebuffer_object} */ inline void attachCubeMapTexture(Target target, unsigned int colorAttachment, CubeMapTexture* texture, CubeMapTexture::Coordinate coordinate, GLint mipLevel) { /** @todo Check for internal format compatibility */ @@ -428,6 +562,7 @@ class MAGNUM_EXPORT Framebuffer { * @param layer Layer of 2D image within a 3D texture * * @requires_gl + * @requires_gl30 Extension @extension{EXT,framebuffer_object} */ inline void attachTexture3D(Target target, DepthStencilAttachment depthStencilAttachment, Texture3D* texture, GLint mipLevel, GLint layer) { /** @todo Check for internal format compatibility */ @@ -445,6 +580,7 @@ class MAGNUM_EXPORT Framebuffer { * @param layer Layer of 2D image within a 3D texture. * * @requires_gl + * @requires_gl30 Extension @extension{EXT,framebuffer_object} */ inline void attachTexture3D(Target target, unsigned int colorAttachment, Texture3D* texture, GLint mipLevel, GLint layer) { /** @todo Check for internal format compatibility */ @@ -455,6 +591,8 @@ class MAGNUM_EXPORT Framebuffer { #endif private: + static ClearMask clearMask; + GLuint framebuffer; };