Counter Strike : Global Offensive Source Code
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.

512 lines
22 KiB

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