Modified source engine (2017) developed by valve and leaked in 2020. Not for commercial purporses
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.

153 lines
4.7 KiB

5 years ago
// STATIC: "CONVERT_TO_SRGB" "0..1" [ps20b][= g_pHardwareConfig->NeedsShaderSRGBConversion()] [PC]
// STATIC: "CONVERT_TO_SRGB" "0..0" [= 0] [XBOX]
// STATIC: "MULTITEXTURE" "0..1"
// STATIC: "FRESNEL" "0..1"
// STATIC: "BLEND" "0..1"
// STATIC: "REFRACTALPHA" "0..1"
// STATIC: "HDRTYPE" "0..2"
// STATIC: "NORMAL_DECODE_MODE" "0..0" [XBOX]
// STATIC: "NORMAL_DECODE_MODE" "0..0" [PC]
// DYNAMIC: "HDRENABLED" "0..1"
// DYNAMIC: "PIXELFOGTYPE" "0..1"
#include "common_ps_fxc.h"
const HALF3 g_WaterFogColor : register( c0 );
const HALF4 g_CheapWaterParams : register( c1 );
const HALF4 g_ReflectTint : register( c2 );
const float4 g_PixelFogParams : register( c3 );
#define g_CheapWaterStart g_CheapWaterParams.x
#define g_CheapWaterEnd g_CheapWaterParams.y
#define g_CheapWaterDeltaRecip g_CheapWaterParams.z
#define g_CheapWaterStartDivDelta g_CheapWaterParams.w
sampler EnvmapSampler : register( s0 );
sampler NormalMapSampler : register( s1 );
#if REFRACTALPHA
sampler RefractSampler : register( s2 );
#endif
sampler NormalizeSampler : register( s6 );
struct PS_INPUT
{
float2 normalMapTexCoord : TEXCOORD0;
HALF3 worldSpaceEyeVect : TEXCOORD1;
HALF3x3 tangentSpaceTranspose : TEXCOORD2;
float4 vRefract_W_ProjZ : TEXCOORD5;
#if MULTITEXTURE
float4 vExtraBumpTexCoord : TEXCOORD6;
#endif
float4 fogFactorW : COLOR1;
};
float4 main( PS_INPUT i ) : COLOR
{
bool bBlend = BLEND ? true : false;
#if MULTITEXTURE
float3 vNormal = tex2D( NormalMapSampler, i.normalMapTexCoord );
float3 vNormal1 = tex2D( NormalMapSampler, i.vExtraBumpTexCoord.xy );
float3 vNormal2 = tex2D( NormalMapSampler, i.vExtraBumpTexCoord.zw );
vNormal = 0.33 * ( vNormal + vNormal1 + vNormal2 );
#if ( NORMAL_DECODE_MODE == NORM_DECODE_ATI2N )
vNormal.xy = vNormal.xy * 2.0f - 1.0f;
vNormal.z = sqrt( 1.0f - dot(vNormal.xy, vNormal.xy) );
#else
vNormal = 2.0 * vNormal - 1.0;
#endif
#else
float3 vNormal = DecompressNormal( NormalMapSampler, i.normalMapTexCoord, NORMAL_DECODE_MODE );
#endif
HALF3 worldSpaceNormal = mul( vNormal, i.tangentSpaceTranspose );
HALF3 worldSpaceEye;
HALF flWorldSpaceDist = 1.0f;
#ifdef NV3X
// for some reason, fxc doesn't convert length( half3 v ) into all _pp opcodes.
if (bBlend)
{
worldSpaceEye = i.worldSpaceEyeVect;
HALF worldSpaceDistSqr = dot( worldSpaceEye, worldSpaceEye );
HALF rcpWorldSpaceDist = rsqrt( worldSpaceDistSqr );
worldSpaceEye *= rcpWorldSpaceDist;
flWorldSpaceDist = worldSpaceDistSqr * rcpWorldSpaceDist;
}
else
{
worldSpaceEye = NormalizeWithCubemap( NormalizeSampler, i.worldSpaceEyeVect );
}
#else // !NV3X
if (bBlend)
{
worldSpaceEye = i.worldSpaceEyeVect;
flWorldSpaceDist = length( worldSpaceEye );
worldSpaceEye /= flWorldSpaceDist;
}
else
{
worldSpaceEye = NormalizeWithCubemap( NormalizeSampler, i.worldSpaceEyeVect );
}
#endif
HALF3 reflectVect = CalcReflectionVectorUnnormalized( worldSpaceNormal, worldSpaceEye );
HALF3 specularLighting = ENV_MAP_SCALE * texCUBE( EnvmapSampler, reflectVect );
specularLighting *= g_ReflectTint;
#if FRESNEL
// FIXME: It's unclear that we want to do this for cheap water
// but the code did this previously and I didn't want to change it
HALF flDotResult = dot( worldSpaceEye, worldSpaceNormal );
flDotResult = 1.0f - max( 0.0f, flDotResult );
HALF flFresnelFactor = flDotResult * flDotResult;
flFresnelFactor *= flFresnelFactor;
flFresnelFactor *= flDotResult;
#else
HALF flFresnelFactor = g_ReflectTint.a;
#endif
HALF flAlpha;
if (bBlend)
{
HALF flReflectAmount = saturate( flWorldSpaceDist * g_CheapWaterDeltaRecip - g_CheapWaterStartDivDelta );
flAlpha = saturate( flFresnelFactor + flReflectAmount );
#if REFRACTALPHA
// Perform division by W only once
float ooW = 1.0f / i.vRefract_W_ProjZ.z;
float2 unwarpedRefractTexCoord = i.vRefract_W_ProjZ * ooW;
float fogDepthValue = tex2D( RefractSampler, unwarpedRefractTexCoord ).a;
// Fade on the border between the water and land.
flAlpha *= saturate( ( fogDepthValue - .05f ) * 20.0f );
#endif
}
else
{
flAlpha = 1.0f;
#if HDRTYPE == 0 || HDRENABLED == 0
specularLighting = lerp( g_WaterFogColor, specularLighting, flFresnelFactor );
#else
specularLighting = lerp( GammaToLinear( g_WaterFogColor ), specularLighting, flFresnelFactor );
#endif
}
// multiply the color by alpha.since we are using alpha blending to blend against dest alpha for borders.
#if (PIXELFOGTYPE == PIXEL_FOG_TYPE_RANGE)
float fogFactor = CalcRangeFog( i.vRefract_W_ProjZ.w, g_PixelFogParams.x, g_PixelFogParams.z, g_PixelFogParams.w );
#else
float fogFactor = 0;
#endif
return FinalOutput( float4( specularLighting, flAlpha ), fogFactor, PIXELFOGTYPE, TONEMAP_SCALE_LINEAR );
}