mirror of https://github.com/mosra/magnum.git
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.
543 lines
17 KiB
543 lines
17 KiB
#ifndef Magnum_Shaders_GenericGL_h |
|
#define Magnum_Shaders_GenericGL_h |
|
/* |
|
This file is part of Magnum. |
|
|
|
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, |
|
2020, 2021, 2022 Vladimír Vondruš <mosra@centrum.cz> |
|
|
|
Permission is hereby granted, free of charge, to any person obtaining a |
|
copy of this software and associated documentation files (the "Software"), |
|
to deal in the Software without restriction, including without limitation |
|
the rights to use, copy, modify, merge, publish, distribute, sublicense, |
|
and/or sell copies of the Software, and to permit persons to whom the |
|
Software is furnished to do so, subject to the following conditions: |
|
|
|
The above copyright notice and this permission notice shall be included |
|
in all copies or substantial portions of the Software. |
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
|
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
|
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
|
DEALINGS IN THE SOFTWARE. |
|
*/ |
|
|
|
/** @file |
|
* @brief Struct @ref Magnum::Shaders::GenericGL, typedef @ref Magnum::Shaders::GenericGL2D, @ref Magnum::Shaders::GenericGL3D |
|
* @m_since_latest |
|
*/ |
|
|
|
#include "Magnum/GL/Attribute.h" |
|
#include "Magnum/Shaders/Shaders.h" |
|
|
|
namespace Magnum { namespace Shaders { |
|
|
|
/** |
|
@brief Generic OpenGL shader definition |
|
@m_since_latest |
|
|
|
Definitions common for majority of OpenGL shaders in the @ref Shaders |
|
namespace, allowing mesh or a framebuffer configured for a generic shader to be |
|
used with any of them. See @ref shaders-generic for more information. |
|
|
|
@section Shaders-GenericGL-allocation Attribute allocation |
|
|
|
The attribute locations are allocated like shown below, with various tradeoffs |
|
as GPUs commonly support only 16 attribtes at most, while the mandated minimum |
|
on OpenGL ES2 and WebGL 1 being only 8. Some locations are only reserved for |
|
future use, with no attribute definition implemented yet. |
|
|
|
@m_class{m-row m-container-inflate} |
|
|
|
@parblock |
|
|
|
@m_class{m-fullwidth} |
|
|
|
<table> |
|
<tr> |
|
<th>\#</th> |
|
<th>Attribute</th> |
|
<th>Alternative</th> |
|
<th>Alternative 2</th> |
|
</tr> |
|
<tr> |
|
<td>0</td> |
|
<td colspan="3"> |
|
@ref Position |
|
</td> |
|
</tr> |
|
<tr> |
|
<td>1</td> |
|
<td colspan="3"> |
|
@ref TextureCoordinates |
|
|
|
* *Reserved* --- third component for a layer |
|
</td> |
|
</tr> |
|
<tr> |
|
<td>2</td> |
|
<td colspan="3"> |
|
@ref Color3 / @ref Color4 (per-vertex or instanced) |
|
</td> |
|
</tr> |
|
<tr> |
|
<td>3</td> |
|
<td> |
|
@ref Tangent / @ref Tangent4 |
|
</td> |
|
<td> |
|
@ref Tangent |
|
</td> |
|
<td> |
|
* *Reserved* --- TBN as a @ref Magnum::Quaternion "Quaternion" |
|
</td> |
|
</tr> |
|
<tr> |
|
<td>4</td> |
|
<td> |
|
@ref ObjectId (instanced) |
|
|
|
* *Reserved* --- additional components could \n |
|
represent material ID and other indices, which \n |
|
could then be used to fetch additional \n |
|
per-instance properties that wouldn't fit into \n |
|
vertex attributes. |
|
</td> |
|
<td colspan="2"> |
|
@ref Bitangent |
|
|
|
Provided only as a convenience for models that \n |
|
don't encode bitangent orientation in the last \n |
|
component of @ref Tangent4. If a model needs \n |
|
both bitangents and object ID for instancing, \n |
|
@ref Tangent4 has to be used. |
|
</td> |
|
</tr> |
|
<tr> |
|
<td>5</td> |
|
<td colspan="3"> |
|
@ref Normal |
|
</td> |
|
</tr> |
|
<tr> |
|
<td>6</td> |
|
<td colspan="3"> |
|
* *Reserved* --- vertex weights |
|
</td> |
|
</tr> |
|
<tr> |
|
<td>7</td> |
|
<td colspan="3"> |
|
* *Reserved* --- bone indices |
|
</td> |
|
</tr> |
|
<tr> |
|
<td>8</td> |
|
<td rowspan="4"> |
|
@ref TransformationMatrix (instanced) |
|
</td> |
|
<td rowspan="2" colspan="2"> |
|
* *Reserved* --- instanced @ref Magnum::DualQuaternion "DualQuaternion" \n transformation for positions and normals |
|
</td> |
|
</tr> |
|
<tr> |
|
<td>9</td> |
|
</tr> |
|
<tr> |
|
<td>10</td> |
|
<td colspan="2"> |
|
* *Reserved* --- 2nd vertex weights |
|
</td> |
|
</tr> |
|
<tr> |
|
<td>11</td> |
|
<td colspan="2"> |
|
* *Reserved* --- 2nd bone indices |
|
</td> |
|
</tr> |
|
<tr> |
|
<td>12</td> |
|
<td rowspan="3"> |
|
@ref NormalMatrix (instanced) |
|
</td> |
|
<td colspan="2"> |
|
* *Reserved* --- instanced scale for positions |
|
</td> |
|
</tr> |
|
<tr> |
|
<td>13</td> |
|
<td rowspan="2"> |
|
* *Reserved* --- instanced texture \n |
|
rotation and scale |
|
</td> |
|
<td> |
|
* *Reserved* --- 2nd vertex colors |
|
</td> |
|
</tr> |
|
<tr> |
|
<td>14</td> |
|
<td> |
|
* *Reserved* --- 3rd texture coords |
|
</td> |
|
</tr> |
|
<tr> |
|
<td>15</td> |
|
<td> |
|
@ref TextureOffset / @ref TextureOffsetLayer (instanced) |
|
</td> |
|
<td> |
|
* *Reserved* --- a single component \n |
|
representing instanced texture layer \n |
|
index, UVs being the same always |
|
</td> |
|
<td> |
|
* *Reserved* --- 2nd texture coords |
|
</td> |
|
</tr> |
|
</table> |
|
|
|
@endparblock |
|
|
|
The three alternative allocations can be mixed freely as long as the locations |
|
don't conflict --- so it's possible to have for example a mesh with two sets of |
|
texture coordinates, weights and colors, as each of those occupies a different |
|
attribute range; but instancing then has to be done using smaller types as full |
|
matrices would occupy the locations used by the secondary sets. Additional |
|
guarantees of the above: |
|
|
|
- @ref Tangent, @ref Bitangent and @ref Normal is in consecutive locations to |
|
allow those being passed as a single TBN @ref Magnum::Matrix3x3 "Matrix3x3" |
|
attribute as well. |
|
- @ref Normal and TBN represented as a quaternion use different locations in |
|
order to allow a mesh to contain both |
|
- Similarly, texture rotation/scale and offset is in consecutive locations to |
|
allow passing a single @ref Matrix3 attribute there. |
|
- Tnstanced texture transformation is available if and only if there's |
|
exactly one set of texture coordinates (as the additional sets would need |
|
additional transformations as well). |
|
|
|
@section Shaders-GenericGL-custom Generic attributes and custom shaders |
|
|
|
Note that while custom shaders don't *have to* follow the above, it's |
|
recommended to so. If the custom shader diverges from predefined locations of |
|
common attributes, meshes configured for the builtin shaders (for example with |
|
@ref MeshTools::compile()) won't work with it and the mesh attribute |
|
configuration has to be done manually. It also becomes impossible to render a |
|
mesh configured for a custom shader with for example @ref MeshVisualizer. |
|
|
|
If you're using @ref GL::AbstractShaderProgram::bindAttributeLocation(), it's |
|
rather easy, as you can simply use the @ref GL::Attribute::Location of given |
|
attribute: |
|
|
|
@snippet MagnumShaders-gl.cpp GenericGL-custom-bind |
|
|
|
For attribute location defined directly in shader code (which is the |
|
recommended way unless you need compatibility with WebGL 1.0 and OpenGL ES |
|
2.0), the attribute locations can be propagated using a preprocessor define. |
|
For example: |
|
|
|
@snippet MagnumShaders-gl.cpp GenericGL-custom-preprocessor |
|
|
|
Then, the attribute definition in a shader will look like this: |
|
|
|
@code{.glsl} |
|
layout(location = POSITION_ATTRIBUTE_LOCATION) in vec3 position; |
|
layout(location = NORMAL_ATTRIBUTE_LOCATION) in vec3 normal; |
|
@endcode |
|
|
|
@see @ref shaders, @ref GenericGL2D, @ref GenericGL3D |
|
*/ |
|
#ifndef DOXYGEN_GENERATING_OUTPUT |
|
template<UnsignedInt> struct GenericGL; |
|
#else |
|
template<UnsignedInt dimensions> struct GenericGL { |
|
/* Keep consistent with generic.glsl and the real definitions below */ |
|
|
|
enum: UnsignedInt { |
|
/** |
|
* Color shader output. Present always, expects three- or |
|
* four-component floating-point or normalized buffer attachment. |
|
*/ |
|
ColorOutput = 0, |
|
|
|
#ifndef MAGNUM_TARGET_GLES2 |
|
/** |
|
* Object ID shader output. Expects a single-component unsigned |
|
* integral attachment. |
|
* @requires_gl30 Extension @gl_extension{EXT,texture_integer} |
|
* @requires_gles30 Object ID output requires integer support in |
|
* shaders, which is not available in OpenGL ES 2.0. |
|
* @requires_webgl20 Object ID output requires integer support in |
|
* shaders, which is not available in WebGL 1.0. |
|
*/ |
|
ObjectIdOutput = 1 |
|
#endif |
|
}; |
|
|
|
/** |
|
* @brief Vertex position |
|
* |
|
* @ref Magnum::Vector2 "Vector2" in 2D and @ref Magnum::Vector3 "Vector3" |
|
* in 3D. Corresponds to @ref Trade::MeshAttribute::Position. |
|
*/ |
|
typedef GL::Attribute<0, T> Position; |
|
|
|
/** |
|
* @brief 2D texture coordinates |
|
* |
|
* @ref Magnum::Vector2 "Vector2". Corresponds to |
|
* @ref Trade::MeshAttribute::TextureCoordinates. |
|
*/ |
|
typedef GL::Attribute<1, Vector2> TextureCoordinates; |
|
|
|
/** |
|
* @brief Three-component vertex color |
|
* |
|
* @ref Magnum::Color3. Use either this or the @ref Color4 attribute. |
|
* Corresponds to @ref Trade::MeshAttribute::Color. |
|
*/ |
|
typedef GL::Attribute<2, Magnum::Color3> Color3; |
|
|
|
/** |
|
* @brief Four-component vertex color |
|
* |
|
* @ref Magnum::Color4. Use either this or the @ref Color3 attribute. |
|
* Corresponds to @ref Trade::MeshAttribute::Color. |
|
*/ |
|
typedef GL::Attribute<2, Magnum::Color4> Color4; |
|
|
|
/** |
|
* @brief Vertex tangent |
|
* @m_since{2019,10} |
|
* |
|
* @ref Magnum::Vector3 "Vector3", defined only in 3D. Use either this or |
|
* the @ref Tangent4 attribute. Corresponds to |
|
* @ref Trade::MeshAttribute::Tangent. |
|
*/ |
|
typedef GL::Attribute<3, Vector3> Tangent; |
|
|
|
/** |
|
* @brief Vertex tangent with a bitangent sign |
|
* @m_since{2020,06} |
|
* |
|
* @ref Magnum::Vector4 "Vector4", defined only in 3D. The last component |
|
* is a sign value (@cpp -1.0f @ce or @cpp +1.0f @ce) defining handedness |
|
* of the tangent basis. Reconstructing the @ref Bitangent attribute can be |
|
* then done like this: |
|
* |
|
* @snippet MagnumTrade.cpp MeshAttribute-bitangent-from-tangent |
|
* |
|
* Use either this or the @ref Tangent attribute. Corresponds to |
|
* @ref Trade::MeshAttribute::Tangent. |
|
*/ |
|
typedef GL::Attribute<3, Vector4> Tangent4; |
|
|
|
/** |
|
* @brief Vertex bitangent |
|
* @m_since{2020,06} |
|
* |
|
* @ref Magnum::Vector3 "Vector3", defined only in 3D. For better storage |
|
* efficiency, the bitangent can be also reconstructed from the normal and |
|
* tangent, see @ref Tangent4 for more information. Corresponds to |
|
* @ref Trade::MeshAttribute::Bitangent. |
|
* |
|
* This attribute conflicts with @ref ObjectId, if you want to use both |
|
* instanced object ID and bitangents, you need to reconstruct them from |
|
* @ref Tangent4 instead. |
|
*/ |
|
typedef GL::Attribute<4, Vector3> Bitangent; |
|
|
|
#ifndef MAGNUM_TARGET_GLES2 |
|
/** |
|
* @brief (Instanced) object ID |
|
* @m_since{2020,06} |
|
* |
|
* @ref Magnum::UnsignedInt "UnsignedInt". Corresponds to |
|
* @ref Trade::MeshAttribute::ObjectId. |
|
* |
|
* This attribute conflicts with @ref Bitangent, if you want to use both |
|
* instanced object ID and bitangents, you need to reconstruct them from |
|
* @ref Tangent4 instead. |
|
* @requires_gl30 Extension @gl_extension{EXT,gpu_shader4} |
|
* @requires_gles30 Object ID output requires integer support in shaders, |
|
* which is not available in OpenGL ES 2.0. |
|
* @requires_webgl20 Object ID output requires integer support in shaders, |
|
* which is not available in WebGL 1.0. |
|
*/ |
|
typedef GL::Attribute<4, UnsignedInt> ObjectId; |
|
#endif |
|
|
|
/* Index 4 also used by MeshVisualizer::VertexIndex (reusing ObjectId). Not |
|
making it generic yet, as its use case is limited to a single shader, |
|
and even there it's just a fallback for platforms w/o gl_VertexID. */ |
|
|
|
/** |
|
* @brief Vertex normal |
|
* |
|
* @ref Magnum::Vector3 "Vector3", defined only in 3D. Corresponds to |
|
* @ref Trade::MeshAttribute::Normal. |
|
*/ |
|
typedef GL::Attribute<5, Vector3> Normal; |
|
|
|
/* 6, 7 reserved for vertex weights / bone IDs */ |
|
|
|
/** |
|
* @brief (Instanced) transformation matrix |
|
* @m_since{2020,06} |
|
* |
|
* @ref Magnum::Matrix3 "Matrix3" in 2D and @ref Magnum::Matrix4 "Matrix4" |
|
* in 3D. Currently doesn't have a corresponding @ref Trade::MeshAttribute. |
|
* @requires_gl33 Extension @gl_extension{ARB,instanced_arrays} |
|
* @requires_gles30 Extension @gl_extension{ANGLE,instanced_arrays}, |
|
* @gl_extension{EXT,instanced_arrays} or |
|
* @gl_extension{NV,instanced_arrays} in OpenGL ES 2.0. |
|
* @requires_webgl20 Extension @webgl_extension{ANGLE,instanced_arrays} |
|
* in WebGL 1.0. |
|
*/ |
|
typedef GL::Attribute<8, T> TransformationMatrix; |
|
|
|
/* 9, 10, 11 occupied by TransformationMatrix */ |
|
|
|
/** |
|
* @brief (Instanced) normal matrix |
|
* @m_since{2020,06} |
|
* |
|
* @ref Magnum::Matrix3 "Matrix3x3", defined only in 3D. Currently doesn't |
|
* have a corresponding @ref Trade::MeshAttribute. |
|
* @requires_gl33 Extension @gl_extension{ARB,instanced_arrays} |
|
* @requires_gles30 Extension @gl_extension{ANGLE,instanced_arrays}, |
|
* @gl_extension{EXT,instanced_arrays} or |
|
* @gl_extension{NV,instanced_arrays} in OpenGL ES 2.0. |
|
* @requires_webgl20 Extension @webgl_extension{ANGLE,instanced_arrays} |
|
* in WebGL 1.0. |
|
*/ |
|
typedef GL::Attribute<12, Matrix3x3> NormalMatrix; |
|
|
|
/* 13, 14 occupied by NormalMatrix */ |
|
|
|
/** |
|
* @brief (Instanced) texture offset |
|
* @m_since{2020,06} |
|
* |
|
* @ref Magnum::Vector2 "Vector2". Use either this or the |
|
* @ref TextureOffsetLayer attribute. Currently doesn't have a |
|
* corresponding @ref Trade::MeshAttribute. |
|
* @requires_gl33 Extension @gl_extension{ARB,instanced_arrays} |
|
* @requires_gles30 Extension @gl_extension{ANGLE,instanced_arrays}, |
|
* @gl_extension{EXT,instanced_arrays} or |
|
* @gl_extension{NV,instanced_arrays} in OpenGL ES 2.0. |
|
* @requires_webgl20 Extension @webgl_extension{ANGLE,instanced_arrays} |
|
* in WebGL 1.0. |
|
*/ |
|
typedef GL::Attribute<15, Vector2> TextureOffset; |
|
|
|
#ifndef MAGNUM_TARGET_GLES2 |
|
/** |
|
* @brief (Instanced) texture offset and layer |
|
* @m_since_latest |
|
* |
|
* @ref Magnum::Vector3 "Vector3", with the last component interpreted as |
|
* an integer. Use either this or the @ref TextureOffset attribute. |
|
* Currently doesn't have a corresponding @ref Trade::MeshAttribute. |
|
* @requires_gl33 Extension @gl_extension{EXT,texture_array} and |
|
* @gl_extension{ARB,instanced_arrays} |
|
* @requires_gles30 Texture arrays are not available in OpenGL ES 2.0. |
|
* @requires_webgl20 Texture arrays are not available in WebGL 1.0. |
|
*/ |
|
typedef GL::Attribute<15, Vector3> TextureOffsetLayer; |
|
#endif |
|
}; |
|
#endif |
|
|
|
/** |
|
@brief Generic 2D OpenGL shader definition |
|
@m_since_latest |
|
*/ |
|
typedef GenericGL<2> GenericGL2D; |
|
|
|
/** |
|
@brief Generic 3D OpenGL shader definition |
|
@m_since_latest |
|
*/ |
|
typedef GenericGL<3> GenericGL3D; |
|
|
|
#ifndef DOXYGEN_GENERATING_OUTPUT |
|
struct BaseGenericGL { |
|
enum: UnsignedInt { |
|
ColorOutput = 0, |
|
#ifndef MAGNUM_TARGET_GLES2 |
|
ObjectIdOutput = 1 |
|
#endif |
|
}; |
|
|
|
typedef GL::Attribute<1, Vector2> TextureCoordinates; |
|
typedef GL::Attribute<2, Magnum::Color3> Color3; |
|
typedef GL::Attribute<2, Magnum::Color4> Color4; |
|
#ifndef MAGNUM_TARGET_GLES2 |
|
typedef GL::Attribute<4, UnsignedInt> ObjectId; |
|
#endif |
|
|
|
typedef GL::Attribute<15, Vector2> TextureOffset; |
|
#ifndef MAGNUM_TARGET_GLES2 |
|
typedef GL::Attribute<15, Vector3> TextureOffsetLayer; |
|
#endif |
|
}; |
|
|
|
template<> struct GenericGL<2>: BaseGenericGL { |
|
typedef GL::Attribute<0, Vector2> Position; |
|
/* 1, 2 used by TextureCoordinates and Color */ |
|
|
|
typedef GL::Attribute<8, Matrix3> TransformationMatrix; |
|
/* 9, 10 occupied by TransformationMatrix */ |
|
/* 15 used by TextureOffset */ |
|
}; |
|
|
|
template<> struct GenericGL<3>: BaseGenericGL { |
|
typedef GL::Attribute<0, Vector3> Position; |
|
/* 1, 2 used by TextureCoordinates and Color */ |
|
typedef GL::Attribute<3, Vector3> Tangent; |
|
typedef GL::Attribute<3, Vector4> Tangent4; |
|
typedef GL::Attribute<4, Vector3> Bitangent; /* also ObjectId */ |
|
typedef GL::Attribute<5, Vector3> Normal; |
|
/* 6, 7 reserved for vertex weights / bone IDs */ |
|
|
|
typedef GL::Attribute<8, Matrix4> TransformationMatrix; |
|
/* 9, 10, 11 occupied by TransformationMatrix */ |
|
typedef GL::Attribute<12, Matrix3x3> NormalMatrix; |
|
/* 13, 14 occupied by NormalMatrix */ |
|
/* 15 used by TextureOffset */ |
|
}; |
|
#endif |
|
|
|
#ifdef MAGNUM_BUILD_DEPRECATED |
|
/* Deprecated aliases present here instead of GenericGL.h, as a lot of existing |
|
code relies on these being transitively included from Phong.h etc., and |
|
there are no forward declarations in Shaders.h as the type is never used |
|
like that. While we *could* include Generic.h from Phong.h, we'd have to |
|
also temporarily disable the CORRADE_DEPRECATED_FILE() macro there and it's |
|
more pain than it's worth. */ |
|
|
|
/** @brief @copybrief GenericGL |
|
* @m_deprecated_since_latest Use @ref GenericGL instead. |
|
*/ |
|
#ifndef CORRADE_MSVC2015_COMPATIBILITY /* Multiple definitions still broken */ |
|
template<UnsignedInt dimensions> using Generic CORRADE_DEPRECATED_ALIAS("use GenericGL instead") = GenericGL<dimensions>; |
|
#endif |
|
|
|
/** @brief @copybrief GenericGL2D |
|
* @m_deprecated_since_latest Use @ref GenericGL2D instead. |
|
*/ |
|
typedef CORRADE_DEPRECATED("use GenericGL2D instead") GenericGL2D Generic2D; |
|
|
|
/** @brief @copybrief GenericGL3D |
|
* @m_deprecated_since_latest Use @ref GenericGL3D instead. |
|
*/ |
|
typedef CORRADE_DEPRECATED("use GenericGL3D instead") GenericGL3D Generic3D; |
|
#endif |
|
|
|
}} |
|
|
|
#endif
|
|
|