aboutsummaryrefslogtreecommitdiff
path: root/mp/src/materialsystem/stdshaders/eye_refract_ps2x.fxc
diff options
context:
space:
mode:
Diffstat (limited to 'mp/src/materialsystem/stdshaders/eye_refract_ps2x.fxc')
-rw-r--r--mp/src/materialsystem/stdshaders/eye_refract_ps2x.fxc494
1 files changed, 494 insertions, 0 deletions
diff --git a/mp/src/materialsystem/stdshaders/eye_refract_ps2x.fxc b/mp/src/materialsystem/stdshaders/eye_refract_ps2x.fxc
new file mode 100644
index 00000000..da053d22
--- /dev/null
+++ b/mp/src/materialsystem/stdshaders/eye_refract_ps2x.fxc
@@ -0,0 +1,494 @@
+//====== Copyright � 1996-2007, Valve Corporation, All rights reserved. ===========================
+
+// STATIC: "FLASHLIGHT" "0..1"
+// STATIC: "LIGHTWARPTEXTURE" "0..1"
+
+// STATIC: "SPHERETEXKILLCOMBO" "0..1" [ps20b]
+// STATIC: "SPHERETEXKILLCOMBO" "0..1" [ps30]
+
+// STATIC: "RAYTRACESPHERE" "0..1" [ps20b]
+// STATIC: "RAYTRACESPHERE" "0..1" [ps30]
+
+// STATIC: "FLASHLIGHTDEPTHFILTERMODE" "0..2" [ps20b] [PC]
+// STATIC: "FLASHLIGHTDEPTHFILTERMODE" "0..2" [ps30] [PC]
+// STATIC: "FLASHLIGHTDEPTHFILTERMODE" "0..0" [ps20b] [XBOX]
+
+// DYNAMIC: "NUM_LIGHTS" "0..2" [ps20]
+// DYNAMIC: "NUM_LIGHTS" "0..4" [ps20b]
+// DYNAMIC: "NUM_LIGHTS" "0..4" [ps30]
+
+// DYNAMIC: "FLASHLIGHTSHADOWS" "0..1" [ps20b]
+// DYNAMIC: "FLASHLIGHTSHADOWS" "0..1" [ps30]
+
+// We don't use other lights when doing the flashlight
+// SKIP: ( $FLASHLIGHT != 0 ) && ( $NUM_LIGHTS > 0 )
+
+// We don't care about flashlight depth unless the flashlight is on
+// SKIP: ( $FLASHLIGHT == 0 ) && ( $FLASHLIGHTSHADOWS == 1 ) [ps20b]
+// SKIP: ( $FLASHLIGHT == 0 ) && ( $FLASHLIGHTSHADOWS == 1 ) [ps30]
+
+// SKIP: ( $RAYTRACESPHERE == 0 ) && ( $SPHERETEXKILLCOMBO == 1 ) [ps30]
+// SKIP: ( $RAYTRACESPHERE == 0 ) && ( $SPHERETEXKILLCOMBO == 1 ) [ps20b]
+
+// Debug 2.0 shader locally
+//#ifdef SHADER_MODEL_PS_2_B
+//#undef SHADER_MODEL_PS_2_B
+//#define SHADER_MODEL_PS_2_0
+//#endif
+
+
+// Includes =======================================================================================
+#include "common_flashlight_fxc.h"
+#include "shader_constant_register_map.h"
+
+// Texture Samplers ===============================================================================
+sampler g_tCorneaSampler : register( s0 );
+sampler g_tIrisSampler : register( s1 );
+sampler g_tEyeReflectionCubemapSampler : register( s2 );
+sampler g_tEyeAmbientOcclSampler : register( s3 );
+sampler g_tLightwarpSampler : register( s4 ); // 1D texture for TF NPR lighting
+
+sampler g_tFlashlightCookieSampler : register( s5 );
+sampler g_tFlashlightDepthSampler : register( s6 );
+sampler g_tRandomRotationSampler : register( s7 );
+
+// Shaders Constants and Globals ==================================================================
+const float4 g_vPackedConst0 : register( c0 );
+#define g_flDilationFactor g_vPackedConst0.x
+#define g_flGlossiness g_vPackedConst0.y
+#define g_flAverageAmbient g_vPackedConst0.z
+#define g_flCorneaBumpStrength g_vPackedConst0.w
+
+const float3 g_vEyeOrigin : register( c1 );
+const float4 g_vIrisProjectionU : register( c2 );
+const float4 g_vIrisProjectionV : register( c3 );
+const float4 g_vCameraPosition : register( c4 );
+const float3 g_cAmbientOcclColor : register( c5 );
+
+const float4 g_vPackedConst6 : register( c6 );
+#define g_flEyeballRadius g_vPackedConst6.y //0.51f
+//#define g_bRaytraceSphere g_vPackedConst6.z //1.0f
+#define g_flParallaxStrength g_vPackedConst6.w //0.25f
+
+// Flashlight constants
+const float4 g_vFlashlightAttenuationFactors : register( c7 ); // FarZ in w
+const float3 g_vFlashlightPos : register( c8 );
+const float4 g_vShadowTweaks : register( c9 );
+const float4 g_ShaderControls : register( c10 );
+#define g_fPixelFogType g_ShaderControls.x
+
+const float4 g_FogParams : register( PSREG_FOG_PARAMS );
+
+PixelShaderLightInfo g_sLightInfo[3] : register( PSREG_LIGHT_INFO_ARRAY ); // 2 registers each - 6 registers total
+
+// Interpolated values ============================================================================
+struct PS_INPUT
+{
+ float4 vAmbientOcclUv_fallbackCorneaUv : TEXCOORD0;
+ float4 cVertexLight : TEXCOORD1; // w is used for the flashlight pass
+ float4 vTangentViewVector : TEXCOORD2; // Tangent view vector (Note: w is used for flashlight pass)
+ float4 vWorldPosition_ProjPosZ : TEXCOORD3;
+ float3 vWorldNormal : TEXCOORD4; // World-space normal
+ float3 vWorldTangent : TEXCOORD5; // World-space tangent
+ float4 vLightFalloffCosine01 : TEXCOORD6; // Light falloff and cosine terms for first two local lights
+ float4 vLightFalloffCosine23 : TEXCOORD7; // Light falloff and cosine terms for next two local lights
+
+ float3 vWorldBinormal : COLOR0; // World-space normal
+};
+
+// Ray sphere intersect returns distance along ray to intersection ================================
+float IntersectRaySphere ( float3 cameraPos, float3 ray, float3 sphereCenter, float sphereRadius)
+{
+ float3 dst = cameraPos.xyz - sphereCenter.xyz;
+ float B = dot(dst, ray);
+ float C = dot(dst, dst) - (sphereRadius * sphereRadius);
+ float D = B*B - C;
+ return (D > 0) ? (-B - sqrt(D)) : 0;
+}
+
+// Calculate both types of Fog and lerp to get result
+float CalcPixelFogFactorConst( float fPixelFogType, const float4 fogParams, const float flEyePosZ, const float flWorldPosZ, const float flProjPosZ )
+{
+ float fRangeFog = CalcRangeFog( flProjPosZ, fogParams.x, fogParams.z, fogParams.w );
+ float fHeightFog = CalcWaterFogAlpha( fogParams.y, flEyePosZ, flWorldPosZ, flProjPosZ, fogParams.w );
+ return lerp( fRangeFog, fHeightFog, fPixelFogType );
+}
+
+// Blend both types of Fog and lerp to get result
+float3 BlendPixelFogConst( const float3 vShaderColor, float pixelFogFactor, const float3 vFogColor, float fPixelFogType )
+{
+ pixelFogFactor = saturate( pixelFogFactor );
+ float3 fRangeResult = lerp( vShaderColor.rgb, vFogColor.rgb, pixelFogFactor * pixelFogFactor ); //squaring the factor will get the middle range mixing closer to hardware fog
+ float3 fHeightResult = lerp( vShaderColor.rgb, vFogColor.rgb, saturate( pixelFogFactor ) );
+ return lerp( fRangeResult, fHeightResult, fPixelFogType );
+}
+
+float4 FinalOutputConst( const float4 vShaderColor, float pixelFogFactor, float fPixelFogType, const int iTONEMAP_SCALE_TYPE )
+{
+ float4 result = vShaderColor;
+ if( iTONEMAP_SCALE_TYPE == TONEMAP_SCALE_LINEAR )
+ {
+ result.rgb *= LINEAR_LIGHT_SCALE;
+ }
+ else if( iTONEMAP_SCALE_TYPE == TONEMAP_SCALE_GAMMA )
+ {
+ result.rgb *= GAMMA_LIGHT_SCALE;
+ }
+
+ result.rgb = BlendPixelFogConst( result.rgb, pixelFogFactor, g_LinearFogColor.rgb, fPixelFogType );
+ result.rgb = SRGBOutput( result.rgb ); //SRGB in pixel shader conversion
+
+ return result;
+}
+
+
+// Main ===========================================================================================
+float4 main( PS_INPUT i ) : COLOR
+{
+ // Set bools to compile out code
+ bool bFlashlight = ( FLASHLIGHT != 0 ) ? true : false;
+ bool bDoDiffuseWarp = LIGHTWARPTEXTURE ? true : false;
+ int nNumLights = FLASHLIGHT ? 1 : NUM_LIGHTS; // Flashlight is considered one light, otherwise, use numlights combo
+
+#if !defined( SHADER_MODEL_PS_2_0 )
+ bool bRayCast = RAYTRACESPHERE ? true : false;
+ bool bRayCastTexKill = SPHERETEXKILLCOMBO ? true : false;
+#endif
+
+ float flFlashlightNDotL = i.vTangentViewVector.w;
+ float4 vFlashlightTexCoord = { 0.0f, 0.0f, 0.0f, 0.0f };
+ if ( bFlashlight )
+ {
+ vFlashlightTexCoord.xyzw = i.cVertexLight.xyzw; // This was hidden in this interpolator
+ i.cVertexLight.rgba = float4( 0.0f, 0.0f, 0.0f, 0.0f );
+ }
+
+ // Interpolated vectors
+ float3 vWorldNormal = i.vWorldNormal.xyz;
+ float3 vWorldTangent = i.vWorldTangent.xyz;
+ float3 vWorldBinormal = ( i.vWorldBinormal.xyz * 2.0f ) - 1.0f; // normalize( cross( vWorldNormal.xyz, vWorldTangent.xyz ) );
+
+ float3 vTangentViewVector = i.vTangentViewVector.xyz;
+
+ // World position
+ float3 vWorldPosition = i.vWorldPosition_ProjPosZ.xyz;
+
+ // World view vector to pixel
+ float3 vWorldViewVector = normalize( vWorldPosition.xyz - g_vCameraPosition.xyz );
+
+ //=================//
+ // TF NPR lighting //
+ //=================//
+ if ( bDoDiffuseWarp )
+ {
+ // Replace the interpolated vertex light
+ if ( bFlashlight == true )
+ {
+ // Deal with this below in the flashlight section
+ }
+ else
+ {
+ if ( nNumLights > 0 )
+ {
+ float3 cWarpedLight = 2.0f * tex1D( g_tLightwarpSampler, i.vLightFalloffCosine01.z ).rgb;
+ i.cVertexLight.rgb += i.vLightFalloffCosine01.x * PixelShaderGetLightColor( g_sLightInfo, 0 ) * cWarpedLight.rgb;
+ }
+
+ if ( nNumLights > 1 )
+ {
+ float3 cWarpedLight = 2.0f * tex1D( g_tLightwarpSampler, i.vLightFalloffCosine01.w ).rgb;
+ i.cVertexLight.rgb += i.vLightFalloffCosine01.y * PixelShaderGetLightColor( g_sLightInfo, 1 ) * cWarpedLight.rgb;
+ }
+
+ if ( nNumLights > 2 )
+ {
+ float3 cWarpedLight = 2.0f * tex1D( g_tLightwarpSampler, i.vLightFalloffCosine23.z ).rgb;
+ i.cVertexLight.rgb += i.vLightFalloffCosine23.x * PixelShaderGetLightColor( g_sLightInfo, 2 ) * cWarpedLight.rgb;
+ }
+
+ if ( nNumLights > 3 )
+ {
+ float3 cWarpedLight = 2.0f * tex1D( g_tLightwarpSampler, i.vLightFalloffCosine23.w ).rgb;
+ i.cVertexLight.rgb += i.vLightFalloffCosine23.y * PixelShaderGetLightColor( g_sLightInfo, 3 ) * cWarpedLight.rgb;
+ }
+ }
+ }
+
+ //==========================================================================================================//
+ // Ray cast against sphere representing eyeball to reduce artifacts from non-spherical morphed eye geometry //
+ //==========================================================================================================//
+#if !defined( SHADER_MODEL_PS_2_0 )
+ if ( bRayCast )
+ {
+ float fSphereRayCastDistance = IntersectRaySphere( g_vCameraPosition.xyz, vWorldViewVector.xyz, g_vEyeOrigin.xyz, g_flEyeballRadius );
+ vWorldPosition.xyz = g_vCameraPosition.xyz + ( vWorldViewVector.xyz * fSphereRayCastDistance );
+ if (fSphereRayCastDistance == 0)
+ {
+ if ( bRayCastTexKill )
+ clip(-1); // texkill to get a better silhouette
+ vWorldPosition.xyz = g_vEyeOrigin.xyz + ( vWorldNormal.xyz * g_flEyeballRadius );
+ }
+ }
+#endif
+
+ //=================================//
+ // Generate sphere and cornea uv's //
+ //=================================//
+#if !defined( SHADER_MODEL_PS_2_0 )
+ float2 vCorneaUv; // Note: Cornea texture is a cropped version of the iris texture
+ vCorneaUv.x = dot( g_vIrisProjectionU, float4( vWorldPosition, 1.0f ) );
+ vCorneaUv.y = dot( g_vIrisProjectionV, float4( vWorldPosition, 1.0f ) );
+ float2 vSphereUv = ( vCorneaUv.xy * 0.5f ) + 0.25f;
+#else // ps_20
+ float2 vCorneaUv = i.vAmbientOcclUv_fallbackCorneaUv.wz; // Note: Cornea texture is a cropped version of the iris texture
+ float2 vSphereUv = ( vCorneaUv.xy * 0.5f ) + 0.25f;
+#endif
+
+ //=================================//
+ // Hacked parallax mapping on iris //
+ //=================================//
+ float fIrisOffset = tex2D( g_tCorneaSampler, vCorneaUv.xy ).b;
+
+#if !defined( SHADER_MODEL_PS_2_0 )
+ float2 vParallaxVector = ( ( vTangentViewVector.xy * fIrisOffset * g_flParallaxStrength ) / ( 1.0f - vTangentViewVector.z ) ); // Note: 0.25 is a magic number
+ vParallaxVector.x = -vParallaxVector.x; //Need to flip x...not sure why.
+ //vParallaxVector.x *= -1.0; //Need to flip x...not sure why.
+ //vParallaxVector = 0.0f; //Disable parallax for debugging
+#else // Disable parallax effect in 2.0 version
+ float2 vParallaxVector = { 0.0f, 0.0f };
+#endif
+
+ float2 vIrisUv = vSphereUv.xy - vParallaxVector.xy;
+
+ // Note: We fetch from this texture twice right now with different uv's for the color and alpha
+ float2 vCorneaNoiseUv = vSphereUv.xy + ( vParallaxVector.xy * 0.5 );
+ float fCorneaNoise = tex2D( g_tIrisSampler, vCorneaNoiseUv.xy ).a;
+
+ //===============//
+ // Cornea normal //
+ //===============//
+ // Sample 2D normal from texture
+ float3 vCorneaTangentNormal = { 0.0, 0.0, 1.0 };
+ float4 vCorneaSample = tex2D( g_tCorneaSampler, vCorneaUv.xy );
+ vCorneaTangentNormal.xy = vCorneaSample.rg - 0.5f; // Note: This scales the bump to 50% strength
+
+ // Scale strength of normal
+ vCorneaTangentNormal.xy *= g_flCorneaBumpStrength;
+
+ // Add in surface noise and imperfections (NOTE: This should be baked into the normal map!)
+ vCorneaTangentNormal.xy += fCorneaNoise * 0.1f;
+
+ // Normalize tangent vector
+#if !defined( SHADER_MODEL_PS_2_0 )
+ // Since this isn't used later in 2.0, skip the normalize to save shader instructions
+ vCorneaTangentNormal.xyz = normalize( vCorneaTangentNormal.xyz );
+#endif
+
+ // Transform into world space
+ float3 vCorneaWorldNormal = Vec3TangentToWorldNormalized( vCorneaTangentNormal.xyz, vWorldNormal.xyz, vWorldTangent.xyz, vWorldBinormal.xyz );
+
+ //============//
+ // Flashlight //
+ //============//
+ float3 vFlashlightVector = { 0.0f, 0.0f, 0.0f };
+ float3 cFlashlightColorFalloff = { 0.0f, 0.0f, 0.0f };
+ if ( bFlashlight == true )
+ {
+ // Flashlight vector
+ vFlashlightVector.xyz = normalize( g_vFlashlightPos.xyz - i.vWorldPosition_ProjPosZ.xyz );
+
+ // Distance attenuation for flashlight and to fade out shadow over distance
+ float3 vDelta = g_vFlashlightPos.xyz - i.vWorldPosition_ProjPosZ.xyz;
+ float flDistSquared = dot( vDelta, vDelta );
+ float flDist = sqrt( flDistSquared );
+ float flFlashlightAttenuation = dot( g_vFlashlightAttenuationFactors.xyz, float3( 1.0f, 1.0f/flDist, 1.0f/flDistSquared ) );
+
+ // Flashlight cookie
+#if !defined( SHADER_MODEL_PS_2_0 )
+ float3 vProjCoords = vFlashlightTexCoord.xyz / vFlashlightTexCoord.w;
+ float3 cFlashlightCookieColor = tex2D( g_tFlashlightCookieSampler, vProjCoords );
+#else
+ float3 cFlashlightCookieColor = tex2Dproj( g_tFlashlightCookieSampler, vFlashlightTexCoord.xyzw );
+#endif
+
+ // Shadow depth map
+#if FLASHLIGHTSHADOWS && !defined( SHADER_MODEL_PS_2_0 )
+ int nShadowLevel = FLASHLIGHTDEPTHFILTERMODE;
+ float flShadow = DoFlashlightShadow( g_tFlashlightDepthSampler, g_tRandomRotationSampler, vProjCoords, float2(0,0), nShadowLevel, g_vShadowTweaks, false );
+ float flAttenuated = lerp( flShadow, 1.0f, g_vShadowTweaks.y ); // Blend between fully attenuated and not attenuated
+ flShadow = lerp( flAttenuated, flShadow, flFlashlightAttenuation ); // Blend between shadow and above, according to light attenuation
+ cFlashlightCookieColor *= flShadow; // Apply shadow term to cookie color
+#endif
+
+ // Flashlight color intensity (needs to be multiplied by global flashlight color later)
+ cFlashlightColorFalloff.rgb = flFlashlightAttenuation * cFlashlightCookieColor.rgb;
+
+ // Add this into the interpolated lighting
+ if ( bDoDiffuseWarp )
+ {
+ //float3 cWarpedLight = 2.0f * tex1D( g_tLightwarpSampler, flFlashlightNDotL ).rgb;
+ //i.cVertexLight.rgb += cFlashlightColorFalloff.rgb * cFlashlightColor.rgb * cWarpedLight.rgb;
+ i.cVertexLight.rgb += cFlashlightColorFalloff.rgb * cFlashlightColor.rgb * flFlashlightNDotL; // No light warp for now
+ }
+ else
+ {
+ i.cVertexLight.rgb += cFlashlightColorFalloff.rgb * cFlashlightColor.rgb * flFlashlightNDotL;
+ }
+ }
+
+ //==============//
+ // Dilate pupil //
+ //==============//
+#if !defined( SHADER_MODEL_PS_2_0 )
+ vIrisUv.xy -= 0.5f; // Center around (0,0)
+ float fPupilCenterToBorder = saturate( length( vIrisUv.xy ) / 0.2f ); //Note: 0.2 is the uv radius of the iris
+ float fPupilDilateFactor = g_flDilationFactor; // This value should be between 0-1
+ vIrisUv.xy *= lerp (1.0f, fPupilCenterToBorder, saturate( fPupilDilateFactor ) * 2.5f - 1.25f );
+ vIrisUv.xy += 0.5f;
+#endif
+
+ //============//
+ // Iris color //
+ //============//
+ float4 cIrisColor = tex2D( g_tIrisSampler, vIrisUv.xy );
+
+ //==========================//
+ // Iris lighting highlights //
+ //==========================//
+ float3 cIrisLighting = float3( 0.0f, 0.0f, 0.0f );
+
+#if !defined( SHADER_MODEL_PS_2_0 )
+ // Mask off everything but the iris pixels
+ float fIrisHighlightMask = tex2D( g_tCorneaSampler, vCorneaUv.xy ).a;
+
+ // Generate the normal
+ float3 vIrisTangentNormal = vCorneaTangentNormal.xyz;
+ vIrisTangentNormal.xy *= -2.5f; // I'm not normalizing on purpose
+
+ for ( int j=0; j < nNumLights; j++ )
+ {
+ // World light vector
+ float3 vWorldLightVector;
+ if ( ( j == 0 ) && ( bFlashlight == true ) )
+ vWorldLightVector = vFlashlightVector.xyz;
+ else
+ vWorldLightVector = PixelShaderGetLightVector( i.vWorldPosition_ProjPosZ.xyz, g_sLightInfo, j );
+
+ // Tangent light vector
+ float3 vTangentLightVector = Vec3WorldToTangent( vWorldLightVector.xyz, vWorldNormal.xyz, vWorldTangent.xyz, vWorldBinormal.xyz );
+
+ // Adjust the tangent light vector to generate the iris lighting
+ float3 tmpv = -vTangentLightVector.xyz;
+ tmpv.xy *= -0.5f; //Flatten tangent view
+ tmpv.z = max( tmpv.z, 0.5f ); //Clamp z of tangent view to help maintain highlight
+ tmpv.xyz = normalize( tmpv.xyz );
+
+ // Core iris lighting math
+ float fIrisFacing = pow( abs( dot( vIrisTangentNormal.xyz, tmpv.xyz ) ), 6.0f ) * 0.5f; // Yes, 6.0 and 0.5 are magic numbers
+
+ // Cone of darkness to darken iris highlights when light falls behind eyeball past a certain point
+ float flConeOfDarkness = pow( 1.0f - saturate( ( -vTangentLightVector.z - 0.25f ) / 0.75f ), 4.0f );
+ //float flConeOfDarkness = pow( 1.0f - saturate( ( -dot( vIrisTangentNormal.xyz, vTangentLightVector.xyz ) - 0.15f ) / 0.85f ), 8.0f );
+
+ // Tint by iris color and cone of darkness
+ float3 cIrisLightingTmp = fIrisFacing * fIrisHighlightMask * flConeOfDarkness;
+
+ // Attenuate by light color and light falloff
+ if ( ( j == 0 ) && ( bFlashlight == true ) )
+ cIrisLightingTmp.rgb *= cFlashlightColorFalloff.rgb * cFlashlightColor.rgb;
+ else if ( j == 0 )
+ cIrisLightingTmp.rgb *= i.vLightFalloffCosine01.x * PixelShaderGetLightColor( g_sLightInfo, 0 );
+ else if ( j == 1 )
+ cIrisLightingTmp.rgb *= i.vLightFalloffCosine01.y * PixelShaderGetLightColor( g_sLightInfo, 1 );
+ else if ( j == 2 )
+ cIrisLightingTmp.rgb *= i.vLightFalloffCosine23.x * PixelShaderGetLightColor( g_sLightInfo, 2 );
+ else
+ cIrisLightingTmp.rgb *= i.vLightFalloffCosine23.y * PixelShaderGetLightColor( g_sLightInfo, 3 );
+
+ // Sum into final variable
+ cIrisLighting.rgb += cIrisLightingTmp.rgb;
+ }
+
+ // Add slight view dependent iris lighting based on ambient light intensity to enhance situations with no local lights (0.5f is to help keep it subtle)
+ cIrisLighting.rgb += saturate( dot( vIrisTangentNormal.xyz, -vTangentViewVector.xyz ) ) * g_flAverageAmbient * fIrisHighlightMask * 0.5f;
+#else
+ // Else, intensify light over cornea to simulate the brightening that happens above
+ cIrisLighting.rgb += i.cVertexLight.rgb * vCorneaSample.a;
+#endif
+
+ //===================//
+ // Ambient occlusion //
+ //===================//
+ float3 cAmbientOcclFromTexture = tex2D( g_tEyeAmbientOcclSampler, i.vAmbientOcclUv_fallbackCorneaUv.xy ).rgb;
+ float3 cAmbientOcclColor = lerp( g_cAmbientOcclColor, 1.0f, cAmbientOcclFromTexture.rgb ); // Color the ambient occlusion
+ i.cVertexLight.rgb *= cAmbientOcclColor.rgb;
+
+ //==========================//
+ // Reflection from cube map //
+ //==========================//
+ float3 vCorneaReflectionVector = reflect ( vWorldViewVector.xyz, vCorneaWorldNormal.xyz );
+
+ //float3 cReflection = ENV_MAP_SCALE * texCUBE( g_tEyeReflectionCubemapSampler, vCorneaReflectionVector.xyz ).rgb;
+ float3 cReflection = g_flGlossiness * texCUBE( g_tEyeReflectionCubemapSampler, vCorneaReflectionVector.xyz ).rgb;
+
+ // Hack: Only add in half of the env map for the flashlight pass. This looks reasonable.
+ if ( bFlashlight )
+ {
+ cReflection.rgb *= 0.5f;
+ }
+
+ //===========================//
+ // Glint specular highlights //
+ //===========================//
+ float3 cSpecularHighlights = 0.0f;
+ if ( bFlashlight )
+ {
+ cSpecularHighlights.rgb += pow( saturate( dot( vCorneaReflectionVector.xyz, vFlashlightVector.xyz ) ), 128.0f ) * cFlashlightColorFalloff.rgb * cFlashlightColor.rgb;
+ }
+ else // no flashlight
+ {
+ if ( nNumLights > 0 )
+ cSpecularHighlights.rgb += pow( saturate( dot( vCorneaReflectionVector.xyz, PixelShaderGetLightVector( i.vWorldPosition_ProjPosZ.xyz, g_sLightInfo, 0 ) ) ), 128.0f ) * i.vLightFalloffCosine01.x * PixelShaderGetLightColor( g_sLightInfo, 0 );
+
+ if ( nNumLights > 1 )
+ cSpecularHighlights.rgb += pow( saturate( dot( vCorneaReflectionVector.xyz, PixelShaderGetLightVector( i.vWorldPosition_ProjPosZ.xyz, g_sLightInfo, 1 ) ) ), 128.0f ) * i.vLightFalloffCosine01.y * PixelShaderGetLightColor( g_sLightInfo, 1 );
+
+ if ( nNumLights > 2 )
+ cSpecularHighlights.rgb += pow( saturate( dot( vCorneaReflectionVector.xyz, PixelShaderGetLightVector( i.vWorldPosition_ProjPosZ.xyz, g_sLightInfo, 2 ) ) ), 128.0f ) * i.vLightFalloffCosine23.x * PixelShaderGetLightColor( g_sLightInfo, 2 );
+
+ if ( nNumLights > 3 )
+ cSpecularHighlights.rgb += pow( saturate( dot( vCorneaReflectionVector.xyz, PixelShaderGetLightVector( i.vWorldPosition_ProjPosZ.xyz, g_sLightInfo, 3 ) ) ), 128.0f ) * i.vLightFalloffCosine23.y * PixelShaderGetLightColor( g_sLightInfo, 3 );
+ }
+
+ //===============//
+ // Combine terms //
+ //===============//
+ float4 result;
+
+ // Unlit iris, pupil, and sclera color
+ result.rgb = cIrisColor.rgb;
+
+ // Add in slight cornea noise to help define raised cornea layer for close-ups
+ result.rgb += fCorneaNoise * 0.1f;
+
+ // Diffuse light (Vertex lighting + extra iris caustic lighting)
+ result.rgb *= i.cVertexLight.rgb + cIrisLighting.rgb;
+
+ // Environment map
+ result.rgb += cReflection.rgb * i.cVertexLight.rgb;
+
+ // Local light glints
+ result.rgb += cSpecularHighlights.rgb;
+
+ // Set alpha to 1.0 by default
+ result.a = 1.0;
+
+#if !defined( SHADER_MODEL_PS_2_0 )
+ float fogFactor = CalcPixelFogFactorConst( g_fPixelFogType, g_FogParams, g_vCameraPosition.z, i.vWorldPosition_ProjPosZ.z, i.vWorldPosition_ProjPosZ.w );
+ return FinalOutputConst( result, fogFactor, g_fPixelFogType, TONEMAP_SCALE_LINEAR );
+#else
+ float fogFactor = CalcPixelFogFactor( PIXEL_FOG_TYPE_NONE, g_FogParams, g_vCameraPosition.z, i.vWorldPosition_ProjPosZ.z, i.vWorldPosition_ProjPosZ.w );
+ return FinalOutput( result, fogFactor, PIXEL_FOG_TYPE_NONE, TONEMAP_SCALE_LINEAR );
+#endif
+
+}