Vertex Animation Texture(VAT) for WebGL with Houdini (Rigid body)

I talked about VAT for WebGL at previous article, and I continue to implement about Rigid Body method.
It used by expressing destruction, that each meshes have some hardness to simulate movement and collision.

So, I will lecture the point of shader code.

You exported position texture and rotation texture, that width is the total amount of child meshes. Of course height is total frame which is common thing for other methods.

It’s vertex shader code.

varying vec3 vNormal;

attribute vec2 uv2;
attribute vec3 color;

uniform float time;
uniform float boudingBoxMax;
uniform float boundingBoxMin;
uniform float pivotMax;
uniform float pivotMin;
uniform float currentFrame;
uniform float totalFrame;
uniform sampler2D positionMap;
uniform sampler2D rotationMap;

vec4 DecodeQuaternion(vec4 encodedRotation) {
    return vec4(mix( vec4(-1.0), vec4(1.0), encodedRotation));

vec3 RotateVectorUsingQuaternionFast(vec4 q, vec3 v) {
    vec3 t = 2.0 * cross(, v);
    return v + q.w * t + cross(, t);

void main() {

    float boundingBoxRange = boudingBoxMax - boundingBoxMin;
    float pu = uv2.x;
    float pv = 1.0 - fract( currentFrame / totalFrame );
    vec2 shiftUv = vec2( pu, pv );

    vec4 samplePosition = texture2D( positionMap, shiftUv );
    samplePosition *= boundingBoxRange;
    samplePosition += boundingBoxMin;

    vec4 sampleRotation = texture2D( rotationMap, shiftUv );
    vec4 decodedRotation = DecodeQuaternion( sampleRotation );

    // decode pivot from vertex color
    vec3 pivot = color;
    float pivotRange = pivotMax - pivotMin;
    pivot *= pivotRange;
    pivot += pivotMin;

    vec3 offsetPosition = position - pivot;
    vec3 rotatedPosition = RotateVectorUsingQuaternionFast( decodedRotation, offsetPosition );

    vec3 outPosition = rotatedPosition +;

    gl_Position = projectionMatrix * modelViewMatrix * vec4( outPosition, 1.0 );

    vNormal = normalMatrix * RotateVectorUsingQuaternionFast( decodedRotation, normal );


  1. Retrive position coord from position texture.
  2. Decode quaternion from rotation texture, and translate to rotation vector.
  3. Normal is calculated at normal attribute when it’s exported. So you should recalculate with rotation vector.


Thats’ all.
However, I saw cracks on the surface of RubberToy before it started to scatter with this code.

The answer is the difference of position texture precision probarbly.
I introduced the way to export assets at previous article, which precision was half-float, although the position attribute is full float.
If you want to fix this problem, you need to export two position texture for making good precision.



Vertex Animation Texture(VAT) for WebGL with Houdini (Soft body)


Shader graph: Rigid body animation using vertex animation textures