Files
2026-08-09 04:23:10 -07:00

753 lines
24 KiB
C++

/*
==================================================================================
CALC_TEXCOORDS
uses vertex.texcoord0;
out float4 texcoords;
==================================================================================
*/
#template CALC_TEXCOORDS( texcoords )
{
// base coordinates modified by stScaleBias for 16 bit vertex elements
texcoords = ( vertex.texcoord0.xy * $vertexStScaleBias.xy + $vertexStScaleBias.zw ).xyxy;
}
#endtemplate
/*
==================================================================================
CALC_TEXCOORDS_BLEND
uses vertex.texcoord0;
out float4 texcoords;
==================================================================================
*/
#template CALC_TEXCOORDS_BLEND( texcoords )
{
// base coordinates modified by stScaleBias for 16 bit vertex elements
texcoords = ( vertex.texcoord0.xyxy * $vertexStScaleBias.xyxy + $vertexStScaleBias.zwzw ) + skinOffsets.xyzw;
}
#endtemplate
/*
==================================================================================
CALC_POSITION
uses vertex.position;
out float4 resultPosition;
==================================================================================
*/
#template CALC_POSITION( resultPosition )
{
// Convert back from 16 bit vertex elements.
float4 localPosition = vertex.position * $vertexXYZScale + $vertexXYZBias;
resultPosition.x = dot4( localPosition, $mvpMatrixX );
resultPosition.y = dot4( localPosition, $mvpMatrixY );
resultPosition.z = dot4( localPosition, $mvpMatrixZ );
resultPosition.w = dot4( localPosition, $mvpMatrixW );
}
#endtemplate
/*
==================================================================================
CALC_MUZZLE_FLASH_VECTOR
uses MFOffset;
out MFVector;
==================================================================================
*/
#template CALC_MUZZLE_FLASH_VECTOR( MFOffset, MFVector )
{
//float3 globalPosition = _float4( 0.0 );
//globalPosition.x = dot4( position, $modelMatrixX );
//globalPosition.y = dot4( position, $modelMatrixY );
//globalPosition.z = dot4( position, $modelMatrixZ );
float3 globalMFOffset = _float3( 0.0 );
//float3 altGlobalViewFwd = cross( $globalViewLeft.xyz, $globalViewUp.xyz );
//globalMFOffset.xyz = altGlobalViewFwd.xyz * _float3( MFOffset.x );
globalMFOffset.xyz = $globalViewFwd.xyz * _float3( MFOffset.x );
globalMFOffset.xyz += $globalViewLeft.xyz * _float3( MFOffset.y );
globalMFOffset.xyz += $globalViewUp.xyz * _float3( MFOffset.z );
//float3 globalMFPosition = $globalViewOrigin.xyz + globalMFOffset;
MFVector.xyz = normalize( globalMFOffset );
//MFVector.xyz = normalize( $globalViewFwd.xyz );
MFVector.w = 1.0;
//float4 localPosition = vertex.position * $vertexXYZScale + $vertexXYZBias;
//MFOffset = normalize( MFOffset - localPosition );
//MFVector.x = dot3( MFOffset, $modelMatrixX );
//MFVector.y = dot3( MFOffset, $modelMatrixY );
//MFVector.z = dot3( MFOffset, $modelMatrixZ );
//MFVector.w = 0.0;
}
#endtemplate
/*
==================================================================================
CALC_POSITION_NORMALS
uses vertex.position;
uses vertex.normal;
uses vertex.tangent;
out float4 resultPosition;
out float4 localToGlobalX;
out float4 localToGlobalY;
out float4 localToGlobalZ;
out float4 viewOriginToVertex;
==================================================================================
*/
#template CALC_POSITION_NORMALS( resultPosition, localToGlobalX, localToGlobalY, localToGlobalZ, viewOriginToVertex )
{
// Convert back from 16 bit vertex elements.
float4 localPosition = vertex.position * $vertexXYZScale + $vertexXYZBias;
float4 normal = vertex.normal * 2.0 - 1.0;
float4 tangent = vertex.tangent * 2.0 - 1.0;
float3 bitangent = cross( normal.xyz, tangent.xyz ) * tangent.w;
resultPosition.x = dot4( localPosition, $mvpMatrixX );
resultPosition.y = dot4( localPosition, $mvpMatrixY );
resultPosition.z = dot4( localPosition, $mvpMatrixZ );
resultPosition.w = dot4( localPosition, $mvpMatrixW );
localToGlobalX.x = dot3( tangent, $modelMatrixX );
localToGlobalX.y = dot3( bitangent, $modelMatrixX );
localToGlobalX.z = dot3( normal, $modelMatrixX );
localToGlobalX.w = 0.0;
localToGlobalY.x = dot3( tangent, $modelMatrixY );
localToGlobalY.y = dot3( bitangent, $modelMatrixY );
localToGlobalY.z = dot3( normal, $modelMatrixY );
localToGlobalY.w = 0.0;
localToGlobalZ.x = dot3( tangent, $modelMatrixZ );
localToGlobalZ.y = dot3( bitangent, $modelMatrixZ );
localToGlobalZ.z = dot3( normal, $modelMatrixZ );
localToGlobalZ.w = 0.0;
viewOriginToVertex.x = dot4( localPosition, $modelMatrixX );
viewOriginToVertex.y = dot4( localPosition, $modelMatrixY );
viewOriginToVertex.z = dot4( localPosition, $modelMatrixZ );
viewOriginToVertex.xyz -= $globalViewOrigin.xyz;
viewOriginToVertex.w = 0.0;
}
#endtemplate
/*
==================================================================================
CALC_SKINNED_POSITIONS
uses vertex.position;
out float4 localPosition;
out float4 resultPosition;
==================================================================================
*/
// CALC_SKINNED_POSITIONS is a reduced form of CALC_SKINNED_POSITIONS_NORMALS
#template CALC_SKINNED_POSITIONS( localPosition, resultPosition )
{
// Convert back from 16 bit vertex elements.
localPosition = vertex.position * $vertexXYZScale + $vertexXYZBias;
#if defined( XBOX )
if ( bHardwareSkinning ) {
float4 vertexPosition = localPosition;
if ( bHardwareMorphing ) {
#if 0
// Fetch the morph value with inline asm,
// so it only gets getched when bHardwareMorphing is
// enabled. If we just used vertex.morph.xyz, it would
// always be fetched, and gives streams of Pix warnings
// when the stream buffer is bound to NULL.
float4 vertexMorph;
int index = vertex.index;
asm {
vfetch vertexMorph, index, color2
};
float3 morphVector = ( vertexMorph.xyz * 2 ) - 1;
vertexPosition.xyz += ( morphVector * vertexMorph.w * 32.0f );
#else
float3 morphVector = ( vertex.morph.xyz * 2 ) - 1;
vertexPosition.xyz += ( morphVector * vertex.morph.w * 32.0f );
#endif
}
// multiplying with 255.1 give us the same result and is faster than floor( w * 255 + 0.5 )
float weights = vertex.normal.w * 255.1; // [0, 1] -> [0, 255]
float w1 = floor( weights / 16 ); // [0, 15] (= 4 bits)
float w2 = floor( weights / 4 ) - ( w1 * 4 ); // [0, 3] (= 2 bits)
float w3 = weights - ( w2 * 4 ) - ( w1 * 16 ); // [0, 3] (= 2 bits)
w1 *= 1.0 / 30.0; // [0, 15] -> [0, 1/2]
w2 *= 1.0 / 9.0; // [0, 3] -> [0, 1/3]
w3 *= 1.0 / 12.0; // [0, 3] -> [0, 1/4]
float w0 = 1 - ( w1 + w2 + w3 ); // [1/4, 1]
float4 matX, matY, matZ;
float joint = vertex.color.a * 255.1;
asm {
vfetch matX, joint, position1, UseTextureCache=true, RoundIndex = true
vfetch matY, joint, position2, UseTextureCache=true, RoundIndex = true
vfetch matZ, joint, position3, UseTextureCache=true, RoundIndex = true
};
matX *= w0;
matY *= w0;
matZ *= w0;
float4 tmatX, tmatY, tmatZ;
joint = vertex.color.b * 255.1;
asm {
vfetch tmatX, joint, position1, UseTextureCache=true, RoundIndex = true
vfetch tmatY, joint, position2, UseTextureCache=true, RoundIndex = true
vfetch tmatZ, joint, position3, UseTextureCache=true, RoundIndex = true
};
matX += tmatX * w1;
matY += tmatY * w1;
matZ += tmatZ * w1;
joint = vertex.color.g * 255.1;
asm {
vfetch tmatX, joint, position1, UseTextureCache=true, RoundIndex = true
vfetch tmatY, joint, position2, UseTextureCache=true, RoundIndex = true
vfetch tmatZ, joint, position3, UseTextureCache=true, RoundIndex = true
};
matX += tmatX * w2;
matY += tmatY * w2;
matZ += tmatZ * w2;
joint = vertex.color.r * 255.1;
asm {
vfetch tmatX, joint, position1, UseTextureCache=true, RoundIndex = true
vfetch tmatY, joint, position2, UseTextureCache=true, RoundIndex = true
vfetch tmatZ, joint, position3, UseTextureCache=true, RoundIndex = true
};
matX += tmatX * w3;
matY += tmatY * w3;
matZ += tmatZ * w3;
localPosition.x = dot4( vertexPosition, matX );
localPosition.y = dot4( vertexPosition, matY );
localPosition.z = dot4( vertexPosition, matZ );
localPosition.w = 1.0;
}
#elif defined( PS3 )
if ( hardwareSkinning ) {
float4 vertexPosition = localPosition;
if ( hardwareMorphing ) {
float3 morphVector = ( vertex.morph.xyz * 2 ) - 1;
vertexPosition.xyz += ( morphVector * vertex.morph.w * 32.0f );
}
// multiplying with 255.1 give us the same result and is faster than floor( w * 255 + 0.5 )
float weights = vertex.normal.w * 255.1; // [0, 1] -> [0, 255]
float w1 = floor( weights / 16 ); // [0, 15] (= 4 bits)
float w2 = floor( weights / 4 ) - ( w1 * 4 ); // [0, 3] (= 2 bits)
float w3 = weights - ( w2 * 4 ) - ( w1 * 16 ); // [0, 3] (= 2 bits)
w1 *= 1.0 / 30.0; // [0, 15] -> [0, 1/2]
w2 *= 1.0 / 9.0; // [0, 3] -> [0, 1/3]
w3 *= 1.0 / 12.0; // [0, 3] -> [0, 1/4]
float w0 = 1 - ( w1 + w2 + w3 ); // [1/4, 1]
float4 matX, matY, matZ;
float joint = vertex.color.r * 255.1 * 3;
matX = matrices[joint+0] * w0;
matY = matrices[joint+1] * w0;
matZ = matrices[joint+2] * w0;
joint = vertex.color.g * 255.1 * 3;
matX += matrices[joint+0] * w1;
matY += matrices[joint+1] * w1;
matZ += matrices[joint+2] * w1;
joint = vertex.color.b * 255.1 * 3;
matX += matrices[joint+0] * w2;
matY += matrices[joint+1] * w2;
matZ += matrices[joint+2] * w2;
joint = vertex.color.a * 255.1 * 3;
matX += matrices[joint+0] * w3;
matY += matrices[joint+1] * w3;
matZ += matrices[joint+2] * w3;
localPosition.x = dot4( vertexPosition, matX );
localPosition.y = dot4( vertexPosition, matY );
localPosition.z = dot4( vertexPosition, matZ );
localPosition.w = 1.0;
}
#elif defined( PC_D3D )
if ( hardwareSkinning.x != 0.0 ) {
float4 vertexPosition = localPosition;
if ( hardwareSkinning.y != 0.0 ) {
float3 morphVector = ( vertex.morph.xyz * 2 ) - 1;
vertexPosition.xyz += ( morphVector * vertex.morph.w * 32.0f );
}
float weights = vertex.normal.w * 255; // [0, 1] -> [0, 255]
float w1 = floor( weights / 16 ); // [0, 15] (= 4 bits)
float w2 = floor( weights / 4 ) - ( w1 * 4 ); // [0, 3] (= 2 bits)
float w3 = weights - ( w2 * 4 ) - ( w1 * 16 ); // [0, 3] (= 2 bits)
w1 *= 1.0 / 30.0; // [0, 15] -> [0, 1/2]
w2 *= 1.0 / 9.0; // [0, 3] -> [0, 1/3]
w3 *= 1.0 / 12.0; // [0, 3] -> [0, 1/4]
float w0 = 1 - ( w1 + w2 + w3 ); // [1/4, 1]
float4 matX, matY, matZ;
float joint = vertex.color.r * 255;
matX = matrices[int(joint*3+0)] * w0;
matY = matrices[int(joint*3+1)] * w0;
matZ = matrices[int(joint*3+2)] * w0;
joint = vertex.color.g * 255;
matX += matrices[int(joint*3+0)] * w1;
matY += matrices[int(joint*3+1)] * w1;
matZ += matrices[int(joint*3+2)] * w1;
joint = vertex.color.b * 255;
matX += matrices[int(joint*3+0)] * w2;
matY += matrices[int(joint*3+1)] * w2;
matZ += matrices[int(joint*3+2)] * w2;
joint = vertex.color.a * 255;
matX += matrices[int(joint*3+0)] * w3;
matY += matrices[int(joint*3+1)] * w3;
matZ += matrices[int(joint*3+2)] * w3;
localPosition.x = dot4( vertexPosition, matX );
localPosition.y = dot4( vertexPosition, matY );
localPosition.z = dot4( vertexPosition, matZ );
localPosition.w = 1.0;
}
#elif defined( PC )
// apply vertex morphs
if ( hardwareSkinning.z != 0.0 ) {
localPosition += $vertexMorphScale.x * vertex.position1;
}
if ( hardwareSkinning.x != 0.0 ) {
float4 vertexPosition = localPosition;
if ( hardwareSkinning.y != 0.0 ) {
float3 morphVector = ( vertex.morph.xyz * 2 ) - 1;
vertexPosition.xyz += ( morphVector * vertex.morph.w * 32.0f );
}
float weights = vertex.normal.w * 255; // [0, 1] -> [0, 255]
float w1 = floor( weights / 16 ); // [0, 15] (= 4 bits)
float w2 = floor( weights / 4 ) - ( w1 * 4 ); // [0, 3] (= 2 bits)
float w3 = weights - ( w2 * 4 ) - ( w1 * 16 ); // [0, 3] (= 2 bits)
w1 *= 1.0 / 30.0; // [0, 15] -> [0, 1/2]
w2 *= 1.0 / 9.0; // [0, 3] -> [0, 1/3]
w3 *= 1.0 / 12.0; // [0, 3] -> [0, 1/4]
float w0 = 1 - ( w1 + w2 + w3 ); // [1/4, 1]
float4 matX, matY, matZ;
float joint = vertex.color.r * 255;
matX = matrices[int(joint*3+0)] * w0;
matY = matrices[int(joint*3+1)] * w0;
matZ = matrices[int(joint*3+2)] * w0;
joint = vertex.color.g * 255;
matX += matrices[int(joint*3+0)] * w1;
matY += matrices[int(joint*3+1)] * w1;
matZ += matrices[int(joint*3+2)] * w1;
joint = vertex.color.b * 255;
matX += matrices[int(joint*3+0)] * w2;
matY += matrices[int(joint*3+1)] * w2;
matZ += matrices[int(joint*3+2)] * w2;
joint = vertex.color.a * 255;
matX += matrices[int(joint*3+0)] * w3;
matY += matrices[int(joint*3+1)] * w3;
matZ += matrices[int(joint*3+2)] * w3;
localPosition.x = dot4( vertexPosition, matX );
localPosition.y = dot4( vertexPosition, matY );
localPosition.z = dot4( vertexPosition, matZ );
localPosition.w = 1.0;
}
#else
#error "unknown platform"
#endif
resultPosition.x = dot4( localPosition, $mvpMatrixX );
resultPosition.y = dot4( localPosition, $mvpMatrixY );
resultPosition.z = dot4( localPosition, $mvpMatrixZ );
resultPosition.w = dot4( localPosition, $mvpMatrixW );
}
#endtemplate
/*
==================================================================================
CALC_SKINNED_POSITIONS_NORMALS
uses vertex.position;
uses vertex.normal;
uses vertex.tangent;
out float4 localPosition;
out float4 resultPosition;
out float4 localToGlobalX;
out float4 localToGlobalY;
out float4 localToGlobalZ;
out float4 viewOriginToVertex;
==================================================================================
*/
#template CALC_PNT( position, normal, tangent )
{
// Convert back from 16 bit vertex elements.
position = vertex.position * $vertexXYZScale + $vertexXYZBias;
normal = vertex.normal * 2.0 - 1.0;
tangent = vertex.tangent * 2.0 - 1.0;
//float morphScale = 0.0f;
}
#endtemplate
// CALC_SKINNED_POSITIONS is a reduced form of CALC_SKINNED_POSITIONS_NORMALS
#template CALC_SKINNED_POSITIONS_NORMALS( localPosition, resultPosition, localToGlobalX, localToGlobalY, localToGlobalZ, viewOriginToVertex, position, normal, tangent, worldPosition )
{
// Convert back from 16 bit vertex elements.
//localPosition = vertex.position * $vertexXYZScale + $vertexXYZBias;
//float4 normal = vertex.normal * 2.0 - 1.0;
//float4 tangent = vertex.tangent * 2.0 - 1.0;
float morphScale = 0.0f;
localPosition = position;
#if defined( XBOX )
if ( bHardwareSkinning ) {
float4 vertexPosition = localPosition;
if ( bHardwareMorphing ) {
#if 0
// Fetch the morph value with inline asm,
// so it only gets getched when bHardwareMorphing is
// enabled. If we just used vertex.morph.xyz, it would
// always be fetched, and gives streams of Pix warnings
// when the stream buffer is bound to NULL.
float4 vertexMorph;
int index = vertex.index;
asm {
vfetch vertexMorph, index, color2
};
float3 morphVector = ( vertexMorph.xyz * 2 ) - 1;
morphScale = vertexMorph.w;
vertexPosition.xyz += ( morphVector * morphScale * 32.0f );
#else
float3 morphVector = ( vertex.morph.xyz * 2 ) - 1;
morphScale = vertex.morph.w;
vertexPosition.xyz += ( morphVector * morphScale * 32.0f );
#endif
}
// multiplying with 255.1 give us the same result and is faster than floor( w * 255 + 0.5 )
float weights = vertex.normal.w * 255.1; // [0, 1] -> [0, 255]
float w1 = floor( weights / 16 ); // [0, 15] (= 4 bits)
float w2 = floor( weights / 4 ) - ( w1 * 4 ); // [0, 3] (= 2 bits)
float w3 = weights - ( w2 * 4 ) - ( w1 * 16 ); // [0, 3] (= 2 bits)
w1 *= 1.0 / 30.0; // [0, 15] -> [0, 1/2]
w2 *= 1.0 / 9.0; // [0, 3] -> [0, 1/3]
w3 *= 1.0 / 12.0; // [0, 3] -> [0, 1/4]
float w0 = 1 - ( w1 + w2 + w3 ); // [1/4, 1]
float4 matX, matY, matZ;
float joint = vertex.color.a * 255.1;
asm {
vfetch matX, joint, position1, UseTextureCache=true, RoundIndex = true
vfetch matY, joint, position2, UseTextureCache=true, RoundIndex = true
vfetch matZ, joint, position3, UseTextureCache=true, RoundIndex = true
};
matX *= w0;
matY *= w0;
matZ *= w0;
float4 tmatX, tmatY, tmatZ;
joint = vertex.color.b * 255.1;
asm {
vfetch tmatX, joint, position1, UseTextureCache=true, RoundIndex = true
vfetch tmatY, joint, position2, UseTextureCache=true, RoundIndex = true
vfetch tmatZ, joint, position3, UseTextureCache=true, RoundIndex = true
};
matX += tmatX * w1;
matY += tmatY * w1;
matZ += tmatZ * w1;
joint = vertex.color.g * 255.1;
asm {
vfetch tmatX, joint, position1, UseTextureCache=true, RoundIndex = true
vfetch tmatY, joint, position2, UseTextureCache=true, RoundIndex = true
vfetch tmatZ, joint, position3, UseTextureCache=true, RoundIndex = true
};
matX += tmatX * w2;
matY += tmatY * w2;
matZ += tmatZ * w2;
joint = vertex.color.r * 255.1;
asm {
vfetch tmatX, joint, position1, UseTextureCache=true, RoundIndex = true
vfetch tmatY, joint, position2, UseTextureCache=true, RoundIndex = true
vfetch tmatZ, joint, position3, UseTextureCache=true, RoundIndex = true
};
matX += tmatX * w3;
matY += tmatY * w3;
matZ += tmatZ * w3;
localPosition.x = dot4( vertexPosition, matX );
localPosition.y = dot4( vertexPosition, matY );
localPosition.z = dot4( vertexPosition, matZ );
localPosition.w = 1.0;
float4 tempNormal = normal;
normal.x = dot3( tempNormal, matX );
normal.y = dot3( tempNormal, matY );
normal.z = dot3( tempNormal, matZ );
float4 tempTangent = tangent;
tangent.x = dot3( tempTangent, matX );
tangent.y = dot3( tempTangent, matY );
tangent.z = dot3( tempTangent, matZ );
}
#elif defined( PS3 )
if ( hardwareSkinning ) {
float4 vertexPosition = localPosition;
if ( hardwareMorphing ) {
float3 morphVector = ( vertex.morph.xyz * 2 ) - 1;
morphScale = vertex.morph.w;
vertexPosition.xyz += ( morphVector * morphScale * 32.0f );
}
// multiplying with 255.1 give us the same result and is faster than floor( w * 255 + 0.5 )
float weights = vertex.normal.w * 255.1; // [0, 1] -> [0, 255]
float w1 = floor( weights / 16 ); // [0, 15] (= 4 bits)
float w2 = floor( weights / 4 ) - ( w1 * 4 ); // [0, 3] (= 2 bits)
float w3 = weights - ( w2 * 4 ) - ( w1 * 16 ); // [0, 3] (= 2 bits)
w1 *= 1.0 / 30.0; // [0, 15] -> [0, 1/2]
w2 *= 1.0 / 9.0; // [0, 3] -> [0, 1/3]
w3 *= 1.0 / 12.0; // [0, 3] -> [0, 1/4]
float w0 = 1 - ( w1 + w2 + w3 ); // [1/4, 1]
float4 matX, matY, matZ;
float joint = vertex.color.r * 255.1 * 3;
matX = matrices[joint+0] * w0;
matY = matrices[joint+1] * w0;
matZ = matrices[joint+2] * w0;
joint = vertex.color.g * 255.1 * 3;
matX += matrices[joint+0] * w1;
matY += matrices[joint+1] * w1;
matZ += matrices[joint+2] * w1;
joint = vertex.color.b * 255.1 * 3;
matX += matrices[joint+0] * w2;
matY += matrices[joint+1] * w2;
matZ += matrices[joint+2] * w2;
joint = vertex.color.a * 255.1 * 3;
matX += matrices[joint+0] * w3;
matY += matrices[joint+1] * w3;
matZ += matrices[joint+2] * w3;
localPosition.x = dot4( vertexPosition, matX );
localPosition.y = dot4( vertexPosition, matY );
localPosition.z = dot4( vertexPosition, matZ );
localPosition.w = 1.0;
float4 tempNormal = normal;
normal.x = dot3( tempNormal, matX );
normal.y = dot3( tempNormal, matY );
normal.z = dot3( tempNormal, matZ );
float4 tempTangent = tangent;
tangent.x = dot3( tempTangent, matX );
tangent.y = dot3( tempTangent, matY );
tangent.z = dot3( tempTangent, matZ );
}
#elif defined( PC_D3D )
// FIXME_D3D
#elif defined( PC )
// apply vertex morphs
if ( hardwareSkinning.z != 0.0 ) {
localPosition += $vertexMorphScale.x * vertex.position1;
}
if ( hardwareSkinning.x != 0.0 ) {
float4 vertexPosition = localPosition;
if ( hardwareSkinning.y != 0.0 ) {
float3 morphVector = ( vertex.morph.xyz * 2 ) - 1;
morphScale = vertex.morph.w;
vertexPosition.xyz += ( morphVector * morphScale * 32.0f );
}
float weights = vertex.normal.w * 255; // [0, 1] -> [0, 255]
float w1 = floor( weights / 16 ); // [0, 15] (= 4 bits)
float w2 = floor( weights / 4 ) - ( w1 * 4 ); // [0, 3] (= 2 bits)
float w3 = weights - ( w2 * 4 ) - ( w1 * 16 ); // [0, 3] (= 2 bits)
w1 *= 1.0 / 30.0; // [0, 15] -> [0, 1/2]
w2 *= 1.0 / 9.0; // [0, 3] -> [0, 1/3]
w3 *= 1.0 / 12.0; // [0, 3] -> [0, 1/4]
float w0 = 1 - ( w1 + w2 + w3 ); // [1/4, 1]
float4 matX, matY, matZ;
float joint = vertex.color.r * 255;
matX = matrices[int(joint*3+0)] * w0;
matY = matrices[int(joint*3+1)] * w0;
matZ = matrices[int(joint*3+2)] * w0;
joint = vertex.color.g * 255;
matX += matrices[int(joint*3+0)] * w1;
matY += matrices[int(joint*3+1)] * w1;
matZ += matrices[int(joint*3+2)] * w1;
joint = vertex.color.b * 255;
matX += matrices[int(joint*3+0)] * w2;
matY += matrices[int(joint*3+1)] * w2;
matZ += matrices[int(joint*3+2)] * w2;
joint = vertex.color.a * 255;
matX += matrices[int(joint*3+0)] * w3;
matY += matrices[int(joint*3+1)] * w3;
matZ += matrices[int(joint*3+2)] * w3;
localPosition.x = dot4( vertexPosition, matX );
localPosition.y = dot4( vertexPosition, matY );
localPosition.z = dot4( vertexPosition, matZ );
localPosition.w = 1.0;
float4 tempNormal = normal;
normal.x = dot3( tempNormal, matX );
normal.y = dot3( tempNormal, matY );
normal.z = dot3( tempNormal, matZ );
float4 tempTangent = tangent;
tangent.x = dot3( tempTangent, matX );
tangent.y = dot3( tempTangent, matY );
tangent.z = dot3( tempTangent, matZ );
}
#else
#error "unknown platform"
#endif
float3 bitangent = cross( normal.xyz, tangent.xyz ) * tangent.w;
position = localPosition;
// vertex position
resultPosition.x = dot4( localPosition, $mvpMatrixX );
resultPosition.y = dot4( localPosition, $mvpMatrixY );
resultPosition.z = dot4( localPosition, $mvpMatrixZ );
resultPosition.w = dot4( localPosition, $mvpMatrixW );
// transform matrix from vertex local space to world space
worldPosition.x = dot4( localPosition, $modelMatrixX );
worldPosition.y = dot4( localPosition, $modelMatrixY );
worldPosition.z = dot4( localPosition, $modelMatrixZ );
// transform matrix from vertex local space to world space
localToGlobalX.x = dot3( tangent, $modelMatrixX );
localToGlobalX.y = dot3( bitangent, $modelMatrixX );
localToGlobalX.z = dot3( normal, $modelMatrixX );
localToGlobalX.w = morphScale;
localToGlobalY.x = dot3( tangent, $modelMatrixY );
localToGlobalY.y = dot3( bitangent, $modelMatrixY );
localToGlobalY.z = dot3( normal, $modelMatrixY );
localToGlobalY.w = 0.0;
localToGlobalZ.x = dot3( tangent, $modelMatrixZ );
localToGlobalZ.y = dot3( bitangent, $modelMatrixZ );
localToGlobalZ.z = dot3( normal, $modelMatrixZ );
localToGlobalZ.w = 0.0;
// dir from the viewer to the vertex
viewOriginToVertex.x = dot4( localPosition, $modelMatrixX );
viewOriginToVertex.y = dot4( localPosition, $modelMatrixY );
viewOriginToVertex.z = dot4( localPosition, $modelMatrixZ );
viewOriginToVertex.xyz -= $globalViewOrigin.xyz;
viewOriginToVertex.w = 0.0;
}
#endtemplate
/*
==================================================================================
CALC_SKINNED_POSITION
uses vertex.position;
out float4 resultPosition;
==================================================================================
*/
#template CALC_SKINNED_POSITION( resultPosition )
{
float4 localPosition;
CALC_SKINNED_POSITIONS( localPosition, resultPosition );
}
#endtemplate
/*
==================================================================================
CALC_SKINNED_POSITIONS_NORMALS
uses vertex.position;
uses vertex.normal;
uses vertex.tangent;
out float4 resultPosition;
out float4 localToGlobalX;
out float4 localToGlobalY;
out float4 localToGlobalZ;
out float4 viewOriginToVertex;
==================================================================================
*/
#template CALC_SKINNED_POSITION_NORMALS( resultPosition, localToGlobalX, localToGlobalY, localToGlobalZ, viewOriginToVertex, position, normal, tangent, worldPosition )
{
float4 localPosition;
CALC_SKINNED_POSITIONS_NORMALS( localPosition, resultPosition, localToGlobalX, localToGlobalY, localToGlobalZ, viewOriginToVertex, position, normal, tangent, worldPosition );
}
#endtemplate