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.
152 lines
4.7 KiB
152 lines
4.7 KiB
// 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 ); |
|
}
|
|
|