You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
356 lines
12 KiB
356 lines
12 KiB
//========== Copyright (c) Valve Corporation, All rights reserved. ==========//
|
|
|
|
// STATIC: "COMPOSITEMODE" "0..2"
|
|
// STATIC: "CASCADED_SHADOW_MAPPING" "0..1" [ps30]
|
|
// STATIC: "CSM_MODE" "0..0" [ = 0 ] [ps20] [ps20b] [PC]
|
|
// STATIC: "CSM_MODE" "0..3" [ps30] [PC]
|
|
// STATIC: "USE_PATTERN1" "0..1"
|
|
// STATIC: "USE_PATTERN2" "0..1"
|
|
// STATIC: "USE_PATTERN_OFFSET" "0..1"
|
|
// STATIC: "USE_LOGO1" "0..1"
|
|
// STATIC: "USE_LOGO2" "0..1"
|
|
// STATIC: "SWAP_PATTERN_MASKS" "0..1"
|
|
|
|
// DYNAMIC: "NUM_LIGHTS" "0..2" [ps20]
|
|
// DYNAMIC: "NUM_LIGHTS" "0..4" [ps20b] [ps30]
|
|
// DYNAMIC: "DYN_CSM_ENABLED" "0..1"
|
|
// DYNAMIC: "AO_MODE" "0..1"
|
|
|
|
// SKIP: ( ( $COMPOSITEMODE == 1 ) && ( $CASCADED_SHADOW_MAPPING != 0 ) )
|
|
// SKIP: ( ( $COMPOSITEMODE == 1 ) && ( $NUM_LIGHTS != 0 ) )
|
|
// SKIP: ( $CASCADED_SHADOW_MAPPING == 0 ) && ( $DYN_CSM_ENABLED == 1 )
|
|
// SKIP: ( $CASCADED_SHADOW_MAPPING == 0 ) && ( $CSM_MODE != 0 )
|
|
|
|
// SKIP: ( $USE_PATTERN2 == 1 ) && ( $USE_PATTERN1 == 0 )
|
|
// SKIP: ( $USE_PATTERN_OFFSET == 1 ) && ( $USE_PATTERN1 == 0 && $USE_PATTERN2 == 0 )
|
|
// SKIP: ( $SWAP_PATTERN_MASKS == 1 ) && ( $USE_PATTERN1 == 0 && $USE_PATTERN2 == 0 )
|
|
// SKIP: ( $USE_LOGO2 == 1 ) && ( $USE_LOGO1 == 0 )
|
|
|
|
// SKIP: ( $COMPOSITEMODE == 2 ) && ( $USE_PATTERN1 == 1 )
|
|
// SKIP: ( $COMPOSITEMODE == 2 ) && ( $USE_PATTERN2 == 1 )
|
|
// SKIP: ( $COMPOSITEMODE == 2 ) && ( $USE_PATTERN_OFFSET == 1 )
|
|
// SKIP: ( $COMPOSITEMODE == 2 ) && ( $USE_LOGO1 == 1 )
|
|
// SKIP: ( $COMPOSITEMODE == 2 ) && ( $USE_LOGO2 == 1 )
|
|
|
|
// SKIP: ( $AO_MODE == 1 ) && ( $COMPOSITEMODE == 1 )
|
|
// SKIP: ( $AO_MODE == 1 ) && ( $NUM_LIGHTS != 0 )
|
|
// SKIP: ( $AO_MODE == 1 ) && ( $DYN_CSM_ENABLED == 1 )
|
|
|
|
#include "common_ps_fxc.h"
|
|
#include "shader_constant_register_map.h"
|
|
|
|
#define NEED_COMPOSITE_INPUTS ( COMPOSITEMODE == 0 || COMPOSITEMODE == 1 ) //3D preview or 2D composite
|
|
#define IS_3D_MODE ( COMPOSITEMODE != 1 ) //Not mode 1, that is anything other than 2D composite mode. Silly name to avoid starting with a numeral
|
|
#define IS_3D_POSTCOMPOSITE ( COMPOSITEMODE == 2 )
|
|
|
|
#define USE_HALF_LAMBERT false
|
|
|
|
#define SSAO_EFFECT_MULTIPLIER 0.9f
|
|
|
|
// SAMPLERS
|
|
sampler BaseSampler : register( s0 );
|
|
sampler NormalMapSampler : register( s1 );
|
|
|
|
#if AO_MODE == 0
|
|
sampler SSAOMapSampler : register( s10 );
|
|
#endif
|
|
|
|
#if NEED_COMPOSITE_INPUTS
|
|
sampler AOMapSampler : register( s2 );
|
|
sampler MaskMapSampler : register( s3 );
|
|
#if USE_PATTERN1
|
|
sampler Pattern1Sampler : register( s4 );
|
|
#endif
|
|
#if USE_PATTERN2
|
|
sampler Pattern2Sampler : register( s6 );
|
|
#endif
|
|
sampler GrimeSampler : register( s7 );
|
|
#if USE_PATTERN_OFFSET
|
|
sampler OffsetSampler : register( s8 );
|
|
#endif
|
|
#if USE_LOGO1
|
|
sampler LogoSampler : register( s9 );
|
|
#endif
|
|
#endif
|
|
|
|
#if IS_3D_MODE
|
|
sampler NormalizeSampler : register( s5 );
|
|
#endif
|
|
|
|
#if ( CASCADED_SHADOW_MAPPING == 1 )
|
|
sampler CSMDepthAtlasSampler : register( s15 );
|
|
#undef CASCADE_SIZE
|
|
#define CASCADE_SIZE 3
|
|
#define CSM_ENABLED 1
|
|
//#define CSM_VERTEXLIT_AND_UNLIT_GENERIC_BUMP //use the same CSM const registers?
|
|
#include "csm_common_fxc.h"
|
|
#endif
|
|
|
|
|
|
// REGISTERS
|
|
#if IS_3D_MODE
|
|
const float3 g_cAmbientCube[6] : register( PSREG_AMBIENT_CUBE ); // 4 through 9
|
|
PixelShaderLightInfo cLightInfo[3] : register( PSREG_LIGHT_INFO_ARRAY ); // 20 through 25
|
|
|
|
//for normalized screen-space coords
|
|
const float4 g_fvConstRegister17 : register( c17 );
|
|
|
|
const float4 g_fvConstRegister18 : register( c18 );
|
|
#define g_vEyePos g_fvConstRegister18.xyz
|
|
#define g_flElementDistance g_fvConstRegister18.w
|
|
|
|
#endif
|
|
|
|
#if NEED_COMPOSITE_INPUTS
|
|
const float4 g_fvConstRegister0 : register( c0 );
|
|
const float4 g_fvConstRegister1 : register( c1 );
|
|
const float4 g_fvConstRegister2 : register( c2 );
|
|
const float4 g_fvConstRegister10 : register( c10 );
|
|
const float4 g_fvConstRegister11 : register( c11 );
|
|
const float4 g_fvConstRegister12 : register( c12 );
|
|
|
|
#define g_vPattern1Color1 float3( g_fvConstRegister0.x, g_fvConstRegister0.y, g_fvConstRegister0.z )
|
|
#define g_vPattern1Color2 float3( g_fvConstRegister1.x, g_fvConstRegister1.y, g_fvConstRegister1.z )
|
|
#define g_vPattern1Color3 float3( g_fvConstRegister2.x, g_fvConstRegister2.y, g_fvConstRegister2.z )
|
|
#define g_vPattern1Color4 float3( g_fvConstRegister0.w, g_fvConstRegister1.w, g_fvConstRegister2.w )
|
|
|
|
#define g_vPattern2Color1 float3( g_fvConstRegister10.x, g_fvConstRegister10.y, g_fvConstRegister10.z )
|
|
#define g_vPattern2Color2 float3( g_fvConstRegister11.x, g_fvConstRegister11.y, g_fvConstRegister11.z )
|
|
#define g_vPattern2Color3 float3( g_fvConstRegister12.x, g_fvConstRegister12.y, g_fvConstRegister12.z )
|
|
#define g_vPattern2Color4 float3( g_fvConstRegister10.w, g_fvConstRegister11.w, g_fvConstRegister12.w )
|
|
|
|
const float4 g_fvConstRegister13 : register( c13 );
|
|
#define g_vPattern1Scale g_fvConstRegister13.x
|
|
#define g_vPattern2Scale g_fvConstRegister13.y
|
|
#define g_flCavityPower g_fvConstRegister13.z
|
|
#define g_flOffsetAmount g_fvConstRegister13.w
|
|
|
|
const float4 g_fvConstRegister14 : register( c14 );
|
|
#define g_vLogoOffset g_fvConstRegister14.xy
|
|
#define g_fLogoScale g_fvConstRegister14.z
|
|
#define g_fLogoRotation g_fvConstRegister14.w
|
|
|
|
const float4 g_fvConstRegister15 : register( c15 );
|
|
#define g_vLogo2Offset g_fvConstRegister15.xy
|
|
#define g_fLogo2Scale g_fvConstRegister15.z
|
|
#define g_fLogo2Rotation g_fvConstRegister15.w
|
|
|
|
const float4 g_fvConstRegister16 : register( c16 );
|
|
#define g_fLogoMaskCrispnessMin g_fvConstRegister16.x
|
|
#define g_fLogoMaskCrispnessMax g_fvConstRegister16.y
|
|
#define g_fLogoWear g_fvConstRegister16.z
|
|
#endif
|
|
|
|
#define DESAT float3( 0.3f, 0.59f, 0.11f )
|
|
|
|
float2 rotate( float2 inputUV, float rotateTau )
|
|
{
|
|
return float2( inputUV.x * cos(rotateTau) - inputUV.y * sin(rotateTau),
|
|
inputUV.x * sin(rotateTau) + inputUV.y * cos(rotateTau) );
|
|
}
|
|
|
|
float2 getLogoUV( float2 inputUV, float2 inputOffset, float inputScale, float inputRotation )
|
|
{
|
|
float2 vLogoUV = inputUV;
|
|
vLogoUV -= float2( 0.5f , 0.5f );
|
|
vLogoUV -= inputOffset;
|
|
vLogoUV *= inputScale;
|
|
vLogoUV = rotate( vLogoUV, inputRotation );
|
|
return (vLogoUV + float2( 0.5f , 0.5f ));
|
|
}
|
|
|
|
struct PS_INPUT
|
|
{
|
|
|
|
float4 vBaseUV_PatternUV : TEXCOORD0;
|
|
float4 vWearUV_GrungeUV : TEXCOORD1;
|
|
|
|
#if IS_3D_MODE
|
|
float4 lightAtten : TEXCOORD2;
|
|
float3 worldPos : TEXCOORD3;
|
|
float3x3 tangentSpaceTranspose : TEXCOORD4;
|
|
// second row : TEXCOORD5;
|
|
// third row : TEXCOORD6;
|
|
float4 vProjPos : TEXCOORD7;
|
|
#endif
|
|
};
|
|
|
|
float3 PhotoshopOverlay( float3 cBase, float3 cBlend )
|
|
{
|
|
float3 cNew;
|
|
cNew = step( 0.5, cBase );
|
|
cNew = lerp( (cBase*cBlend*2), (1.0-(2.0*(1.0-cBase)*(1.0-cBlend))), cNew );
|
|
return cNew;
|
|
}
|
|
|
|
float2 PackFloat2( float f)
|
|
{
|
|
float2 packed;
|
|
f *= 256.0f;
|
|
packed.x = floor( f ) * (1.0f / 256.0f);
|
|
packed.y = frac( f );
|
|
return packed;
|
|
}
|
|
|
|
float4_color_return_type main( PS_INPUT i ) : COLOR
|
|
{
|
|
|
|
#if AO_MODE == 1
|
|
|
|
float flLocalDistance = smoothstep( g_flElementDistance - 40.0f, g_flElementDistance + 40.0f, length( g_vEyePos.xyz - i.worldPos.xyz ) );
|
|
|
|
float3 vNormalTexel = 2.0f * (tex2D( NormalMapSampler, i.vBaseUV_PatternUV.xy ).rgb) - 1.0f;
|
|
float3 vWorldPixelNormal = normalize( mul( (float3x3)i.tangentSpaceTranspose, vNormalTexel ) );
|
|
|
|
float3 vEyeDir = normalize(g_vEyePos.xyz - i.worldPos.xyz);
|
|
float3 vLeftDir = cross( vEyeDir, float3(0,0,1) );
|
|
float3 vUpDir = cross( vEyeDir, vLeftDir );
|
|
|
|
return float4( (dot( vLeftDir, vWorldPixelNormal ) + 1.0f) * 0.5f, (dot( vUpDir, vWorldPixelNormal ) + 1.0f) * 0.5f, PackFloat2( flLocalDistance ) );
|
|
|
|
//return float4( dot( vLeftDir, vWorldPixelNormal ), dot( vUpDir, vWorldPixelNormal ), PackFloat2( flLocalDistance ) );
|
|
|
|
#else
|
|
|
|
float3 vColorTexel = tex2D( BaseSampler, i.vBaseUV_PatternUV.xy ).rgb;
|
|
|
|
#if NEED_COMPOSITE_INPUTS
|
|
|
|
float3 vMasksTexel = tex2D( MaskMapSampler, i.vBaseUV_PatternUV.xy ).rgb;
|
|
|
|
float3 vAOTexel = tex2D( AOMapSampler, i.vBaseUV_PatternUV.xy ).rgb;
|
|
float flCavityPostPow = pow(vAOTexel.g, g_flCavityPower);
|
|
vAOTexel.b = smoothstep( g_fLogoMaskCrispnessMin, g_fLogoMaskCrispnessMax, vAOTexel.b );
|
|
|
|
float3 vGrime = tex2D( GrimeSampler, i.vBaseUV_PatternUV.xy ).rgb;
|
|
|
|
#if USE_PATTERN1
|
|
|
|
#if SWAP_PATTERN_MASKS
|
|
vMasksTexel.rg = vMasksTexel.gr;
|
|
#endif
|
|
|
|
float2 vPatternUV = i.vBaseUV_PatternUV.xy;
|
|
|
|
#if USE_PATTERN_OFFSET
|
|
float distAlphaMask = tex2D( OffsetSampler, i.vBaseUV_PatternUV.xy ).a;
|
|
//offset pattern UVs by distance-field offset mask
|
|
vPatternUV.x += step( 0.5f, distAlphaMask ) * g_flOffsetAmount;
|
|
#endif
|
|
|
|
//sample patterns
|
|
float3 vColorPattern1 = tex2D( Pattern1Sampler, vPatternUV * g_vPattern1Scale ).rgb;
|
|
#if USE_PATTERN2
|
|
float3 vColorPattern2 = tex2D( Pattern2Sampler, vPatternUV * g_vPattern2Scale ).rgb;
|
|
#endif
|
|
|
|
//bash pattern1 by solid color mask (fixme)
|
|
vColorPattern1 = lerp( vColorPattern1, float3(0,1,0), vMasksTexel.b );
|
|
#if USE_PATTERN2
|
|
vColorPattern2 = lerp( vColorPattern2, float3(0,0,1), vMasksTexel.b );
|
|
#endif
|
|
|
|
//colorize patterns
|
|
vColorPattern1 = lerp( lerp( lerp( g_vPattern1Color1, g_vPattern1Color2, vColorPattern1.r ), g_vPattern1Color3, vColorPattern1.g ), g_vPattern1Color4, vColorPattern1.b );
|
|
#if USE_PATTERN2
|
|
vColorPattern2 = lerp( lerp( lerp( g_vPattern2Color1, g_vPattern2Color2, vColorPattern2.r ), g_vPattern2Color3, vColorPattern2.g ), g_vPattern2Color4, vColorPattern2.b );
|
|
#endif
|
|
|
|
//apply colorized patterns using per-pattern masks
|
|
vColorTexel = lerp( vColorTexel, vColorPattern1, vMasksTexel.r );
|
|
#if USE_PATTERN2
|
|
vColorTexel = lerp( vColorTexel, vColorPattern2, vMasksTexel.g );
|
|
#endif
|
|
|
|
#if USE_PATTERN_OFFSET
|
|
//darken seams caused by pattern offset
|
|
float flPatternOffsetSeamMask = saturate( (abs(distAlphaMask - 0.5f) * 8.0f) + 0.5f);
|
|
vColorTexel *= flPatternOffsetSeamMask;
|
|
#endif
|
|
|
|
#endif //USE_PATTERN1
|
|
|
|
#if USE_LOGO1
|
|
float fLogoMaskCavity = vAOTexel.b * pow( (1.0f - flCavityPostPow), g_fLogoWear );
|
|
|
|
//logo1
|
|
float4 vLogoColor = tex2D( LogoSampler, getLogoUV( i.vBaseUV_PatternUV.xy, g_vLogoOffset, g_fLogoScale, g_fLogoRotation ) );
|
|
//apply logo with alpha
|
|
vColorTexel.rgb = lerp( vColorTexel.rgb, vLogoColor.rgb, vLogoColor.a * fLogoMaskCavity );
|
|
|
|
#if USE_LOGO2
|
|
//logo2
|
|
float4 vLogo2Color = tex2D( LogoSampler, getLogoUV( i.vBaseUV_PatternUV.xy, g_vLogo2Offset, g_fLogo2Scale, g_fLogo2Rotation ) );
|
|
//apply logo2 with alpha
|
|
vColorTexel.rgb = lerp( vColorTexel.rgb, vLogo2Color.rgb, vLogo2Color.a * fLogoMaskCavity );
|
|
#endif
|
|
|
|
#endif //USE_LOGO1
|
|
|
|
//desaturate by cavity and apply grime
|
|
vColorTexel = lerp( vColorTexel, dot(DESAT, vColorTexel) * vGrime.rgb, flCavityPostPow );
|
|
|
|
//apply ao
|
|
vColorTexel *= (2.0f * vAOTexel.r);
|
|
|
|
#endif // NEED_COMPOSITE_INPUTS
|
|
|
|
|
|
|
|
#if !(IS_3D_MODE) // (2d compositing)
|
|
|
|
// draw pink squares onto the composite to make sure it's working
|
|
//if ( fmod( i.vBaseUV_PatternUV.x, 0.1f ) < 0.05f && fmod( i.vBaseUV_PatternUV.y, 0.1f ) < 0.05f )
|
|
//{
|
|
// vColorTexel = float3(1,0,1);
|
|
//}
|
|
|
|
float4 cOut = float4( vColorTexel.rgb, 1 );
|
|
return cOut;
|
|
|
|
#else // (any 3d mode)
|
|
|
|
// apply normal map driven lighting in 3d mode
|
|
|
|
float3 vNormalTexel = 2.0f * (tex2D( NormalMapSampler, i.vBaseUV_PatternUV.xy ).rgb) - 1.0f;
|
|
float3 vWorldPixelNormal = normalize( mul( (float3x3)i.tangentSpaceTranspose, vNormalTexel ) );
|
|
|
|
//return float4( vNormalTexel, 1 );
|
|
|
|
#if ( (CASCADED_SHADOW_MAPPING == 1) && (DYN_CSM_ENABLED == 1) )
|
|
float flCSMShadow = CSMComputeShadowing( i.worldPos );
|
|
#else
|
|
float flCSMShadow = 1.0f;
|
|
#endif
|
|
|
|
float3 linearColor = PixelShaderDoLighting( i.worldPos, vWorldPixelNormal, float3( 0.1f, 0.1f, 0.1f),
|
|
false, true, i.lightAtten, g_cAmbientCube, NormalizeSampler, NUM_LIGHTS, cLightInfo,
|
|
USE_HALF_LAMBERT, false, NULL, flCSMShadow );
|
|
|
|
|
|
#if IS_3D_POSTCOMPOSITE
|
|
|
|
//incorporate AO from the offscreen buffer rendered earlier in the frame
|
|
|
|
float2 vScreenPos = (i.vProjPos.xy / i.vProjPos.w) * g_fvConstRegister17.xy + g_fvConstRegister17.zw;
|
|
vScreenPos += float2( 0.0005f, 0.0005f );
|
|
float3 vAO = tex2D( SSAOMapSampler, vScreenPos).rgb;
|
|
|
|
float flCenterDepth = length( g_vEyePos.xyz - i.worldPos.xyz );
|
|
float flDepthFadeDistance = smoothstep( 500.0f, 400.f, flCenterDepth );
|
|
|
|
linearColor = lerp( linearColor, linearColor * vAO, flDepthFadeDistance * SSAO_EFFECT_MULTIPLIER );
|
|
|
|
#endif // IS_3D_POSTCOMPOSITE
|
|
|
|
|
|
vColorTexel *= linearColor;
|
|
//vColorTexel = linearColor;
|
|
|
|
float4 cOut = float4( vColorTexel.rgb, 1 );
|
|
return FinalOutput( cOut, 0, PIXEL_FOG_TYPE_NONE, TONEMAP_SCALE_LINEAR );
|
|
|
|
#endif // any 3D mode
|
|
|
|
#endif // not AO_MODE
|
|
}
|