1#include "DualQuaternion_Common.hlsl" 2 3 4struct v2p 5{ 6 float4 oPosition : SV_POSITION; 7 float2 oUv : TEXCOORD0; 8 float4 colour : COLOR; 9}; 10 11struct dualQuaternionHardwareSkinningTwoWeights_vp_in 12{ 13 float4 position : SV_POSITION; 14 float3 normal : NORMAL; 15 float2 uv : TEXCOORD0; 16 float4 blendIdx : BLENDINDICES; 17 float4 blendWgt : BLENDWEIGHT; 18}; 19//Dual quaternion skinning with per-vertex antipodality handling (this is the most robust, but not the most efficient way): 20v2p dualQuaternionHardwareSkinningTwoWeights_vp( 21 dualQuaternionHardwareSkinningTwoWeights_vp_in input, 22 uniform float2x4 worldDualQuaternion2x4Array[24], 23 uniform float4x4 viewProjectionMatrix, 24 uniform float4 lightPos[2], 25 uniform float4 lightDiffuseColour[2], 26 uniform float4 ambient, 27 uniform float4 diffuse) 28{ 29 v2p output; 30 float2x4 blendDQ = blendTwoWeightsAntipod(input.blendWgt, input.blendIdx, worldDualQuaternion2x4Array); 31 32 float len = length(blendDQ[0]); 33 blendDQ /= len; 34 35 float3 blendPosition = calculateBlendPosition(input.position.xyz, blendDQ); 36 37 //No need to normalize, the magnitude of the normal is preserved because only rotation is performed 38 float3 blendNormal = calculateBlendNormal(input.normal, blendDQ); 39 40 output.oPosition = mul(viewProjectionMatrix, float4(blendPosition, 1.0)); 41 42 // Lighting - support point and directional 43 float3 lightDir0 = normalize(lightPos[0].xyz - (blendPosition.xyz * lightPos[0].w)); 44 float3 lightDir1 = normalize(lightPos[1].xyz - (blendPosition.xyz * lightPos[1].w)); 45 46 output.oUv = input.uv; 47 48 output.colour = diffuse * (ambient + (saturate(dot(lightDir0, blendNormal)) * lightDiffuseColour[0]) + 49 (saturate(dot(lightDir1, blendNormal)) * lightDiffuseColour[1])); 50 51 return output; 52} 53 54struct dualQuaternionHardwareSkinningTwoWeightsCaster_vp_in 55{ 56 float4 position : SV_POSITION; 57 float4 blendIdx : BLENDINDICES; 58 float4 blendWgt : BLENDWEIGHT; 59}; 60 61struct v2ps 62{ 63 float4 oPosition : SV_POSITION; 64 float4 colour : COLOR; 65}; 66//Shadow caster pass 67v2ps dualQuaternionHardwareSkinningTwoWeightsCaster_vp( 68 dualQuaternionHardwareSkinningTwoWeightsCaster_vp_in input, 69 uniform float2x4 worldDualQuaternion2x4Array[24], 70 uniform float4x4 viewProjectionMatrix, 71 uniform float4 ambient) 72{ 73 v2ps output; 74 float2x4 blendDQ = blendTwoWeightsAntipod(input.blendWgt, input.blendIdx, worldDualQuaternion2x4Array); 75 76 float len = length(blendDQ[0]); 77 blendDQ /= len; 78 79 float3 blendPosition = calculateBlendPosition(input.position.xyz, blendDQ); 80 81 // view / projection 82 output.oPosition = mul(viewProjectionMatrix, float4(blendPosition, 1.0)); 83 84 output.colour = ambient; 85 return output; 86} 87 88//Two-phase skinning: dual quaternion skinning with scale and shear transformations 89v2p dualQuaternionHardwareSkinningTwoWeightsTwoPhase_vp( 90 dualQuaternionHardwareSkinningTwoWeights_vp_in input, 91 uniform float2x4 worldDualQuaternion2x4Array[24], 92 uniform float3x4 scaleM[24], 93 uniform float4x4 viewProjectionMatrix, 94 uniform float4 lightPos[2], 95 uniform float4 lightDiffuseColour[2], 96 uniform float4 ambient, 97 uniform float4 diffuse) 98{ 99 v2p output; 100 //First phase - applies scaling and shearing: 101 float3x4 blendS = input.blendWgt.x*scaleM[input.blendIdx.x]; 102 blendS += input.blendWgt.y*scaleM[input.blendIdx.y]; 103 104 float3 pass1_position = mul(blendS, input.position); 105 float3x3 blendSrotAT = adjointTransposeMatrix(blendS); 106 float3 pass1_normal = normalize(mul(blendSrotAT, input.normal.xyz)); 107 108 //Second phase 109 float2x4 blendDQ = blendTwoWeightsAntipod(input.blendWgt, input.blendIdx, worldDualQuaternion2x4Array); 110 111 float len = length(blendDQ[0]); 112 blendDQ /= len; 113 114 float3 blendPosition = calculateBlendPosition(pass1_position, blendDQ); 115 116 //No need to normalize, the magnitude of the normal is preserved because only rotation is performed 117 float3 blendNormal = calculateBlendNormal(pass1_normal, blendDQ); 118 119 output.oPosition = mul(viewProjectionMatrix, float4(blendPosition, 1.0)); 120 121 // Lighting - support point and directional 122 float3 lightDir0 = normalize(lightPos[0].xyz - (blendPosition.xyz * lightPos[0].w)); 123 float3 lightDir1 = normalize(lightPos[1].xyz - (blendPosition.xyz * lightPos[1].w)); 124 125 output.oUv = input.uv; 126 output.colour = diffuse * (ambient + (saturate(dot(lightDir0, blendNormal)) * lightDiffuseColour[0]) + 127 (saturate(dot(lightDir1, blendNormal)) * lightDiffuseColour[1])); 128 return output; 129} 130 131//Two-phase skinning shadow caster pass 132v2ps dualQuaternionHardwareSkinningTwoWeightsTwoPhaseCaster_vp( 133 dualQuaternionHardwareSkinningTwoWeightsCaster_vp_in input, 134 uniform float2x4 worldDualQuaternion2x4Array[24], 135 uniform float3x4 scaleM[24], 136 uniform float4x4 viewProjectionMatrix, 137 uniform float4 ambient) 138{ 139 v2ps output; 140 //First phase - applies scaling and shearing: 141 float3x4 blendS = input.blendWgt.x*scaleM[input.blendIdx.x]; 142 blendS += input.blendWgt.y*scaleM[input.blendIdx.y]; 143 144 float3 pass1_position = mul(blendS, input.position); 145 146 //Second phase 147 float2x4 blendDQ = blendTwoWeightsAntipod(input.blendWgt, input.blendIdx, worldDualQuaternion2x4Array); 148 149 float len = length(blendDQ[0]); 150 blendDQ /= len; 151 152 float3 blendPosition = calculateBlendPosition(pass1_position, blendDQ); 153 154 // view / projection 155 output.oPosition = mul(viewProjectionMatrix, float4(blendPosition, 1.0)); 156 157 output.colour = ambient; 158 return output; 159} 160 161