259 lines
8.8 KiB
C
259 lines
8.8 KiB
C
//========= 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
|
|
}
|