diff --git a/doc/shaders.dox b/doc/shaders.dox index bde05664b..ba45fe20c 100644 --- a/doc/shaders.dox +++ b/doc/shaders.dox @@ -228,6 +228,30 @@ using the usual vertex color attribute, only instanced: @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 Unless the shader requires a texture to work (which is the case of diff --git a/doc/snippets/MagnumShaders-gl.cpp b/doc/snippets/MagnumShaders-gl.cpp index 72028fe21..9e85f9db3 100644 --- a/doc/snippets/MagnumShaders-gl.cpp +++ b/doc/snippets/MagnumShaders-gl.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include #include "Magnum/ImageView.h" @@ -47,6 +48,7 @@ #include "Magnum/Math/Matrix3.h" #include "Magnum/Math/Matrix4.h" #include "Magnum/Math/FunctionsBatch.h" +#include "Magnum/MeshTools/Compile.h" #include "Magnum/MeshTools/Duplicate.h" #include "Magnum/Shaders/DistanceFieldVectorGL.h" #include "Magnum/Shaders/FlatGL.h" @@ -55,6 +57,8 @@ #include "Magnum/Shaders/VectorGL.h" #include "Magnum/Shaders/VertexColorGL.h" #include "Magnum/Trade/LightData.h" +#include "Magnum/Trade/MeshData.h" +#include "Magnum/Trade/SkinData.h" #ifndef MAGNUM_TARGET_GLES2 #include "Magnum/GL/TextureArray.h" @@ -270,6 +274,63 @@ shader /* [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 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 absoluteTransformations{DOXYGEN_ELLIPSIS()}; +DOXYGEN_ELLIPSIS() + +/* Gather joint transformations for this skin, upload and draw */ +Containers::Array 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 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; /* [shaders-textures] */ diff --git a/src/Magnum/Shaders/FlatGL.h b/src/Magnum/Shaders/FlatGL.h index 892dd811e..99752de7f 100644 --- a/src/Magnum/Shaders/FlatGL.h +++ b/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 per-vertex primary and secondary joint count in @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 counts, set the maximum used joint count in @ref Configuration::setJointCount() diff --git a/src/Magnum/Shaders/MeshVisualizerGL.h b/src/Magnum/Shaders/MeshVisualizerGL.h index 7fc6d3a83..1b060893b 100644 --- a/src/Magnum/Shaders/MeshVisualizerGL.h +++ b/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 per-vertex primary and secondary joint count in @ref Configuration::setJointCount() and upload appropriate joint matrices with -@ref setJointMatrices(). Currently, the mesh visualizer supports only -transforming the mesh vertices for feature parity with other shaders, -no skinning-specific visualization feature is implemented. +@ref setJointMatrices(). The usage is similar for all shaders, see +@ref shaders-usage-skinning for an example. Currently, the mesh visualizer +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 counts, set the maximum used joint count in @ref Configuration::setJointCount() diff --git a/src/Magnum/Shaders/PhongGL.h b/src/Magnum/Shaders/PhongGL.h index d2437ee61..3822e2a09 100644 --- a/src/Magnum/Shaders/PhongGL.h +++ b/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 per-vertex primary and secondary joint count in @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 counts, set the maximum used joint count in @ref Configuration::setJointCount()