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.

301 lines
13 KiB

  1. //========== Copyright (c) Valve Corporation, All rights reserved. ==========//
  2. // X360 and PS3 cascaded shadow mapping
  3. // 7LS TODO - PS3
  4. #if defined(_X360)
  5. float CSMSampleShadowBuffer360Simple( sampler DepthSampler, const float3 vProjCoords )
  6. {
  7. float fLOD;
  8. float2 shadowMapCenter = vProjCoords.xy; // Center of shadow filter
  9. float objDepth = min( vProjCoords.z, 0.99999 ); // Object depth in shadow space
  10. // TODO: why doesn't the reverse depth path work with CSM's here since CPU side is set to flip z
  11. //#if defined( REVERSE_DEPTH_ON_X360 )
  12. // objDepth = 1.0f - objDepth;
  13. //#endif
  14. float4 vSampledDepths, vWeights;
  15. asm
  16. {
  17. tfetch2D vSampledDepths.x___, shadowMapCenter, DepthSampler, OffsetX = -0.5, OffsetY = -0.5, UseComputedLOD=false, UseRegisterLOD=false, MagFilter = point, MinFilter = point
  18. tfetch2D vSampledDepths._x__, shadowMapCenter, DepthSampler, OffsetX = 0.5, OffsetY = -0.5, UseComputedLOD=false, UseRegisterLOD=false, MagFilter = point, MinFilter = point
  19. tfetch2D vSampledDepths.__x_, shadowMapCenter, DepthSampler, OffsetX = -0.5, OffsetY = 0.5, UseComputedLOD=false, UseRegisterLOD=false, MagFilter = point, MinFilter = point
  20. tfetch2D vSampledDepths.___x, shadowMapCenter, DepthSampler, OffsetX = 0.5, OffsetY = 0.5, UseComputedLOD=false, UseRegisterLOD=false, MagFilter = point, MinFilter = point
  21. };
  22. asm
  23. {
  24. getWeights2D vWeights, shadowMapCenter.xy, DepthSampler, MagFilter=linear, MinFilter=linear, UseComputedLOD=false, UseRegisterLOD=false
  25. };
  26. vWeights = float4( (1-vWeights.x)*(1-vWeights.y), vWeights.x*(1-vWeights.y), (1-vWeights.x)*vWeights.y, vWeights.x*vWeights.y );
  27. //#if defined( REVERSE_DEPTH_ON_X360 )
  28. // float4 vCompare = (vSampledDepths < objDepth.xxxx);
  29. //#else
  30. float4 vCompare = (vSampledDepths > objDepth.xxxx);
  31. //#endif
  32. return 1.0f - dot( vCompare, vWeights );
  33. }
  34. float CSMSampleShadowBuffer3604x4( sampler DepthSampler, const float3 vProjCoords )
  35. {
  36. float2 vShadowMapCenter = vProjCoords.xy + float2( .5f / 1408.0f, .5f / 1408.0f ); // Center of shadow filter
  37. // This shader assumes REVERSE_DEPTH_ON_X360 is always defined.
  38. // TODO: why doesn't the reverse depth path work on CSM's since CPU code is set to flip z
  39. //float flObjDepth = 1.0f - min( vProjCoords.z, 0.99999f ); // Object depth in shadow space
  40. float flObjDepth = min( vProjCoords.z, 0.99999f ); // Object depth in shadow space
  41. // projective distance from z plane in view coords
  42. float4 vDist4 = float4( flObjDepth, flObjDepth, flObjDepth, flObjDepth );
  43. //fraction component of projected coordinates; here FLASHLIGHT_SHADOW_TEXTURE_RESOLUTION represents the shadowmap size
  44. float2 vTexRes = float2( 1408.0f, 1408.0f );
  45. float2 vFrac = frac( vShadowMapCenter * vTexRes );
  46. float4 vWeights = float4( vFrac.x, vFrac.y, 1.0f - vFrac.x, 1.0f - vFrac.y );
  47. float flPercentInLight;
  48. [isolate]
  49. {
  50. float4 vShadowMapVals, vInLight;
  51. asm
  52. {
  53. tfetch2D vShadowMapVals.x___, vShadowMapCenter, DepthSampler, OffsetX = -1.0, OffsetY = -2.0, UseComputedLOD=false, UseRegisterLOD=false, MagFilter = point, MinFilter = point
  54. tfetch2D vShadowMapVals._x__, vShadowMapCenter, DepthSampler, OffsetX = -2.0, OffsetY = -1.0, UseComputedLOD=false, UseRegisterLOD=false, MagFilter = point, MinFilter = point
  55. tfetch2D vShadowMapVals.__x_, vShadowMapCenter, DepthSampler, OffsetX = -1.0, OffsetY = -1.0, UseComputedLOD=false, UseRegisterLOD=false, MagFilter = point, MinFilter = point
  56. tfetch2D vShadowMapVals.___x, vShadowMapCenter, DepthSampler, OffsetX = -2.0, OffsetY = -2.0, UseComputedLOD=false, UseRegisterLOD=false, MagFilter = point, MinFilter = point
  57. sgt vInLight, vShadowMapVals, vDist4
  58. };
  59. //7LS flipped z sub for above sgt args
  60. //sgt vInLight, vDist4, vShadowMapVals
  61. float4 vShadowMapWeights = float4( vWeights.w, vWeights.z, 1, vWeights.z * vWeights.w );
  62. flPercentInLight = dot( vInLight, vShadowMapWeights );
  63. }
  64. [isolate]
  65. {
  66. float4 vShadowMapVals, vInLight;
  67. asm
  68. {
  69. tfetch2D vShadowMapVals.x___, vShadowMapCenter, DepthSampler, OffsetX = 1.0, OffsetY = -2.0, UseComputedLOD=false, UseRegisterLOD=false, MagFilter = point, MinFilter = point
  70. tfetch2D vShadowMapVals._x__, vShadowMapCenter, DepthSampler, OffsetX = 0.0, OffsetY = -1.0, UseComputedLOD=false, UseRegisterLOD=false, MagFilter = point, MinFilter = point
  71. tfetch2D vShadowMapVals.__x_, vShadowMapCenter, DepthSampler, OffsetX = 1.0, OffsetY = -1.0, UseComputedLOD=false, UseRegisterLOD=false, MagFilter = point, MinFilter = point
  72. tfetch2D vShadowMapVals.___x, vShadowMapCenter, DepthSampler, OffsetX = 0.0, OffsetY = -2.0, UseComputedLOD=false, UseRegisterLOD=false, MagFilter = point, MinFilter = point
  73. sgt vInLight, vShadowMapVals, vDist4
  74. };
  75. float4 vShadowMapWeights = float4( vWeights.x * vWeights.w, 1, vWeights.x, vWeights.w );
  76. flPercentInLight += dot( vInLight, vShadowMapWeights );
  77. }
  78. [isolate]
  79. {
  80. float4 vShadowMapVals, vInLight;
  81. asm
  82. {
  83. tfetch2D vShadowMapVals.x___, vShadowMapCenter, DepthSampler, OffsetX = -1.0, OffsetY = 0.0, UseComputedLOD=false, UseRegisterLOD=false, MagFilter = point, MinFilter = point
  84. tfetch2D vShadowMapVals._x__, vShadowMapCenter, DepthSampler, OffsetX = -2.0, OffsetY = 1.0, UseComputedLOD=false, UseRegisterLOD=false, MagFilter = point, MinFilter = point
  85. tfetch2D vShadowMapVals.__x_, vShadowMapCenter, DepthSampler, OffsetX = -1.0, OffsetY = 1.0, UseComputedLOD=false, UseRegisterLOD=false, MagFilter = point, MinFilter = point
  86. tfetch2D vShadowMapVals.___x, vShadowMapCenter, DepthSampler, OffsetX = -2.0, OffsetY = 0.0, UseComputedLOD=false, UseRegisterLOD=false, MagFilter = point, MinFilter = point
  87. sgt vInLight, vShadowMapVals, vDist4
  88. };
  89. float4 vShadowMapWeights = float4( 1, vWeights.z * vWeights.y, vWeights.y, vWeights.z );
  90. flPercentInLight += dot( vInLight, vShadowMapWeights );
  91. }
  92. [isolate]
  93. {
  94. float4 vShadowMapVals, vInLight;
  95. asm
  96. {
  97. tfetch2D vShadowMapVals.x___, vShadowMapCenter, DepthSampler, OffsetX = 1.0, OffsetY = 0.0, UseComputedLOD=false, UseRegisterLOD=false, MagFilter = point, MinFilter = point
  98. tfetch2D vShadowMapVals._x__, vShadowMapCenter, DepthSampler, OffsetX = 0.0, OffsetY = 1.0, UseComputedLOD=false, UseRegisterLOD=false, MagFilter = point, MinFilter = point
  99. tfetch2D vShadowMapVals.__x_, vShadowMapCenter, DepthSampler, OffsetX = 1.0, OffsetY = 1.0, UseComputedLOD=false, UseRegisterLOD=false, MagFilter = point, MinFilter = point
  100. tfetch2D vShadowMapVals.___x, vShadowMapCenter, DepthSampler, OffsetX = 0.0, OffsetY = 0.0, UseComputedLOD=false, UseRegisterLOD=false, MagFilter = point, MinFilter = point
  101. sgt vInLight, vShadowMapVals, vDist4
  102. };
  103. float4 vShadowMapWeights = float4( vWeights.x, vWeights.y, vWeights.x * vWeights.y, 1 );
  104. flPercentInLight += dot( vInLight, vShadowMapWeights );
  105. }
  106. //sum of weights is 9 since border taps are bilinearly filtered
  107. return 1.0f - (( 1.0f / 9.0f ) * flPercentInLight);
  108. }
  109. #elif defined(_PS3)
  110. // keep this in sync with c_env_cascade_light.cpp
  111. #define CASCADE_RESOLUTION 768
  112. // 1 2 1
  113. // 2 4 2
  114. // 1 2 1
  115. // Tweaked for good code gen with the SCE Cg compiler.
  116. half CSMSampleShadowBufferPS33x3( sampler DepthSampler, const float3 shadowMapPos )
  117. {
  118. float fTexelEpsilon = 1.0f / CASCADE_RESOLUTION;
  119. float3 shadowMapCenter_objDepth = shadowMapPos.xyz;
  120. float3 shadowMapCenter = shadowMapCenter_objDepth.xyz; // Center of shadow filter
  121. float4 vUV0 = shadowMapCenter.xyzx + float4( fTexelEpsilon, fTexelEpsilon, 0.0f, -fTexelEpsilon );
  122. float4 vUV1 = shadowMapCenter.xyzx + float4( fTexelEpsilon, -fTexelEpsilon, 0.0f, -fTexelEpsilon );
  123. half4 vOneTaps;
  124. vOneTaps.x = h4tex2D( DepthSampler, vUV0.xyz ).x;
  125. vOneTaps.y = h4tex2D( DepthSampler, vUV0.wyz ).y;
  126. vOneTaps.z = h4tex2D( DepthSampler, vUV1.xyz ).z;
  127. vOneTaps.w = h4tex2D( DepthSampler, vUV1.wyz ).w;
  128. half flSum = dot( vOneTaps, half4(1.0f, 1.0f, 1.0f, 1.0f));
  129. float4 vUV2 = shadowMapCenter.xyzx + float4( fTexelEpsilon, 0.0f, 0.0f, -fTexelEpsilon );
  130. float4 vUV3 = shadowMapCenter.xyzy + float4( 0.0f, -fTexelEpsilon, 0.0f, fTexelEpsilon );
  131. half4 vTwoTaps;
  132. vTwoTaps.x = h4tex2D( DepthSampler, vUV2.xyz ).x;
  133. vTwoTaps.y = h4tex2D( DepthSampler, vUV2.wyz ).y;
  134. vTwoTaps.z = h4tex2D( DepthSampler, vUV3.xyz ).z;
  135. vTwoTaps.w = h4tex2D( DepthSampler, vUV3.xwz ).w;
  136. flSum += dot( vTwoTaps, half4(2.0f, 2.0f, 2.0f, 2.0f));
  137. flSum += tex2D( DepthSampler, shadowMapCenter ).x * half(4.0f);
  138. // Sum all 9 Taps
  139. return flSum * (1.0h / 16.0h);
  140. }
  141. #else
  142. #error Unsupported
  143. #endif // #elif defined(_PS3)
  144. float CSMSampleShadowBuffer1Tap( float2 vPositionLs, float flComparisonDepth )
  145. {
  146. #if defined(_X360)
  147. #if (CSM_VIEWMODELQUALITY == 0)
  148. return CSMSampleShadowBuffer360Simple( CSMDepthAtlasSampler, float3( vPositionLs.x, vPositionLs.y, flComparisonDepth ) );
  149. #else
  150. return CSMSampleShadowBuffer3604x4( CSMDepthAtlasSampler, float3( vPositionLs.x, vPositionLs.y, flComparisonDepth ) );
  151. #endif
  152. #elif defined(_PS3)
  153. #if (CSM_VIEWMODELQUALITY == 0)
  154. return tex2Dproj( CSMDepthAtlasSampler, float4( vPositionLs.x, vPositionLs.y, flComparisonDepth.x, 1.0f ) );
  155. #else
  156. return CSMSampleShadowBufferPS33x3( CSMDepthAtlasSampler, float3( vPositionLs.x, vPositionLs.y, flComparisonDepth ) );
  157. #endif
  158. #else
  159. #error Unsupported
  160. #endif
  161. }
  162. float CSMSampleShadowBuffer( float2 vPositionLs, float flComparisonDepth )
  163. {
  164. return CSMSampleShadowBuffer1Tap( vPositionLs, flComparisonDepth );
  165. }
  166. int CSMRangeTestExpanded( float2 vCoords )
  167. {
  168. // Returns true if the coordinates are within [.02,.98] - purposely a little sloppy to prevent the shadow filter kernel from leaking outside the cascade's portion of the atlas.
  169. vCoords = vCoords * ( 1.0f / .96f ) - float2( .02f / .96f, .02f / .96f );
  170. return ( dot( saturate( vCoords.xy ) - vCoords.xy, float2( 1, 1 ) ) == 0.0f );
  171. }
  172. int CSMRangeTestNonExpanded( float2 vCoords )
  173. {
  174. return ( dot( saturate( vCoords.xy ) - vCoords.xy, float2( 1, 1 ) ) == 0.0f );
  175. }
  176. float CSMComputeSplitLerpFactor( float2 vPositionToSampleLs )
  177. {
  178. float2 vSplitLerpFactorTemp = float2( 1.0f, 1.0f ) - saturate( ( abs( vPositionToSampleLs.xy - float2( .5f, .5f ) ) - float2( g_flSunShadowingSplitLerpFactorBase, g_flSunShadowingSplitLerpFactorBase ) ) * float2( g_flSunShadowingSplitLerpFactorInvRange, g_flSunShadowingSplitLerpFactorInvRange ) );
  179. return vSplitLerpFactorTemp.x * vSplitLerpFactorTemp.y;
  180. }
  181. float4 CSMTransformLightToTexture( float4 pos, float4x4 mat )
  182. {
  183. #if defined(_PS3)
  184. return mul( mat, pos );
  185. #else
  186. return mul( pos, mat );
  187. #endif
  188. }
  189. #if ( CASCADE_SIZE == 0 )
  190. float CSMComputeShadowing( float3 vPositionWs )
  191. {
  192. return 1.0f;
  193. }
  194. #elif ( CSM_MODE >= 1 )
  195. #error Invalid CSM_MODE
  196. #else
  197. // CSM shader quality level 0 (the only supported level on gameconsole)
  198. float CSMComputeShadowing( float3 vPositionWs )
  199. {
  200. float flShadowScalar = 1.0f;
  201. float4 vPosition4Ws = float4( vPositionWs.xyz, 1.0f );
  202. float3 vPositionToSampleLs = float3( 0.0f, 0.0f, CSMTransformLightToTexture( vPosition4Ws.xyzw, g_matWorldToShadowTexMatrices[0] ).z );
  203. #if ( CSM_VIEWMODELQUALITY == 0 )
  204. // only consider cascade 1 and 2 for console perf
  205. #if defined(_PS3)
  206. float4 cascadeAtlasUVOffsets_1 = g_vCascadeAtlasUVOffsets[1];
  207. float4 cascadeAtlasUVOffsets_2 = g_vCascadeAtlasUVOffsets[2];
  208. float4 cascadeAtlasUVOffset = cascadeAtlasUVOffsets_1;
  209. #else
  210. int nCascadeIndex = 1;
  211. #endif
  212. vPositionToSampleLs.xy = CSMTransformLightToTexture( vPosition4Ws.xyzw, g_matWorldToShadowTexMatrices[1] ).xy;
  213. if ( !CSMRangeTestExpanded( vPositionToSampleLs.xy ) )
  214. {
  215. vPositionToSampleLs.xy = CSMTransformLightToTexture( vPosition4Ws.xyzw, g_matWorldToShadowTexMatrices[2] ).xy;
  216. #if defined(_PS3)
  217. cascadeAtlasUVOffset = cascadeAtlasUVOffsets_2;
  218. #else
  219. nCascadeIndex = 2;
  220. #endif
  221. }
  222. #if defined(_PS3)
  223. vPositionToSampleLs.xy = saturate( vPositionToSampleLs.xy ) * cascadeAtlasUVOffset.zw + cascadeAtlasUVOffset.xy;
  224. #else
  225. vPositionToSampleLs.xy = saturate( vPositionToSampleLs.xy ) * g_vCascadeAtlasUVOffsets[nCascadeIndex].zw + g_vCascadeAtlasUVOffsets[nCascadeIndex].xy;
  226. #endif
  227. float3 vCamDelta = vPositionWs - g_vCamPosition.xyz;
  228. float flZLerpFactor = saturate( dot( vCamDelta, vCamDelta ) * g_flSunShadowingZLerpFactorRange + g_flSunShadowingZLerpFactorBase );
  229. flShadowScalar = CSMSampleShadowBuffer( vPositionToSampleLs.xy, vPositionToSampleLs.z );
  230. flShadowScalar = lerp( flShadowScalar, 1.0f, flZLerpFactor );
  231. #else
  232. // Viewmodel shadowing
  233. // only use cascade 0 for viewmodel rendering
  234. vPositionToSampleLs.xy = CSMTransformLightToTexture( vPosition4Ws.xyzw, g_matWorldToShadowTexMatrices[0] ).xy;
  235. vPositionToSampleLs.xy = saturate( vPositionToSampleLs.xy ) * g_vCascadeAtlasUVOffsets[0].zw + g_vCascadeAtlasUVOffsets[0].xy;
  236. flShadowScalar = CSMSampleShadowBuffer( vPositionToSampleLs.xy, vPositionToSampleLs.z );
  237. #endif // CSM_VIEWMODELQUALITY == 0
  238. return flShadowScalar;
  239. }
  240. #endif // #if ( CSM_MODE == 0 )