//********************************************************************** // Vertex Shaders //********************************************************************** float4x4 Model : WORLD; float4x4 View : VIEW; float4x4 Projection : PROJECTION; // #define MaxBones 58 // 最大ボーン数 // この数値を変えた時にはSkinnedModelProcessorの // MaxBonesも変えることを忘れないように #define MaxBones 108 // 暫定(最大116?) // float4x4 Bones[MaxBones]; // ボーンの回転部分 float4 BoneRotations[MaxBones]; // ボーンの平行移動部分 float3 BoneTranslations[MaxBones]; //----------------------------------------------------------------------------- // クォータニオンヘルパーメソッド //============================================================================= // クォータニオンによる回転 float3 TransformByQuaternion( float3 position, float4 quaternion) { float4 Q = quaternion; float3 v = position; return 2.0f * ( ( Q.w * Q.w - 0.5f ) * v + dot( v, Q.xyz ) * Q.xyz + Q.w * cross( Q.xyz, v ) ); } // クォータニオンと平行移動による頂点変換 float3 TransformByQuatTransform( float3 position, float4 quaternion, float3 translation ) { float3 p = TransformByQuaternion( position, quaternion ); p += translation; return p; } // クォータニオンと平行移動から行列に変換する // スキニングに使用する場合、単純にこのメソッドを4回呼ぶのが理想的だが // SM2.0だと一時レジスタ(12個)を超えてしまうので、そのままでは使えない float4x4 CreateTransformFromQuaternionTransform( float4 quaternion, float3 translation ) { float4 q = quaternion; float ww = q.w * q.w - 0.5f; float3 v00 = float3( ww , q.x * q.y, q.x * q.z ); float3 v01 = float3( q.x * q.x, q.w * q.z,-q.w * q.y ); float3 v10 = float3( q.x * q.y, ww, q.y * q.z ); float3 v11 = float3( q.w * q.z,-q.y * q.y, q.w * q.x ); float3 v20 = float3( q.x * q.z, q.y * q.z, ww ); float3 v21 = float3( q.w * q.y,-q.w * q.x, q.z * q.z ); return float4x4( 2.0f * ( v00 + v01 ), 0, 2.0f * ( v10 + v11 ), 0, 2.0f * ( v20 + v21 ), 0, translation, 1 ); } // 4つクォータニオンと平行移動から行列に変換する // SM2.0の一時レジスタ(12個)数制限を回避するために、一時レジスタの使用量を抑えるように // 書き換えたもの float4x4 CreateTransformFromQuaternionTransforms( float4 q1, float3 t1, float4 q2, float3 t2, float4 q3, float3 t3, float4 q4, float3 t4, float4 weights ) { float ww = q1.w * q1.w - 0.5f; float3 row10 = float3( ww , q1.x * q1.y, q1.x * q1.z ) + float3( q1.x * q1.x, q1.w * q1.z,-q1.w * q1.y ); float3 row11 = float3( q1.x * q1.y, ww, q1.y * q1.z ) + float3(-q1.w * q1.z, q1.y * q1.y, q1.w * q1.x ); float3 row12 = float3( q1.x * q1.z, q1.y * q1.z, ww ) + float3( q1.w * q1.y,-q1.w * q1.x, q1.z * q1.z ); ww = q2.w * q2.w - 0.5f; float3 row20 = float3( ww, q2.x * q2.y, q2.x * q2.z ) + float3( q2.x * q2.x, q2.w * q2.z,-q2.w * q2.y ); float3 row21 = float3( q2.x * q2.y, ww, q2.y * q2.z ) + float3(-q2.w * q2.z, q2.y * q2.y, q2.w * q2.x ); float3 row22 = float3( q2.x * q2.z, q2.y * q2.z, ww ) + float3( q2.w * q2.y,-q2.w * q2.x, q2.z * q2.z ); ww = q3.w * q3.w - 0.5f; float3 row30 = float3( ww, q3.x * q3.y, q3.x * q3.z ) + float3( q3.x * q3.x, q3.w * q3.z,-q3.w * q3.y ); float3 row31 = float3( q3.x * q3.y, ww, q3.y * q3.z ) + float3(-q3.w * q3.z, q3.y * q3.y, q3.w * q3.x ); float3 row32 = float3( q3.x * q3.z, q3.y * q3.z, ww ) + float3( q3.w * q3.y,-q3.w * q3.x, q3.z * q3.z ); ww = q4.w * q4.w - 0.5f; float3 row40 = float3( ww, q4.x * q4.y, q4.x * q4.z ) + float3( q4.x * q4.x, q4.w * q4.z,-q4.w * q4.y ); float3 row41 = float3( q4.x * q4.y, ww, q4.y * q4.z ) + float3(-q4.w * q4.z, q4.y * q4.y, q4.w * q4.x ); float3 row42 = float3( q4.x * q4.z, q4.y * q4.z, ww ) + float3( q4.w * q4.y,-q4.w * q4.x, q4.z * q4.z ); float4 w2 = 2.0f * weights; return float4x4( row10 * w2.x + row20 * w2.y + row30 * w2.z + row40 * w2.w, 0, row11 * w2.x + row21 * w2.y + row31 * w2.z + row41 * w2.w, 0, row12 * w2.x + row22 * w2.y + row32 * w2.z + row42 * w2.w, 0, t1 * weights.x + t2 * weights.y + t3 * weights.z + t4 * weights.w, 1 ); } //----------------------------------------------------------------------------- // 頂点シェーダー //============================================================================= XSI_VertexToPixel VSSkinned ( XSI_AppToVertex IN ) { XSI_VertexToPixel OUT; // Blend between the weighted bone matrices. float4x4 skinTransform = 0; // skinTransform += Bones[IN.BoneIndices.x] * IN.BoneWeights.x; // skinTransform += Bones[IN.BoneIndices.y] * IN.BoneWeights.y; // skinTransform += Bones[IN.BoneIndices.z] * IN.BoneWeights.z; // skinTransform += Bones[IN.BoneIndices.w] * IN.BoneWeights.w; // スキン変換行列の取得 skinTransform = CreateTransformFromQuaternionTransforms( BoneRotations[IN.BoneIndices.x], BoneTranslations[IN.BoneIndices.x], BoneRotations[IN.BoneIndices.y], BoneTranslations[IN.BoneIndices.y], BoneRotations[IN.BoneIndices.z], BoneTranslations[IN.BoneIndices.z], BoneRotations[IN.BoneIndices.w], BoneTranslations[IN.BoneIndices.w], IN.BoneWeights ); // Skin the vertex position. float4 weightedposition = mul(IN.position, skinTransform); // transform in screen space OUT.position = mul( mul(weightedposition, View), Projection ); // position in global space is in TC4 OUT.texcoord4 = weightedposition; // Tangent to world space is stored in TC5,6,7 float3 N = IN.normal; #ifdef _BIASED_TANGENTS_ float3 T = (IN.color0 * 2) - 1; #else float3 T = IN.color0; #endif float3 B = N.yzx * T.zxy; B = (-T.yzx * N.zxy) + B; N = mul(N, skinTransform); T = mul(T, skinTransform); B = mul(B, skinTransform); OUT.texcoord5 = normalize(B).xyzz; OUT.texcoord6 = normalize(T).xyzz; OUT.texcoord7 = normalize(N).xyzz; // position in global space is stored in TC7 // these texture coordinates are used as texture coordinates OUT.texcoord0 = IN.texcoord0; OUT.texcoord1 = IN.texcoord1; OUT.texcoord2 = IN.texcoord2; OUT.texcoord3 = IN.texcoord3; // leftovers OUT.color0 = IN.color0; OUT.color1 = IN.color1; return OUT; } XSI_VertexToPixel VSStatic ( XSI_AppToVertex IN ) { XSI_VertexToPixel OUT; float4 position = mul(IN.position, Model); // transform in screen space OUT.position = mul( mul(position, View), Projection ); // position in global space is in TC4 OUT.texcoord4 = position; // Tangent to world space is stored in TC5,6,7 float3 N = IN.normal; float3 T = (IN.color0 * 2) - 1; float3 B = N.yzx * T.zxy; B = (-T.yzx * N.zxy) + B; N = mul(N, Model); T = mul(T, Model); B = mul(B, Model); OUT.texcoord5 = normalize(B).xyzz; OUT.texcoord6 = normalize(T).xyzz; OUT.texcoord7 = normalize(N).xyzz; // position in global space is stored in TC7 // these texture coordinates are used as texture coordinates OUT.texcoord0 = IN.texcoord0; OUT.texcoord1 = IN.texcoord1; OUT.texcoord2 = IN.texcoord2; OUT.texcoord3 = IN.texcoord3; // leftovers OUT.color0 = IN.color0; OUT.color1 = IN.color1; return OUT; }