template<UnsignedInt dimensions>
Magnum::Shaders::Generic struct

Generic shader definition.

Definitions common for majority of shaders in the Shaders namespace, allowing mesh or a framebuffer configured for a generic shader to be used with any of them. See Generic vertex attributes and framebuffer attachments for more information.

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.

#AttributeAlternativeAlternative 2
0Position
1

TextureCoordinates

Reserved — third component for a layer

2Color3 / Color4 (per-vertex or instanced)
3Tangent / Tangent4TangentReserved — TBN as a Quaternion
4

ObjectId (instanced)

Reserved — additional components could
represent material ID and other indices, which
could then be used to fetch additional
per-instance properties that wouldn't fit into
vertex attributes.

Bitangent

Provided only as a convenience for models that
don't encode bitangent orientation in the last
component of Tangent4. If a model needs
both bitangents and object ID for instancing,
Tangent4 has to be used.

5Normal
6Reserved — vertex weights
7Reserved — bone indices
8TransformationMatrix (instanced)Reserved — instanced DualQuaternion
transformation for positions and normals
9
10Reserved — 2nd vertex weights
11Reserved — 2nd bone indices
12NormalMatrix (instanced)Reserved — instanced scale for positions
13Reserved — instanced texture
rotation and scale
Reserved — 2nd vertex colors
14Reserved — 3rd texture coords
15

TextureOffset (instanced)

Reserved — third component for a layer

Reserved — a single component
representing instanced texture layer
index, UVs being the same always
Reserved — 2nd texture coords

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:

  • Tangent, Bitangent and Normal is in consecutive locations to allow those being passed as a single TBN Matrix3x3 attribute as well.
  • 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 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).

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 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 MeshVisualizer.

If you're using GL::AbstractShaderProgram::bindAttributeLocation(), it's rather easy, as you can simply use the GL::Attribute::Location of given attribute:

bindAttributeLocation(Shaders::Generic3D::Position::Location, "position");
bindAttributeLocation(Shaders::Generic3D::Normal::Location, "normal");

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:

vert.addSource(Utility::formatString(
    "#define POSITION_ATTRIBUTE_LOCATION {}\n"
    "#define NORMAL_ATTRIBUTE_LOCATION {}\n",
    Shaders::Generic3D::Position::Location,
    Shaders::Generic3D::Normal::Location))
    // …
    .addFile("MyShader.vert");

Then, the attribute definition in a shader will look like this:

layout(location = POSITION_ATTRIBUTE_LOCATION) in vec3 position;
layout(location = NORMAL_ATTRIBUTE_LOCATION) in vec3 normal;

Public types

enum (anonymous): UnsignedInt { ColorOutput = 0, ObjectIdOutput = 1 }
using Position = GL::Attribute<0, T>
Vertex position.
using TextureCoordinates = GL::Attribute<1, Vector2>
2D texture coordinates
using Color3 = GL::Attribute<2, Magnum::Color3>
Three-component vertex color.
using Color4 = GL::Attribute<2, Magnum::Color4>
Four-component vertex color.
using Tangent = GL::Attribute<3, Vector3> new in 2019.10
Vertex tangent.
using Tangent4 = GL::Attribute<3, Vector4> new in 2020.06
Vertex tangent with a bitangent sign.
using Bitangent = GL::Attribute<4, Vector3> new in 2020.06
Vertex bitangent.
using ObjectId = GL::Attribute<4, UnsignedInt> new in 2020.06
(Instanced) object ID
using Normal = GL::Attribute<5, Vector3>
Vertex normal.
using TransformationMatrix = GL::Attribute<8, T> new in 2020.06
(Instanced) transformation matrix
using NormalMatrix = GL::Attribute<12, Matrix3x3> new in 2020.06
(Instanced) normal matrix
using TextureOffset = GL::Attribute<15, Vector2> new in 2020.06
(Instanced) texture offset

Enum documentation

template<UnsignedInt dimensions>
enum Magnum::Shaders::Generic<dimensions>::(anonymous): UnsignedInt

Enumerators
ColorOutput

Color shader output. Present always, expects three- or four-component floating-point or normalized buffer attachment.

ObjectIdOutput

