1#include "DualQuaternionSkinning_Shadow.cg"
2
3//Dual quaternion skinning with per-vertex antipodality handling (this is the most robust, but not the most efficient way):
4void dualQuaternionHardwareSkinningTwoWeights_vp(
5	float4 position : POSITION,
6	float3 normal   : NORMAL,
7	float2 uv       : TEXCOORD0,
8	float4 blendIdx : BLENDINDICES,
9	float4 blendWgt : BLENDWEIGHT,
10
11	out float4 oPosition : POSITION,
12	out float2 oUv       : TEXCOORD0,
13	out float4 colour    : COLOR,
14	// Support up to 24 bones of float3x4
15	// vs_1_1 only supports 96 params so more than this is not feasible
16	uniform float2x4 worldDualQuaternion2x4Array[24],
17	uniform float4x4 viewProjectionMatrix,
18	uniform float4   lightPos[2],
19	uniform float4   lightDiffuseColour[2],
20	uniform float4   ambient,
21	uniform float4   diffuse)
22{
23	float2x4 blendDQ = blendTwoWeightsAntipod(blendWgt, blendIdx, worldDualQuaternion2x4Array);
24
25	float len = length(blendDQ[0]);
26	blendDQ /= len;
27
28	float3 blendPosition = calculateBlendPosition(position, blendDQ);
29
30	//No need to normalize, the magnitude of the normal is preserved because only rotation is performed
31	float3 blendNormal = calculateBlendNormal(normal, blendDQ);
32
33	oPosition = mul(viewProjectionMatrix, float4(blendPosition, 1.0));
34
35	// Lighting - support point and directional
36	float3 lightDir0 = normalize(lightPos[0].xyz - (blendPosition.xyz * lightPos[0].w));
37	float3 lightDir1 = normalize(lightPos[1].xyz - (blendPosition.xyz * lightPos[1].w));
38
39	oUv = uv;
40
41	colour = diffuse * (ambient + (saturate(dot(lightDir0, blendNormal)) * lightDiffuseColour[0]) +
42		(saturate(dot(lightDir1, blendNormal)) * lightDiffuseColour[1]));
43}
44
45//Two-phase skinning: dual quaternion skinning with scale and shear transformations
46void dualQuaternionHardwareSkinningTwoWeightsTwoPhase_vp(
47	float4 position : POSITION,
48	float3 normal   : NORMAL,
49	float2 uv       : TEXCOORD0,
50	float4 blendIdx : BLENDINDICES,
51	float4 blendWgt : BLENDWEIGHT,
52
53
54	out float4 oPosition : POSITION,
55	out float2 oUv       : TEXCOORD0,
56	out float4 colour    : COLOR,
57	// Support up to 24 bones of float3x4
58	// vs_1_1 only supports 96 params so more than this is not feasible
59	uniform float2x4 worldDualQuaternion2x4Array[24],
60	uniform float3x4 scaleM[24],
61	uniform float4x4 viewProjectionMatrix,
62	uniform float4   lightPos[2],
63	uniform float4   lightDiffuseColour[2],
64	uniform float4   ambient,
65	uniform float4   diffuse)
66{
67	//First phase - applies scaling and shearing:
68	float3x4 blendS = blendWgt.x*scaleM[blendIdx.x];
69	blendS += blendWgt.y*scaleM[blendIdx.y];
70
71	float3 pass1_position = mul(blendS, position);
72	float3x3 blendSrotAT = adjointTransposeMatrix(float3x3(blendS));
73	float3 pass1_normal = normalize(mul(blendSrotAT, normal.xyz));
74
75	//Second phase
76	float2x4 blendDQ = blendTwoWeightsAntipod(blendWgt, blendIdx, worldDualQuaternion2x4Array);
77
78	float len = length(blendDQ[0]);
79	blendDQ /= len;
80
81	float3 blendPosition = calculateBlendPosition(float4(pass1_position, 1.0), blendDQ);
82
83	//No need to normalize, the magnitude of the normal is preserved because only rotation is performed
84	float3 blendNormal = calculateBlendNormal(pass1_normal, blendDQ);
85
86	oPosition = mul(viewProjectionMatrix, float4(blendPosition, 1.0));
87
88	// Lighting - support point and directional
89	float3 lightDir0 = normalize(lightPos[0].xyz - (blendPosition.xyz * lightPos[0].w));
90	float3 lightDir1 = normalize(lightPos[1].xyz - (blendPosition.xyz * lightPos[1].w));
91
92	oUv = uv;
93	colour = diffuse * (ambient + (saturate(dot(lightDir0, blendNormal)) * lightDiffuseColour[0]) +
94		(saturate(dot(lightDir1, blendNormal)) * lightDiffuseColour[1]));
95}
96