diff options
Diffstat (limited to 'materialsystem/stdshaders/cloak_ps2x.fxc')
| -rw-r--r-- | materialsystem/stdshaders/cloak_ps2x.fxc | 201 |
1 files changed, 201 insertions, 0 deletions
diff --git a/materialsystem/stdshaders/cloak_ps2x.fxc b/materialsystem/stdshaders/cloak_ps2x.fxc new file mode 100644 index 0000000..66c332b --- /dev/null +++ b/materialsystem/stdshaders/cloak_ps2x.fxc @@ -0,0 +1,201 @@ +//====== Copyright � 1996-2005, Valve Corporation, All rights reserved. ======= +// +// Purpose: +// +//============================================================================= + +// STATIC: "CONVERT_TO_SRGB" "0..1" [ps20b][= g_pHardwareConfig->NeedsShaderSRGBConversion()] [PC] +// STATIC: "CONVERT_TO_SRGB" "0..1" [ps30][= g_pHardwareConfig->NeedsShaderSRGBConversion()] [PC] +// STATIC: "CONVERT_TO_SRGB" "0..0" [= 0] [XBOX] +// STATIC: "LIGHTWARPTEXTURE" "0..1" +// DYNAMIC: "PIXELFOGTYPE" "0..1" +// DYNAMIC: "WRITEWATERFOGTODESTALPHA" "0..1" +// DYNAMIC: "NUM_LIGHTS" "0..2" [ps20] +// DYNAMIC: "NUM_LIGHTS" "0..4" [ps20b] +// DYNAMIC: "NUM_LIGHTS" "0..4" [ps30] + + +#include "shader_constant_register_map.h" + +sampler BaseSampler : register( s0 ); // Base map +sampler DiffuseWarpSampler : register( s1 ); // 1D texture for diffuse lighting modification +sampler RefractSampler : register( s2 ); // Refraction map copied from back buffer +sampler NormalSampler : register( s3 ); // Normal map +sampler SpecExponentSampler : register( s4 ); // Flashlight cookie +sampler NormalizeSampler : register( s5 ); // Normalization cube map + +const float3x3 g_ViewProj : register( c0 ); // 1st row of Projection matrix +// c1 // 2nd row +// c2 // 4th row +const float2 g_CloakControl : register( c3 ); // { refract amount, cloak, ?, ? } +const float3 cAmbientCube[6] : register( PSREG_AMBIENT_CUBE ); +const float4 g_EyePos_SpecExponent : register( PSREG_EYEPOS_SPEC_EXPONENT ); +const float4 g_FogParams : register( PSREG_FOG_PARAMS ); +const float4 g_FlashlightAttenuationFactors_RimMask : register( PSREG_FLASHLIGHT_ATTENUATION ); // On non-flashlight pass, x has rim mask control +const float4 g_RimBoost : register( PSREG_FLASHLIGHT_POSITION_RIM_BOOST ); +const float4 g_FresnelSpecParams : register( PSREG_FRESNEL_SPEC_PARAMS ); // xyz are fresnel, w is specular boost +const float4 g_SpecularRimParams : register( PSREG_SPEC_RIM_PARAMS ); // xyz are specular tint color, w is rim power +PixelShaderLightInfo cLightInfo[3] : register( PSREG_LIGHT_INFO_ARRAY ); // 2 registers each - 6 registers total + +#define g_fRimBoost g_RimBoost.w +#define g_FresnelRanges g_FresnelSpecParams.xyz +#define g_SpecularBoost g_FresnelSpecParams.w +#define g_SpecularTint g_SpecularRimParams.xyz +#define g_RimExponent g_SpecularRimParams.w +#define g_FlashlightAttenuationFactors g_FlashlightAttenuationFactors_RimMask +#define g_RimMaskControl g_FlashlightAttenuationFactors_RimMask.x + +// 8 2D Poisson offsets (designed to use .xy and .wz swizzles (not .zw) +static const float4 gPoissonOffset[4] = { float4 (-0.0876f, 0.9703f, 0.5651f, 0.4802f ), + float4 ( 0.1851f, 0.1580f, -0.0617f, -0.2616f ), + float4 (-0.5477f, -0.6603f, 0.0711f, -0.5325f ), + float4 (-0.0751f, -0.8954f, 0.4054f, 0.6384f ) }; + +struct PS_INPUT +{ + float2 vBaseTexCoord : TEXCOORD0; + float3x3 tangentSpaceTranspose : TEXCOORD1; + // second row : TEXCOORD2; + // third row : TEXCOORD3; + float3 worldPos : TEXCOORD4; + float3 projPos : TEXCOORD5; + float4 lightAtten : TEXCOORD6; +}; + +float4 main( PS_INPUT i ) : COLOR +{ + float3 vSpecular = float3( 0.0f, 0.0f, 0.0f ); + bool bDoDiffuseWarp = LIGHTWARPTEXTURE ? true : false; + int nNumLights = NUM_LIGHTS; + + // Base color + float4 albedo = tex2D( BaseSampler, i.vBaseTexCoord ); + + // Load normal and expand range + float4 vNormalSample = tex2D( NormalSampler, i.vBaseTexCoord ); + float3 tangentSpaceNormal = 2.0f * vNormalSample.xyz - 1.0f; + + // We need a world space normal if we're doing any lighting + float3 vWorldNormal = normalize( mul( i.tangentSpaceTranspose, tangentSpaceNormal ) ); + float3 vWorldEyeDir = normalize( g_EyePos_SpecExponent.xyz - i.worldPos ); + + // Vanilla 1-(N.V) fresnel term used later in transition lerp + float fresnel = 1-saturate( dot( vWorldNormal, vWorldEyeDir ) ); + + // Summation of diffuse illumination from all local lights + float3 diffuseLighting = PixelShaderDoLighting( i.worldPos, vWorldNormal, + float3( 0.0f, 0.0f, 0.0f ), false, + true, i.lightAtten, cAmbientCube, NormalizeSampler, + nNumLights, cLightInfo, true, false, 1.0f, + bDoDiffuseWarp, DiffuseWarpSampler ); + + + + + + // Transform world space normal into clip space and project + float2 vProjNormal; + vProjNormal.x = dot( vWorldNormal, g_ViewProj[0] ); // 1st row + vProjNormal.y = dot( vWorldNormal, g_ViewProj[1] ); // 2nd row + + // Compute coordinates for sampling refraction + float2 vRefractTexCoordNoWarp = i.projPos.xy / i.projPos.z; + float2 vRefractTexCoord = vProjNormal.xy; + float scale = lerp( g_CloakControl.x, 0.0f, g_CloakControl.y ); + vRefractTexCoord *= scale; + vRefractTexCoord += vRefractTexCoordNoWarp; + +#ifdef SHADER_MODEL_PS_2_0 + float3 vRefract = tex2D( RefractSampler, vRefractTexCoordNoWarp ); +#endif + + // Extra refraction rays, specular, rim etc are only done on ps_2_b +#if defined( SHADER_MODEL_PS_2_B ) || defined( SHADER_MODEL_PS_3_0 ) + // Blur by scalable Poisson filter + float fBlurAmount = lerp( 0.05f, 0.0f, g_CloakControl.y ); + float3 vRefract = tex2D( RefractSampler, vRefractTexCoord ); + vRefract += tex2D( RefractSampler, vRefractTexCoord + gPoissonOffset[0].xy * fBlurAmount ); + vRefract += tex2D( RefractSampler, vRefractTexCoord + gPoissonOffset[0].wz * fBlurAmount ); + vRefract += tex2D( RefractSampler, vRefractTexCoord + gPoissonOffset[1].xy * fBlurAmount ); + vRefract += tex2D( RefractSampler, vRefractTexCoord + gPoissonOffset[1].wz * fBlurAmount ); + vRefract += tex2D( RefractSampler, vRefractTexCoord + gPoissonOffset[2].xy * fBlurAmount ); + vRefract += tex2D( RefractSampler, vRefractTexCoord + gPoissonOffset[2].wz * fBlurAmount ); + +// We're right at the hairy edge of constant register usage and hence have to drop these taps... +// vRefract += tex2D( RefractSampler, vRefractTexCoord + gPoissonOffset[3].xy * fBlurAmount ); +// vRefract += tex2D( RefractSampler, vRefractTexCoord + gPoissonOffset[3].wz * fBlurAmount ); + vRefract /= 7.0f; + + float3 rimLighting = float3( 0.0f, 0.0f, 0.0f ); + float3 specularLighting = float3( 0.0f, 0.0f, 0.0f ); + float fSpecExp = g_EyePos_SpecExponent.w; + float fSpecMask = vNormalSample.a; + + float4 vSpecExpMap = tex2D( SpecExponentSampler, i.vBaseTexCoord ); + float fSpecExpMap = vSpecExpMap.r; + float fRimMask = 1.0f;//lerp( 1.0f, vSpecExpMap.a, g_RimMaskControl ); // Select rim mask + float3 vSpecularTint; + + // If the exponent passed in as a constant is zero, use the value from the map as the exponent + if ( fSpecExp == 0 ) + fSpecExp = 1.0f - fSpecExpMap + 150.0f * fSpecExpMap; + + // If constant tint is negative, tint with albedo, based upon scalar tint map + if ( g_SpecularTint.r == -1 ) + vSpecularTint = lerp( float3(1.0f, 1.0f, 1.0f), albedo, vSpecExpMap.g ); + else + vSpecularTint = g_SpecularTint.rgb; + + // Fresnel to match regular specular lighting + float fFresnelRanges = Fresnel( vWorldNormal, vWorldEyeDir, g_FresnelRanges ); + + // Summation of specular from all local lights besides the flashlight + PixelShaderDoSpecularLighting( i.worldPos, vWorldNormal, fSpecExp, vWorldEyeDir, + i.lightAtten, nNumLights, cLightInfo, false, 1.0f, false, + NormalizeSampler, 1.0f, true, g_RimExponent, + + // Outputs + specularLighting, rimLighting ); + + // Modulate with spec mask, boost, tint and fresnel ranges + specularLighting *= fSpecMask * g_SpecularBoost * fFresnelRanges * vSpecularTint; + + float fRimFresnel = Fresnel4( vWorldNormal, vWorldEyeDir ); + + // Add in rim light modulated with tint, mask and traditional Fresnel (not using Fresnel ranges) + rimLighting *= vSpecularTint * fRimMask * fRimFresnel; + + // Fold rim lighting into specular term by using the max so that we don't really add light twice... + specularLighting = max (specularLighting, rimLighting); + + // Add in view-ray lookup from ambient cube + specularLighting += fRimFresnel * fRimMask * vSpecularTint /* g_fRimBoost */ * PixelShaderAmbientLight( vWorldEyeDir, cAmbientCube) * saturate(dot(vWorldNormal, float3(0, 0 , 1)) ); + + float tintLerpFactor = saturate(lerp( 1, fresnel-1.1, saturate(g_CloakControl.y))); + tintLerpFactor = smoothstep( 0.4f, 0.425f, tintLerpFactor ); + float3 vTintedRefract = lerp( vRefract, albedo * vRefract, 0.7f ); + vRefract = lerp( vRefract, vTintedRefract, tintLerpFactor ); + + vSpecular = specularLighting * smoothstep( 0.98, 0.8, saturate(g_CloakControl.y )); +#endif + + // Blend refraction component with diffusely lit model + float diffuseLerpFactor = saturate(lerp( 1, fresnel - 1.35, saturate(g_CloakControl.y))); + diffuseLerpFactor = smoothstep( 0.4f, 0.425f, diffuseLerpFactor ); + + float3 fDiffuse = lerp( vRefract, albedo * diffuseLighting, diffuseLerpFactor ); + float3 result = fDiffuse + vSpecular; + + float alpha = 1.0f; + + // Emulate LinearColorToHDROutput() when uncloaked + result = lerp( result.xyz * LINEAR_LIGHT_SCALE, result, saturate(g_CloakControl.y) ); + + float fogFactor = CalcPixelFogFactor( PIXELFOGTYPE, g_FogParams, g_EyePos_SpecExponent.z, i.worldPos.z, i.projPos.z ); + +#if WRITEWATERFOGTODESTALPHA && (PIXELFOGTYPE == PIXEL_FOG_TYPE_HEIGHT) + alpha = fogFactor; +#endif + + return FinalOutput( float4( result, alpha ), fogFactor, PIXELFOGTYPE, TONEMAP_SCALE_NONE ); +} |