Object ID shader output. Expects a single-component unsigned integral attachment.

Typedef documentation

template<UnsignedInt dimensions>
typedef GL::Attribute<0, T> Magnum::Shaders::Generic<dimensions>::Position

Vertex position.

Vector2 in 2D and Vector3 in 3D. Corresponds to Trade::MeshAttribute::Position.

template<UnsignedInt dimensions>
typedef GL::Attribute<1, Vector2> Magnum::Shaders::Generic<dimensions>::TextureCoordinates

2D texture coordinates

Vector2. Corresponds to Trade::MeshAttribute::TextureCoordinates.

template<UnsignedInt dimensions>
typedef GL::Attribute<2, Magnum::Color3> Magnum::Shaders::Generic<dimensions>::Color3

Three-component vertex color.

Magnum::Color3. Use either this or the Color4 attribute. Corresponds to Trade::MeshAttribute::Color.

template<UnsignedInt dimensions>
typedef GL::Attribute<2, Magnum::Color4> Magnum::Shaders::Generic<dimensions>::Color4

Four-component vertex color.

Magnum::Color4. Use either this or the Color3 attribute. Corresponds to Trade::MeshAttribute::Color.

template<UnsignedInt dimensions>
typedef GL::Attribute<3, Vector3> Magnum::Shaders::Generic<dimensions>::Tangent new in 2019.10

Vertex tangent.

Vector3, defined only in 3D. Use either this or the Tangent4 attribute. Corresponds to Trade::MeshAttribute::Tangent.

template<UnsignedInt dimensions>
typedef GL::Attribute<3, Vector4> Magnum::Shaders::Generic<dimensions>::Tangent4 new in 2020.06

Vertex tangent with a bitangent sign.

Vector4, defined only in 3D. The last component is a sign value (-1.0f or +1.0f) defining handedness of the tangent basis. Reconstructing the Bitangent attribute can be then done like this:

Vector3 bitangent = Math::cross(normal, tangent.xyz())*tangent.w();

Use either this or the Tangent attribute. Corresponds to Trade::MeshAttribute::Tangent.

template<UnsignedInt dimensions>
typedef GL::Attribute<4, Vector3> Magnum::Shaders::Generic<dimensions>::Bitangent new in 2020.06

Vertex bitangent.

Vector3, defined only in 3D. For better storage efficiency, the bitangent can be also reconstructed from the normal and tangent, see Tangent4 for more information. Corresponds to Trade::MeshAttribute::Bitangent.

This attribute conflicts with ObjectId, if you want to use both instanced object ID and bitangents, you need to reconstruct them from Tangent4 instead.

template<UnsignedInt dimensions>
typedef GL::Attribute<4, UnsignedInt> Magnum::Shaders::Generic<dimensions>::ObjectId new in 2020.06

(Instanced) object ID

UnsignedInt. Corresponds to Trade::MeshAttribute::ObjectId.

This attribute conflicts with Bitangent, if you want to use both instanced object ID and bitangents, you need to reconstruct them from Tangent4 instead.

template<UnsignedInt dimensions>
typedef GL::Attribute<5, Vector3> Magnum::Shaders::Generic<dimensions>::Normal

Vertex normal.

Vector3, defined only in 3D. Corresponds to Trade::MeshAttribute::Normal.

template<UnsignedInt dimensions>
typedef GL::Attribute<8, T> Magnum::Shaders::Generic<dimensions>::TransformationMatrix new in 2020.06

(Instanced) transformation matrix

Matrix3 in 2D and Matrix4 in 3D. Currently doesn't have a corresponding Trade::MeshAttribute.

template<UnsignedInt dimensions>
typedef GL::Attribute<12, Matrix3x3> Magnum::Shaders::Generic<dimensions>::NormalMatrix new in 2020.06

(Instanced) normal matrix

Matrix3x3, defined only in 3D. Currently doesn't have a corresponding Trade::MeshAttribute.

template<UnsignedInt dimensions>
typedef GL::Attribute<15, Vector2> Magnum::Shaders::Generic<dimensions>::TextureOffset new in 2020.06

(Instanced) texture offset

Vector2. Currently doesn't have a corresponding Trade::MeshAttribute.