You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

649 lines
24 KiB

#ifndef Magnum_Renderer_h
#define Magnum_Renderer_h
/*
Copyright © 2010, 2011, 2012 Vladimír Vondruš <mosra@centrum.cz>
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 <Containers/EnumSet.h>
#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 {
public:
Renderer() = delete;
/**
* @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<GLenum>(feature)) : glDisable(static_cast<GLenum>(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<GLenum>(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<GLenum>(facing), static_cast<GLenum>(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<GLenum>(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<GLenum>(facing), static_cast<GLenum>(stencilFail), static_cast<GLenum>(depthFail), static_cast<GLenum>(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<GLenum>(stencilFail), static_cast<GLenum>(depthFail), static_cast<GLenum>(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<GLenum>(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<GLenum>(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<GLenum>(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<GLenum>(rgb), static_cast<GLenum>(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<GLenum>(source), static_cast<GLenum>(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<GLenum>(sourceRgb), static_cast<GLenum>(destinationRgb), static_cast<GLenum>(sourceAlpha), static_cast<GLenum>(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<GLenum>(operation));
}
/*@}*/
#endif
};
}
#endif