Graphics Reference
In-Depth Information
In order to reduce the memory bandwidth, the number of bones should be reduced to
a number that reflects more realistically the maximum number of bones within the models
used (for example, between 64 and 100). The value of 1024 is used in this recipe to highlight
the fact that this is the maximum number of 4 x 4 matrices that can be stored within a
constant buffer in Shader Model 4/5 (or 65,536 bytes). In contrast, Shader Model 3 supports
256 constant float registers that can hold a single float4 component, or a maximum of
sixty-four 4 x 4 matrices. This is shared between other floating point data. So, the actual
number available would be less.
There are tricks to increase the number of bones, such as using 4
x 3 matrices, as bones rarely require non-affine transformations.
For DirectX 11 class hardware, there is probably no need; although,
perhaps on some mobile devices or if you must support older
hardware, it may still be something to consider.
With the armature's skin matrices in place, we can apply the vertex skinning within the vertex
shader. For each of the bone influences (specified in SkinIndices ), the skin transform
matrix is retrieved and multiplied by the bone-weight (stored in SkinWeights ). These four
matrices are then added together to determine the final skin transform for this vertex.
float4x4 skinTransform = Bones[bones.x] * weights.x +
Bones[bones.y] * weights.y +
Bones[bones.z] * weights.z +
Bones[bones.w] * weights.w;
// Apply skinning to vertex and normal
position = mul(position, skinTransform);
normal = mul(normal, (float3x3)skinTransform);
We then apply the skin transform to the vertex position and vertex normal. The normal
transformation presented here will only work if the bone matrices always contain uniform
scaling. For this to work with non-uniform scaling, it requires the usage of an inverse
transpose of the matrix as described in the Preparing the vertex and constant buffers for
material and lighting recipe in Chapter 3 , Rendering Meshes .
If the first bone has a weight of zero, we are skipping this process. This is important because
we are using this vertex shader for meshes whether or not they have any bones. A very small
performance improvement can possibly be gained by splitting the vertex shader into two and
choosing which shader to use on the CPU per mesh instead of making the decision within
a single vertex shader for each vertex. There is, however, a performance overhead when
switching shaders; so your results may vary.
The result of applying a skin matrix of zero upon all of our vertices will place them all
at the origin. In the case of triangle primitives, this will result in no output. This symptom
can indicate that the PerArmature constant buffer hasn't been updated correctly.
 
Search WWH ::




Custom Search