|
|
//========= Copyright Valve Corporation, All rights reserved. ============//
#include "common_ps_fxc.h"
struct DrawWater_params_t { float2 vBumpTexCoord; #if MULTITEXTURE
float4 vExtraBumpTexCoord; #endif
float4 vReflectXY_vRefractYX; float w; float4 vReflectRefractScale; float fReflectOverbright; float4 vReflectTint; float4 vRefractTint; half3 vTangentEyeVect; float4 waterFogColor; #if BASETEXTURE
HALF4 lightmapTexCoord1And2; HALF4 lightmapTexCoord3; #endif
float4 vProjPos; float4 pixelFogParams; float fWaterFogStart; float fWaterFogEndMinusStart; };
void DrawWater( in DrawWater_params_t i, #if BASETEXTURE
in sampler BaseTextureSampler, in sampler LightmapSampler, #endif
in sampler NormalSampler, in sampler RefractSampler, in sampler ReflectSampler, out float4 result, out float fogFactor ) { bool bReflect = REFLECT ? true : false; bool bRefract = REFRACT ? true : false;
#if MULTITEXTURE
float4 vNormal = tex2D( NormalSampler, i.vBumpTexCoord ); float4 vNormal1 = tex2D( NormalSampler, i.vExtraBumpTexCoord.xy ); float4 vNormal2 = tex2D( NormalSampler, 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) ); vNormal.a = 1.0f; #else
vNormal.xyz = 2.0 * vNormal.xyz - 1.0; #endif
#else
float4 vNormal = DecompressNormal( NormalSampler, i.vBumpTexCoord, NORMAL_DECODE_MODE ); #endif
// Perform division by W only once
float ooW = 1.0f / i.w;
float2 unwarpedRefractTexCoord = i.vReflectXY_vRefractYX.wz * ooW;
#if ABOVEWATER
float waterFogDepthValue = tex2D( RefractSampler, unwarpedRefractTexCoord ).a; #else
// We don't actually have valid depth values in alpha when we are underwater looking out, so
// just set to farthest value.
float waterFogDepthValue = 1.0f; #endif
float4 reflectRefractScale = i.vReflectRefractScale; #if !BASETEXTURE
#if ( BLURRY_REFRACT == 0 )
reflectRefractScale *= waterFogDepthValue; #endif
#endif
// Compute coordinates for sampling Reflection
float2 vReflectTexCoord; float2 vRefractTexCoord;
// vectorize the dependent UV calculations (reflect = .xy, refract = .wz)
float4 vN; vN.xy = vNormal.xy; vN.w = vNormal.x; vN.z = vNormal.y; float4 vDependentTexCoords = vN * vNormal.a * reflectRefractScale;
vDependentTexCoords += ( i.vReflectXY_vRefractYX * ooW ); vReflectTexCoord = vDependentTexCoords.xy; vRefractTexCoord = vDependentTexCoords.wz;
HALF4 vReflectColor = tex2D( ReflectSampler, vReflectTexCoord ); #if BLURRY_REFRACT
// Sample reflection and refraction
float2 ddx1=float2(0.005,0); float2 ddy1=float2(0,0.005); float4 vRefractColor=float4(0,0,0,0);
#if 0
float sumweights=0; for(int ix=-2;ix<=2;ix++) { for(int iy=-2;iy<=2;iy++) { float weight=1; ///(1+abs(ix)+abs(iy));
vRefractColor += weight*tex2D( RefractSampler, vRefractTexCoord+ix*ddx1+iy*ddy1); sumweights+=weight; } } #else
// NOTE: Generated by genwaterloop.pl in the stdshaders directory.
// Need to unroll for 360 to avoid shader compilation problems.
// Modified genwaterloop.pl and regenerate if you need different params
vRefractColor += tex2D( RefractSampler, vRefractTexCoord + -2 * ddx1 + -2 * ddy1 ); vRefractColor += tex2D( RefractSampler, vRefractTexCoord + -2 * ddx1 + -1 * ddy1 ); vRefractColor += tex2D( RefractSampler, vRefractTexCoord + -2 * ddx1 + 0 * ddy1 ); vRefractColor += tex2D( RefractSampler, vRefractTexCoord + -2 * ddx1 + 1 * ddy1 ); vRefractColor += tex2D( RefractSampler, vRefractTexCoord + -2 * ddx1 + 2 * ddy1 ); vRefractColor += tex2D( RefractSampler, vRefractTexCoord + -1 * ddx1 + -2 * ddy1 ); vRefractColor += tex2D( RefractSampler, vRefractTexCoord + -1 * ddx1 + -1 * ddy1 ); vRefractColor += tex2D( RefractSampler, vRefractTexCoord + -1 * ddx1 + 0 * ddy1 ); vRefractColor += tex2D( RefractSampler, vRefractTexCoord + -1 * ddx1 + 1 * ddy1 ); vRefractColor += tex2D( RefractSampler, vRefractTexCoord + -1 * ddx1 + 2 * ddy1 ); vRefractColor += tex2D( RefractSampler, vRefractTexCoord + 0 * ddx1 + -2 * ddy1 ); vRefractColor += tex2D( RefractSampler, vRefractTexCoord + 0 * ddx1 + -1 * ddy1 ); vRefractColor += tex2D( RefractSampler, vRefractTexCoord + 0 * ddx1 + 0 * ddy1 ); vRefractColor += tex2D( RefractSampler, vRefractTexCoord + 0 * ddx1 + 1 * ddy1 ); vRefractColor += tex2D( RefractSampler, vRefractTexCoord + 0 * ddx1 + 2 * ddy1 ); vRefractColor += tex2D( RefractSampler, vRefractTexCoord + 1 * ddx1 + -2 * ddy1 ); vRefractColor += tex2D( RefractSampler, vRefractTexCoord + 1 * ddx1 + -1 * ddy1 ); vRefractColor += tex2D( RefractSampler, vRefractTexCoord + 1 * ddx1 + 0 * ddy1 ); vRefractColor += tex2D( RefractSampler, vRefractTexCoord + 1 * ddx1 + 1 * ddy1 ); vRefractColor += tex2D( RefractSampler, vRefractTexCoord + 1 * ddx1 + 2 * ddy1 ); vRefractColor += tex2D( RefractSampler, vRefractTexCoord + 2 * ddx1 + -2 * ddy1 ); vRefractColor += tex2D( RefractSampler, vRefractTexCoord + 2 * ddx1 + -1 * ddy1 ); vRefractColor += tex2D( RefractSampler, vRefractTexCoord + 2 * ddx1 + 0 * ddy1 ); vRefractColor += tex2D( RefractSampler, vRefractTexCoord + 2 * ddx1 + 1 * ddy1 ); vRefractColor += tex2D( RefractSampler, vRefractTexCoord + 2 * ddx1 + 2 * ddy1 ); float sumweights = 25; // NOTE: end of generated code.
#endif
vRefractColor *= (1.0/sumweights); vReflectColor *= i.fReflectOverbright; vReflectColor *= i.vReflectTint; vRefractColor *= i.vRefractTint; # if ABOVEWATER
// Don't mess with this in the underwater case since we don't really have
// depth values there.
// get the blurred depth value to be used for fog.
waterFogDepthValue = vRefractColor.a; # endif
#else
vReflectColor *= i.vReflectTint; HALF4 vRefractColor = tex2D( RefractSampler, vRefractTexCoord ); // get the depth value from the refracted sample to be used for fog.
# if ABOVEWATER
// Don't mess with this in the underwater case since we don't really have
// depth values there.
waterFogDepthValue = tex2D( RefractSampler, vRefractTexCoord ).a; # endif
#endif
half3 vEyeVect; vEyeVect = normalize( i.vTangentEyeVect );
// Fresnel term
HALF fNdotV = saturate( dot( vEyeVect, vNormal ) ); HALF fFresnel = pow( 1.0 - fNdotV, 5 );
#if !BASETEXTURE
// fFresnel == 1.0f means full reflection
fFresnel *= saturate( ( waterFogDepthValue - 0.05f ) * 20.0f ); #endif
// blend between refraction and fog color.
#if ABOVEWATER
vRefractColor = lerp( vRefractColor, i.waterFogColor * LINEAR_LIGHT_SCALE, saturate( waterFogDepthValue - 0.05f ) ); #else
float waterFogFactor = saturate( ( i.vProjPos.z - i.fWaterFogStart ) / i.fWaterFogEndMinusStart ); vRefractColor = lerp( vRefractColor, i.waterFogColor * LINEAR_LIGHT_SCALE, waterFogFactor ); #endif
#if BASETEXTURE
float4 baseSample = tex2D( BaseTextureSampler, i.vBumpTexCoord.xy ); HALF2 bumpCoord1; HALF2 bumpCoord2; HALF2 bumpCoord3; ComputeBumpedLightmapCoordinates( i.lightmapTexCoord1And2, i.lightmapTexCoord3.xy, bumpCoord1, bumpCoord2, bumpCoord3 );
HALF4 lightmapSample1 = tex2D( LightmapSampler, bumpCoord1 ); HALF3 lightmapColor1 = lightmapSample1.rgb; HALF3 lightmapColor2 = tex2D( LightmapSampler, bumpCoord2 ); HALF3 lightmapColor3 = tex2D( LightmapSampler, bumpCoord3 );
float3 dp; dp.x = saturate( dot( vNormal, bumpBasis[0] ) ); dp.y = saturate( dot( vNormal, bumpBasis[1] ) ); dp.z = saturate( dot( vNormal, bumpBasis[2] ) ); dp *= dp;
float3 diffuseLighting = dp.x * lightmapColor1 + dp.y * lightmapColor2 + dp.z * lightmapColor3; float sum = dot( dp, float3( 1.0f, 1.0f, 1.0f ) ); diffuseLighting *= LIGHT_MAP_SCALE / sum; HALF3 diffuseComponent = baseSample.rgb * diffuseLighting; #endif
if( bReflect && bRefract ) { result = lerp( vRefractColor, vReflectColor, fFresnel ); } else if( bReflect ) { #if BASETEXTURE
result = float4( diffuseComponent, 1.0f ) + vReflectColor * fFresnel * baseSample.a; #else
result = vReflectColor; #endif
} else if( bRefract ) { result = vRefractColor; } else { result = float4( 0.0f, 0.0f, 0.0f, 0.0f ); }
#if (PIXELFOGTYPE == PIXEL_FOG_TYPE_RANGE)
fogFactor = CalcRangeFog( i.vProjPos.z, i.pixelFogParams.x, i.pixelFogParams.z, i.pixelFogParams.w ); #else
fogFactor = 0; #endif
}
|