Skip to content

Commit

Permalink
Shaders: implement instancing in Flat.
Browse files Browse the repository at this point in the history
  • Loading branch information
mosra committed Apr 5, 2020
1 parent e601038 commit a1f1f66
Show file tree
Hide file tree
Showing 10 changed files with 367 additions and 29 deletions.
1 change: 1 addition & 0 deletions doc/changelog.dox
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,7 @@ See also:
@ref Shaders::Generic::TransformationMatrix,
@ref Shaders::Generic::NormalMatrix and
@ref Shaders::Generic::TextureOffset for instancing
- Instancing in @ref Shaders::Flat

@subsubsection changelog-latest-new-trade Trade library

Expand Down
20 changes: 20 additions & 0 deletions doc/snippets/MagnumShaders.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,26 @@ framebuffer.mapForDraw({
}
#endif

{
GL::Mesh mesh;
/* [Flat-usage-instancing] */
struct {
Matrix4 transformation;
Color3 color;
} instanceData[] {
{Matrix4::translation({1.0f, 2.0f, 0.0f}), 0xff3333_rgbf},
{Matrix4::translation({2.0f, 1.0f, 0.0f}), 0x33ff33_rgbf},
{Matrix4::translation({3.0f, 0.0f, 1.0f}), 0x3333ff_rgbf},
// ...
};

mesh.setInstanceCount(Containers::arraySize(instanceData))
.addVertexBufferInstanced(GL::Buffer{instanceData}, 1, 0,
Shaders::Flat3D::TransformationMatrix{},
Shaders::Flat3D::Color3{});
/* [Flat-usage-instancing] */
}

{
/* [MeshVisualizer-usage-geom1] */
struct Vertex {
Expand Down
13 changes: 11 additions & 2 deletions src/Magnum/Shaders/Flat.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@ template<UnsignedInt dimensions> Flat<dimensions>::Flat(const Flags flags): _fla
#ifndef MAGNUM_TARGET_GLES2
.addSource(flags >= Flag::InstancedObjectId ? "#define INSTANCED_OBJECT_ID\n" : "")
#endif
.addSource(flags & Flag::InstancedTransformation ? "#define INSTANCED_TRANSFORMATION\n" : "")
.addSource(flags >= Flag::InstancedTextureOffset ? "#define INSTANCED_TEXTURE_OFFSET\n" : "")
.addSource(rs.get("generic.glsl"))
.addSource(rs.get("Flat.vert"));
frag.addSource(flags & Flag::Textured ? "#define TEXTURED\n" : "")
Expand Down Expand Up @@ -107,6 +109,10 @@ template<UnsignedInt dimensions> Flat<dimensions>::Flat(const Flags flags): _fla
}
if(flags >= Flag::InstancedObjectId)
bindAttributeLocation(ObjectId::Location, "instanceObjectId");
if(flags & Flag::InstancedTransformation)
bindAttributeLocation(TransformationMatrix::Location, "instancedTransformationMatrix");
if(flags >= Flag::InstancedTextureOffset)
bindAttributeLocation(TextureOffset::Location, "instancedTextureOffset");
#endif
}
#endif
Expand Down Expand Up @@ -203,6 +209,8 @@ Debug& operator<<(Debug& debug, const FlatFlag value) {
_c(ObjectId)
_c(InstancedObjectId)
#endif
_c(InstancedTransformation)
_c(InstancedTextureOffset)
#undef _c
/* LCOV_EXCL_STOP */
}
Expand All @@ -215,12 +223,13 @@ Debug& operator<<(Debug& debug, const FlatFlags value) {
FlatFlag::Textured,
FlatFlag::AlphaMask,
FlatFlag::VertexColor,
FlatFlag::InstancedTextureOffset, /* Superset of TextureTransformation */
FlatFlag::TextureTransformation,
#ifndef MAGNUM_TARGET_GLES2
FlatFlag::InstancedObjectId, /* Superset of ObjectId */
FlatFlag::ObjectId
FlatFlag::ObjectId,
#endif
});
FlatFlag::InstancedTransformation});
}

}
Expand Down
95 changes: 93 additions & 2 deletions src/Magnum/Shaders/Flat.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,10 @@ namespace Implementation {
TextureTransformation = 1 << 3,
#ifndef MAGNUM_TARGET_GLES2
ObjectId = 1 << 4,
InstancedObjectId = (1 << 5)|ObjectId
InstancedObjectId = (1 << 5)|ObjectId,
#endif
InstancedTransformation = 1 << 6,
InstancedTextureOffset = (1 << 7)|TextureTransformation
};
typedef Containers::EnumSet<FlatFlag> FlatFlags;
}
Expand Down Expand Up @@ -120,6 +122,28 @@ from @ref setObjectId().
@requires_gles30 Object ID output requires integer buffer attachments, which
are not available in OpenGL ES 2.0 or WebGL 1.0.
@section Shaders-Flat-instancing Instanced rendering
Enabling @ref Flag::InstancedTransformation will turn the shader into an
instanced one. It'll take per-instance transformation from the
@ref TransformationMatrix attribute, applying it before the matrix set by
@ref setTransformationProjectionMatrix(). Besides that, @ref Flag::VertexColor
(and the @ref Color3 / @ref Color4) attributes can work as both per-vertex and
per-instance, and for texturing it's possible to have per-instance texture
offset taken from @ref TextureOffset when @ref Flag::InstancedTextureOffset is
enabled (similarly to transformation, applied before @ref setTextureMatrix()).
The snippet below shows adding a buffer with per-instance transformation and
color to a mesh:
@snippet MagnumShaders.cpp Flat-usage-instancing
@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.
@see @ref shaders, @ref Flat2D, @ref Flat3D
*/
template<UnsignedInt dimensions> class MAGNUM_SHADERS_EXPORT Flat: public GL::AbstractShaderProgram {
Expand Down Expand Up @@ -176,6 +200,37 @@ template<UnsignedInt dimensions> class MAGNUM_SHADERS_EXPORT Flat: public GL::Ab
typedef typename Generic<dimensions>::ObjectId ObjectId;
#endif

/**
* @brief (Instanced) transformation matrix
* @m_since_latest
*
* @ref shaders-generic "Generic attribute", @ref Magnum::Matrix3 in
* 2D, @ref Magnum::Matrix4 in 3D. Used only if
* @ref Flag::InstancedTransformation is set.
* @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 typename Generic<dimensions>::TransformationMatrix TransformationMatrix;

/**
* @brief (Instanced) texture offset
* @m_since_latest
*
* @ref shaders-generic "Generic attribute", @ref Magnum::Vector2. Used
* only if @ref Flag::InstancedTextureOffset is set.
* @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 typename Generic<dimensions>::TextureOffset TextureOffset;

enum: UnsignedInt {
/**
* Color shader output. Present always, expects three- or
Expand Down Expand Up @@ -263,8 +318,44 @@ template<UnsignedInt dimensions> class MAGNUM_SHADERS_EXPORT Flat: public GL::Ab
* WebGL 1.0.
* @m_since_latest
*/
InstancedObjectId = (1 << 5)|ObjectId
InstancedObjectId = (1 << 5)|ObjectId,
#endif

/**
* Instanced transformation. Retrieves a per-instance
* transformation matrix from the @ref TransformationMatrix
* attribute and uses it together with the matrix coming from
* @ref setTransformationProjectionMatrix() (first the
* per-instance, then the uniform matrix). See
* @ref Shaders-Flat-instancing for more information.
* @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.
* @m_since_latest
*/
InstancedTransformation = 1 << 6,

/**
* Instanced texture offset. Retrieves a per-instance offset vector
* from the @ref TextureOffset attribute and uses it together with
* the matrix coming from @ref setTextureMatrix() (first the
* per-instance vector, then the uniform matrix). Instanced texture
* scaling and rotation is not supported at the moment, you can
* specify that only via the uniform @ref setTextureMatrix().
* Implicitly enables @ref Flag::TextureTransformation. See
* @ref Shaders-Flat-instancing for more information.
* @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.
* @m_since_latest
*/
InstancedTextureOffset = (1 << 7)|TextureTransformation
};

