Counter Strike : Global Offensive Source Code
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

//========== 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
}