Team Fortress 2 Source Code as on 22/4/2020
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.

494 lines
21 KiB

  1. //====== Copyright � 1996-2007, Valve Corporation, All rights reserved. ===========================
  2. // STATIC: "FLASHLIGHT" "0..1"
  3. // STATIC: "LIGHTWARPTEXTURE" "0..1"
  4. // STATIC: "SPHERETEXKILLCOMBO" "0..1" [ps20b]
  5. // STATIC: "SPHERETEXKILLCOMBO" "0..1" [ps30]
  6. // STATIC: "RAYTRACESPHERE" "0..1" [ps20b]
  7. // STATIC: "RAYTRACESPHERE" "0..1" [ps30]
  8. // STATIC: "FLASHLIGHTDEPTHFILTERMODE" "0..2" [ps20b] [PC]
  9. // STATIC: "FLASHLIGHTDEPTHFILTERMODE" "0..2" [ps30] [PC]
  10. // STATIC: "FLASHLIGHTDEPTHFILTERMODE" "0..0" [ps20b] [XBOX]
  11. // DYNAMIC: "NUM_LIGHTS" "0..2" [ps20]
  12. // DYNAMIC: "NUM_LIGHTS" "0..4" [ps20b]
  13. // DYNAMIC: "NUM_LIGHTS" "0..4" [ps30]
  14. // DYNAMIC: "FLASHLIGHTSHADOWS" "0..1" [ps20b]
  15. // DYNAMIC: "FLASHLIGHTSHADOWS" "0..1" [ps30]
  16. // We don't use other lights when doing the flashlight
  17. // SKIP: ( $FLASHLIGHT != 0 ) && ( $NUM_LIGHTS > 0 )
  18. // We don't care about flashlight depth unless the flashlight is on
  19. // SKIP: ( $FLASHLIGHT == 0 ) && ( $FLASHLIGHTSHADOWS == 1 ) [ps20b]
  20. // SKIP: ( $FLASHLIGHT == 0 ) && ( $FLASHLIGHTSHADOWS == 1 ) [ps30]
  21. // SKIP: ( $RAYTRACESPHERE == 0 ) && ( $SPHERETEXKILLCOMBO == 1 ) [ps30]
  22. // SKIP: ( $RAYTRACESPHERE == 0 ) && ( $SPHERETEXKILLCOMBO == 1 ) [ps20b]
  23. // Debug 2.0 shader locally
  24. //#ifdef SHADER_MODEL_PS_2_B
  25. //#undef SHADER_MODEL_PS_2_B
  26. //#define SHADER_MODEL_PS_2_0
  27. //#endif
  28. // Includes =======================================================================================
  29. #include "common_flashlight_fxc.h"
  30. #include "shader_constant_register_map.h"
  31. // Texture Samplers ===============================================================================
  32. sampler g_tCorneaSampler : register( s0 );
  33. sampler g_tIrisSampler : register( s1 );
  34. sampler g_tEyeReflectionCubemapSampler : register( s2 );
  35. sampler g_tEyeAmbientOcclSampler : register( s3 );
  36. sampler g_tLightwarpSampler : register( s4 ); // 1D texture for TF NPR lighting
  37. sampler g_tFlashlightCookieSampler : register( s5 );
  38. sampler g_tFlashlightDepthSampler : register( s6 );
  39. sampler g_tRandomRotationSampler : register( s7 );
  40. // Shaders Constants and Globals ==================================================================
  41. const float4 g_vPackedConst0 : register( c0 );
  42. #define g_flDilationFactor g_vPackedConst0.x
  43. #define g_flGlossiness g_vPackedConst0.y
  44. #define g_flAverageAmbient g_vPackedConst0.z
  45. #define g_flCorneaBumpStrength g_vPackedConst0.w
  46. const float3 g_vEyeOrigin : register( c1 );
  47. const float4 g_vIrisProjectionU : register( c2 );
  48. const float4 g_vIrisProjectionV : register( c3 );
  49. const float4 g_vCameraPosition : register( c4 );
  50. const float3 g_cAmbientOcclColor : register( c5 );
  51. const float4 g_vPackedConst6 : register( c6 );
  52. #define g_flEyeballRadius g_vPackedConst6.y //0.51f
  53. //#define g_bRaytraceSphere g_vPackedConst6.z //1.0f
  54. #define g_flParallaxStrength g_vPackedConst6.w //0.25f
  55. // Flashlight constants
  56. const float4 g_vFlashlightAttenuationFactors : register( c7 ); // FarZ in w
  57. const float3 g_vFlashlightPos : register( c8 );
  58. const float4 g_vShadowTweaks : register( c9 );
  59. const float4 g_ShaderControls : register( c10 );
  60. #define g_fPixelFogType g_ShaderControls.x
  61. const float4 g_FogParams : register( PSREG_FOG_PARAMS );
  62. PixelShaderLightInfo g_sLightInfo[3] : register( PSREG_LIGHT_INFO_ARRAY ); // 2 registers each - 6 registers total
  63. // Interpolated values ============================================================================
  64. struct PS_INPUT
  65. {
  66. float4 vAmbientOcclUv_fallbackCorneaUv : TEXCOORD0;
  67. float4 cVertexLight : TEXCOORD1; // w is used for the flashlight pass
  68. float4 vTangentViewVector : TEXCOORD2; // Tangent view vector (Note: w is used for flashlight pass)
  69. float4 vWorldPosition_ProjPosZ : TEXCOORD3;
  70. float3 vWorldNormal : TEXCOORD4; // World-space normal
  71. float3 vWorldTangent : TEXCOORD5; // World-space tangent
  72. float4 vLightFalloffCosine01 : TEXCOORD6; // Light falloff and cosine terms for first two local lights
  73. float4 vLightFalloffCosine23 : TEXCOORD7; // Light falloff and cosine terms for next two local lights
  74. float3 vWorldBinormal : COLOR0; // World-space normal
  75. };
  76. // Ray sphere intersect returns distance along ray to intersection ================================
  77. float IntersectRaySphere ( float3 cameraPos, float3 ray, float3 sphereCenter, float sphereRadius)
  78. {
  79. float3 dst = cameraPos.xyz - sphereCenter.xyz;
  80. float B = dot(dst, ray);
  81. float C = dot(dst, dst) - (sphereRadius * sphereRadius);
  82. float D = B*B - C;
  83. return (D > 0) ? (-B - sqrt(D)) : 0;
  84. }
  85. // Calculate both types of Fog and lerp to get result
  86. float CalcPixelFogFactorConst( float fPixelFogType, const float4 fogParams, const float flEyePosZ, const float flWorldPosZ, const float flProjPosZ )
  87. {
  88. float fRangeFog = CalcRangeFog( flProjPosZ, fogParams.x, fogParams.z, fogParams.w );
  89. float fHeightFog = CalcWaterFogAlpha( fogParams.y, flEyePosZ, flWorldPosZ, flProjPosZ, fogParams.w );
  90. return lerp( fRangeFog, fHeightFog, fPixelFogType );
  91. }
  92. // Blend both types of Fog and lerp to get result
  93. float3 BlendPixelFogConst( const float3 vShaderColor, float pixelFogFactor, const float3 vFogColor, float fPixelFogType )
  94. {
  95. pixelFogFactor = saturate( pixelFogFactor );
  96. float3 fRangeResult = lerp( vShaderColor.rgb, vFogColor.rgb, pixelFogFactor * pixelFogFactor ); //squaring the factor will get the middle range mixing closer to hardware fog
  97. float3 fHeightResult = lerp( vShaderColor.rgb, vFogColor.rgb, saturate( pixelFogFactor ) );
  98. return lerp( fRangeResult, fHeightResult, fPixelFogType );
  99. }
  100. float4 FinalOutputConst( const float4 vShaderColor, float pixelFogFactor, float fPixelFogType, const int iTONEMAP_SCALE_TYPE )
  101. {
  102. float4 result = vShaderColor;
  103. if( iTONEMAP_SCALE_TYPE == TONEMAP_SCALE_LINEAR )
  104. {
  105. result.rgb *= LINEAR_LIGHT_SCALE;
  106. }
  107. else if( iTONEMAP_SCALE_TYPE == TONEMAP_SCALE_GAMMA )
  108. {
  109. result.rgb *= GAMMA_LIGHT_SCALE;
  110. }
  111. result.rgb = BlendPixelFogConst( result.rgb, pixelFogFactor, g_LinearFogColor.rgb, fPixelFogType );
  112. result.rgb = SRGBOutput( result.rgb ); //SRGB in pixel shader conversion
  113. return result;
  114. }
  115. // Main ===========================================================================================
  116. float4 main( PS_INPUT i ) : COLOR
  117. {
  118. // Set bools to compile out code
  119. bool bFlashlight = ( FLASHLIGHT != 0 ) ? true : false;
  120. bool bDoDiffuseWarp = LIGHTWARPTEXTURE ? true : false;
  121. int nNumLights = FLASHLIGHT ? 1 : NUM_LIGHTS; // Flashlight is considered one light, otherwise, use numlights combo
  122. #if !defined( SHADER_MODEL_PS_2_0 )
  123. bool bRayCast = RAYTRACESPHERE ? true : false;
  124. bool bRayCastTexKill = SPHERETEXKILLCOMBO ? true : false;
  125. #endif
  126. float flFlashlightNDotL = i.vTangentViewVector.w;
  127. float4 vFlashlightTexCoord = { 0.0f, 0.0f, 0.0f, 0.0f };
  128. if ( bFlashlight )
  129. {
  130. vFlashlightTexCoord.xyzw = i.cVertexLight.xyzw; // This was hidden in this interpolator
  131. i.cVertexLight.rgba = float4( 0.0f, 0.0f, 0.0f, 0.0f );
  132. }
  133. // Interpolated vectors
  134. float3 vWorldNormal = i.vWorldNormal.xyz;
  135. float3 vWorldTangent = i.vWorldTangent.xyz;
  136. float3 vWorldBinormal = ( i.vWorldBinormal.xyz * 2.0f ) - 1.0f; // normalize( cross( vWorldNormal.xyz, vWorldTangent.xyz ) );
  137. float3 vTangentViewVector = i.vTangentViewVector.xyz;
  138. // World position
  139. float3 vWorldPosition = i.vWorldPosition_ProjPosZ.xyz;
  140. // World view vector to pixel
  141. float3 vWorldViewVector = normalize( vWorldPosition.xyz - g_vCameraPosition.xyz );
  142. //=================//
  143. // TF NPR lighting //
  144. //=================//
  145. if ( bDoDiffuseWarp )
  146. {
  147. // Replace the interpolated vertex light
  148. if ( bFlashlight == true )
  149. {
  150. // Deal with this below in the flashlight section
  151. }
  152. else
  153. {
  154. if ( nNumLights > 0 )
  155. {
  156. float3 cWarpedLight = 2.0f * tex1D( g_tLightwarpSampler, i.vLightFalloffCosine01.z ).rgb;
  157. i.cVertexLight.rgb += i.vLightFalloffCosine01.x * PixelShaderGetLightColor( g_sLightInfo, 0 ) * cWarpedLight.rgb;
  158. }
  159. if ( nNumLights > 1 )
  160. {
  161. float3 cWarpedLight = 2.0f * tex1D( g_tLightwarpSampler, i.vLightFalloffCosine01.w ).rgb;
  162. i.cVertexLight.rgb += i.vLightFalloffCosine01.y * PixelShaderGetLightColor( g_sLightInfo, 1 ) * cWarpedLight.rgb;
  163. }
  164. if ( nNumLights > 2 )
  165. {
  166. float3 cWarpedLight = 2.0f * tex1D( g_tLightwarpSampler, i.vLightFalloffCosine23.z ).rgb;
  167. i.cVertexLight.rgb += i.vLightFalloffCosine23.x * PixelShaderGetLightColor( g_sLightInfo, 2 ) * cWarpedLight.rgb;
  168. }
  169. if ( nNumLights > 3 )
  170. {
  171. float3 cWarpedLight = 2.0f * tex1D( g_tLightwarpSampler, i.vLightFalloffCosine23.w ).rgb;
  172. i.cVertexLight.rgb += i.vLightFalloffCosine23.y * PixelShaderGetLightColor( g_sLightInfo, 3 ) * cWarpedLight.rgb;
  173. }
  174. }
  175. }
  176. //==========================================================================================================//
  177. // Ray cast against sphere representing eyeball to reduce artifacts from non-spherical morphed eye geometry //
  178. //==========================================================================================================//
  179. #if !defined( SHADER_MODEL_PS_2_0 )
  180. if ( bRayCast )
  181. {
  182. float fSphereRayCastDistance = IntersectRaySphere( g_vCameraPosition.xyz, vWorldViewVector.xyz, g_vEyeOrigin.xyz, g_flEyeballRadius );
  183. vWorldPosition.xyz = g_vCameraPosition.xyz + ( vWorldViewVector.xyz * fSphereRayCastDistance );
  184. if (fSphereRayCastDistance == 0)
  185. {
  186. if ( bRayCastTexKill )
  187. clip(-1); // texkill to get a better silhouette
  188. vWorldPosition.xyz = g_vEyeOrigin.xyz + ( vWorldNormal.xyz * g_flEyeballRadius );
  189. }
  190. }
  191. #endif
  192. //=================================//
  193. // Generate sphere and cornea uv's //
  194. //=================================//
  195. #if !defined( SHADER_MODEL_PS_2_0 )
  196. float2 vCorneaUv; // Note: Cornea texture is a cropped version of the iris texture
  197. vCorneaUv.x = dot( g_vIrisProjectionU, float4( vWorldPosition, 1.0f ) );
  198. vCorneaUv.y = dot( g_vIrisProjectionV, float4( vWorldPosition, 1.0f ) );
  199. float2 vSphereUv = ( vCorneaUv.xy * 0.5f ) + 0.25f;
  200. #else // ps_20
  201. float2 vCorneaUv = i.vAmbientOcclUv_fallbackCorneaUv.wz; // Note: Cornea texture is a cropped version of the iris texture
  202. float2 vSphereUv = ( vCorneaUv.xy * 0.5f ) + 0.25f;
  203. #endif
  204. //=================================//
  205. // Hacked parallax mapping on iris //
  206. //=================================//
  207. float fIrisOffset = tex2D( g_tCorneaSampler, vCorneaUv.xy ).b;
  208. #if !defined( SHADER_MODEL_PS_2_0 )
  209. float2 vParallaxVector = ( ( vTangentViewVector.xy * fIrisOffset * g_flParallaxStrength ) / ( 1.0f - vTangentViewVector.z ) ); // Note: 0.25 is a magic number
  210. vParallaxVector.x = -vParallaxVector.x; //Need to flip x...not sure why.
  211. //vParallaxVector.x *= -1.0; //Need to flip x...not sure why.
  212. //vParallaxVector = 0.0f; //Disable parallax for debugging
  213. #else // Disable parallax effect in 2.0 version
  214. float2 vParallaxVector = { 0.0f, 0.0f };
  215. #endif
  216. float2 vIrisUv = vSphereUv.xy - vParallaxVector.xy;
  217. // Note: We fetch from this texture twice right now with different uv's for the color and alpha
  218. float2 vCorneaNoiseUv = vSphereUv.xy + ( vParallaxVector.xy * 0.5 );
  219. float fCorneaNoise = tex2D( g_tIrisSampler, vCorneaNoiseUv.xy ).a;
  220. //===============//
  221. // Cornea normal //
  222. //===============//
  223. // Sample 2D normal from texture
  224. float3 vCorneaTangentNormal = { 0.0, 0.0, 1.0 };
  225. float4 vCorneaSample = tex2D( g_tCorneaSampler, vCorneaUv.xy );
  226. vCorneaTangentNormal.xy = vCorneaSample.rg - 0.5f; // Note: This scales the bump to 50% strength
  227. // Scale strength of normal
  228. vCorneaTangentNormal.xy *= g_flCorneaBumpStrength;
  229. // Add in surface noise and imperfections (NOTE: This should be baked into the normal map!)
  230. vCorneaTangentNormal.xy += fCorneaNoise * 0.1f;
  231. // Normalize tangent vector
  232. #if !defined( SHADER_MODEL_PS_2_0 )
  233. // Since this isn't used later in 2.0, skip the normalize to save shader instructions
  234. vCorneaTangentNormal.xyz = normalize( vCorneaTangentNormal.xyz );
  235. #endif
  236. // Transform into world space
  237. float3 vCorneaWorldNormal = Vec3TangentToWorldNormalized( vCorneaTangentNormal.xyz, vWorldNormal.xyz, vWorldTangent.xyz, vWorldBinormal.xyz );
  238. //============//
  239. // Flashlight //
  240. //============//
  241. float3 vFlashlightVector = { 0.0f, 0.0f, 0.0f };
  242. float3 cFlashlightColorFalloff = { 0.0f, 0.0f, 0.0f };
  243. if ( bFlashlight == true )
  244. {
  245. // Flashlight vector
  246. vFlashlightVector.xyz = normalize( g_vFlashlightPos.xyz - i.vWorldPosition_ProjPosZ.xyz );
  247. // Distance attenuation for flashlight and to fade out shadow over distance
  248. float3 vDelta = g_vFlashlightPos.xyz - i.vWorldPosition_ProjPosZ.xyz;
  249. float flDistSquared = dot( vDelta, vDelta );
  250. float flDist = sqrt( flDistSquared );
  251. float flFlashlightAttenuation = dot( g_vFlashlightAttenuationFactors.xyz, float3( 1.0f, 1.0f/flDist, 1.0f/flDistSquared ) );
  252. // Flashlight cookie
  253. #if !defined( SHADER_MODEL_PS_2_0 )
  254. float3 vProjCoords = vFlashlightTexCoord.xyz / vFlashlightTexCoord.w;
  255. float3 cFlashlightCookieColor = tex2D( g_tFlashlightCookieSampler, vProjCoords );
  256. #else
  257. float3 cFlashlightCookieColor = tex2Dproj( g_tFlashlightCookieSampler, vFlashlightTexCoord.xyzw );
  258. #endif
  259. // Shadow depth map
  260. #if FLASHLIGHTSHADOWS && !defined( SHADER_MODEL_PS_2_0 )
  261. int nShadowLevel = FLASHLIGHTDEPTHFILTERMODE;
  262. float flShadow = DoFlashlightShadow( g_tFlashlightDepthSampler, g_tRandomRotationSampler, vProjCoords, float2(0,0), nShadowLevel, g_vShadowTweaks, false );
  263. float flAttenuated = lerp( flShadow, 1.0f, g_vShadowTweaks.y ); // Blend between fully attenuated and not attenuated
  264. flShadow = lerp( flAttenuated, flShadow, flFlashlightAttenuation ); // Blend between shadow and above, according to light attenuation
  265. cFlashlightCookieColor *= flShadow; // Apply shadow term to cookie color
  266. #endif
  267. // Flashlight color intensity (needs to be multiplied by global flashlight color later)
  268. cFlashlightColorFalloff.rgb = flFlashlightAttenuation * cFlashlightCookieColor.rgb;
  269. // Add this into the interpolated lighting
  270. if ( bDoDiffuseWarp )
  271. {
  272. //float3 cWarpedLight = 2.0f * tex1D( g_tLightwarpSampler, flFlashlightNDotL ).rgb;
  273. //i.cVertexLight.rgb += cFlashlightColorFalloff.rgb * cFlashlightColor.rgb * cWarpedLight.rgb;
  274. i.cVertexLight.rgb += cFlashlightColorFalloff.rgb * cFlashlightColor.rgb * flFlashlightNDotL; // No light warp for now
  275. }
  276. else
  277. {
  278. i.cVertexLight.rgb += cFlashlightColorFalloff.rgb * cFlashlightColor.rgb * flFlashlightNDotL;
  279. }
  280. }
  281. //==============//
  282. // Dilate pupil //
  283. //==============//
  284. #if !defined( SHADER_MODEL_PS_2_0 )
  285. vIrisUv.xy -= 0.5f; // Center around (0,0)
  286. float fPupilCenterToBorder = saturate( length( vIrisUv.xy ) / 0.2f ); //Note: 0.2 is the uv radius of the iris
  287. float fPupilDilateFactor = g_flDilationFactor; // This value should be between 0-1
  288. vIrisUv.xy *= lerp (1.0f, fPupilCenterToBorder, saturate( fPupilDilateFactor ) * 2.5f - 1.25f );
  289. vIrisUv.xy += 0.5f;
  290. #endif
  291. //============//
  292. // Iris color //
  293. //============//
  294. float4 cIrisColor = tex2D( g_tIrisSampler, vIrisUv.xy );
  295. //==========================//
  296. // Iris lighting highlights //
  297. //==========================//
  298. float3 cIrisLighting = float3( 0.0f, 0.0f, 0.0f );
  299. #if !defined( SHADER_MODEL_PS_2_0 )
  300. // Mask off everything but the iris pixels
  301. float fIrisHighlightMask = tex2D( g_tCorneaSampler, vCorneaUv.xy ).a;
  302. // Generate the normal
  303. float3 vIrisTangentNormal = vCorneaTangentNormal.xyz;
  304. vIrisTangentNormal.xy *= -2.5f; // I'm not normalizing on purpose
  305. for ( int j=0; j < nNumLights; j++ )
  306. {
  307. // World light vector
  308. float3 vWorldLightVector;
  309. if ( ( j == 0 ) && ( bFlashlight == true ) )
  310. vWorldLightVector = vFlashlightVector.xyz;
  311. else
  312. vWorldLightVector = PixelShaderGetLightVector( i.vWorldPosition_ProjPosZ.xyz, g_sLightInfo, j );
  313. // Tangent light vector
  314. float3 vTangentLightVector = Vec3WorldToTangent( vWorldLightVector.xyz, vWorldNormal.xyz, vWorldTangent.xyz, vWorldBinormal.xyz );
  315. // Adjust the tangent light vector to generate the iris lighting
  316. float3 tmpv = -vTangentLightVector.xyz;
  317. tmpv.xy *= -0.5f; //Flatten tangent view
  318. tmpv.z = max( tmpv.z, 0.5f ); //Clamp z of tangent view to help maintain highlight
  319. tmpv.xyz = normalize( tmpv.xyz );
  320. // Core iris lighting math
  321. float fIrisFacing = pow( abs( dot( vIrisTangentNormal.xyz, tmpv.xyz ) ), 6.0f ) * 0.5f; // Yes, 6.0 and 0.5 are magic numbers
  322. // Cone of darkness to darken iris highlights when light falls behind eyeball past a certain point
  323. float flConeOfDarkness = pow( 1.0f - saturate( ( -vTangentLightVector.z - 0.25f ) / 0.75f ), 4.0f );
  324. //float flConeOfDarkness = pow( 1.0f - saturate( ( -dot( vIrisTangentNormal.xyz, vTangentLightVector.xyz ) - 0.15f ) / 0.85f ), 8.0f );
  325. // Tint by iris color and cone of darkness
  326. float3 cIrisLightingTmp = fIrisFacing * fIrisHighlightMask * flConeOfDarkness;
  327. // Attenuate by light color and light falloff
  328. if ( ( j == 0 ) && ( bFlashlight == true ) )
  329. cIrisLightingTmp.rgb *= cFlashlightColorFalloff.rgb * cFlashlightColor.rgb;
  330. else if ( j == 0 )
  331. cIrisLightingTmp.rgb *= i.vLightFalloffCosine01.x * PixelShaderGetLightColor( g_sLightInfo, 0 );
  332. else if ( j == 1 )
  333. cIrisLightingTmp.rgb *= i.vLightFalloffCosine01.y * PixelShaderGetLightColor( g_sLightInfo, 1 );
  334. else if ( j == 2 )
  335. cIrisLightingTmp.rgb *= i.vLightFalloffCosine23.x * PixelShaderGetLightColor( g_sLightInfo, 2 );
  336. else
  337. cIrisLightingTmp.rgb *= i.vLightFalloffCosine23.y * PixelShaderGetLightColor( g_sLightInfo, 3 );
  338. // Sum into final variable
  339. cIrisLighting.rgb += cIrisLightingTmp.rgb;
  340. }
  341. // 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)
  342. cIrisLighting.rgb += saturate( dot( vIrisTangentNormal.xyz, -vTangentViewVector.xyz ) ) * g_flAverageAmbient * fIrisHighlightMask * 0.5f;
  343. #else
  344. // Else, intensify light over cornea to simulate the brightening that happens above
  345. cIrisLighting.rgb += i.cVertexLight.rgb * vCorneaSample.a;
  346. #endif
  347. //===================//
  348. // Ambient occlusion //
  349. //===================//
  350. float3 cAmbientOcclFromTexture = tex2D( g_tEyeAmbientOcclSampler, i.vAmbientOcclUv_fallbackCorneaUv.xy ).rgb;
  351. float3 cAmbientOcclColor = lerp( g_cAmbientOcclColor, 1.0f, cAmbientOcclFromTexture.rgb ); // Color the ambient occlusion
  352. i.cVertexLight.rgb *= cAmbientOcclColor.rgb;
  353. //==========================//
  354. // Reflection from cube map //
  355. //==========================//
  356. float3 vCorneaReflectionVector = reflect ( vWorldViewVector.xyz, vCorneaWorldNormal.xyz );
  357. //float3 cReflection = ENV_MAP_SCALE * texCUBE( g_tEyeReflectionCubemapSampler, vCorneaReflectionVector.xyz ).rgb;
  358. float3 cReflection = g_flGlossiness * texCUBE( g_tEyeReflectionCubemapSampler, vCorneaReflectionVector.xyz ).rgb;
  359. // Hack: Only add in half of the env map for the flashlight pass. This looks reasonable.
  360. if ( bFlashlight )
  361. {
  362. cReflection.rgb *= 0.5f;
  363. }
  364. //===========================//
  365. // Glint specular highlights //
  366. //===========================//
  367. float3 cSpecularHighlights = 0.0f;
  368. if ( bFlashlight )
  369. {
  370. cSpecularHighlights.rgb += pow( saturate( dot( vCorneaReflectionVector.xyz, vFlashlightVector.xyz ) ), 128.0f ) * cFlashlightColorFalloff.rgb * cFlashlightColor.rgb;
  371. }
  372. else // no flashlight
  373. {
  374. if ( nNumLights > 0 )
  375. cSpecularHighlights.rgb += pow( saturate( dot( vCorneaReflectionVector.xyz, PixelShaderGetLightVector( i.vWorldPosition_ProjPosZ.xyz, g_sLightInfo, 0 ) ) ), 128.0f ) * i.vLightFalloffCosine01.x * PixelShaderGetLightColor( g_sLightInfo, 0 );
  376. if ( nNumLights > 1 )
  377. cSpecularHighlights.rgb += pow( saturate( dot( vCorneaReflectionVector.xyz, PixelShaderGetLightVector( i.vWorldPosition_ProjPosZ.xyz, g_sLightInfo, 1 ) ) ), 128.0f ) * i.vLightFalloffCosine01.y * PixelShaderGetLightColor( g_sLightInfo, 1 );
  378. if ( nNumLights > 2 )
  379. cSpecularHighlights.rgb += pow( saturate( dot( vCorneaReflectionVector.xyz, PixelShaderGetLightVector( i.vWorldPosition_ProjPosZ.xyz, g_sLightInfo, 2 ) ) ), 128.0f ) * i.vLightFalloffCosine23.x * PixelShaderGetLightColor( g_sLightInfo, 2 );
  380. if ( nNumLights > 3 )
  381. cSpecularHighlights.rgb += pow( saturate( dot( vCorneaReflectionVector.xyz, PixelShaderGetLightVector( i.vWorldPosition_ProjPosZ.xyz, g_sLightInfo, 3 ) ) ), 128.0f ) * i.vLightFalloffCosine23.y * PixelShaderGetLightColor( g_sLightInfo, 3 );
  382. }
  383. //===============//
  384. // Combine terms //
  385. //===============//
  386. float4 result;
  387. // Unlit iris, pupil, and sclera color
  388. result.rgb = cIrisColor.rgb;
  389. // Add in slight cornea noise to help define raised cornea layer for close-ups
  390. result.rgb += fCorneaNoise * 0.1f;
  391. // Diffuse light (Vertex lighting + extra iris caustic lighting)
  392. result.rgb *= i.cVertexLight.rgb + cIrisLighting.rgb;
  393. // Environment map
  394. result.rgb += cReflection.rgb * i.cVertexLight.rgb;
  395. // Local light glints
  396. result.rgb += cSpecularHighlights.rgb;
  397. // Set alpha to 1.0 by default
  398. result.a = 1.0;
  399. #if !defined( SHADER_MODEL_PS_2_0 )
  400. float fogFactor = CalcPixelFogFactorConst( g_fPixelFogType, g_FogParams, g_vCameraPosition.z, i.vWorldPosition_ProjPosZ.z, i.vWorldPosition_ProjPosZ.w );
  401. return FinalOutputConst( result, fogFactor, g_fPixelFogType, TONEMAP_SCALE_LINEAR );
  402. #else
  403. float fogFactor = CalcPixelFogFactor( PIXEL_FOG_TYPE_NONE, g_FogParams, g_vCameraPosition.z, i.vWorldPosition_ProjPosZ.z, i.vWorldPosition_ProjPosZ.w );
  404. return FinalOutput( result, fogFactor, PIXEL_FOG_TYPE_NONE, TONEMAP_SCALE_LINEAR );
  405. #endif
  406. }