/**
Expand Down
38 changes: 35 additions & 3 deletions src/Magnum/Shaders/Flat.vert
Original file line number Diff line number Diff line change
Expand Up @@ -96,11 +96,39 @@ in highp uint instanceObjectId;
flat out highp uint interpolatedInstanceObjectId;
#endif

#ifdef INSTANCED_TRANSFORMATION
#ifdef EXPLICIT_ATTRIB_LOCATION
layout(location = TRANSFORMATION_MATRIX_ATTRIBUTE_LOCATION)
#endif
#ifdef TWO_DIMENSIONS
in highp mat3 instancedTransformationMatrix;
#elif defined(THREE_DIMENSIONS)
in highp mat4 instancedTransformationMatrix;
#else
#error
#endif
#endif

#ifdef INSTANCED_TEXTURE_OFFSET
#ifdef EXPLICIT_ATTRIB_LOCATION
layout(location = TEXTURE_OFFSET_ATTRIBUTE_LOCATION)
#endif
in mediump vec2 instancedTextureOffset;
#endif

void main() {
#ifdef TWO_DIMENSIONS
gl_Position.xywz = vec4(transformationProjectionMatrix*vec3(position, 1.0), 0.0);
gl_Position.xywz = vec4(transformationProjectionMatrix*
#ifdef INSTANCED_TRANSFORMATION
instancedTransformationMatrix*
#endif
vec3(position, 1.0), 0.0);
#elif defined(THREE_DIMENSIONS)
gl_Position = transformationProjectionMatrix*position;
gl_Position = transformationProjectionMatrix*
#ifdef INSTANCED_TRANSFORMATION
instancedTransformationMatrix*
#endif
position;
#else
#error
#endif
Expand All @@ -109,7 +137,11 @@ void main() {
/* Texture coordinates, if needed */
interpolatedTextureCoordinates =
#ifdef TEXTURE_TRANSFORMATION
(textureMatrix*vec3(textureCoordinates, 1.0)).xy
(textureMatrix*vec3(
#ifdef INSTANCED_TEXTURE_OFFSET
instancedTextureOffset +
#endif
textureCoordinates, 1.0)).xy
#else
textureCoordinates
#endif
Expand Down
2 changes: 2 additions & 0 deletions src/Magnum/Shaders/Test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,8 @@ if(BUILD_GL_TESTS)
FlatTestFiles/colored2D.tga
FlatTestFiles/colored3D.tga
FlatTestFiles/defaults.tga
FlatTestFiles/instanced2D.tga
FlatTestFiles/instanced3D.tga
FlatTestFiles/textured2D.tga
FlatTestFiles/textured3D.tga
FlatTestFiles/textured2D-alpha.tga
Expand Down
Loading

0 comments on commit a1f1f66

Please sign in to comment.