source-engine/materialsystem/stdshaders/water_ps2x_helper.h

240 lines
8.1 KiB
C
Raw Normal View History

2020-04-22 16:56:21 +00:00
//========= 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
}