Bone weights on vertices should be normalized most of the time, if not all the time, right?
I'm thinking about packing 4 bones and 3 weights in a float4: .x is an u32 with the bone IDs packed and .yzw would be the weights for bone 1-3. You'd derive bone 0's weight by solving a Pythagorean equation.
That, if the weights are effectively a normalized vector of 1 to 4 components.
I'm hesitating between using 0xFF and 0xFF as index for an invalid bone. 0xff is the classic case but 0x00 could allow me to still evaluate and mask the calculation easily given that it's going to almost exclusively be the root bone, if that would improve vectorization
@neon I haven't really given a shot at skinning yet, I'm planning theorically but that's a good point. I could try this too, thanks for the idea.
@Ronflaix yes, but IME it's better to normalize late in the vertex shader to fix low-precision problems, I do this in my skinning shader:
vec4 weights = skin_weights / dot(skin_weights, vec4(1.0));
@Ronflaix I use UBYTE4 for 4 joint indices, and UBYTE4N for 4 weights (which limits skinning to the 4 most important influence joints, and 255 joints per skeleton - can be worked around with 'joint palettes')
@Ronflaix ...the joint matrices are provided via a texture or storage buffer with 3 transposed vec4 (e.g. xxxx, yyyy, zzzz) to directly perform the matrix multiplication as 3 dot products... which then results in this skinning function (the storage buffer method which is a bit simpler):
I've been using that method since forever, it's very basic but works ;)
> can be worked around with 'joint palettes'
...or I guess it's better these days to just increase the joint index type to 16 bits :)
@floooh thanks for the info about your own pipeline, I appreciate the effort! I'll see what I'll end up with but your method sounds pretty close to what I expect a lot of modern engines to do (ignoring stuff like compute-based skinning)