// STATIC: "CONVERT_TO_SRGB" "0..1" [ps20b][= g_pHardwareConfig->NeedsShaderSRGBConversion()] [PC] // STATIC: "CONVERT_TO_SRGB" "0..0" [= 0] [XBOX] // STATIC: "BASETEXTURE" "0..1" // STATIC: "REFLECT" "0..1" // STATIC: "REFRACT" "0..1" // STATIC: "ENVMAPMASK" "0..1" // DYNAMIC: "PIXELFOGTYPE" "0..1" // DYNAMIC: "WRITE_DEPTH_TO_DESTALPHA" "0..1" [ps20b] [PC] // DYNAMIC: "WRITE_DEPTH_TO_DESTALPHA" "0..0" [ps20b] [XBOX] #if defined( SHADER_MODEL_PS_2_0 ) # define WRITE_DEPTH_TO_DESTALPHA 0 #endif #include "common_ps_fxc.h" sampler RefractSampler : register( s0 ); sampler BaseTextureSampler : register( s1 ); sampler ReflectSampler : register( s2 ); #if BASETEXTURE sampler LightmapSampler : register( s3 ); #endif #if ENVMAPMASK sampler EnvMapMaskSampler : register( s6 ); #endif sampler NormalSampler : register( s4 ); const HALF4 vRefractTint : register( c1 ); const float4 g_FresnelConstants : register( c3 ); const HALF4 vReflectTint : register( c4 ); const float4 g_ReflectRefractScale : register( c5 ); // xy - reflect scale, zw - refract scale const float4 g_PixelFogParams : register( c8 ); static const bool g_bReflect = REFLECT ? true : false; static const bool g_bRefract = REFRACT ? true : false; struct PS_INPUT { float4 vBumpTexCoordXY_vTexCoordXY : TEXCOORD0; half3 vTangentEyeVect : TEXCOORD1; float4 vReflectXY_vRefractYX : TEXCOORD2; float W : TEXCOORD3; float4 vProjPos : TEXCOORD4; float screenCoord : TEXCOORD5; #if BASETEXTURE // CENTROID: TEXCOORD6 HALF4 lightmapTexCoord1And2 : TEXCOORD6; // CENTROID: TEXCOORD7 HALF4 lightmapTexCoord3 : TEXCOORD7; #endif float4 fogFactorW : COLOR1; }; float4 main( PS_INPUT i ) : COLOR { // Load normal and expand range HALF4 vNormalSample = tex2D( NormalSampler, i.vBumpTexCoordXY_vTexCoordXY.xy ); HALF3 vNormal = normalize( vNormalSample * 2.0 - 1.0 ); // Perform division by W only once float ooW = 1.0f / i.W; float2 unwarpedRefractTexCoord = i.vReflectXY_vRefractYX.wz * ooW; float4 reflectRefractScale = g_ReflectRefractScale; // Compute coordinates for sampling Reflection float2 vReflectTexCoord; float2 vRefractTexCoord; // vectorize the dependent UV calculations (reflect = .xy, refract = .wz) #ifdef NV3X float4 vDependentTexCoords = vNormal.xyxy * vNormalSample.a * reflectRefractScale; #else float4 vN; vN.xy = vNormal.xy; vN.w = vNormal.x; vN.z = vNormal.y; float4 vDependentTexCoords = vN * vNormalSample.a * reflectRefractScale; #endif vDependentTexCoords += ( i.vReflectXY_vRefractYX * ooW ); vReflectTexCoord = vDependentTexCoords.xy; vRefractTexCoord = vDependentTexCoords.wz; // Sample reflection and refraction HALF4 vReflectColor = tex2D( ReflectSampler, vReflectTexCoord ); HALF4 vRefractColor = tex2D( RefractSampler, vRefractTexCoord ); vReflectColor *= vReflectTint; vRefractColor *= vRefractTint; half3 vEyeVect; vEyeVect = normalize( i.vTangentEyeVect ); // Fresnel term HALF fNdotV = saturate( dot( vEyeVect, vNormal ) ); HALF fFresnelScalar = g_FresnelConstants.x * pow( 1.0 - fNdotV, g_FresnelConstants.y ) + g_FresnelConstants.z; HALF4 fFresnel = HALF4( fFresnelScalar, fFresnelScalar, fFresnelScalar, fFresnelScalar ); #if BASETEXTURE float4 baseSample = tex2D( BaseTextureSampler, i.vBumpTexCoordXY_vTexCoordXY.zw ); 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 float4 flMask; #if ENVMAPMASK flMask = tex2D( EnvMapMaskSampler, i.vBumpTexCoordXY_vTexCoordXY.zw ); #else flMask = float4( 1.0f, 1.0f, 1.0f, 1.0f ); #endif // NOTE: the BASETEXTURE path hasn't been tested (or really written for that matter, just copied from water) // What I think should happen is that the alpha of base texture should be its 'translucency' // which should indicate how much refraction to use. // We should add an envmapmask to deal with how much reflection to use // along with all the focus, etc. features float4 result; float flAlpha = 1.0f; if( g_bReflect && g_bRefract ) { result = lerp( vRefractColor, vReflectColor, fFresnel ) * flMask; #if BASETEXTURE result += float4( diffuseComponent, 1.0f ); flAlpha = baseSample.a; #endif } else if( g_bReflect ) { #if BASETEXTURE result = float4( diffuseComponent, 1.0f ) + vReflectColor * flMask; flAlpha = baseSample.a; #else result = vReflectColor; #endif } else if( g_bRefract ) { #if BASETEXTURE result = float4( diffuseComponent, 1.0f ) + vRefractColor * flMask; flAlpha = baseSample.a; #else result = vRefractColor; #endif } else { #if BASETEXTURE result = float4( diffuseComponent, 1.0f ); flAlpha = baseSample.a; #else result = float4( 0.0f, 0.0f, 0.0f, 0.0f ); #endif } #if ( PIXELFOGTYPE == PIXEL_FOG_TYPE_RANGE ) float fogFactor = CalcRangeFog( i.vProjPos.z, g_PixelFogParams.x, g_PixelFogParams.z, g_PixelFogParams.w ); #else float fogFactor = 0; #endif return FinalOutput( float4( result.rgb, flAlpha ), fogFactor, PIXELFOGTYPE, TONEMAP_SCALE_NONE, (WRITE_DEPTH_TO_DESTALPHA != 0), i.vProjPos.z ); }