156 lines
6.2 KiB
Plaintext
156 lines
6.2 KiB
Plaintext
{
|
|
parms {
|
|
stageSort sortCoverage
|
|
}
|
|
state {
|
|
depthfunc GL_LEQUAL
|
|
depthmask
|
|
#ifdef PS3
|
|
alphamask // the ps3 does not make a copy of the alpha buffer
|
|
#endif
|
|
}
|
|
hlsl_vp {
|
|
#include "skinning_normals.inc"
|
|
|
|
// vertex position
|
|
result.position.x = dot4( position, $mvpMatrixX );
|
|
result.position.y = dot4( position, $mvpMatrixY );
|
|
result.position.z = dot4( position, $mvpMatrixZ );
|
|
result.position.w = dot4( position, $mvpMatrixW );
|
|
|
|
// Convert back from 16 bit vertex elements.
|
|
float2 texcoord0 = vertex.texcoord0 * $vertexStScaleBias.xy + $vertexStScaleBias.zw;
|
|
|
|
// texture 0 takes the base and offseted coordinates
|
|
result.texcoord0.x = dot4( texcoord0, $sMatrix );
|
|
result.texcoord0.y = dot4( texcoord0, $tMatrix );
|
|
result.texcoord0.z = dot4( texcoord0, $rMatrix );
|
|
result.texcoord0.w = dot4( texcoord0, $qMatrix );
|
|
|
|
// transform the local space vectors to world space
|
|
result.texcoord1.x = dot3( tangent, $modelMatrixX );
|
|
result.texcoord1.y = dot3( bitangent, $modelMatrixX );
|
|
result.texcoord1.z = dot3( normal, $modelMatrixX );
|
|
result.texcoord1.w = morphScale;
|
|
|
|
result.texcoord2.x = dot3( tangent, $modelMatrixY );
|
|
result.texcoord2.y = dot3( bitangent, $modelMatrixY );
|
|
result.texcoord2.z = dot3( normal, $modelMatrixY );
|
|
result.texcoord2.w = 0.0;
|
|
|
|
result.texcoord3.x = dot3( tangent, $modelMatrixZ );
|
|
result.texcoord3.y = dot3( bitangent, $modelMatrixZ );
|
|
result.texcoord3.z = dot3( normal, $modelMatrixZ );
|
|
result.texcoord3.w = 0.0;
|
|
|
|
// texture 4 takes the dir to the viewer and the fog value
|
|
result.texcoord4.x = dot4( position, $modelMatrixX );
|
|
result.texcoord4.y = dot4( position, $modelMatrixY );
|
|
result.texcoord4.z = dot4( position, $modelMatrixZ );
|
|
result.texcoord4.xyz -= $globalViewOrigin.xyz;
|
|
result.texcoord4.w = -( clamp( result.position.w - $fogStart.x, 0.0, $fogEnd.x ) * $fogScale.x );
|
|
}
|
|
hlsl_fp {
|
|
float2 texcoord = fragment.texcoord0.xy;
|
|
|
|
float4 diffuse = tex2D( $spare1Map, texcoord );
|
|
float4 specular = tex2D( $spareSpecularMap, texcoord );
|
|
float4 bump = tex2D( $spareBumpMap, texcoord );
|
|
|
|
// blend in another texture based on the morph map
|
|
BRANCH if ( $useSkinBlending.x > 0.0 ) { // fragment.htexcoord1.w > 0.0
|
|
float4 diffuse2 = tex2D( $spare2Map, texcoord );
|
|
float4 specular2 = tex2D( $spareSpecularMap2, texcoord );
|
|
float4 bump2 = tex2D( $spareBumpMap2, texcoord );
|
|
|
|
float morphScale = fragment.htexcoord1.w;
|
|
diffuse = lerp( diffuse, diffuse2, morphScale );
|
|
specular = lerp( specular, specular2, morphScale );
|
|
bump = lerp( bump, bump2, morphScale );
|
|
}
|
|
|
|
//--------- environment mapping ----------
|
|
|
|
// Note that the optimized derivation of the localNormal below results in a vector that is half-unit length!
|
|
half3 localNormal = bump.wyz - 0.5;
|
|
localNormal.z = sqrt( abs( dot( localNormal.xy, localNormal.xy ) - 0.25 ) );
|
|
|
|
// transform into global space
|
|
half3 globalNormal;
|
|
globalNormal.x = dot3( localNormal, fragment.htexcoord1.xyz );
|
|
globalNormal.y = dot3( localNormal, fragment.htexcoord2.xyz );
|
|
globalNormal.z = dot3( localNormal, fragment.htexcoord3.xyz );
|
|
globalNormal = normalize( globalNormal );
|
|
|
|
// normalize the direction from the viewer
|
|
half3 fromViewer = normalize( fragment.htexcoord4.xyz );
|
|
|
|
// reflection vector
|
|
half4 reflection;
|
|
reflection.xyz = fromViewer - ( globalNormal * dot3( fromViewer, globalNormal ) * 2.0 );
|
|
|
|
// power factor is stored in bumpPage.x as 0.0 - 1.0, we want a 0 | 1 | 2 | 3 mip value
|
|
// we could probably skip the floor, but I am wary of hardware / api rounding
|
|
// the artists really prefer white to be shiny instead of dull, so invert it here
|
|
// reflection.w = floor( ( 1.0 - powerFactor ) * 4.0 + $newPowerScale.x );
|
|
reflection.w = 0.0;
|
|
|
|
half3 envColor = texCUBElod( $dynamicEnvMap, reflection ).xyz;
|
|
|
|
//--------- read the dimshadow factor ----------
|
|
|
|
// this is normalized window space, not strict openGL window space
|
|
// that uses integer viewport values.
|
|
float4 window;
|
|
window.xy = screenPosToTexcoord( fragment.position.xy, $renderPositionToViewTexture );
|
|
window.z = 0.0;
|
|
window.w = 0.0; // blur factor
|
|
|
|
float shadow = tex2Dlod( $viewColorMap, window ).w; // from alpha channel
|
|
|
|
// only use half the dimshadow value, since we can't separate the
|
|
// contribution along the shadow from the remainder
|
|
shadow = saturate( shadow + $primeLightMin.x );
|
|
|
|
//---------------------------------------------------------------
|
|
// calculate direct lighting, applying the shadow factor to the first
|
|
// light, which should be in the same direction as the dimshadow projection.
|
|
//---------------------------------------------------------------
|
|
float3 primeLight = shadow * $primeLightColor.xyz *
|
|
saturate( dot3( $primeLightDir, globalNormal ) - 0.2 );
|
|
float3 light = primeLight
|
|
+ max( globalNormal.x * $channelLight0.xyz, 0 )
|
|
+ max( -globalNormal.x * $channelLight1.xyz, 0 )
|
|
+ max( globalNormal.y * $channelLight2.xyz, 0 )
|
|
+ max( -globalNormal.y * $channelLight3.xyz, 0 )
|
|
+ max( globalNormal.z * $channelLight4.xyz, 0 )
|
|
+ max( -globalNormal.z * $channelLight5.xyz, 0 );
|
|
|
|
//---------------------------------------------------------------
|
|
// calculate the view grazing fraction
|
|
//---------------------------------------------------------------
|
|
half graze = saturate( dot3( -fromViewer, globalNormal ) );
|
|
graze = saturate( ( $viewGraze.x - max( graze, -graze ) ) / max( $viewGraze.x, 0.0001 ) );
|
|
diffuse.xyz = lerp( diffuse.xyz, $grazingDiffuseColor.xyz, graze );
|
|
specular.xyz = lerp( specular.xyz, $grazingSpecularColor.xyz, graze );
|
|
|
|
//---------------------------------------------------------------
|
|
// sum everything up
|
|
//---------------------------------------------------------------
|
|
|
|
// automatically scale diffuseScale by 2.0 to match the baked-in behavior
|
|
|
|
// only have specular with primeLight to avoid shiny ambient guys
|
|
half3 color = light * ( envColor * specular.xyz * $newSpecularScale.xyz )
|
|
+ light * ( diffuse.xyz * $newDiffuseScale.xyz * 2.0 );
|
|
|
|
// calculate fog term
|
|
half fog = saturate( exp2( fragment.htexcoord4.w ) );
|
|
|
|
// lerp towards the fog color by the fog factor
|
|
result.color.xyz = lerp( $fogColor.xyz, color.xyz, fog );
|
|
#ifndef PS3
|
|
result.color.w = specular.w;
|
|
#endif
|
|
}
|
|
} |