17b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens/*
27b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens	If the current vertex is affected by bones then the vertex position and
37b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens	normal will be transformed by the bone matrices. Each vertex wil have up
47b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens	to 4 bone indices (inBoneIndex) and bone weights (inBoneWeights).
57b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens
67b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens	The indices are used to index into the array of bone matrices
77b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens	(BoneMatrixArray) to get the required bone matrix for transformation. The
87b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens	amount of influence a particular bone has on a vertex is determined by the
97b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens	weights which should always total 1. So if a vertex is affected by 2 bones
107b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens	the vertex position in world space is given by the following equation:
117b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens
127b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens	position = (BoneMatrixArray[Index0] * inVertex) * Weight0 +
137b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens	           (BoneMatrixArray[Index1] * inVertex) * Weight1
147b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens
157b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens	The same proceedure is applied to the normals but the translation part of
167b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens	the transformation is ignored.
177b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens
187b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens	After this the position is multiplied by the view and projection matrices
197b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens	only as the bone matrices already contain the model transform for this
207b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens	particular mesh. The two-step transformation is required because lighting
217b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens	will not work properly in clip space.
227b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens*/
237b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens
247b21f276fa91ad62fd2055844688b07829f12205Nicolas Capensattribute highp   vec3 inVertex;
257b21f276fa91ad62fd2055844688b07829f12205Nicolas Capensattribute mediump vec3 inNormal;
267b21f276fa91ad62fd2055844688b07829f12205Nicolas Capensattribute mediump vec3 inTangent;
277b21f276fa91ad62fd2055844688b07829f12205Nicolas Capensattribute mediump vec3 inBiNormal;
287b21f276fa91ad62fd2055844688b07829f12205Nicolas Capensattribute mediump vec2 inTexCoord;
297b21f276fa91ad62fd2055844688b07829f12205Nicolas Capensattribute mediump vec4 inBoneIndex;
307b21f276fa91ad62fd2055844688b07829f12205Nicolas Capensattribute mediump vec4 inBoneWeights;
317b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens
327b21f276fa91ad62fd2055844688b07829f12205Nicolas Capensuniform highp   mat4 ViewProjMatrix;
337b21f276fa91ad62fd2055844688b07829f12205Nicolas Capensuniform mediump vec3 LightPos;
347b21f276fa91ad62fd2055844688b07829f12205Nicolas Capensuniform mediump	int	 BoneCount;
357b21f276fa91ad62fd2055844688b07829f12205Nicolas Capensuniform highp   mat4 BoneMatrixArray[8];
367b21f276fa91ad62fd2055844688b07829f12205Nicolas Capensuniform highp   mat3 BoneMatrixArrayIT[8];
377b21f276fa91ad62fd2055844688b07829f12205Nicolas Capensuniform bool	bUseDot3;
387b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens
397b21f276fa91ad62fd2055844688b07829f12205Nicolas Capensvarying mediump vec3 Light;
407b21f276fa91ad62fd2055844688b07829f12205Nicolas Capensvarying mediump vec2 TexCoord;
417b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens
427b21f276fa91ad62fd2055844688b07829f12205Nicolas Capensvoid main()
437b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens{
447b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens	if(BoneCount > 0)
457b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens	{
467b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens		// On PowerVR SGX it is possible to index the components of a vector
477b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens		// with the [] operator. However this can cause trouble with PC
487b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens		// emulation on some hardware so we "rotate" the vectors instead.
497b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens		mediump ivec4 boneIndex = ivec4(inBoneIndex);
507b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens		mediump vec4 boneWeights = inBoneWeights;
517b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens
527b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens		highp mat4 boneMatrix = BoneMatrixArray[boneIndex.x];
537b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens		mediump mat3 normalMatrix = BoneMatrixArrayIT[boneIndex.x];
547b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens
557b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens		highp vec4 position = boneMatrix * vec4(inVertex, 1.0) * boneWeights.x;
567b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens		mediump vec3 worldNormal = normalMatrix * inNormal * boneWeights.x;
577b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens
587b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens		mediump vec3 worldTangent;
597b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens		mediump vec3 worldBiNormal;
607b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens
617b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens		if(bUseDot3)
627b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens		{
637b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens			worldTangent = normalMatrix * inTangent * boneWeights.x;
647b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens			worldBiNormal = normalMatrix * inBiNormal * boneWeights.x;
657b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens		}
667b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens
677b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens		for (lowp int i = 1; i < 3; ++i)
687b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens		{
697b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens			if(i < BoneCount)
707b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens			{
717b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens				// "rotate" the vector components
727b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens				boneIndex = boneIndex.yzwx;
737b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens				boneWeights = boneWeights.yzwx;
747b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens
757b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens				boneMatrix = BoneMatrixArray[boneIndex.x];
767b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens				normalMatrix = BoneMatrixArrayIT[boneIndex.x];
777b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens
787b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens				position += boneMatrix * vec4(inVertex, 1.0) * boneWeights.x;
797b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens				worldNormal += normalMatrix * inNormal * boneWeights.x;
807b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens
817b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens				if(bUseDot3)
827b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens				{
837b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens					worldTangent += normalMatrix * inTangent * boneWeights.x;
847b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens					worldBiNormal += normalMatrix * inBiNormal * boneWeights.x;
857b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens				}
867b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens			}
877b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens		}
887b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens		gl_Position = ViewProjMatrix * position;
897b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens
907b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens		// lighting
917b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens		mediump vec3 TmpLightDir = normalize(LightPos - position.xyz);
927b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens
937b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens		if(bUseDot3)
947b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens		{
957b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens			Light.x = dot(normalize(worldTangent), TmpLightDir);
967b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens			Light.y = dot(normalize(worldBiNormal), TmpLightDir);
977b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens			Light.z = dot(normalize(worldNormal), TmpLightDir);
987b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens		}
997b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens		else
1007b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens		{
1017b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens			Light.x = dot(normalize(worldNormal), TmpLightDir);
1027b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens		}
1037b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens	}
1047b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens
1057b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens
1067b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens	// Pass through texcoords
1077b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens	TexCoord = inTexCoord;
1087b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens}
1097b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens