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.
 
 
 
 
 
 

381 lines
11 KiB

//========== Copyright (c) Valve Corporation, All rights reserved. ==========//
// STATIC: "ADDITIVE" "0..1"
// STATIC: "DETAIL1" "0..1"
// STATIC: "DETAIL1BLENDMODE" "0..1"
// STATIC: "DETAIL2" "0..1"
// STATIC: "DETAIL2BLENDMODE" "0..1"
// STATIC: "TANGENTTOPACITY" "0..1"
// STATIC: "TANGENTSOPACITY" "0..1"
// STATIC: "FRESNELOPACITY" "0..1"
// STATIC: "DEPTHBLEND" "0..1" [CONSOLE]
// STATIC: "DEPTHBLEND" "0..0" [PC]
// STATIC: "VERTEXCOLOR" "0..1"
// STATIC: "FLOWMAP" "0..1"
// STATIC: "FLOW_CHEAP" "0..1" [PC]
// STATIC: "FLOW_CHEAP" "0..0" [CONSOLE]
// DYNAMIC: "ACTIVE" "0..1"
// DYNAMIC: "POWERUP" "0..1"
// DYNAMIC: "VORTEX1" "0..1"
// DYNAMIC: "VORTEX2" "0..1"
// SKIP: ( ( $DETAIL1 == 0 ) && ( $DETAIL2 != 0 ) )
// SKIP: ( ( $DETAIL1 == 0 ) && ( $DETAIL1BLENDMODE != 0 ) )
// SKIP: ( ( $DETAIL2 == 0 ) && ( $DETAIL2BLENDMODE != 0 ) )
// SKIP: ( $TANGENTTOPACITY && $TANGENTSOPACITY )
// SKIP: ( $FRESNELOPACITY ) && ( $TANGENTTOPACITY || $TANGENTSOPACITY )
// SKIP: ( $FLOWMAP && ( $DETAIL1 || $DETAIL2 ) )
// SKIP: ( $FLOW_CHEAP && !$FLOWMAP )
// SKIP: ( ( $FLOWMAP == 0 ) && ( $VORTEX1 || $VORTEX2 || $POWERUP ) )
// SKIP: ( ( $ACTIVE == 0 ) && ( $VORTEX1 || $VORTEX2 || $POWERUP ) )
#include "common_fog_ps_fxc.h"
#include "shader_constant_register_map.h"
// SAMPLERS
sampler g_tBase : register( s0 );
#if DETAIL1
sampler g_tDetail1 : register( s1 );
#endif
#if DEPTHBLEND
sampler g_tDepth : register( s3 );
#endif
#if DETAIL2
sampler g_tDetail2 : register( s4 );
#endif
#if FLOWMAP
sampler g_tFlowMap : register( s5 );
sampler g_tFlowNoise : register( s6 );
sampler g_tFlowBounds : register( s7 );
#endif
// SHADER CONSTANTS
const float4 g_vTangentTOpacityRanges : register( c0 );
const float4 g_vTangentSOpacityRanges : register( c1 );
const float4 g_vFresnelOpacityRanges : register( c2 );
const float4 g_vWriteDepthToAlpha_FlowParams : register( c3 );
#define g_bWriteDepthToAlpha ( g_vWriteDepthToAlpha_FlowParams.x )
#define g_flTime ( g_vWriteDepthToAlpha_FlowParams.y )
#define g_flPowerUp ( g_vWriteDepthToAlpha_FlowParams.z )
#define g_flIntensity ( g_vWriteDepthToAlpha_FlowParams.w )
const float4 g_DepthFeatheringConstants : register( c4 );
const float4 g_DiffuseModulation : register( c5 );
const float4 g_vFlowParams1 : register( c6 );
#define g_flWorldUvScale ( g_vFlowParams1.x ) // 1.0f / 10.0f
#define g_flNormalUvScale ( g_vFlowParams1.y ) // 1.0f / 1.15f
//#define UNUSED g_vFlowParams1.z
#define g_flOutputIntensity ( g_vFlowParams1.w )
const float4 g_vFlowParams2 : register( c7 );
#define g_flFlowTimeIntervalInSeconds ( g_vFlowParams2.x ) // 0.4f // Number of seconds to lerp from texture 1 to texture 2
#define g_flFlowUvScrollDistance ( g_vFlowParams2.y ) // 0.25f // Distance in uv space to fetch
//#define UNUSED ( g_vFlowParams2.z )
#define g_flColorFlowLerpExp ( g_vFlowParams2.w )
const float4 g_vFlowColor : register( c8 );
#define g_cFlow ( g_vFlowColor.xyz )
//#define UNUSED g_cFlow.w
const float4 g_vVortexParams : register( c9 );
#define g_cVortex ( g_vVortexParams.xyz )
#define g_flVortexSize ( g_vVortexParams.w )
struct PS_INPUT
{
float4 vUV0_UV1 : TEXCOORD0;
float4 vFlowUV_UV2 : TEXCOORD1;
float4 vIteratedProjPos : TEXCOORD2;
#if ( VORTEX1 )
float3 vVortexPositions1 : TEXCOORD3;
#endif
#if ( VORTEX2 )
float3 vVortexPositions2 : TEXCOORD4;
#endif
#if ( TANGENTSOPACITY || TANGENTTOPACITY || FRESNELOPACITY )
float4 vWorldNormal_worldEyeX : TEXCOORD5;
float4 vWorldTangent_worldEyeY : TEXCOORD6;
float4 vTangentAlignedView_worldEyeZ : TEXCOORD7;
#endif
#if ( VERTEXCOLOR )
float4 vColor : COLOR0;
#endif
};
float4_color_return_type main( PS_INPUT i ) : COLOR
{
float4 cOut = { 0.0f, 0.0f, 0.0f, 1.0f };
float4 cBase = { 0.0f, 0.0f, 0.0f, 1.0f };
float3 vWorldEyeDir = float3( 0.0f, 0.0f, 0.0f );
float3 vWorldNormal = float3( 0.0f, 0.0f, 0.0f );
float3 vWorldTangent = float3( 0.0f, 0.0f, 0.0f );
#if( TANGENTSOPACITY || TANGENTTOPACITY || FRESNELOPACITY )
vWorldEyeDir = float3( i.vWorldNormal_worldEyeX.w, i.vWorldTangent_worldEyeY.w, i.vTangentAlignedView_worldEyeZ.w );
vWorldNormal = i.vWorldNormal_worldEyeX.xyz;
vWorldTangent = i.vWorldTangent_worldEyeY.xyz;
#endif
float fBackfaceRatio = 0.0f;
#if ( ACTIVE )
{
#if ( FLOWMAP )
{
float4 vBoundsTexel = tex2D( g_tFlowBounds, i.vUV0_UV1.xy );
float2 vFlowVectorTs = float2( 0.0f, 0.0f );
#if ( !FLOW_CHEAP )
{
float2 vFlowUV = i.vFlowUV_UV2.xy * g_flWorldUvScale;
float4 vFlowTexel = tex2D( g_tFlowMap, vFlowUV.xy );
vFlowVectorTs = ( vFlowTexel.rg * 2.0f ) - 1.0f;
vFlowVectorTs *= vBoundsTexel.r; // slow flow
}
#endif
float flVortexIntensity = 0.0f;
// vortex 1
#if ( VORTEX1 )
{
float flVortex1Intensity = saturate( g_flVortexSize / length( i.vVortexPositions1.xyz ) - 0.5f );
#if ( !FLOW_CHEAP )
{
vFlowVectorTs = lerp( vFlowVectorTs, normalize( i.vVortexPositions1.xy ), flVortex1Intensity * 0.5f );
}
#endif
flVortexIntensity += flVortex1Intensity;
}
#endif
#if ( VORTEX2 )
{
float flVortex2Intensity = saturate( g_flVortexSize / length( i.vVortexPositions2.xyz ) - 0.5f );
#if ( !FLOW_CHEAP )
{
vFlowVectorTs = lerp( vFlowVectorTs, normalize( i.vVortexPositions2.xy ), flVortex2Intensity * 0.5f );
}
#endif
flVortexIntensity += flVortex2Intensity;
}
#endif
// Unpack world flow vector from texture
float flNoise = tex2D( g_tFlowNoise, i.vFlowUV_UV2.zw ).g;
// Every interval has a unique offset so we don't see the same bump texels repeating continuously
float flTimeInIntervals = ( g_flTime / ( g_flFlowTimeIntervalInSeconds * 2.0f ) ) + flNoise;
float flScrollTime1 = frac( flTimeInIntervals ) - 0.5;
float flScrollTime2 = frac( flTimeInIntervals + 0.5f ) - 0.5; // Half an interval off from texture 1
float flOffset1 = 0.0f;
float flOffset2 = 0.5f;
#if ( !FLOW_CHEAP )
{
flOffset1 = floor( flTimeInIntervals ) * 0.311f;
flOffset2 = floor( flTimeInIntervals + 0.5f ) * 0.311f + 0.5f; // The +0.5 is to match the phase offset
}
#endif
float flColorFlowLerpExp = g_flColorFlowLerpExp;
float flWeight1 = abs( ( 2.0f * frac( flTimeInIntervals + 0.5f ) ) - 1.0f );
float flWeight2 = abs( ( 2.0f * frac( flTimeInIntervals ) ) - 1.0f );
#if ( !FLOW_CHEAP )
{
flWeight1 = pow( flWeight1, g_flColorFlowLerpExp );
flWeight2 = pow( flWeight2, g_flColorFlowLerpExp );
}
#else
{
flWeight1 *= flWeight1;
flWeight2 *= flWeight2;
}
#endif
float flFlowUvScrollDistance = g_flFlowUvScrollDistance;
float2 vFlowUV0 = i.vUV0_UV1.zw + flOffset1;
float2 vFlowUV1 = i.vUV0_UV1.zw + flOffset2;
#if ( !FLOW_CHEAP )
{
flFlowUvScrollDistance *= ( 1.0f + flVortexIntensity );
vFlowUV0 += ( flScrollTime1 * ( flFlowUvScrollDistance * vFlowVectorTs.xy ) );
vFlowUV1 += ( flScrollTime2 * ( flFlowUvScrollDistance * vFlowVectorTs.xy ) );
}
#endif
cBase.rgba = tex2D( g_tBase, vFlowUV0 ) * flWeight1;
cBase.rgba += tex2D( g_tBase, vFlowUV1 ) * flWeight2;
#if ( POWERUP )
{
float flNoiseReveal = ( flNoise + ( 1.0f - vBoundsTexel.g ) ) * 0.5;
float flPowerStage1 = saturate( 0.7f - g_flPowerUp );
float flPowerStage2 = saturate( g_flPowerUp * 3.0f );
float flPowerUpRange1 = smoothstep( 0.02f, 0.0f, abs( flNoiseReveal - g_flPowerUp ) );
float flPowerUpRange2 = smoothstep( 0.02f, 0.0f, ( flNoiseReveal - g_flPowerUp ) );
cBase.ag += flPowerUpRange1 * g_flPowerUp * (1.0f - g_flPowerUp );
cBase.ag *= flPowerStage2 * flPowerUpRange2;
cBase.ag += vBoundsTexel.g * flPowerStage2;
}
#else
{
cBase.ag += vBoundsTexel.g;
}
#endif
float3 cFlowField = cBase.a * g_cFlow.rgb;
#if( VORTEX1 || VORTEX2 )
{
float3 cVortex = cBase.g * g_cVortex.rgb;
cBase.rgb = lerp( cFlowField, cVortex, flVortexIntensity );
}
#else
{
cBase.rgb = cFlowField;
}
#endif
cBase.rgb *= vBoundsTexel.b * g_flIntensity;
}
#else
{
cBase = tex2D( g_tBase, i.vUV0_UV1.xy );
}
#endif
#if( TANGENTTOPACITY || TANGENTSOPACITY || FRESNELOPACITY )
{
vWorldEyeDir.xyz = normalize( vWorldEyeDir.xyz );
vWorldNormal.xyz = normalize( vWorldNormal.xyz );
fBackfaceRatio = dot( vWorldEyeDir.xyz, vWorldNormal.xyz ) * 0.5f + 0.5f;
fBackfaceRatio *= fBackfaceRatio;
}
#endif
#if( TANGENTSOPACITY || TANGENTTOPACITY )
{
vWorldTangent.xyz = normalize( vWorldTangent.xyz );
}
#endif
//alpha
float alpha = 1.0f;
float fBackfaceAlpha = 1.0f;
#if TANGENTTOPACITY
{
float fTTFacing = abs( dot( vWorldTangent, normalize( i.vTangentAlignedView_worldEyeZ.xyz ) ) );
alpha *= lerp( g_vTangentTOpacityRanges.x, g_vTangentTOpacityRanges.y, pow( fTTFacing, g_vTangentTOpacityRanges.z ) );
fBackfaceAlpha = lerp( 1.0f, g_vTangentTOpacityRanges.w, fBackfaceRatio );
}
#endif
#if TANGENTSOPACITY
{
float fTSFacing = abs( dot( vWorldTangent, normalize( i.vTangentAlignedView_worldEyeZ.xyz ) ) );
alpha *= lerp( g_vTangentSOpacityRanges.x, g_vTangentSOpacityRanges.y, pow( fTSFacing, g_vTangentTOpacityRanges.z ) );
fBackfaceAlpha = min( fBackfaceAlpha, lerp( g_vTangentSOpacityRanges.w, 1.0f, fBackfaceRatio ) );
}
#endif
#if FRESNELOPACITY
{
float tNFacing = abs( dot( vWorldNormal, vWorldEyeDir.xyz ) );
alpha *= lerp( g_vFresnelOpacityRanges.x, g_vFresnelOpacityRanges.y, pow( tNFacing, g_vFresnelOpacityRanges.z ) );
fBackfaceAlpha = min( fBackfaceAlpha, lerp( g_vFresnelOpacityRanges.w, 1.0f, dot( vWorldEyeDir.xyz, vWorldNormal.xyz ) * 0.5f + 0.5f ) );
}
#endif
alpha *= fBackfaceAlpha;
#if DEPTHBLEND
{
alpha *= DepthFeathering( g_tDepth, i.vIteratedProjPos, g_DepthFeatheringConstants );
}
#endif
#if ( !FLOWMAP && !TANGENTTOPACITY && !TANGENTSOPACITY && !FRESNELOPACITY && !( DETAIL1 && DETAIL1BLENDMODE == 1 ) )
alpha *= cBase.a;
#endif
float flCameraFade = ComputeCameraFade( i.vIteratedProjPos );
//color
float4 cDetail1 = float4( 0.0f, 0.0f, 0.0f, 0.0f );
float4 cDetail2 = float4( 0.0f, 0.0f, 0.0f, 0.0f );
#if( DETAIL2 )
{
cDetail2 = tex2D( g_tDetail2, i.vFlowUV_UV2.zw );
}
#endif
#if( DETAIL1 )
{
cDetail1 = tex2D( g_tDetail1, i.vUV0_UV1.zw );
#if( DETAIL1BLENDMODE == 0 )
{
cBase.rgb *= 2.0f * cDetail1.rgb;
}
#else
{
cBase.rgb = lerp( cBase.rgb * cDetail1.rgb, cBase.rgb, cBase.a );
}
#endif
}
#endif
#if( DETAIL2 )
{
#if( DETAIL2BLENDMODE == 0 )
{
#if( DETAIL1 )
{
cDetail2.rgb *= cDetail1.rgb;
}
#endif
cBase.rgb += cDetail2.rgb;
}
#else
{
cBase.rgb *= cDetail2.rgb;
}
#endif
}
#endif
cOut.a = alpha;
cOut.rgb = cBase.rgb;
#if ( POWERUP && !FLOWMAP )
{
cOut.rgb *= g_flPowerUp;
}
#endif
#if ( ADDITIVE )
{
cOut.rgb *= ( 1.0f + alpha ) * flCameraFade;
cOut.a = 1.0f;
}
#endif
#if ( VERTEXCOLOR )
{
// fun with saturation:
float3 vColor = pow( i.vColor.rgb, ( 2.0f - alpha ) * 2.0f );
cOut.rgb *= vColor.rgb;
}
#endif
}
#endif // ACTIVE
// Limit tonemap scalar to 0.0-1.0 so the colors don't oversaturate, but let it drop down to 0 in case we're fading
float flTonemapScalar = saturate( LINEAR_LIGHT_SCALE );
// g_flOutputIntensity is normally 1.0f, except to work around overall intensity problems on platforms that blend in gamma space (such as PS3).
return FinalOutput( cOut, 0, PIXEL_FOG_TYPE_NONE, TONEMAP_SCALE_NONE ) * flTonemapScalar * g_flOutputIntensity;
}