Shadows.hlsl 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302
  1. #ifndef UNIVERSAL_SHADOWS_INCLUDED
  2. #define UNIVERSAL_SHADOWS_INCLUDED
  3. #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl"
  4. #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Shadow/ShadowSamplingTent.hlsl"
  5. #include "Core.hlsl"
  6. #define SHADOWS_SCREEN 0
  7. #define MAX_SHADOW_CASCADES 4
  8. #if !defined(_RECEIVE_SHADOWS_OFF)
  9. #if defined(_MAIN_LIGHT_SHADOWS)
  10. #define MAIN_LIGHT_CALCULATE_SHADOWS
  11. #if !defined(_MAIN_LIGHT_SHADOWS_CASCADE)
  12. #define REQUIRES_VERTEX_SHADOW_COORD_INTERPOLATOR
  13. #endif
  14. #endif
  15. #if defined(_ADDITIONAL_LIGHT_SHADOWS)
  16. #define ADDITIONAL_LIGHT_CALCULATE_SHADOWS
  17. #endif
  18. #endif
  19. #if defined(_ADDITIONAL_LIGHTS) || defined(_MAIN_LIGHT_SHADOWS_CASCADE)
  20. #define REQUIRES_WORLD_SPACE_POS_INTERPOLATOR
  21. #endif
  22. SCREENSPACE_TEXTURE(_ScreenSpaceShadowmapTexture);
  23. SAMPLER(sampler_ScreenSpaceShadowmapTexture);
  24. TEXTURE2D_SHADOW(_MainLightShadowmapTexture);
  25. SAMPLER_CMP(sampler_MainLightShadowmapTexture);
  26. TEXTURE2D_SHADOW(_AdditionalLightsShadowmapTexture);
  27. SAMPLER_CMP(sampler_AdditionalLightsShadowmapTexture);
  28. // Last cascade is initialized with a no-op matrix. It always transforms
  29. // shadow coord to half3(0, 0, NEAR_PLANE). We use this trick to avoid
  30. // branching since ComputeCascadeIndex can return cascade index = MAX_SHADOW_CASCADES
  31. float4x4 _MainLightWorldToShadow[MAX_SHADOW_CASCADES + 1];
  32. float4 _CascadeShadowSplitSpheres0;
  33. float4 _CascadeShadowSplitSpheres1;
  34. float4 _CascadeShadowSplitSpheres2;
  35. float4 _CascadeShadowSplitSpheres3;
  36. float4 _CascadeShadowSplitSphereRadii;
  37. half4 _MainLightShadowOffset0;
  38. half4 _MainLightShadowOffset1;
  39. half4 _MainLightShadowOffset2;
  40. half4 _MainLightShadowOffset3;
  41. half4 _MainLightShadowParams; // (x: shadowStrength, y: 1.0 if soft shadows, 0.0 otherwise)
  42. float4 _MainLightShadowmapSize; // (xy: 1/width and 1/height, zw: width and height)
  43. #if USE_STRUCTURED_BUFFER_FOR_LIGHT_DATA
  44. StructuredBuffer<ShadowData> _AdditionalShadowsBuffer;
  45. StructuredBuffer<int> _AdditionalShadowsIndices;
  46. #else
  47. float4x4 _AdditionalLightsWorldToShadow[MAX_VISIBLE_LIGHTS];
  48. half4 _AdditionalShadowParams[MAX_VISIBLE_LIGHTS];
  49. #endif
  50. half4 _AdditionalShadowOffset0;
  51. half4 _AdditionalShadowOffset1;
  52. half4 _AdditionalShadowOffset2;
  53. half4 _AdditionalShadowOffset3;
  54. float4 _AdditionalShadowmapSize; // (xy: 1/width and 1/height, zw: width and height)
  55. float4 _ShadowBias; // x: depth bias, y: normal bias
  56. #define BEYOND_SHADOW_FAR(shadowCoord) shadowCoord.z <= 0.0 || shadowCoord.z >= 1.0
  57. struct ShadowSamplingData
  58. {
  59. half4 shadowOffset0;
  60. half4 shadowOffset1;
  61. half4 shadowOffset2;
  62. half4 shadowOffset3;
  63. float4 shadowmapSize;
  64. };
  65. ShadowSamplingData GetMainLightShadowSamplingData()
  66. {
  67. ShadowSamplingData shadowSamplingData;
  68. shadowSamplingData.shadowOffset0 = _MainLightShadowOffset0;
  69. shadowSamplingData.shadowOffset1 = _MainLightShadowOffset1;
  70. shadowSamplingData.shadowOffset2 = _MainLightShadowOffset2;
  71. shadowSamplingData.shadowOffset3 = _MainLightShadowOffset3;
  72. shadowSamplingData.shadowmapSize = _MainLightShadowmapSize;
  73. return shadowSamplingData;
  74. }
  75. ShadowSamplingData GetAdditionalLightShadowSamplingData()
  76. {
  77. ShadowSamplingData shadowSamplingData;
  78. shadowSamplingData.shadowOffset0 = _AdditionalShadowOffset0;
  79. shadowSamplingData.shadowOffset1 = _AdditionalShadowOffset1;
  80. shadowSamplingData.shadowOffset2 = _AdditionalShadowOffset2;
  81. shadowSamplingData.shadowOffset3 = _AdditionalShadowOffset3;
  82. shadowSamplingData.shadowmapSize = _AdditionalShadowmapSize;
  83. return shadowSamplingData;
  84. }
  85. // ShadowParams
  86. // x: ShadowStrength
  87. // y: 1.0 if shadow is soft, 0.0 otherwise
  88. half4 GetMainLightShadowParams()
  89. {
  90. return _MainLightShadowParams;
  91. }
  92. // ShadowParams
  93. // x: ShadowStrength
  94. // y: 1.0 if shadow is soft, 0.0 otherwise
  95. half4 GetAdditionalLightShadowParams(int lightIndex)
  96. {
  97. #if USE_STRUCTURED_BUFFER_FOR_LIGHT_DATA
  98. return _AdditionalShadowsBuffer[lightIndex].shadowParams;
  99. #else
  100. return _AdditionalShadowParams[lightIndex];
  101. #endif
  102. }
  103. half SampleScreenSpaceShadowmap(float4 shadowCoord)
  104. {
  105. shadowCoord.xy /= shadowCoord.w;
  106. // The stereo transform has to happen after the manual perspective divide
  107. shadowCoord.xy = UnityStereoTransformScreenSpaceTex(shadowCoord.xy);
  108. #if defined(UNITY_STEREO_INSTANCING_ENABLED) || defined(UNITY_STEREO_MULTIVIEW_ENABLED)
  109. half attenuation = SAMPLE_TEXTURE2D_ARRAY(_ScreenSpaceShadowmapTexture, sampler_ScreenSpaceShadowmapTexture, shadowCoord.xy, unity_StereoEyeIndex).x;
  110. #else
  111. half attenuation = SAMPLE_TEXTURE2D(_ScreenSpaceShadowmapTexture, sampler_ScreenSpaceShadowmapTexture, shadowCoord.xy).x;
  112. #endif
  113. return attenuation;
  114. }
  115. real SampleShadowmapFiltered(TEXTURE2D_SHADOW_PARAM(ShadowMap, sampler_ShadowMap), float4 shadowCoord, ShadowSamplingData samplingData)
  116. {
  117. real attenuation;
  118. #if defined(SHADER_API_MOBILE) || defined(SHADER_API_SWITCH)
  119. // 4-tap hardware comparison
  120. real4 attenuation4;
  121. attenuation4.x = SAMPLE_TEXTURE2D_SHADOW(ShadowMap, sampler_ShadowMap, shadowCoord.xyz + samplingData.shadowOffset0.xyz);
  122. attenuation4.y = SAMPLE_TEXTURE2D_SHADOW(ShadowMap, sampler_ShadowMap, shadowCoord.xyz + samplingData.shadowOffset1.xyz);
  123. attenuation4.z = SAMPLE_TEXTURE2D_SHADOW(ShadowMap, sampler_ShadowMap, shadowCoord.xyz + samplingData.shadowOffset2.xyz);
  124. attenuation4.w = SAMPLE_TEXTURE2D_SHADOW(ShadowMap, sampler_ShadowMap, shadowCoord.xyz + samplingData.shadowOffset3.xyz);
  125. attenuation = dot(attenuation4, 0.25);
  126. #else
  127. float fetchesWeights[9];
  128. float2 fetchesUV[9];
  129. SampleShadow_ComputeSamples_Tent_5x5(samplingData.shadowmapSize, shadowCoord.xy, fetchesWeights, fetchesUV);
  130. attenuation = fetchesWeights[0] * SAMPLE_TEXTURE2D_SHADOW(ShadowMap, sampler_ShadowMap, float3(fetchesUV[0].xy, shadowCoord.z));
  131. attenuation += fetchesWeights[1] * SAMPLE_TEXTURE2D_SHADOW(ShadowMap, sampler_ShadowMap, float3(fetchesUV[1].xy, shadowCoord.z));
  132. attenuation += fetchesWeights[2] * SAMPLE_TEXTURE2D_SHADOW(ShadowMap, sampler_ShadowMap, float3(fetchesUV[2].xy, shadowCoord.z));
  133. attenuation += fetchesWeights[3] * SAMPLE_TEXTURE2D_SHADOW(ShadowMap, sampler_ShadowMap, float3(fetchesUV[3].xy, shadowCoord.z));
  134. attenuation += fetchesWeights[4] * SAMPLE_TEXTURE2D_SHADOW(ShadowMap, sampler_ShadowMap, float3(fetchesUV[4].xy, shadowCoord.z));
  135. attenuation += fetchesWeights[5] * SAMPLE_TEXTURE2D_SHADOW(ShadowMap, sampler_ShadowMap, float3(fetchesUV[5].xy, shadowCoord.z));
  136. attenuation += fetchesWeights[6] * SAMPLE_TEXTURE2D_SHADOW(ShadowMap, sampler_ShadowMap, float3(fetchesUV[6].xy, shadowCoord.z));
  137. attenuation += fetchesWeights[7] * SAMPLE_TEXTURE2D_SHADOW(ShadowMap, sampler_ShadowMap, float3(fetchesUV[7].xy, shadowCoord.z));
  138. attenuation += fetchesWeights[8] * SAMPLE_TEXTURE2D_SHADOW(ShadowMap, sampler_ShadowMap, float3(fetchesUV[8].xy, shadowCoord.z));
  139. #endif
  140. return attenuation;
  141. }
  142. real SampleShadowmap(TEXTURE2D_SHADOW_PARAM(ShadowMap, sampler_ShadowMap), float4 shadowCoord, ShadowSamplingData samplingData, half4 shadowParams, bool isPerspectiveProjection = true)
  143. {
  144. // Compiler will optimize this branch away as long as isPerspectiveProjection is known at compile time
  145. if (isPerspectiveProjection)
  146. shadowCoord.xyz /= shadowCoord.w;
  147. real attenuation;
  148. real shadowStrength = shadowParams.x;
  149. // TODO: We could branch on if this light has soft shadows (shadowParams.y) to save perf on some platforms.
  150. #ifdef _SHADOWS_SOFT
  151. attenuation = SampleShadowmapFiltered(TEXTURE2D_SHADOW_ARGS(ShadowMap, sampler_ShadowMap), shadowCoord, samplingData);
  152. #else
  153. // 1-tap hardware comparison
  154. attenuation = SAMPLE_TEXTURE2D_SHADOW(ShadowMap, sampler_ShadowMap, shadowCoord.xyz);
  155. #endif
  156. attenuation = LerpWhiteTo(attenuation, shadowStrength);
  157. // Shadow coords that fall out of the light frustum volume must always return attenuation 1.0
  158. // TODO: We could use branch here to save some perf on some platforms.
  159. return BEYOND_SHADOW_FAR(shadowCoord) ? 1.0 : attenuation;
  160. }
  161. half ComputeCascadeIndex(float3 positionWS)
  162. {
  163. float3 fromCenter0 = positionWS - _CascadeShadowSplitSpheres0.xyz;
  164. float3 fromCenter1 = positionWS - _CascadeShadowSplitSpheres1.xyz;
  165. float3 fromCenter2 = positionWS - _CascadeShadowSplitSpheres2.xyz;
  166. float3 fromCenter3 = positionWS - _CascadeShadowSplitSpheres3.xyz;
  167. float4 distances2 = float4(dot(fromCenter0, fromCenter0), dot(fromCenter1, fromCenter1), dot(fromCenter2, fromCenter2), dot(fromCenter3, fromCenter3));
  168. half4 weights = half4(distances2 < _CascadeShadowSplitSphereRadii);
  169. weights.yzw = saturate(weights.yzw - weights.xyz);
  170. return 4 - dot(weights, half4(4, 3, 2, 1));
  171. }
  172. float4 TransformWorldToShadowCoord(float3 positionWS)
  173. {
  174. #ifdef _MAIN_LIGHT_SHADOWS_CASCADE
  175. half cascadeIndex = ComputeCascadeIndex(positionWS);
  176. #else
  177. half cascadeIndex = 0;
  178. #endif
  179. return mul(_MainLightWorldToShadow[cascadeIndex], float4(positionWS, 1.0));
  180. }
  181. half MainLightRealtimeShadow(float4 shadowCoord)
  182. {
  183. #if !defined(MAIN_LIGHT_CALCULATE_SHADOWS)
  184. return 1.0h;
  185. #endif
  186. ShadowSamplingData shadowSamplingData = GetMainLightShadowSamplingData();
  187. half4 shadowParams = GetMainLightShadowParams();
  188. return SampleShadowmap(TEXTURE2D_ARGS(_MainLightShadowmapTexture, sampler_MainLightShadowmapTexture), shadowCoord, shadowSamplingData, shadowParams, false);
  189. }
  190. half AdditionalLightRealtimeShadow(int lightIndex, float3 positionWS)
  191. {
  192. #if !defined(ADDITIONAL_LIGHT_CALCULATE_SHADOWS)
  193. return 1.0h;
  194. #endif
  195. ShadowSamplingData shadowSamplingData = GetAdditionalLightShadowSamplingData();
  196. #if USE_STRUCTURED_BUFFER_FOR_LIGHT_DATA
  197. lightIndex = _AdditionalShadowsIndices[lightIndex];
  198. // We have to branch here as otherwise we would sample buffer with lightIndex == -1.
  199. // However this should be ok for platforms that store light in SSBO.
  200. UNITY_BRANCH
  201. if (lightIndex < 0)
  202. return 1.0;
  203. float4 shadowCoord = mul(_AdditionalShadowsBuffer[lightIndex].worldToShadowMatrix, float4(positionWS, 1.0));
  204. #else
  205. float4 shadowCoord = mul(_AdditionalLightsWorldToShadow[lightIndex], float4(positionWS, 1.0));
  206. #endif
  207. half4 shadowParams = GetAdditionalLightShadowParams(lightIndex);
  208. return SampleShadowmap(TEXTURE2D_ARGS(_AdditionalLightsShadowmapTexture, sampler_AdditionalLightsShadowmapTexture), shadowCoord, shadowSamplingData, shadowParams, true);
  209. }
  210. float4 GetShadowCoord(VertexPositionInputs vertexInput)
  211. {
  212. return TransformWorldToShadowCoord(vertexInput.positionWS);
  213. }
  214. float3 ApplyShadowBias(float3 positionWS, float3 normalWS, float3 lightDirection)
  215. {
  216. float invNdotL = 1.0 - saturate(dot(lightDirection, normalWS));
  217. float scale = invNdotL * _ShadowBias.y;
  218. // normal bias is negative since we want to apply an inset normal offset
  219. positionWS = lightDirection * _ShadowBias.xxx + positionWS;
  220. positionWS = normalWS * scale.xxx + positionWS;
  221. return positionWS;
  222. }
  223. ///////////////////////////////////////////////////////////////////////////////
  224. // Deprecated /
  225. ///////////////////////////////////////////////////////////////////////////////
  226. // Renamed -> _MainLightShadowParams
  227. #define _MainLightShadowData _MainLightShadowParams
  228. // Deprecated: Use GetMainLightShadowParams instead.
  229. half GetMainLightShadowStrength()
  230. {
  231. return _MainLightShadowData.x;
  232. }
  233. // Deprecated: Use GetAdditionalLightShadowParams instead.
  234. half GetAdditionalLightShadowStrenth(int lightIndex)
  235. {
  236. #if USE_STRUCTURED_BUFFER_FOR_LIGHT_DATA
  237. return _AdditionalShadowsBuffer[lightIndex].shadowParams.x;
  238. #else
  239. return _AdditionalShadowParams[lightIndex].x;
  240. #endif
  241. }
  242. // Deprecated: Use SampleShadowmap that takes shadowParams instead of strength.
  243. real SampleShadowmap(float4 shadowCoord, TEXTURE2D_SHADOW_PARAM(ShadowMap, sampler_ShadowMap), ShadowSamplingData samplingData, half shadowStrength, bool isPerspectiveProjection = true)
  244. {
  245. half4 shadowParams = half4(shadowStrength, 1.0, 0.0, 0.0);
  246. return SampleShadowmap(TEXTURE2D_SHADOW_ARGS(ShadowMap, sampler_ShadowMap), shadowCoord, samplingData, shadowParams, isPerspectiveProjection);
  247. }
  248. #endif