1.In a submesh, is there a situation where vertex A is bound to 2 bones and vertex B is bound to 3 bones? Do we need to execute different shader scripts?
Yes, this is possible, but the same shader can be used since the other empty bones should have no effect.
But the system is a bit weird, in Mesh::compileBoneAssignments it shows that it only writes the data when needed, so if a mesh has 3 bones per vertex, it will only write three of them even if the shader uses a uint4+float4 (for the indices+weights), which means that you will still need to use a vertex shader that then only handles 3 bones, instead of a vertex shader that always handles 4 bones.
It is rather annoying for sure, but that is how the system works currently even in the latest version as well.
I wish it would instead write all 4 variables even if only 1 bone is being used, since in that case only a single shader could be used. But right now when trying to use a shader of 4 bones on a mesh that only has 3 bones, it will look very strange and simply not work.
2.Is there a submesh1 vertex bound to 1 bone, and a submesh2 vertex bound to 2 bones? Do I need to execute different shader scripts?
I am not sure about this, but since every submesh is its own thing it might work like that unless the mesh is using shared vertex data (as seen in Mesh::_compileBoneAssignments).
3.How to know how many bones are bound to the submesh or mesh vertices?
That is tricky as well. In my game I just try the 4 bones shader first, and if something is not right I go down to the 3 bones shader (none so far has used 2 or 1 bones luckily).
It seems you can also use this code on the mesh or submesh:
Code: Select all
unsigned short maxBones = mesh->_rationaliseBoneAssignments(mesh->sharedVertexData->vertexCount, mesh->getBoneAssignments());
4.After we determine how many bones are bound, can we pass the bound number into the shader to make “boneNum” in it work? Or do we need to use different shaders according to the bound number?
- You can add it as a param_named in the shader material and then simply use that in the shader.
- Or, you can add it as a compile argument to be used as a define. The positive thing for this is that it is faster, since a loop with a param_named in it is often very unoptimized since it cannot unroll and optimize the loop when it compiles.
For a compile argument, add this to the top of your vertex shader:
Code: Select all
#if !defined(MAX_BONES)
#define MAX_BONES 4
#endif
Then, when you make the shader material of it, do it like this to set the define to 3 instead if you want:
Code: Select all
vertex_program Skinning3Bones_VS hlsl
{
source Skinning3Bones_VS.hlsl
entry_point main_vs
target vs_3_0
includes_skeletal_animation true
column_major_matrices false
preprocessor_defines MAX_BONES=3
...
5.I noticed that there is no case where the number of bones is 3 in the shader examples, but is it actually possible?
(we have hardwareSkinningOneWeight_vp hardwareSkinningTwoWeights_vp hardwareSkinningFourWeights_vp)
Yes. 1, 2, 3 and 4 is possible.
But overall, regarding this whole issue, if I were you I would first try to change the Ogre source code to always allow 4 bones to be used, which means that most (if not all) of your problems would go away, since then you can only use "4" instead of "numBones" and use the same shader for all meshes and submeshes without having to think about it.
I would simply try to change this code in Mesh::compileBoneAssignments:
Code: Select all
// write out the weights as floats
float* pWeight;
pWeightElem->baseVertexPointerToElement( pBase, &pWeight );
for ( int ii = 0; ii < numBlendWeightsPerVertex; ++ii )
{
*pWeight++ = weights[ ii ];
}
To this (because for everything under 4 bones will have uninitialized memory otherwise):
Code: Select all
// write out the weights as floats
float* pWeight;
pWeightElem->baseVertexPointerToElement( pBase, &pWeight );
for ( int ii = 0; ii < 4; ++ii )
{
*pWeight++ = weights[ ii ];
}
I should also try this for my game, since it would then make the handling of these issues so much easier, but I have too many other issues right now to fix so I cannot try this at the moment.