Browse Source

doc: add a short overview of shader skinning support.

pull/499/head
Vladimír Vondruš 3 years ago
parent
commit
e1b4f37f9b
  1. 24
      doc/shaders.dox
  2. 61
      doc/snippets/MagnumShaders-gl.cpp
  3. 3
      src/Magnum/Shaders/FlatGL.h
  4. 7
      src/Magnum/Shaders/MeshVisualizerGL.h
  5. 3
      src/Magnum/Shaders/PhongGL.h

24
doc/shaders.dox

@ -228,6 +228,30 @@ using the usual vertex color attribute, only instanced:
@snippet MagnumShaders-gl.cpp shaders-instancing @snippet MagnumShaders-gl.cpp shaders-instancing
@subsection shaders-usage-skinning Skinning
@ref Shaders::FlatGL, @ref Shaders::MeshVisualizerGL3D "Shaders::MeshVisualizerGL*D"
and @ref Shaders::PhongGL are capable of rendering skinned meshes. Such meshes
are commonly imported from files such as glTF or FBX together with the skeleton
hierarchy and associated animations. The following snippet shows compiling a
@ref Trade::MeshData to a @ref GL::Mesh using @ref MeshTools::compile(), using
@ref Trade::SkinData and @ref MeshTools::compiledPerVertexJointCount() to
set up shader parameters and finally uploading calculated joint matrices to
perform the skinning animation:
@snippet MagnumShaders-gl.cpp shaders-skinning
The above hardcodes the joint counts in the shader, which makes it the most
optimal for rendering given mesh. However, with multiple skinned meshes it'd
mean having a dedicated shader instance tailored for each. To avoid that, you
can set the joint count and per-vertex joint count to the maximum that the
meshes would need, enable @ref Shaders::PhongGL::Flag::DynamicPerVertexJointCount "Flag::DynamicPerVertexJointCount",
for a particular draw upload just a subset of joint matrices the mesh would
reference and set the count of actually used per-vertex joints via
@ref Shaders::PhongGL::setPerVertexJointCount(). Thus, compared to above:
@snippet MagnumShaders-gl.cpp shaders-skinning-dynamic
@subsection shaders-usage-textures Using textures @subsection shaders-usage-textures Using textures
Unless the shader requires a texture to work (which is the case of Unless the shader requires a texture to work (which is the case of

61
doc/snippets/MagnumShaders-gl.cpp

@ -27,6 +27,7 @@
#include <Corrade/Containers/Array.h> #include <Corrade/Containers/Array.h>
#include <Corrade/Containers/ArrayViewStl.h> #include <Corrade/Containers/ArrayViewStl.h>
#include <Corrade/Containers/Iterable.h> #include <Corrade/Containers/Iterable.h>
#include <Corrade/Containers/Pair.h>
#include <Corrade/Utility/FormatStl.h> #include <Corrade/Utility/FormatStl.h>
#include "Magnum/ImageView.h" #include "Magnum/ImageView.h"
@ -47,6 +48,7 @@
#include "Magnum/Math/Matrix3.h" #include "Magnum/Math/Matrix3.h"
#include "Magnum/Math/Matrix4.h" #include "Magnum/Math/Matrix4.h"
#include "Magnum/Math/FunctionsBatch.h" #include "Magnum/Math/FunctionsBatch.h"
#include "Magnum/MeshTools/Compile.h"
#include "Magnum/MeshTools/Duplicate.h" #include "Magnum/MeshTools/Duplicate.h"
#include "Magnum/Shaders/DistanceFieldVectorGL.h" #include "Magnum/Shaders/DistanceFieldVectorGL.h"
#include "Magnum/Shaders/FlatGL.h" #include "Magnum/Shaders/FlatGL.h"
@ -55,6 +57,8 @@
#include "Magnum/Shaders/VectorGL.h" #include "Magnum/Shaders/VectorGL.h"
#include "Magnum/Shaders/VertexColorGL.h" #include "Magnum/Shaders/VertexColorGL.h"
#include "Magnum/Trade/LightData.h" #include "Magnum/Trade/LightData.h"
#include "Magnum/Trade/MeshData.h"
#include "Magnum/Trade/SkinData.h"
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
#include "Magnum/GL/TextureArray.h" #include "Magnum/GL/TextureArray.h"
@ -270,6 +274,63 @@ shader
/* [shaders-instancing] */ /* [shaders-instancing] */
} }
#ifndef MAGNUM_TARGET_GLES2
{
/* [shaders-skinning] */
/* Import and compile the mesh */
Trade::MeshData meshData = DOXYGEN_ELLIPSIS(Trade::MeshData{MeshPrimitive::Triangles, 0});
GL::Mesh mesh = MeshTools::compile(meshData);
Containers::Pair<UnsignedInt, UnsignedInt> meshPerVertexJointCount =
MeshTools::compiledPerVertexJointCount(meshData);
/* Import the skin associated with the mesh */
Trade::SkinData3D skin = DOXYGEN_ELLIPSIS(Trade::SkinData3D{{}, {}});
/* Set up a skinned shader */
Shaders::PhongGL shader{Shaders::PhongGL::Configuration{}
.setJointCount(skin.joints().size(), meshPerVertexJointCount.first(),
meshPerVertexJointCount.second())};
DOXYGEN_ELLIPSIS()
/* Absolute transformations for all nodes in the scene, possibly animated */
Containers::Array<Matrix4> absoluteTransformations{DOXYGEN_ELLIPSIS()};
DOXYGEN_ELLIPSIS()
/* Gather joint transformations for this skin, upload and draw */
Containers::Array<Matrix4> jointTransformations{NoInit, skin.joints().size()};
for(std::size_t i = 0; i != jointTransformations.size(); ++i)
jointTransformations[i] = absoluteTransformations[skin.joints()[i]]*
skin.inverseBindMatrices()[i];
shader
.setJointMatrices(jointTransformations)
DOXYGEN_ELLIPSIS()
.draw(mesh);
/* [shaders-skinning] */
}
{
Matrix4 jointTransformations[2];
UnsignedInt maxSkinJointCount{};
Containers::Pair<UnsignedInt, UnsignedInt> meshPerVertexJointCount;
GL::Mesh mesh;
/* [shaders-skinning-dynamic] */
Shaders::PhongGL shader{Shaders::PhongGL::Configuration{}
.setFlags(Shaders::PhongGL::Flag::DynamicPerVertexJointCount)
.setJointCount(maxSkinJointCount, 4, 4)};
DOXYGEN_ELLIPSIS()
shader
.setJointMatrices(jointTransformations)
.setPerVertexJointCount(meshPerVertexJointCount.first(),
meshPerVertexJointCount.second())
DOXYGEN_ELLIPSIS()
.draw(mesh);
/* [shaders-skinning-dynamic] */
}
#endif
{ {
GL::Mesh mesh; GL::Mesh mesh;
/* [shaders-textures] */ /* [shaders-textures] */

3
src/Magnum/Shaders/FlatGL.h

@ -150,7 +150,8 @@ and weight attributes to @ref JointIds / @ref SecondaryJointIds and
@ref Weights / @ref SecondaryWeights, set an appropriate joint count and @ref Weights / @ref SecondaryWeights, set an appropriate joint count and
per-vertex primary and secondary joint count in per-vertex primary and secondary joint count in
@ref Configuration::setJointCount() and upload appropriate joint matrices with @ref Configuration::setJointCount() and upload appropriate joint matrices with
@ref setJointMatrices(). @ref setJointMatrices(). The usage is similar for all shaders, see
@ref shaders-usage-skinning for an example.
To avoid having to compile multiple shader variants for different joint matrix To avoid having to compile multiple shader variants for different joint matrix
counts, set the maximum used joint count in @ref Configuration::setJointCount() counts, set the maximum used joint count in @ref Configuration::setJointCount()

7
src/Magnum/Shaders/MeshVisualizerGL.h

@ -1505,9 +1505,10 @@ and weight attributes to @ref JointIds / @ref SecondaryJointIds and
@ref Weights / @ref SecondaryWeights, set an appropriate joint count and @ref Weights / @ref SecondaryWeights, set an appropriate joint count and
per-vertex primary and secondary joint count in per-vertex primary and secondary joint count in
@ref Configuration::setJointCount() and upload appropriate joint matrices with @ref Configuration::setJointCount() and upload appropriate joint matrices with
@ref setJointMatrices(). Currently, the mesh visualizer supports only @ref setJointMatrices(). The usage is similar for all shaders, see
transforming the mesh vertices for feature parity with other shaders, @ref shaders-usage-skinning for an example. Currently, the mesh visualizer
no skinning-specific visualization feature is implemented. supports only transforming the mesh vertices for feature parity with other
shaders, no skinning-specific visualization feature is implemented.
To avoid having to compile multiple shader variants for different joint matrix To avoid having to compile multiple shader variants for different joint matrix
counts, set the maximum used joint count in @ref Configuration::setJointCount() counts, set the maximum used joint count in @ref Configuration::setJointCount()

3
src/Magnum/Shaders/PhongGL.h

@ -239,7 +239,8 @@ and weight attributes to @ref JointIds / @ref SecondaryJointIds and
@ref Weights / @ref SecondaryWeights, set an appropriate joint count and @ref Weights / @ref SecondaryWeights, set an appropriate joint count and
per-vertex primary and secondary joint count in per-vertex primary and secondary joint count in
@ref Configuration::setJointCount() and upload appropriate joint matrices with @ref Configuration::setJointCount() and upload appropriate joint matrices with
@ref setJointMatrices(). @ref setJointMatrices(). The usage is similar for all shaders, see
@ref shaders-usage-skinning for an example.
To avoid having to compile multiple shader variants for different joint matrix To avoid having to compile multiple shader variants for different joint matrix
counts, set the maximum used joint count in @ref Configuration::setJointCount() counts, set the maximum used joint count in @ref Configuration::setJointCount()

Loading…
Cancel
Save