diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index a9d4b9d59..a65f447a9 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -71,6 +71,7 @@ set(Magnum_HEADERS Profiler.h Query.h Renderbuffer.h + Renderer.h Resource.h ResourceManager.h Shader.h diff --git a/src/Framebuffer.h b/src/Framebuffer.h index f4aba3115..67ae17619 100644 --- a/src/Framebuffer.h +++ b/src/Framebuffer.h @@ -43,84 +43,6 @@ class MAGNUM_EXPORT Framebuffer { Framebuffer& operator=(Framebuffer&& other) = delete; public: - /** - * @brief Affected polygon facing for culling, stencil operations and masks - * - * @see setFaceCullingMode(), - * setStencilFunction(PolygonFacing, StencilFunction, GLint, GLuint), - * setStencilOperation(PolygonFacing, StencilOperation, StencilOperation, StencilOperation), - * setStencilMask(PolygonFacing, GLuint) - */ - enum class PolygonFacing: GLenum { - Front = GL_FRONT, /**< Front-facing polygons */ - Back = GL_BACK, /**< Back-facing polygons */ - FrontAndBack = GL_FRONT_AND_BACK /**< Front- and back-facing polygons */ - }; - - /** @{ @name Framebuffer features */ - - /** - * @brief Features - * - * If not specified otherwise, all features are disabled by default. - * @see setFeature() - */ - enum class Feature: GLenum { - /** - * Blending - * @see setBlendEquation(), setBlendFunction(), setBlendColor() - */ - Blending = GL_BLEND, - - #ifndef MAGNUM_TARGET_GLES - /** - * Logical operation - * @see setLogicOperation() - * @requires_gl Logical operations on framebuffer are not - * available in OpenGL ES. - */ - LogicOperation = GL_COLOR_LOGIC_OP, - - /** - * Depth clamping. If enabled, ignores near and far clipping plane. - * @requires_gl32 Extension @extension{ARB,depth_clamp} - * @requires_gl Depth clamping is not available in OpenGL ES. - */ - DepthClamp = GL_DEPTH_CLAMP, - #endif - - /** - * Scissor test - * @see setScissor() - */ - ScissorTest = GL_SCISSOR_TEST, - 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 Set feature - * - * @see @fn_gl{Enable}/@fn_gl{Disable} - */ - inline static void setFeature(Feature feature, bool enabled) { - enabled ? glEnable(static_cast(feature)) : glDisable(static_cast(feature)); - } - - /** - * @brief Which polygon facing to cull - * - * Initial value is `PolygonFacing::Back`. If set to both front and - * back, only points and lines are drawn. - * @attention You have to also enable face culling with setFeature(). - * @see @fn_gl{CullFace} - */ - inline static void setFaceCullingMode(PolygonFacing mode) { - glCullFace(static_cast(mode)); - } - /** * @brief Set viewport size * @@ -131,10 +53,6 @@ class MAGNUM_EXPORT Framebuffer { glViewport(position.x(), position.y(), size.x(), size.y()); } - /*@}*/ - - /** @{ @name Clearing the framebuffer */ - /** * @brief Mask for clearing * @@ -153,534 +71,12 @@ class MAGNUM_EXPORT Framebuffer { /** * @brief Clear specified buffers in framebuffer * - * @see clear(), setClearColor(), setClearDepth(), setClearStencil(), - * @fn_gl{Clear} + * @see clear(), Renderer::setClearColor(), Renderer::setClearDepth(), + * Renderer::setClearStencil(), @fn_gl{Clear} * @todo Clearing only given draw buffer */ inline static void clear(ClearMask mask) { glClear(static_cast(mask)); } - /** - * @brief Set clear color - * - * Initial value is `{0.0f, 0.0f, 0.0f, 1.0f}`. - * @see @fn_gl{ClearColor} - */ - inline static void setClearColor(const Color4<>& color) { - glClearColor(color.r(), color.g(), color.b(), color.a()); - } - - #ifndef MAGNUM_TARGET_GLES - /** - * @brief Set clear depth - * - * Initial value is `1.0`. - * @see @fn_gl{ClearDepth} - * @requires_gl See setClearDepth(GLfloat), which is available in OpenGL ES. - */ - inline static void setClearDepth(GLdouble depth) { glClearDepth(depth); } - #endif - - /** - * @overload - * - * @see @fn_gl{ClearDepth} - * @requires_gl41 Extension @extension{ARB,ES2_compatibility} - * @todo Call double version if the extension is not available - */ - inline static void setClearDepth(GLfloat depth) { glClearDepthf(depth); } - - /** - * @brief Set clear stencil - * - * Initial value is `0`. - * @see @fn_gl{ClearStencil} - */ - inline static void setClearStencil(GLint stencil) { glClearStencil(stencil); } - - /*@}*/ - - /** @{ @name Scissor operations */ - - /** - * @brief Set scissor rectangle - * @param bottomLeft Bottom left corner. Initial value is `(0, 0)`. - * @param size Scissor rectangle size. Initial value is - * size of the window when the context is first attached to a - * window. - * - * @attention You have to enable scissoring with setFeature() first. - * @see @fn_gl{Scissor} - */ - inline static void setScissor(const Vector2i& bottomLeft, const Vector2i& size) { - glScissor(bottomLeft.x(), bottomLeft.y(), size.x(), size.y()); - } - - /*@}*/ - - /** @{ @name Stencil operations */ - - /** - * @brief Stencil function - * - * @see setStencilFunction() - */ - enum class StencilFunction: GLenum { - Never = GL_NEVER, /**< Never pass the test. */ - Always = GL_ALWAYS, /**< Always pass the test. */ - Less = GL_LESS, /**< Pass when reference value is less than buffer value. */ - LessOrEqual = GL_LEQUAL, /**< Pass when reference value is less than or equal to buffer value. */ - Equal = GL_EQUAL, /**< Pass when reference value is equal to buffer value. */ - NotEqual = GL_NOTEQUAL, /**< Pass when reference value is not equal to buffer value. */ - GreaterOrEqual = GL_GEQUAL, /**< Pass when reference value is greater than or equal to buffer value. */ - Greater = GL_GREATER /**< Pass when reference value is greater than buffer value. */ - }; - - /** - * @brief Stencil operation - * - * @see setStencilOperation() - */ - enum class StencilOperation: GLenum { - Keep = GL_KEEP, /**< Keep the current value. */ - Zero = GL_ZERO, /**< Set the stencil buffer value to `0`. */ - - /** - * Set the stencil value to reference value specified by - * setStencilFunction(). - */ - Replace = GL_REPLACE, - - /** - * Increment the current stencil buffer value, clamp to maximum - * possible value on overflow. - */ - Increment = GL_INCR, - - /** - * Increment the current stencil buffer value, wrap to zero on - * overflow. - */ - IncrementWrap = GL_INCR_WRAP, - - /** - * Increment the current stencil buffer value, clamp to minimum - * possible value on underflow. - */ - Decrement = GL_DECR, - - /** - * Decrement the current stencil buffer value, wrap to maximum - * possible value on underflow. - */ - DecrementWrap = GL_DECR_WRAP, - - /** - * Bitwise invert the current stencil buffer value. - */ - Invert = GL_INVERT - }; - - /** - * @brief Set stencil function - * @param facing Affected polygon facing - * @param function Stencil function. Initial value is - * `StencilFunction::Always`. - * @param referenceValue Reference value. Initial value is `0`. - * @param mask Mask for both reference and buffer value. - * Initial value is all `1`s. - * - * @attention You have to enable stencil test with setFeature() first. - * @see setStencilFunction(StencilFunction, GLint, GLuint), - * @fn_gl{StencilFuncSeparate} - */ - inline static void setStencilFunction(PolygonFacing facing, StencilFunction function, GLint referenceValue, GLuint mask) { - glStencilFuncSeparate(static_cast(facing), static_cast(function), referenceValue, mask); - } - - /** - * @brief Set stencil function - * - * The same as setStencilFunction(PolygonFacing, StencilFunction, GLint, GLuint) - * with `facing` set to `PolygonFacing::FrontAndBack`. - * @see @fn_gl{StencilFunc} - */ - inline static void setStencilFunction(StencilFunction function, GLint referenceValue, GLuint mask) { - glStencilFunc(static_cast(function), referenceValue, mask); - } - - /** - * @brief Set stencil operation - * @param facing Affected polygon facing - * @param stencilFail Action when stencil test fails - * @param depthFail Action when stencil test passes, but depth - * test fails - * @param depthPass Action when both stencil and depth test - * pass - * - * Initial value for all fields is `StencilOperation::Keep`. - * @attention You have to enable stencil test with setFeature() first. - * @see setStencilOperation(StencilOperation, StencilOperation, StencilOperation), - * @fn_gl{StencilOpSeparate} - */ - inline static void setStencilOperation(PolygonFacing facing, StencilOperation stencilFail, StencilOperation depthFail, StencilOperation depthPass) { - glStencilOpSeparate(static_cast(facing), static_cast(stencilFail), static_cast(depthFail), static_cast(depthPass)); - } - - /** - * @brief Set stencil operation - * - * The same as setStencilOperation(PolygonFacing, StencilOperation, StencilOperation, StencilOperation) - * with `facing` set to `PolygonFacing::FrontAndBack`. - * @see @fn_gl{StencilOp} - */ - inline static void setStencilOperation(StencilOperation stencilFail, StencilOperation depthFail, StencilOperation depthPass) { - glStencilOp(static_cast(stencilFail), static_cast(depthFail), static_cast(depthPass)); - } - - /*@}*/ - - /** @{ @name Depth testing */ - - /** - * @brief Depth function - * - * @see setDepthFunction() - */ - typedef StencilFunction DepthFunction; - - /** - * @brief Set depth function - * - * Initial value is `DepthFunction::Less`. - * @attention You have to enable depth test with setFeature() first. - * @see @fn_gl{DepthFunc} - */ - inline static void setDepthFunction(DepthFunction function) { - glDepthFunc(static_cast(function)); - } - - /*@}*/ - - /** @{ @name Masking writes */ - - /** - * @brief Mask color writes - * - * Set to `false` to disallow writing to given color channel. Initial - * values are all `true`. - * @see @fn_gl{ColorMask} - * @todo Masking only given draw buffer - */ - inline static void setColorMask(GLboolean allowRed, GLboolean allowGreen, GLboolean allowBlue, GLboolean allowAlpha) { - glColorMask(allowRed, allowGreen, allowBlue, allowAlpha); - } - - /** - * @brief Mask depth writes - * - * Set to `false` to disallow writing to depth buffer. Initial value - * is `true`. - * @see @fn_gl{DepthMask} - */ - inline static void setDepthMask(GLboolean allow) { - glDepthMask(allow); - } - - /** - * @brief Mask stencil writes - * - * Set given bit to `0` to disallow writing stencil value for given - * faces to it. Initial value is all `1`s. - * @see setStencilMask(GLuint), @fn_gl{StencilMaskSeparate} - */ - inline static void setStencilMask(PolygonFacing facing, GLuint allowBits) { - glStencilMaskSeparate(static_cast(facing), allowBits); - } - - /** - * @brief Mask stencil writes - * - * The same as setStencilMask(PolygonFacing, GLuint) with `facing` set - * to `PolygonFacing::FrontAndBack`. - * @see @fn_gl{StencilMask} - */ - inline static void setStencilMask(GLuint allowBits) { - glStencilMask(allowBits); - } - - /*@}*/ - - /** @{ @name Blending - * You have to enable blending with setFeature() first. - * @todo Blending for given draw buffer - */ - - /** - * @brief Blend equation - * - * @see setBlendEquation() - */ - enum class BlendEquation: GLenum { - Add = GL_FUNC_ADD, /**< `source + destination` */ - Subtract = GL_FUNC_SUBTRACT, /**< `source - destination` */ - ReverseSubtract = GL_FUNC_REVERSE_SUBTRACT /**< `destination - source` */ - - #ifndef MAGNUM_TARGET_GLES2 - , - /** - * `min(source, destination)` - * @requires_gles30 %Extension @es_extension2{EXT,blend_minmax,blend_minmax} - */ - Min = GL_MIN, - - /** - * `max(source, destination)` - * @requires_gles30 %Extension @es_extension2{EXT,blend_minmax,blend_minmax} - */ - Max = GL_MAX - #endif - }; - - /** - * @brief Blend function - * - * @see setBlendFunction() - */ - enum class BlendFunction: GLenum { - /** Zero (@f$ RGB = (0.0, 0.0, 0.0); A = 0.0 @f$) */ - Zero = GL_ZERO, - - /** One (@f$ RGB = (1.0, 1.0, 1.0); A = 1.0 @f$) */ - One = GL_ONE, - - /** - * Constant color (@f$ RGB = (R_c, G_c, B_c); A = A_c @f$) - * - * @see setBlendColor() - */ - ConstantColor = GL_CONSTANT_COLOR, - - /** - * One minus constant color (@f$ RGB = (1.0 - R_c, 1.0 - G_c, 1.0 - B_c); A = 1.0 - A_c @f$) - * - * @see setBlendColor() - */ - OneMinusConstantColor = GL_ONE_MINUS_CONSTANT_COLOR, - - /** - * Constant alpha (@f$ RGB = (A_c, A_c, A_c); A = A_c @f$) - * - * @see setBlendColor() - */ - ConstantAlpha = GL_CONSTANT_ALPHA, - - /** - * One minus constant alpha (@f$ RGB = (1.0 - A_c, 1.0 - A_c, 1.0 - A_c); A = 1.0 - A_c @f$) - * - * @see setBlendColor() - */ - OneMinusConstantAlpha = GL_ONE_MINUS_CONSTANT_ALPHA, - - /** Source color (@f$ RGB = (R_{s0}, G_{s0}, B_{s0}); A = A_{s0} @f$) */ - SourceColor = GL_SRC_COLOR, - - #ifndef MAGNUM_TARGET_GLES - /** - * Second source color (@f$ RGB = (R_{s1}, G_{s1}, B_{s1}); A = A_{s1} @f$) - * - * @see AbstractShaderProgram::bindFragmentDataLocationIndexed() - * @requires_gl33 Extension @extension{ARB,blend_func_extended} - * @requires_gl Multiple blending inputs are not available in - * OpenGL ES. - */ - SecondSourceColor = GL_SRC1_COLOR, - #endif - - /** - * One minus source color (@f$ RGB = (1.0 - R_{s0}, 1.0 - G_{s0}, 1.0 - B_{s0}); A = 1.0 - A_{s0} @f$) - */ - OneMinusSourceColor = GL_ONE_MINUS_SRC_COLOR, - - #ifndef MAGNUM_TARGET_GLES - /** - * One minus second source color (@f$ RGB = (1.0 - R_{s1}, 1.0 - G_{s1}, 1.0 - B_{s1}); A = 1.0 - A_{s1} @f$) - * - * @see AbstractShaderProgram::bindFragmentDataLocationIndexed() - * @requires_gl33 Extension @extension{ARB,blend_func_extended} - * @requires_gl Multiple blending inputs are not available in - * OpenGL ES. - */ - OneMinusSecondSourceColor = GL_ONE_MINUS_SRC1_COLOR, - #endif - - /** Source alpha (@f$ RGB = (A_{s0}, A_{s0}, A_{s0}); A = A_{s0} @f$) */ - SourceAlpha = GL_SRC_ALPHA, - - /** - * Saturate source alpha (@f$ RGB = (f, f, f); A = 1.0; f = min(A_s, 1.0 - A_d) @f$) - * - * Can be used only in source parameter of setBlendFunction(). - */ - SourceAlphaSaturate = GL_SRC_ALPHA_SATURATE, - - #ifndef MAGNUM_TARGET_GLES - /** - * Second source alpha (@f$ RGB = (A_{s1}, A_{s1}, A_{s1}); A = A_{s1} @f$) - * - * @see AbstractShaderProgram::bindFragmentDataLocationIndexed() - * @requires_gl33 Extension @extension{ARB,blend_func_extended} - * @requires_gl Multiple blending inputs are not available in - * OpenGL ES. - */ - SecondSourceAlpha = GL_SRC1_ALPHA, - #endif - - /** - * One minus source alpha (@f$ RGB = (1.0 - A_{s0}, 1.0 - A_{s0}, 1.0 - A_{s0}); A = 1.0 - A_{s0} @f$) - */ - OneMinusSourceAlpha = GL_ONE_MINUS_SRC_ALPHA, - - #ifndef MAGNUM_TARGET_GLES - /** - * One minus second source alpha (@f$ RGB = (1.0 - A_{s1}, 1.0 - A_{s1}, 1.0 - A_{s1}); A = 1.0 - A_{s1} @f$) - * - * @see AbstractShaderProgram::bindFragmentDataLocationIndexed() - * @requires_gl33 Extension @extension{ARB,blend_func_extended} - * @requires_gl Multiple blending inputs are not available in - * OpenGL ES. - */ - OneMinusSecondSourceAlpha = GL_ONE_MINUS_SRC1_ALPHA, - #endif - - /** Destination color (@f$ RGB = (R_d, G_d, B_d); A = A_d @f$) */ - DestinationColor = GL_DST_COLOR, - - /** - * One minus source color (@f$ RGB = (1.0 - R_d, 1.0 - G_d, 1.0 - B_d); A = 1.0 - A_d @f$) - */ - OneMinusDestinationColor = GL_ONE_MINUS_DST_COLOR, - - /** Destination alpha (@f$ RGB = (A_d, A_d, A_d); A = A_d @f$) */ - DestinationAlpha = GL_DST_ALPHA, - - /** - * One minus source alpha (@f$ RGB = (1.0 - A_d, 1.0 - A_d, 1.0 - A_d); A = 1.0 - A_d @f$) - */ - OneMinusDestinationAlpha = GL_ONE_MINUS_DST_ALPHA - }; - - /** - * @brief Set blend equation - * - * How to combine source color (pixel value) with destination color - * (framebuffer). Initial value is `BlendEquation::Add`. - * @attention You have to enable blending with setFeature() first. - * @see setBlendEquation(BlendEquation, BlendEquation), - * @fn_gl{BlendEquation} - */ - inline static void setBlendEquation(BlendEquation equation) { - glBlendEquation(static_cast(equation)); - } - - /** - * @brief Set blend equation separately for RGB and alpha components - * - * See setBlendEquation(BlendEquation) for more information. - * @attention You have to enable blending with setFeature() first. - * @see @fn_gl{BlendEquationSeparate} - */ - inline static void setBlendEquation(BlendEquation rgb, BlendEquation alpha) { - glBlendEquationSeparate(static_cast(rgb), static_cast(alpha)); - } - - /** - * @brief Set blend function - * @param source How the source blending factor is computed - * from pixel value. Initial value is `BlendFunction::One`. - * @param destination How the destination blending factor is - * computed from framebuffer. Initial value is - * `BlendFunction::Zero`. - * - * @attention You have to enable blending with setFeature() first. - * @see setBlendFunction(BlendFunction, BlendFunction, BlendFunction, BlendFunction), - * @fn_gl{BlendFunc} - */ - inline static void setBlendFunction(BlendFunction source, BlendFunction destination) { - glBlendFunc(static_cast(source), static_cast(destination)); - } - - /** - * @brief Set blend function separately for RGB and alpha components - * - * See setBlendFunction(BlendFunction, BlendFunction) for more information. - * @attention You have to enable blending with setFeature() first. - * @see @fn_gl{BlendFuncSeparate} - */ - inline static void setBlendFunction(BlendFunction sourceRgb, BlendFunction destinationRgb, BlendFunction sourceAlpha, BlendFunction destinationAlpha) { - glBlendFuncSeparate(static_cast(sourceRgb), static_cast(destinationRgb), static_cast(sourceAlpha), static_cast(destinationAlpha)); - } - - /** - * @brief Set blend color - * - * Sets constant color used in setBlendFunction() by - * `BlendFunction::ConstantColor`, - * `BlendFunction::OneMinusConstantColor`, - * `BlendFunction::ConstantAlpha` and - * `BlendFunction::OneMinusConstantAlpha`. - * @attention You have to enable blending with setFeature() first. - * @see @fn_gl{BlendColor} - */ - inline static void setBlendColor(const Color4<>& color) { - glBlendColor(color.r(), color.g(), color.b(), color.a()); - } - - /*@}*/ - - #ifndef MAGNUM_TARGET_GLES - /** @{ @name Logical operation */ - - /** - * @brief Logical operation - * - * @see setLogicOperation() - * @requires_gl Logical operations on framebuffer are not available in - * OpenGL ES. - */ - enum class LogicOperation: GLenum { - Clear = GL_CLEAR, /**< `0` */ - Set = GL_SET, /**< `1` */ - Copy = GL_COPY, /**< `source` */ - CopyInverted = GL_COPY_INVERTED,/**< `~source` */ - Noop = GL_NOOP, /**< `destination` */ - Invert = GL_INVERT, /**< `~destination` */ - And = GL_AND, /**< `source & destination` */ - AndReverse = GL_AND_REVERSE, /**< `source & ~destination` */ - AndInverted = GL_AND_INVERTED, /**< `~source & destination` */ - Nand = GL_NAND, /**< `~(source & destination)` */ - Or = GL_OR, /**< `source | destination` */ - OrReverse = GL_OR_REVERSE, /**< `source | ~destination` */ - OrInverted = GL_OR_INVERTED, /**< `~source | destination` */ - Nor = GL_NOR, /**< `~(source | destination)` */ - Xor = GL_XOR, /**< `source ^ destination` */ - Equivalence = GL_EQUIV /**< `~(source ^ destination)` */ - }; - - /** - * @brief Set logical operation - * - * @attention You have to enable logical operation with setFeature() first. - * @see @fn_gl{LogicOp} - * @requires_gl Logical operations on framebuffer are not available in - * OpenGL ES. - */ - inline static void setLogicOperation(LogicOperation operation) { - glLogicOp(static_cast(operation)); - } - - /*@}*/ - #endif - /** @{ @name Framebuffer creation and binding */ /** diff --git a/src/Renderer.h b/src/Renderer.h new file mode 100644 index 000000000..d4b319676 --- /dev/null +++ b/src/Renderer.h @@ -0,0 +1,649 @@ +#ifndef Magnum_Renderer_h +#define Magnum_Renderer_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::Renderer + */ + +#include + +#include "AbstractImage.h" +#include "Buffer.h" +#include "CubeMapTexture.h" +#include "Color.h" +#include "Renderbuffer.h" + +namespace Magnum { + +/** @nosubgrouping +@brief %Renderer + +Access to global renderer configuration. +@todo @extension{ARB,viewport_array} +*/ +class MAGNUM_EXPORT Renderer { + Renderer() = delete; + + public: + /** + * @brief Affected polygon facing for culling, stencil operations and masks + * + * @see setFaceCullingMode(), + * setStencilFunction(PolygonFacing, StencilFunction, GLint, GLuint), + * setStencilOperation(PolygonFacing, StencilOperation, StencilOperation, StencilOperation), + * setStencilMask(PolygonFacing, GLuint) + */ + enum class PolygonFacing: GLenum { + Front = GL_FRONT, /**< Front-facing polygons */ + Back = GL_BACK, /**< Back-facing polygons */ + FrontAndBack = GL_FRONT_AND_BACK /**< Front- and back-facing polygons */ + }; + + /** @{ @name Renderer features */ + + /** + * @brief Features + * + * If not specified otherwise, all features are disabled by default. + * @see setFeature() + */ + enum class Feature: GLenum { + /** + * Blending + * @see setBlendEquation(), setBlendFunction(), setBlendColor() + */ + Blending = GL_BLEND, + + #ifndef MAGNUM_TARGET_GLES + /** + * Logical operation + * @see setLogicOperation() + * @requires_gl Logical operations on framebuffer are not + * available in OpenGL ES. + */ + LogicOperation = GL_COLOR_LOGIC_OP, + + /** + * Depth clamping. If enabled, ignores near and far clipping plane. + * @requires_gl32 Extension @extension{ARB,depth_clamp} + * @requires_gl Depth clamping is not available in OpenGL ES. + */ + DepthClamp = GL_DEPTH_CLAMP, + #endif + + /** + * Scissor test + * @see setScissor() + */ + ScissorTest = GL_SCISSOR_TEST, + 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 Set feature + * + * @see @fn_gl{Enable}/@fn_gl{Disable} + */ + inline static void setFeature(Feature feature, bool enabled) { + enabled ? glEnable(static_cast(feature)) : glDisable(static_cast(feature)); + } + + /** + * @brief Which polygon facing to cull + * + * Initial value is `PolygonFacing::Back`. If set to both front and + * back, only points and lines are drawn. + * @attention You have to also enable face culling with setFeature(). + * @see @fn_gl{CullFace} + */ + inline static void setFaceCullingMode(PolygonFacing mode) { + glCullFace(static_cast(mode)); + } + + /*@}*/ + + /** @{ @name Clearing values */ + + /** + * @brief Set clear color + * + * Initial value is `{0.0f, 0.0f, 0.0f, 1.0f}`. + * @see @fn_gl{ClearColor} + */ + inline static void setClearColor(const Color4<>& color) { + glClearColor(color.r(), color.g(), color.b(), color.a()); + } + + #ifndef MAGNUM_TARGET_GLES + /** + * @brief Set clear depth + * + * Initial value is `1.0`. + * @see @fn_gl{ClearDepth} + * @requires_gl See setClearDepth(GLfloat), which is available in OpenGL ES. + */ + inline static void setClearDepth(GLdouble depth) { glClearDepth(depth); } + #endif + + /** + * @overload + * + * @see @fn_gl{ClearDepth} + * @requires_gl41 Extension @extension{ARB,ES2_compatibility} + * @todo Call double version if the extension is not available + */ + inline static void setClearDepth(GLfloat depth) { glClearDepthf(depth); } + + /** + * @brief Set clear stencil + * + * Initial value is `0`. + * @see @fn_gl{ClearStencil} + */ + inline static void setClearStencil(GLint stencil) { glClearStencil(stencil); } + + /*@}*/ + + /** @{ @name Scissor operations */ + + /** + * @brief Set scissor rectangle + * @param bottomLeft Bottom left corner. Initial value is `(0, 0)`. + * @param size Scissor rectangle size. Initial value is + * size of the window when the context is first attached to a + * window. + * + * @attention You have to enable scissoring with setFeature() first. + * @see @fn_gl{Scissor} + */ + inline static void setScissor(const Vector2i& bottomLeft, const Vector2i& size) { + glScissor(bottomLeft.x(), bottomLeft.y(), size.x(), size.y()); + } + + /*@}*/ + + /** @{ @name Stencil operations */ + + /** + * @brief Stencil function + * + * @see setStencilFunction() + */ + enum class StencilFunction: GLenum { + Never = GL_NEVER, /**< Never pass the test. */ + Always = GL_ALWAYS, /**< Always pass the test. */ + Less = GL_LESS, /**< Pass when reference value is less than buffer value. */ + LessOrEqual = GL_LEQUAL, /**< Pass when reference value is less than or equal to buffer value. */ + Equal = GL_EQUAL, /**< Pass when reference value is equal to buffer value. */ + NotEqual = GL_NOTEQUAL, /**< Pass when reference value is not equal to buffer value. */ + GreaterOrEqual = GL_GEQUAL, /**< Pass when reference value is greater than or equal to buffer value. */ + Greater = GL_GREATER /**< Pass when reference value is greater than buffer value. */ + }; + + /** + * @brief Stencil operation + * + * @see setStencilOperation() + */ + enum class StencilOperation: GLenum { + Keep = GL_KEEP, /**< Keep the current value. */ + Zero = GL_ZERO, /**< Set the stencil buffer value to `0`. */ + + /** + * Set the stencil value to reference value specified by + * setStencilFunction(). + */ + Replace = GL_REPLACE, + + /** + * Increment the current stencil buffer value, clamp to maximum + * possible value on overflow. + */ + Increment = GL_INCR, + + /** + * Increment the current stencil buffer value, wrap to zero on + * overflow. + */ + IncrementWrap = GL_INCR_WRAP, + + /** + * Increment the current stencil buffer value, clamp to minimum + * possible value on underflow. + */ + Decrement = GL_DECR, + + /** + * Decrement the current stencil buffer value, wrap to maximum + * possible value on underflow. + */ + DecrementWrap = GL_DECR_WRAP, + + /** + * Bitwise invert the current stencil buffer value. + */ + Invert = GL_INVERT + }; + + /** + * @brief Set stencil function + * @param facing Affected polygon facing + * @param function Stencil function. Initial value is + * `StencilFunction::Always`. + * @param referenceValue Reference value. Initial value is `0`. + * @param mask Mask for both reference and buffer value. + * Initial value is all `1`s. + * + * @attention You have to enable stencil test with setFeature() first. + * @see setStencilFunction(StencilFunction, GLint, GLuint), + * @fn_gl{StencilFuncSeparate} + */ + inline static void setStencilFunction(PolygonFacing facing, StencilFunction function, GLint referenceValue, GLuint mask) { + glStencilFuncSeparate(static_cast(facing), static_cast(function), referenceValue, mask); + } + + /** + * @brief Set stencil function + * + * The same as setStencilFunction(PolygonFacing, StencilFunction, GLint, GLuint) + * with `facing` set to `PolygonFacing::FrontAndBack`. + * @see @fn_gl{StencilFunc} + */ + inline static void setStencilFunction(StencilFunction function, GLint referenceValue, GLuint mask) { + glStencilFunc(static_cast(function), referenceValue, mask); + } + + /** + * @brief Set stencil operation + * @param facing Affected polygon facing + * @param stencilFail Action when stencil test fails + * @param depthFail Action when stencil test passes, but depth + * test fails + * @param depthPass Action when both stencil and depth test + * pass + * + * Initial value for all fields is `StencilOperation::Keep`. + * @attention You have to enable stencil test with setFeature() first. + * @see setStencilOperation(StencilOperation, StencilOperation, StencilOperation), + * @fn_gl{StencilOpSeparate} + */ + inline static void setStencilOperation(PolygonFacing facing, StencilOperation stencilFail, StencilOperation depthFail, StencilOperation depthPass) { + glStencilOpSeparate(static_cast(facing), static_cast(stencilFail), static_cast(depthFail), static_cast(depthPass)); + } + + /** + * @brief Set stencil operation + * + * The same as setStencilOperation(PolygonFacing, StencilOperation, StencilOperation, StencilOperation) + * with `facing` set to `PolygonFacing::FrontAndBack`. + * @see @fn_gl{StencilOp} + */ + inline static void setStencilOperation(StencilOperation stencilFail, StencilOperation depthFail, StencilOperation depthPass) { + glStencilOp(static_cast(stencilFail), static_cast(depthFail), static_cast(depthPass)); + } + + /*@}*/ + + /** @{ @name Depth testing */ + + /** + * @brief Depth function + * + * @see setDepthFunction() + */ + typedef StencilFunction DepthFunction; + + /** + * @brief Set depth function + * + * Initial value is `DepthFunction::Less`. + * @attention You have to enable depth test with setFeature() first. + * @see @fn_gl{DepthFunc} + */ + inline static void setDepthFunction(DepthFunction function) { + glDepthFunc(static_cast(function)); + } + + /*@}*/ + + /** @{ @name Masking writes */ + + /** + * @brief Mask color writes + * + * Set to `false` to disallow writing to given color channel. Initial + * values are all `true`. + * @see @fn_gl{ColorMask} + * @todo Masking only given draw buffer + */ + inline static void setColorMask(GLboolean allowRed, GLboolean allowGreen, GLboolean allowBlue, GLboolean allowAlpha) { + glColorMask(allowRed, allowGreen, allowBlue, allowAlpha); + } + + /** + * @brief Mask depth writes + * + * Set to `false` to disallow writing to depth buffer. Initial value + * is `true`. + * @see @fn_gl{DepthMask} + */ + inline static void setDepthMask(GLboolean allow) { + glDepthMask(allow); + } + + /** + * @brief Mask stencil writes + * + * Set given bit to `0` to disallow writing stencil value for given + * faces to it. Initial value is all `1`s. + * @see setStencilMask(GLuint), @fn_gl{StencilMaskSeparate} + */ + inline static void setStencilMask(PolygonFacing facing, GLuint allowBits) { + glStencilMaskSeparate(static_cast(facing), allowBits); + } + + /** + * @brief Mask stencil writes + * + * The same as setStencilMask(PolygonFacing, GLuint) with `facing` set + * to `PolygonFacing::FrontAndBack`. + * @see @fn_gl{StencilMask} + */ + inline static void setStencilMask(GLuint allowBits) { + glStencilMask(allowBits); + } + + /*@}*/ + + /** @{ @name Blending + * You have to enable blending with setFeature() first. + * @todo Blending for given draw buffer + */ + + /** + * @brief Blend equation + * + * @see setBlendEquation() + */ + enum class BlendEquation: GLenum { + Add = GL_FUNC_ADD, /**< `source + destination` */ + Subtract = GL_FUNC_SUBTRACT, /**< `source - destination` */ + ReverseSubtract = GL_FUNC_REVERSE_SUBTRACT /**< `destination - source` */ + + #ifndef MAGNUM_TARGET_GLES2 + , + /** + * `min(source, destination)` + * @requires_gles30 %Extension @es_extension2{EXT,blend_minmax,blend_minmax} + */ + Min = GL_MIN, + + /** + * `max(source, destination)` + * @requires_gles30 %Extension @es_extension2{EXT,blend_minmax,blend_minmax} + */ + Max = GL_MAX + #endif + }; + + /** + * @brief Blend function + * + * @see setBlendFunction() + */ + enum class BlendFunction: GLenum { + /** Zero (@f$ RGB = (0.0, 0.0, 0.0); A = 0.0 @f$) */ + Zero = GL_ZERO, + + /** One (@f$ RGB = (1.0, 1.0, 1.0); A = 1.0 @f$) */ + One = GL_ONE, + + /** + * Constant color (@f$ RGB = (R_c, G_c, B_c); A = A_c @f$) + * + * @see setBlendColor() + */ + ConstantColor = GL_CONSTANT_COLOR, + + /** + * One minus constant color (@f$ RGB = (1.0 - R_c, 1.0 - G_c, 1.0 - B_c); A = 1.0 - A_c @f$) + * + * @see setBlendColor() + */ + OneMinusConstantColor = GL_ONE_MINUS_CONSTANT_COLOR, + + /** + * Constant alpha (@f$ RGB = (A_c, A_c, A_c); A = A_c @f$) + * + * @see setBlendColor() + */ + ConstantAlpha = GL_CONSTANT_ALPHA, + + /** + * One minus constant alpha (@f$ RGB = (1.0 - A_c, 1.0 - A_c, 1.0 - A_c); A = 1.0 - A_c @f$) + * + * @see setBlendColor() + */ + OneMinusConstantAlpha = GL_ONE_MINUS_CONSTANT_ALPHA, + + /** Source color (@f$ RGB = (R_{s0}, G_{s0}, B_{s0}); A = A_{s0} @f$) */ + SourceColor = GL_SRC_COLOR, + + #ifndef MAGNUM_TARGET_GLES + /** + * Second source color (@f$ RGB = (R_{s1}, G_{s1}, B_{s1}); A = A_{s1} @f$) + * + * @see AbstractShaderProgram::bindFragmentDataLocationIndexed() + * @requires_gl33 Extension @extension{ARB,blend_func_extended} + * @requires_gl Multiple blending inputs are not available in + * OpenGL ES. + */ + SecondSourceColor = GL_SRC1_COLOR, + #endif + + /** + * One minus source color (@f$ RGB = (1.0 - R_{s0}, 1.0 - G_{s0}, 1.0 - B_{s0}); A = 1.0 - A_{s0} @f$) + */ + OneMinusSourceColor = GL_ONE_MINUS_SRC_COLOR, + + #ifndef MAGNUM_TARGET_GLES + /** + * One minus second source color (@f$ RGB = (1.0 - R_{s1}, 1.0 - G_{s1}, 1.0 - B_{s1}); A = 1.0 - A_{s1} @f$) + * + * @see AbstractShaderProgram::bindFragmentDataLocationIndexed() + * @requires_gl33 Extension @extension{ARB,blend_func_extended} + * @requires_gl Multiple blending inputs are not available in + * OpenGL ES. + */ + OneMinusSecondSourceColor = GL_ONE_MINUS_SRC1_COLOR, + #endif + + /** Source alpha (@f$ RGB = (A_{s0}, A_{s0}, A_{s0}); A = A_{s0} @f$) */ + SourceAlpha = GL_SRC_ALPHA, + + /** + * Saturate source alpha (@f$ RGB = (f, f, f); A = 1.0; f = min(A_s, 1.0 - A_d) @f$) + * + * Can be used only in source parameter of setBlendFunction(). + */ + SourceAlphaSaturate = GL_SRC_ALPHA_SATURATE, + + #ifndef MAGNUM_TARGET_GLES + /** + * Second source alpha (@f$ RGB = (A_{s1}, A_{s1}, A_{s1}); A = A_{s1} @f$) + * + * @see AbstractShaderProgram::bindFragmentDataLocationIndexed() + * @requires_gl33 Extension @extension{ARB,blend_func_extended} + * @requires_gl Multiple blending inputs are not available in + * OpenGL ES. + */ + SecondSourceAlpha = GL_SRC1_ALPHA, + #endif + + /** + * One minus source alpha (@f$ RGB = (1.0 - A_{s0}, 1.0 - A_{s0}, 1.0 - A_{s0}); A = 1.0 - A_{s0} @f$) + */ + OneMinusSourceAlpha = GL_ONE_MINUS_SRC_ALPHA, + + #ifndef MAGNUM_TARGET_GLES + /** + * One minus second source alpha (@f$ RGB = (1.0 - A_{s1}, 1.0 - A_{s1}, 1.0 - A_{s1}); A = 1.0 - A_{s1} @f$) + * + * @see AbstractShaderProgram::bindFragmentDataLocationIndexed() + * @requires_gl33 Extension @extension{ARB,blend_func_extended} + * @requires_gl Multiple blending inputs are not available in + * OpenGL ES. + */ + OneMinusSecondSourceAlpha = GL_ONE_MINUS_SRC1_ALPHA, + #endif + + /** Destination color (@f$ RGB = (R_d, G_d, B_d); A = A_d @f$) */ + DestinationColor = GL_DST_COLOR, + + /** + * One minus source color (@f$ RGB = (1.0 - R_d, 1.0 - G_d, 1.0 - B_d); A = 1.0 - A_d @f$) + */ + OneMinusDestinationColor = GL_ONE_MINUS_DST_COLOR, + + /** Destination alpha (@f$ RGB = (A_d, A_d, A_d); A = A_d @f$) */ + DestinationAlpha = GL_DST_ALPHA, + + /** + * One minus source alpha (@f$ RGB = (1.0 - A_d, 1.0 - A_d, 1.0 - A_d); A = 1.0 - A_d @f$) + */ + OneMinusDestinationAlpha = GL_ONE_MINUS_DST_ALPHA + }; + + /** + * @brief Set blend equation + * + * How to combine source color (pixel value) with destination color + * (framebuffer). Initial value is `BlendEquation::Add`. + * @attention You have to enable blending with setFeature() first. + * @see setBlendEquation(BlendEquation, BlendEquation), + * @fn_gl{BlendEquation} + */ + inline static void setBlendEquation(BlendEquation equation) { + glBlendEquation(static_cast(equation)); + } + + /** + * @brief Set blend equation separately for RGB and alpha components + * + * See setBlendEquation(BlendEquation) for more information. + * @attention You have to enable blending with setFeature() first. + * @see @fn_gl{BlendEquationSeparate} + */ + inline static void setBlendEquation(BlendEquation rgb, BlendEquation alpha) { + glBlendEquationSeparate(static_cast(rgb), static_cast(alpha)); + } + + /** + * @brief Set blend function + * @param source How the source blending factor is computed + * from pixel value. Initial value is `BlendFunction::One`. + * @param destination How the destination blending factor is + * computed from framebuffer. Initial value is + * `BlendFunction::Zero`. + * + * @attention You have to enable blending with setFeature() first. + * @see setBlendFunction(BlendFunction, BlendFunction, BlendFunction, BlendFunction), + * @fn_gl{BlendFunc} + */ + inline static void setBlendFunction(BlendFunction source, BlendFunction destination) { + glBlendFunc(static_cast(source), static_cast(destination)); + } + + /** + * @brief Set blend function separately for RGB and alpha components + * + * See setBlendFunction(BlendFunction, BlendFunction) for more information. + * @attention You have to enable blending with setFeature() first. + * @see @fn_gl{BlendFuncSeparate} + */ + inline static void setBlendFunction(BlendFunction sourceRgb, BlendFunction destinationRgb, BlendFunction sourceAlpha, BlendFunction destinationAlpha) { + glBlendFuncSeparate(static_cast(sourceRgb), static_cast(destinationRgb), static_cast(sourceAlpha), static_cast(destinationAlpha)); + } + + /** + * @brief Set blend color + * + * Sets constant color used in setBlendFunction() by + * `BlendFunction::ConstantColor`, + * `BlendFunction::OneMinusConstantColor`, + * `BlendFunction::ConstantAlpha` and + * `BlendFunction::OneMinusConstantAlpha`. + * @attention You have to enable blending with setFeature() first. + * @see @fn_gl{BlendColor} + */ + inline static void setBlendColor(const Color4<>& color) { + glBlendColor(color.r(), color.g(), color.b(), color.a()); + } + + /*@}*/ + + #ifndef MAGNUM_TARGET_GLES + /** @{ @name Logical operation */ + + /** + * @brief Logical operation + * + * @see setLogicOperation() + * @requires_gl Logical operations on framebuffer are not available in + * OpenGL ES. + */ + enum class LogicOperation: GLenum { + Clear = GL_CLEAR, /**< `0` */ + Set = GL_SET, /**< `1` */ + Copy = GL_COPY, /**< `source` */ + CopyInverted = GL_COPY_INVERTED,/**< `~source` */ + Noop = GL_NOOP, /**< `destination` */ + Invert = GL_INVERT, /**< `~destination` */ + And = GL_AND, /**< `source & destination` */ + AndReverse = GL_AND_REVERSE, /**< `source & ~destination` */ + AndInverted = GL_AND_INVERTED, /**< `~source & destination` */ + Nand = GL_NAND, /**< `~(source & destination)` */ + Or = GL_OR, /**< `source | destination` */ + OrReverse = GL_OR_REVERSE, /**< `source | ~destination` */ + OrInverted = GL_OR_INVERTED, /**< `~source | destination` */ + Nor = GL_NOR, /**< `~(source | destination)` */ + Xor = GL_XOR, /**< `source ^ destination` */ + Equivalence = GL_EQUIV /**< `~(source ^ destination)` */ + }; + + /** + * @brief Set logical operation + * + * @attention You have to enable logical operation with setFeature() first. + * @see @fn_gl{LogicOp} + * @requires_gl Logical operations on framebuffer are not available in + * OpenGL ES. + */ + inline static void setLogicOperation(LogicOperation operation) { + glLogicOp(static_cast(operation)); + } + + /*@}*/ + #endif +}; + +} + +#endif