753 lines
24 KiB
C++
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
|