Shadows.hlsl 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423
  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(UNITY_DOTS_INSTANCING_ENABLED)
  20. #define SHADOWMASK_NAME unity_ShadowMasks
  21. #define SHADOWMASK_SAMPLER_NAME samplerunity_ShadowMasks
  22. #define SHADOWMASK_SAMPLE_EXTRA_ARGS , unity_LightmapIndex.x
  23. #else
  24. #define SHADOWMASK_NAME unity_ShadowMask
  25. #define SHADOWMASK_SAMPLER_NAME samplerunity_ShadowMask
  26. #define SHADOWMASK_SAMPLE_EXTRA_ARGS
  27. #endif
  28. #if defined(SHADOWS_SHADOWMASK) && defined(LIGHTMAP_ON)
  29. #define SAMPLE_SHADOWMASK(uv) SAMPLE_TEXTURE2D_LIGHTMAP(SHADOWMASK_NAME, SHADOWMASK_SAMPLER_NAME, uv SHADOWMASK_SAMPLE_EXTRA_ARGS);
  30. #elif !defined (LIGHTMAP_ON)
  31. #define SAMPLE_SHADOWMASK(uv) unity_ProbesOcclusion;
  32. #else
  33. #define SAMPLE_SHADOWMASK(uv) half4(1, 1, 1, 1);
  34. #endif
  35. #define REQUIRES_WORLD_SPACE_POS_INTERPOLATOR
  36. #if defined(LIGHTMAP_ON) || defined(LIGHTMAP_SHADOW_MIXING) || defined(SHADOWS_SHADOWMASK)
  37. #define CALCULATE_BAKED_SHADOWS
  38. #endif
  39. SCREENSPACE_TEXTURE(_ScreenSpaceShadowmapTexture);
  40. SAMPLER(sampler_ScreenSpaceShadowmapTexture);
  41. TEXTURE2D_SHADOW(_MainLightShadowmapTexture);
  42. SAMPLER_CMP(sampler_MainLightShadowmapTexture);
  43. TEXTURE2D_SHADOW(_AdditionalLightsShadowmapTexture);
  44. SAMPLER_CMP(sampler_AdditionalLightsShadowmapTexture);
  45. // GLES3 causes a performance regression in some devices when using CBUFFER.
  46. #ifndef SHADER_API_GLES3
  47. CBUFFER_START(MainLightShadows)
  48. #endif
  49. // Last cascade is initialized with a no-op matrix. It always transforms
  50. // shadow coord to half3(0, 0, NEAR_PLANE). We use this trick to avoid
  51. // branching since ComputeCascadeIndex can return cascade index = MAX_SHADOW_CASCADES
  52. float4x4 _MainLightWorldToShadow[MAX_SHADOW_CASCADES + 1];
  53. float4 _CascadeShadowSplitSpheres0;
  54. float4 _CascadeShadowSplitSpheres1;
  55. float4 _CascadeShadowSplitSpheres2;
  56. float4 _CascadeShadowSplitSpheres3;
  57. float4 _CascadeShadowSplitSphereRadii;
  58. half4 _MainLightShadowOffset0;
  59. half4 _MainLightShadowOffset1;
  60. half4 _MainLightShadowOffset2;
  61. half4 _MainLightShadowOffset3;
  62. half4 _MainLightShadowParams; // (x: shadowStrength, y: 1.0 if soft shadows, 0.0 otherwise, z: oneOverFadeDist, w: minusStartFade)
  63. float4 _MainLightShadowmapSize; // (xy: 1/width and 1/height, zw: width and height)
  64. #ifndef SHADER_API_GLES3
  65. CBUFFER_END
  66. #endif
  67. #if USE_STRUCTURED_BUFFER_FOR_LIGHT_DATA
  68. StructuredBuffer<ShadowData> _AdditionalShadowsBuffer;
  69. StructuredBuffer<int> _AdditionalShadowsIndices;
  70. half4 _AdditionalShadowOffset0;
  71. half4 _AdditionalShadowOffset1;
  72. half4 _AdditionalShadowOffset2;
  73. half4 _AdditionalShadowOffset3;
  74. float4 _AdditionalShadowmapSize; // (xy: 1/width and 1/height, zw: width and height)
  75. #else
  76. // GLES3 causes a performance regression in some devices when using CBUFFER.
  77. #ifndef SHADER_API_GLES3
  78. CBUFFER_START(AdditionalLightShadows)
  79. #endif
  80. float4x4 _AdditionalLightsWorldToShadow[MAX_VISIBLE_LIGHTS];
  81. half4 _AdditionalShadowParams[MAX_VISIBLE_LIGHTS];
  82. half4 _AdditionalShadowOffset0;
  83. half4 _AdditionalShadowOffset1;
  84. half4 _AdditionalShadowOffset2;
  85. half4 _AdditionalShadowOffset3;
  86. float4 _AdditionalShadowmapSize; // (xy: 1/width and 1/height, zw: width and height)
  87. #ifndef SHADER_API_GLES3
  88. CBUFFER_END
  89. #endif
  90. #endif
  91. float4 _ShadowBias; // x: depth bias, y: normal bias
  92. #define BEYOND_SHADOW_FAR(shadowCoord) shadowCoord.z <= 0.0 || shadowCoord.z >= 1.0
  93. struct ShadowSamplingData
  94. {
  95. half4 shadowOffset0;
  96. half4 shadowOffset1;
  97. half4 shadowOffset2;
  98. half4 shadowOffset3;
  99. float4 shadowmapSize;
  100. };
  101. ShadowSamplingData GetMainLightShadowSamplingData()
  102. {
  103. ShadowSamplingData shadowSamplingData;
  104. shadowSamplingData.shadowOffset0 = _MainLightShadowOffset0;
  105. shadowSamplingData.shadowOffset1 = _MainLightShadowOffset1;
  106. shadowSamplingData.shadowOffset2 = _MainLightShadowOffset2;
  107. shadowSamplingData.shadowOffset3 = _MainLightShadowOffset3;
  108. shadowSamplingData.shadowmapSize = _MainLightShadowmapSize;
  109. return shadowSamplingData;
  110. }
  111. ShadowSamplingData GetAdditionalLightShadowSamplingData()
  112. {
  113. ShadowSamplingData shadowSamplingData;
  114. shadowSamplingData.shadowOffset0 = _AdditionalShadowOffset0;
  115. shadowSamplingData.shadowOffset1 = _AdditionalShadowOffset1;
  116. shadowSamplingData.shadowOffset2 = _AdditionalShadowOffset2;
  117. shadowSamplingData.shadowOffset3 = _AdditionalShadowOffset3;
  118. shadowSamplingData.shadowmapSize = _AdditionalShadowmapSize;
  119. return shadowSamplingData;
  120. }
  121. // ShadowParams
  122. // x: ShadowStrength
  123. // y: 1.0 if shadow is soft, 0.0 otherwise
  124. half4 GetMainLightShadowParams()
  125. {
  126. return _MainLightShadowParams;
  127. }
  128. // ShadowParams
  129. // x: ShadowStrength
  130. // y: 1.0 if shadow is soft, 0.0 otherwise
  131. half4 GetAdditionalLightShadowParams(int lightIndex)
  132. {
  133. #if USE_STRUCTURED_BUFFER_FOR_LIGHT_DATA
  134. return _AdditionalShadowsBuffer[lightIndex].shadowParams;
  135. #else
  136. return _AdditionalShadowParams[lightIndex];
  137. #endif
  138. }
  139. half SampleScreenSpaceShadowmap(float4 shadowCoord)
  140. {
  141. shadowCoord.xy /= shadowCoord.w;
  142. // The stereo transform has to happen after the manual perspective divide
  143. shadowCoord.xy = UnityStereoTransformScreenSpaceTex(shadowCoord.xy);
  144. #if defined(UNITY_STEREO_INSTANCING_ENABLED) || defined(UNITY_STEREO_MULTIVIEW_ENABLED)
  145. half attenuation = SAMPLE_TEXTURE2D_ARRAY(_ScreenSpaceShadowmapTexture, sampler_ScreenSpaceShadowmapTexture, shadowCoord.xy, unity_StereoEyeIndex).x;
  146. #else
  147. half attenuation = SAMPLE_TEXTURE2D(_ScreenSpaceShadowmapTexture, sampler_ScreenSpaceShadowmapTexture, shadowCoord.xy).x;
  148. #endif
  149. return attenuation;
  150. }
  151. real SampleShadowmapFiltered(TEXTURE2D_SHADOW_PARAM(ShadowMap, sampler_ShadowMap), float4 shadowCoord, ShadowSamplingData samplingData)
  152. {
  153. real attenuation;
  154. #if defined(SHADER_API_MOBILE) || defined(SHADER_API_SWITCH)
  155. // 4-tap hardware comparison
  156. real4 attenuation4;
  157. attenuation4.x = SAMPLE_TEXTURE2D_SHADOW(ShadowMap, sampler_ShadowMap, shadowCoord.xyz + samplingData.shadowOffset0.xyz);
  158. attenuation4.y = SAMPLE_TEXTURE2D_SHADOW(ShadowMap, sampler_ShadowMap, shadowCoord.xyz + samplingData.shadowOffset1.xyz);
  159. attenuation4.z = SAMPLE_TEXTURE2D_SHADOW(ShadowMap, sampler_ShadowMap, shadowCoord.xyz + samplingData.shadowOffset2.xyz);
  160. attenuation4.w = SAMPLE_TEXTURE2D_SHADOW(ShadowMap, sampler_ShadowMap, shadowCoord.xyz + samplingData.shadowOffset3.xyz);
  161. attenuation = dot(attenuation4, 0.25);
  162. #else
  163. float fetchesWeights[9];
  164. float2 fetchesUV[9];
  165. SampleShadow_ComputeSamples_Tent_5x5(samplingData.shadowmapSize, shadowCoord.xy, fetchesWeights, fetchesUV);
  166. attenuation = fetchesWeights[0] * SAMPLE_TEXTURE2D_SHADOW(ShadowMap, sampler_ShadowMap, float3(fetchesUV[0].xy, shadowCoord.z));
  167. attenuation += fetchesWeights[1] * SAMPLE_TEXTURE2D_SHADOW(ShadowMap, sampler_ShadowMap, float3(fetchesUV[1].xy, shadowCoord.z));
  168. attenuation += fetchesWeights[2] * SAMPLE_TEXTURE2D_SHADOW(ShadowMap, sampler_ShadowMap, float3(fetchesUV[2].xy, shadowCoord.z));
  169. attenuation += fetchesWeights[3] * SAMPLE_TEXTURE2D_SHADOW(ShadowMap, sampler_ShadowMap, float3(fetchesUV[3].xy, shadowCoord.z));
  170. attenuation += fetchesWeights[4] * SAMPLE_TEXTURE2D_SHADOW(ShadowMap, sampler_ShadowMap, float3(fetchesUV[4].xy, shadowCoord.z));
  171. attenuation += fetchesWeights[5] * SAMPLE_TEXTURE2D_SHADOW(ShadowMap, sampler_ShadowMap, float3(fetchesUV[5].xy, shadowCoord.z));
  172. attenuation += fetchesWeights[6] * SAMPLE_TEXTURE2D_SHADOW(ShadowMap, sampler_ShadowMap, float3(fetchesUV[6].xy, shadowCoord.z));
  173. attenuation += fetchesWeights[7] * SAMPLE_TEXTURE2D_SHADOW(ShadowMap, sampler_ShadowMap, float3(fetchesUV[7].xy, shadowCoord.z));
  174. attenuation += fetchesWeights[8] * SAMPLE_TEXTURE2D_SHADOW(ShadowMap, sampler_ShadowMap, float3(fetchesUV[8].xy, shadowCoord.z));
  175. #endif
  176. return attenuation;
  177. }
  178. real SampleShadowmap(TEXTURE2D_SHADOW_PARAM(ShadowMap, sampler_ShadowMap), float4 shadowCoord, ShadowSamplingData samplingData, half4 shadowParams, bool isPerspectiveProjection = true)
  179. {
  180. // Compiler will optimize this branch away as long as isPerspectiveProjection is known at compile time
  181. if (isPerspectiveProjection)
  182. shadowCoord.xyz /= shadowCoord.w;
  183. real attenuation;
  184. real shadowStrength = shadowParams.x;
  185. // TODO: We could branch on if this light has soft shadows (shadowParams.y) to save perf on some platforms.
  186. #ifdef _SHADOWS_SOFT
  187. attenuation = SampleShadowmapFiltered(TEXTURE2D_SHADOW_ARGS(ShadowMap, sampler_ShadowMap), shadowCoord, samplingData);
  188. #else
  189. // 1-tap hardware comparison
  190. attenuation = SAMPLE_TEXTURE2D_SHADOW(ShadowMap, sampler_ShadowMap, shadowCoord.xyz);
  191. #endif
  192. attenuation = LerpWhiteTo(attenuation, shadowStrength);
  193. // Shadow coords that fall out of the light frustum volume must always return attenuation 1.0
  194. // TODO: We could use branch here to save some perf on some platforms.
  195. return BEYOND_SHADOW_FAR(shadowCoord) ? 1.0 : attenuation;
  196. }
  197. half ComputeCascadeIndex(float3 positionWS)
  198. {
  199. float3 fromCenter0 = positionWS - _CascadeShadowSplitSpheres0.xyz;
  200. float3 fromCenter1 = positionWS - _CascadeShadowSplitSpheres1.xyz;
  201. float3 fromCenter2 = positionWS - _CascadeShadowSplitSpheres2.xyz;
  202. float3 fromCenter3 = positionWS - _CascadeShadowSplitSpheres3.xyz;
  203. float4 distances2 = float4(dot(fromCenter0, fromCenter0), dot(fromCenter1, fromCenter1), dot(fromCenter2, fromCenter2), dot(fromCenter3, fromCenter3));
  204. half4 weights = half4(distances2 < _CascadeShadowSplitSphereRadii);
  205. weights.yzw = saturate(weights.yzw - weights.xyz);
  206. return 4 - dot(weights, half4(4, 3, 2, 1));
  207. }
  208. float4 TransformWorldToShadowCoord(float3 positionWS)
  209. {
  210. #ifdef _MAIN_LIGHT_SHADOWS_CASCADE
  211. half cascadeIndex = ComputeCascadeIndex(positionWS);
  212. #else
  213. half cascadeIndex = 0;
  214. #endif
  215. float4 shadowCoord = mul(_MainLightWorldToShadow[cascadeIndex], float4(positionWS, 1.0));
  216. return float4(shadowCoord.xyz, cascadeIndex);
  217. }
  218. half MainLightRealtimeShadow(float4 shadowCoord)
  219. {
  220. #if !defined(MAIN_LIGHT_CALCULATE_SHADOWS)
  221. return 1.0h;
  222. #endif
  223. ShadowSamplingData shadowSamplingData = GetMainLightShadowSamplingData();
  224. half4 shadowParams = GetMainLightShadowParams();
  225. return SampleShadowmap(TEXTURE2D_ARGS(_MainLightShadowmapTexture, sampler_MainLightShadowmapTexture), shadowCoord, shadowSamplingData, shadowParams, false);
  226. }
  227. half AdditionalLightRealtimeShadow(int lightIndex, float3 positionWS)
  228. {
  229. #if !defined(ADDITIONAL_LIGHT_CALCULATE_SHADOWS)
  230. return 1.0h;
  231. #endif
  232. ShadowSamplingData shadowSamplingData = GetAdditionalLightShadowSamplingData();
  233. #if USE_STRUCTURED_BUFFER_FOR_LIGHT_DATA
  234. lightIndex = _AdditionalShadowsIndices[lightIndex];
  235. // We have to branch here as otherwise we would sample buffer with lightIndex == -1.
  236. // However this should be ok for platforms that store light in SSBO.
  237. UNITY_BRANCH
  238. if (lightIndex < 0)
  239. return 1.0;
  240. float4 shadowCoord = mul(_AdditionalShadowsBuffer[lightIndex].worldToShadowMatrix, float4(positionWS, 1.0));
  241. #else
  242. float4 shadowCoord = mul(_AdditionalLightsWorldToShadow[lightIndex], float4(positionWS, 1.0));
  243. #endif
  244. half4 shadowParams = GetAdditionalLightShadowParams(lightIndex);
  245. return SampleShadowmap(TEXTURE2D_ARGS(_AdditionalLightsShadowmapTexture, sampler_AdditionalLightsShadowmapTexture), shadowCoord, shadowSamplingData, shadowParams, true);
  246. }
  247. half GetShadowFade(float3 positionWS)
  248. {
  249. float3 camToPixel = positionWS - _WorldSpaceCameraPos;
  250. float distanceCamToPixel2 = dot(camToPixel, camToPixel);
  251. half fade = saturate(distanceCamToPixel2 * _MainLightShadowParams.z + _MainLightShadowParams.w);
  252. return fade * fade;
  253. }
  254. half MixRealtimeAndBakedShadows(half realtimeShadow, half bakedShadow, half shadowFade)
  255. {
  256. #if defined(LIGHTMAP_SHADOW_MIXING)
  257. return min(lerp(realtimeShadow, 1, shadowFade), bakedShadow);
  258. #else
  259. return lerp(realtimeShadow, bakedShadow, shadowFade);
  260. #endif
  261. }
  262. half BakedShadow(half4 shadowMask, half4 occlusionProbeChannels)
  263. {
  264. // Here occlusionProbeChannels used as mask selector to select shadows in shadowMask
  265. // If occlusionProbeChannels all components are zero we use default baked shadow value 1.0
  266. // This code is optimized for mobile platforms:
  267. // half bakedShadow = any(occlusionProbeChannels) ? dot(shadowMask, occlusionProbeChannels) : 1.0h;
  268. half bakedShadow = 1.0h + dot(shadowMask - 1.0h, occlusionProbeChannels);
  269. return bakedShadow;
  270. }
  271. half MainLightShadow(float4 shadowCoord, float3 positionWS, half4 shadowMask, half4 occlusionProbeChannels)
  272. {
  273. half realtimeShadow = MainLightRealtimeShadow(shadowCoord);
  274. #ifdef CALCULATE_BAKED_SHADOWS
  275. half bakedShadow = BakedShadow(shadowMask, occlusionProbeChannels);
  276. #else
  277. half bakedShadow = 1.0h;
  278. #endif
  279. #ifdef MAIN_LIGHT_CALCULATE_SHADOWS
  280. half shadowFade = GetShadowFade(positionWS);
  281. #else
  282. half shadowFade = 1.0h;
  283. #endif
  284. #if defined(_MAIN_LIGHT_SHADOWS_CASCADE) && defined(CALCULATE_BAKED_SHADOWS)
  285. // shadowCoord.w represents shadow cascade index
  286. // in case we are out of shadow cascade we need to set shadow fade to 1.0 for correct blending
  287. // it is needed when realtime shadows gets cut to early during fade and causes disconnect between baked shadow
  288. shadowFade = shadowCoord.w == 4 ? 1.0h : shadowFade;
  289. #endif
  290. return MixRealtimeAndBakedShadows(realtimeShadow, bakedShadow, shadowFade);
  291. }
  292. half AdditionalLightShadow(int lightIndex, float3 positionWS, half4 shadowMask, half4 occlusionProbeChannels)
  293. {
  294. half realtimeShadow = AdditionalLightRealtimeShadow(lightIndex, positionWS);
  295. #ifdef CALCULATE_BAKED_SHADOWS
  296. half bakedShadow = BakedShadow(shadowMask, occlusionProbeChannels);
  297. #else
  298. half bakedShadow = 1.0h;
  299. #endif
  300. #ifdef ADDITIONAL_LIGHT_CALCULATE_SHADOWS
  301. half shadowFade = GetShadowFade(positionWS);
  302. #else
  303. half shadowFade = 1.0h;
  304. #endif
  305. return MixRealtimeAndBakedShadows(realtimeShadow, bakedShadow, shadowFade);
  306. }
  307. float4 GetShadowCoord(VertexPositionInputs vertexInput)
  308. {
  309. return TransformWorldToShadowCoord(vertexInput.positionWS);
  310. }
  311. float3 ApplyShadowBias(float3 positionWS, float3 normalWS, float3 lightDirection)
  312. {
  313. float invNdotL = 1.0 - saturate(dot(lightDirection, normalWS));
  314. float scale = invNdotL * _ShadowBias.y;
  315. // normal bias is negative since we want to apply an inset normal offset
  316. positionWS = lightDirection * _ShadowBias.xxx + positionWS;
  317. positionWS = normalWS * scale.xxx + positionWS;
  318. return positionWS;
  319. }
  320. ///////////////////////////////////////////////////////////////////////////////
  321. // Deprecated /
  322. ///////////////////////////////////////////////////////////////////////////////
  323. // Renamed -> _MainLightShadowParams
  324. #define _MainLightShadowData _MainLightShadowParams
  325. // Deprecated: Use GetShadowFade instead.
  326. float ApplyShadowFade(float shadowAttenuation, float3 positionWS)
  327. {
  328. float fade = GetShadowFade(positionWS);
  329. return shadowAttenuation + (1 - shadowAttenuation) * fade * fade;
  330. }
  331. // Deprecated: Use GetMainLightShadowParams instead.
  332. half GetMainLightShadowStrength()
  333. {
  334. return _MainLightShadowData.x;
  335. }
  336. // Deprecated: Use GetAdditionalLightShadowParams instead.
  337. half GetAdditionalLightShadowStrenth(int lightIndex)
  338. {
  339. #if USE_STRUCTURED_BUFFER_FOR_LIGHT_DATA
  340. return _AdditionalShadowsBuffer[lightIndex].shadowParams.x;
  341. #else
  342. return _AdditionalShadowParams[lightIndex].x;
  343. #endif
  344. }
  345. // Deprecated: Use SampleShadowmap that takes shadowParams instead of strength.
  346. real SampleShadowmap(float4 shadowCoord, TEXTURE2D_SHADOW_PARAM(ShadowMap, sampler_ShadowMap), ShadowSamplingData samplingData, half shadowStrength, bool isPerspectiveProjection = true)
  347. {
  348. half4 shadowParams = half4(shadowStrength, 1.0, 0.0, 0.0);
  349. return SampleShadowmap(TEXTURE2D_SHADOW_ARGS(ShadowMap, sampler_ShadowMap), shadowCoord, samplingData, shadowParams, isPerspectiveProjection);
  350. }
  351. #endif