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.
239 lines
8.1 KiB
239 lines
8.1 KiB
//========= 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 |
|
}
|
|
|