animatedEntityVertex.glsl - Fish-In-A-Suit/Conquest GitHub Wiki

#version 150

const int MAX_JOINTS = 50;//max joints allowed in a skeleton
const int MAX_WEIGHTS = 3;//max number of joints that can affect a vertex

in vec3 in_position;
in vec2 in_textureCoords;
in vec3 in_normal;
in ivec3 in_jointIndices;
in vec3 in_weights;

out vec2 pass_textureCoords;
out vec3 pass_normal;

uniform mat4 jointTransforms[MAX_JOINTS];
uniform mat4 projectionViewMatrix;

void main(void){
	
	vec4 totalLocalPos = vec4(0.0);
	vec4 totalNormal = vec4(0.0);
	
	for(int i=0;i<MAX_WEIGHTS;i++){
		mat4 jointTransform = jointTransforms[in_jointIndices[i]];
		vec4 posePosition = jointTransform * vec4(in_position, 1.0);
		totalLocalPos += posePosition * in_weights[i];
		
		vec4 worldNormal = jointTransform * vec4(in_normal, 0.0);
		totalNormal += worldNormal * in_weights[i];
	}
	
	gl_Position = projectionViewMatrix * totalLocalPos; //if there were a model matrix, add it here
	pass_normal = totalNormal.xyz;
	pass_textureCoords = in_textureCoords;

}

First, look at the bottom three lines:

gl_Position = projectionViewMatrix * totalLocalPos; //if there were a model matrix, add it here
pass_normal = totalNormal.xyz;
pass_textureCoords = in_textureCoords;

We're just calculating gl_Position by multiplying the position of the vertex (totalLocalPos) by the PV(M) matrix and passing through the normal (slightly modified) and texture coordinates (not modified). The only thing that changes is how vertex position is determined - it is transformed by using the joint transforms and skinning information to move it from it's original position to the position it should be in at the current pose.

The for loop loops once for every joint that could affect this vertex. For each joint that affects the vertex, we first get the index of the joint from in_jointIndices and then use that index to get the current transform for that joint from the jointTransforms array. Then, this transform (jointTransform) is applied to the original vertex position, which transforms the vertex from its original position to the desired position in the pose, as if it was affected by that single joint: vec4 posePosition = jointTransform * vec4(in_position, 1.0); That happens for each joint that affects the vertex, giving us three different end positions and then we basically take a weighted average of those three final positions by multiplying them by the associated joint weight and adding them to totalLocalPos: totalLocalPos += posePosition * in_weights[i];

The exact same thing is performed on the normal for that vertex, since the normal vector is also going to change by the deformation of the vertex.

vec4 worldNormal = jointTransform * vec4(in_normal, 0.0);
totalNormal += worldNormal * in_weights[i];