暫無描述
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.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546
  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 "Packages/com.unity.render-pipelines.core/ShaderLibrary/GlobalSamplers.hlsl"
  6. #include "Core.hlsl"
  7. #include "Shadows.deprecated.hlsl"
  8. #define MAX_SHADOW_CASCADES 4
  9. #if !defined(_RECEIVE_SHADOWS_OFF)
  10. #if defined(_MAIN_LIGHT_SHADOWS) || defined(_MAIN_LIGHT_SHADOWS_CASCADE) || defined(_MAIN_LIGHT_SHADOWS_SCREEN)
  11. #define MAIN_LIGHT_CALCULATE_SHADOWS
  12. #if defined(_MAIN_LIGHT_SHADOWS) || (defined(_MAIN_LIGHT_SHADOWS_SCREEN) && !defined(_SURFACE_TYPE_TRANSPARENT))
  13. #define REQUIRES_VERTEX_SHADOW_COORD_INTERPOLATOR
  14. #endif
  15. #endif
  16. #if defined(_ADDITIONAL_LIGHT_SHADOWS)
  17. #define ADDITIONAL_LIGHT_CALCULATE_SHADOWS
  18. #endif
  19. #endif
  20. #if defined(UNITY_DOTS_INSTANCING_ENABLED) && !defined(USE_LEGACY_LIGHTMAPS)
  21. // ^ GPU-driven rendering is enabled, and we haven't opted-out from lightmap
  22. // texture arrays. This minimizes batch breakages, but texture arrays aren't
  23. // supported in a performant way on all GPUs.
  24. #define SHADOWMASK_NAME unity_ShadowMasks
  25. #define SHADOWMASK_SAMPLER_NAME samplerunity_ShadowMasks
  26. #define SHADOWMASK_SAMPLE_EXTRA_ARGS , unity_LightmapIndex.x
  27. #else
  28. // ^ Lightmaps are not bound as texture arrays, but as individual textures. The
  29. // batch is broken every time lightmaps are changed, but this is well-supported
  30. // on all GPUs.
  31. #define SHADOWMASK_NAME unity_ShadowMask
  32. #define SHADOWMASK_SAMPLER_NAME samplerunity_ShadowMask
  33. #define SHADOWMASK_SAMPLE_EXTRA_ARGS
  34. #endif
  35. #if defined(SHADOWS_SHADOWMASK) && defined(LIGHTMAP_ON)
  36. #define SAMPLE_SHADOWMASK(uv) SAMPLE_TEXTURE2D_LIGHTMAP(SHADOWMASK_NAME, SHADOWMASK_SAMPLER_NAME, uv SHADOWMASK_SAMPLE_EXTRA_ARGS);
  37. #elif !defined (LIGHTMAP_ON)
  38. #define SAMPLE_SHADOWMASK(uv) unity_ProbesOcclusion;
  39. #else
  40. #define SAMPLE_SHADOWMASK(uv) half4(1, 1, 1, 1);
  41. #endif
  42. #define REQUIRES_WORLD_SPACE_POS_INTERPOLATOR
  43. #if defined(LIGHTMAP_ON) || defined(LIGHTMAP_SHADOW_MIXING) || defined(SHADOWS_SHADOWMASK)
  44. #define CALCULATE_BAKED_SHADOWS
  45. #endif
  46. TEXTURE2D_X(_ScreenSpaceShadowmapTexture);
  47. TEXTURE2D_SHADOW(_MainLightShadowmapTexture);
  48. TEXTURE2D_SHADOW(_AdditionalLightsShadowmapTexture);
  49. SAMPLER_CMP(sampler_LinearClampCompare);
  50. // GLES3 causes a performance regression in some devices when using CBUFFER.
  51. #ifndef SHADER_API_GLES3
  52. CBUFFER_START(LightShadows)
  53. #endif
  54. // Last cascade is initialized with a no-op matrix. It always transforms
  55. // shadow coord to half3(0, 0, NEAR_PLANE). We use this trick to avoid
  56. // branching since ComputeCascadeIndex can return cascade index = MAX_SHADOW_CASCADES
  57. float4x4 _MainLightWorldToShadow[MAX_SHADOW_CASCADES + 1];
  58. float4 _CascadeShadowSplitSpheres0;
  59. float4 _CascadeShadowSplitSpheres1;
  60. float4 _CascadeShadowSplitSpheres2;
  61. float4 _CascadeShadowSplitSpheres3;
  62. float4 _CascadeShadowSplitSphereRadii;
  63. float4 _MainLightShadowOffset0; // xy: offset0, zw: offset1
  64. float4 _MainLightShadowOffset1; // xy: offset2, zw: offset3
  65. float4 _MainLightShadowParams; // (x: shadowStrength, y: >= 1.0 if soft shadows, 0.0 otherwise, z: main light fade scale, w: main light fade bias)
  66. float4 _MainLightShadowmapSize; // (xy: 1/width and 1/height, zw: width and height)
  67. float4 _AdditionalShadowOffset0; // xy: offset0, zw: offset1
  68. float4 _AdditionalShadowOffset1; // xy: offset2, zw: offset3
  69. float4 _AdditionalShadowFadeParams; // x: additional light fade scale, y: additional light fade bias, z: 0.0, w: 0.0)
  70. float4 _AdditionalShadowmapSize; // (xy: 1/width and 1/height, zw: width and height)
  71. #if defined(ADDITIONAL_LIGHT_CALCULATE_SHADOWS)
  72. #if !USE_STRUCTURED_BUFFER_FOR_LIGHT_DATA
  73. // Point lights can use 6 shadow slices. Some mobile GPUs performance decrease drastically with uniform
  74. // blocks bigger than 8kb while others have a 64kb max uniform block size. This number ensures size of buffer
  75. // AdditionalLightShadows stays reasonable. It also avoids shader compilation errors on SHADER_API_GLES30
  76. // devices where max number of uniforms per shader GL_MAX_FRAGMENT_UNIFORM_VECTORS is low (224)
  77. float4 _AdditionalShadowParams[MAX_VISIBLE_LIGHTS]; // Per-light data
  78. float4x4 _AdditionalLightsWorldToShadow[MAX_VISIBLE_LIGHTS]; // Per-shadow-slice-data
  79. #endif
  80. #endif
  81. #ifndef SHADER_API_GLES3
  82. CBUFFER_END
  83. #endif
  84. #if defined(ADDITIONAL_LIGHT_CALCULATE_SHADOWS)
  85. #if USE_STRUCTURED_BUFFER_FOR_LIGHT_DATA
  86. StructuredBuffer<float4> _AdditionalShadowParams_SSBO; // Per-light data - TODO: test if splitting _AdditionalShadowParams_SSBO[lightIndex].w into a separate StructuredBuffer<int> buffer is faster
  87. StructuredBuffer<float4x4> _AdditionalLightsWorldToShadow_SSBO; // Per-shadow-slice-data - A shadow casting light can have 6 shadow slices (if it's a point light)
  88. #endif
  89. #endif
  90. float4 _ShadowBias; // x: depth bias, y: normal bias
  91. #define BEYOND_SHADOW_FAR(shadowCoord) shadowCoord.z <= 0.0 || shadowCoord.z >= 1.0
  92. // Should match: UnityEngine.Rendering.Universal + 1
  93. #define SOFT_SHADOW_QUALITY_OFF half(0.0)
  94. #define SOFT_SHADOW_QUALITY_LOW half(1.0)
  95. #define SOFT_SHADOW_QUALITY_MEDIUM half(2.0)
  96. #define SOFT_SHADOW_QUALITY_HIGH half(3.0)
  97. struct ShadowSamplingData
  98. {
  99. half4 shadowOffset0;
  100. half4 shadowOffset1;
  101. float4 shadowmapSize;
  102. half softShadowQuality;
  103. };
  104. ShadowSamplingData GetMainLightShadowSamplingData()
  105. {
  106. ShadowSamplingData shadowSamplingData;
  107. // shadowOffsets are used in SampleShadowmapFiltered for low quality soft shadows.
  108. shadowSamplingData.shadowOffset0 = half4(_MainLightShadowOffset0);
  109. shadowSamplingData.shadowOffset1 = half4(_MainLightShadowOffset1);
  110. // shadowmapSize is used in SampleShadowmapFiltered otherwise
  111. shadowSamplingData.shadowmapSize = _MainLightShadowmapSize;
  112. shadowSamplingData.softShadowQuality = half(_MainLightShadowParams.y);
  113. return shadowSamplingData;
  114. }
  115. ShadowSamplingData GetAdditionalLightShadowSamplingData(int index)
  116. {
  117. ShadowSamplingData shadowSamplingData = (ShadowSamplingData)0;
  118. #if defined(ADDITIONAL_LIGHT_CALCULATE_SHADOWS)
  119. // shadowOffsets are used in SampleShadowmapFiltered for low quality soft shadows.
  120. shadowSamplingData.shadowOffset0 = _AdditionalShadowOffset0;
  121. shadowSamplingData.shadowOffset1 = _AdditionalShadowOffset1;
  122. // shadowmapSize is used in SampleShadowmapFiltered otherwise.
  123. shadowSamplingData.shadowmapSize = _AdditionalShadowmapSize;
  124. shadowSamplingData.softShadowQuality = _AdditionalShadowParams[index].y;
  125. #endif
  126. return shadowSamplingData;
  127. }
  128. // ShadowParams
  129. // x: ShadowStrength
  130. // y: 1.0 if shadow is soft, 0.0 otherwise
  131. half4 GetMainLightShadowParams()
  132. {
  133. return half4(_MainLightShadowParams);
  134. }
  135. // ShadowParams
  136. // x: ShadowStrength
  137. // y: >= 1.0 if shadow is soft, 0.0 otherwise. Higher value for higher quality. (1.0 == low, 2.0 == medium, 3.0 == high)
  138. // z: 1.0 if cast by a point light (6 shadow slices), 0.0 if cast by a spot light (1 shadow slice)
  139. // w: first shadow slice index for this light, there can be 6 in case of point lights. (-1 for non-shadow-casting-lights)
  140. half4 GetAdditionalLightShadowParams(int lightIndex)
  141. {
  142. half4 results;
  143. #if defined(ADDITIONAL_LIGHT_CALCULATE_SHADOWS)
  144. #if USE_STRUCTURED_BUFFER_FOR_LIGHT_DATA
  145. results = _AdditionalShadowParams_SSBO[lightIndex];
  146. #else
  147. results = _AdditionalShadowParams[lightIndex];
  148. results.w = lightIndex < 0 ? -1 : results.w;
  149. #endif
  150. #else
  151. // Same defaults as set in AdditionalLightsShadowCasterPass.cs
  152. return half4(0, 0, 0, -1);
  153. #endif
  154. return results;
  155. }
  156. half SampleScreenSpaceShadowmap(float4 shadowCoord)
  157. {
  158. shadowCoord.xy /= max(0.00001, shadowCoord.w); // Prevent division by zero.
  159. // The stereo transform has to happen after the manual perspective divide
  160. shadowCoord.xy = UnityStereoTransformScreenSpaceTex(shadowCoord.xy);
  161. #if defined(UNITY_STEREO_INSTANCING_ENABLED) || defined(UNITY_STEREO_MULTIVIEW_ENABLED)
  162. half attenuation = SAMPLE_TEXTURE2D_ARRAY(_ScreenSpaceShadowmapTexture, sampler_PointClamp, shadowCoord.xy, unity_StereoEyeIndex).x;
  163. #else
  164. half attenuation = half(SAMPLE_TEXTURE2D(_ScreenSpaceShadowmapTexture, sampler_PointClamp, shadowCoord.xy).x);
  165. #endif
  166. return attenuation;
  167. }
  168. real SampleShadowmapFilteredLowQuality(TEXTURE2D_SHADOW_PARAM(ShadowMap, sampler_ShadowMap), float4 shadowCoord, ShadowSamplingData samplingData)
  169. {
  170. // 4-tap hardware comparison
  171. real4 attenuation4;
  172. attenuation4.x = real(SAMPLE_TEXTURE2D_SHADOW(ShadowMap, sampler_ShadowMap, shadowCoord.xyz + float3(samplingData.shadowOffset0.xy, 0)));
  173. attenuation4.y = real(SAMPLE_TEXTURE2D_SHADOW(ShadowMap, sampler_ShadowMap, shadowCoord.xyz + float3(samplingData.shadowOffset0.zw, 0)));
  174. attenuation4.z = real(SAMPLE_TEXTURE2D_SHADOW(ShadowMap, sampler_ShadowMap, shadowCoord.xyz + float3(samplingData.shadowOffset1.xy, 0)));
  175. attenuation4.w = real(SAMPLE_TEXTURE2D_SHADOW(ShadowMap, sampler_ShadowMap, shadowCoord.xyz + float3(samplingData.shadowOffset1.zw, 0)));
  176. return dot(attenuation4, real(0.25));
  177. }
  178. real SampleShadowmapFilteredMediumQuality(TEXTURE2D_SHADOW_PARAM(ShadowMap, sampler_ShadowMap), float4 shadowCoord, ShadowSamplingData samplingData)
  179. {
  180. real fetchesWeights[9];
  181. real2 fetchesUV[9];
  182. SampleShadow_ComputeSamples_Tent_5x5(samplingData.shadowmapSize, shadowCoord.xy, fetchesWeights, fetchesUV);
  183. return fetchesWeights[0] * SAMPLE_TEXTURE2D_SHADOW(ShadowMap, sampler_ShadowMap, float3(fetchesUV[0].xy, shadowCoord.z))
  184. + fetchesWeights[1] * SAMPLE_TEXTURE2D_SHADOW(ShadowMap, sampler_ShadowMap, float3(fetchesUV[1].xy, shadowCoord.z))
  185. + fetchesWeights[2] * SAMPLE_TEXTURE2D_SHADOW(ShadowMap, sampler_ShadowMap, float3(fetchesUV[2].xy, shadowCoord.z))
  186. + fetchesWeights[3] * SAMPLE_TEXTURE2D_SHADOW(ShadowMap, sampler_ShadowMap, float3(fetchesUV[3].xy, shadowCoord.z))
  187. + fetchesWeights[4] * SAMPLE_TEXTURE2D_SHADOW(ShadowMap, sampler_ShadowMap, float3(fetchesUV[4].xy, shadowCoord.z))
  188. + fetchesWeights[5] * SAMPLE_TEXTURE2D_SHADOW(ShadowMap, sampler_ShadowMap, float3(fetchesUV[5].xy, shadowCoord.z))
  189. + fetchesWeights[6] * SAMPLE_TEXTURE2D_SHADOW(ShadowMap, sampler_ShadowMap, float3(fetchesUV[6].xy, shadowCoord.z))
  190. + fetchesWeights[7] * SAMPLE_TEXTURE2D_SHADOW(ShadowMap, sampler_ShadowMap, float3(fetchesUV[7].xy, shadowCoord.z))
  191. + fetchesWeights[8] * SAMPLE_TEXTURE2D_SHADOW(ShadowMap, sampler_ShadowMap, float3(fetchesUV[8].xy, shadowCoord.z));
  192. }
  193. real SampleShadowmapFilteredHighQuality(TEXTURE2D_SHADOW_PARAM(ShadowMap, sampler_ShadowMap), float4 shadowCoord, ShadowSamplingData samplingData)
  194. {
  195. real fetchesWeights[16];
  196. real2 fetchesUV[16];
  197. SampleShadow_ComputeSamples_Tent_7x7(samplingData.shadowmapSize, shadowCoord.xy, fetchesWeights, fetchesUV);
  198. return fetchesWeights[0] * SAMPLE_TEXTURE2D_SHADOW(ShadowMap, sampler_ShadowMap, float3(fetchesUV[0].xy, shadowCoord.z))
  199. + fetchesWeights[1] * SAMPLE_TEXTURE2D_SHADOW(ShadowMap, sampler_ShadowMap, float3(fetchesUV[1].xy, shadowCoord.z))
  200. + fetchesWeights[2] * SAMPLE_TEXTURE2D_SHADOW(ShadowMap, sampler_ShadowMap, float3(fetchesUV[2].xy, shadowCoord.z))
  201. + fetchesWeights[3] * SAMPLE_TEXTURE2D_SHADOW(ShadowMap, sampler_ShadowMap, float3(fetchesUV[3].xy, shadowCoord.z))
  202. + fetchesWeights[4] * SAMPLE_TEXTURE2D_SHADOW(ShadowMap, sampler_ShadowMap, float3(fetchesUV[4].xy, shadowCoord.z))
  203. + fetchesWeights[5] * SAMPLE_TEXTURE2D_SHADOW(ShadowMap, sampler_ShadowMap, float3(fetchesUV[5].xy, shadowCoord.z))
  204. + fetchesWeights[6] * SAMPLE_TEXTURE2D_SHADOW(ShadowMap, sampler_ShadowMap, float3(fetchesUV[6].xy, shadowCoord.z))
  205. + fetchesWeights[7] * SAMPLE_TEXTURE2D_SHADOW(ShadowMap, sampler_ShadowMap, float3(fetchesUV[7].xy, shadowCoord.z))
  206. + fetchesWeights[8] * SAMPLE_TEXTURE2D_SHADOW(ShadowMap, sampler_ShadowMap, float3(fetchesUV[8].xy, shadowCoord.z))
  207. + fetchesWeights[9] * SAMPLE_TEXTURE2D_SHADOW(ShadowMap, sampler_ShadowMap, float3(fetchesUV[9].xy, shadowCoord.z))
  208. + fetchesWeights[10] * SAMPLE_TEXTURE2D_SHADOW(ShadowMap, sampler_ShadowMap, float3(fetchesUV[10].xy, shadowCoord.z))
  209. + fetchesWeights[11] * SAMPLE_TEXTURE2D_SHADOW(ShadowMap, sampler_ShadowMap, float3(fetchesUV[11].xy, shadowCoord.z))
  210. + fetchesWeights[12] * SAMPLE_TEXTURE2D_SHADOW(ShadowMap, sampler_ShadowMap, float3(fetchesUV[12].xy, shadowCoord.z))
  211. + fetchesWeights[13] * SAMPLE_TEXTURE2D_SHADOW(ShadowMap, sampler_ShadowMap, float3(fetchesUV[13].xy, shadowCoord.z))
  212. + fetchesWeights[14] * SAMPLE_TEXTURE2D_SHADOW(ShadowMap, sampler_ShadowMap, float3(fetchesUV[14].xy, shadowCoord.z))
  213. + fetchesWeights[15] * SAMPLE_TEXTURE2D_SHADOW(ShadowMap, sampler_ShadowMap, float3(fetchesUV[15].xy, shadowCoord.z));
  214. }
  215. real SampleShadowmapFiltered(TEXTURE2D_SHADOW_PARAM(ShadowMap, sampler_ShadowMap), float4 shadowCoord, ShadowSamplingData samplingData)
  216. {
  217. real attenuation = real(1.0);
  218. if (samplingData.softShadowQuality == SOFT_SHADOW_QUALITY_LOW)
  219. {
  220. attenuation = SampleShadowmapFilteredLowQuality(TEXTURE2D_SHADOW_ARGS(ShadowMap, sampler_ShadowMap), shadowCoord, samplingData);
  221. }
  222. else if(samplingData.softShadowQuality == SOFT_SHADOW_QUALITY_MEDIUM)
  223. {
  224. attenuation = SampleShadowmapFilteredMediumQuality(TEXTURE2D_SHADOW_ARGS(ShadowMap, sampler_ShadowMap), shadowCoord, samplingData);
  225. }
  226. else // SOFT_SHADOW_QUALITY_HIGH
  227. {
  228. attenuation = SampleShadowmapFilteredHighQuality(TEXTURE2D_SHADOW_ARGS(ShadowMap, sampler_ShadowMap), shadowCoord, samplingData);
  229. }
  230. return attenuation;
  231. }
  232. real SampleShadowmap(TEXTURE2D_SHADOW_PARAM(ShadowMap, sampler_ShadowMap), float4 shadowCoord, ShadowSamplingData samplingData, half4 shadowParams, bool isPerspectiveProjection = true)
  233. {
  234. // Compiler will optimize this branch away as long as isPerspectiveProjection is known at compile time
  235. if (isPerspectiveProjection)
  236. shadowCoord.xyz /= shadowCoord.w;
  237. real attenuation;
  238. real shadowStrength = shadowParams.x;
  239. // Quality levels are only for platforms requiring strict static branches
  240. #if defined(_SHADOWS_SOFT_LOW)
  241. attenuation = SampleShadowmapFilteredLowQuality(TEXTURE2D_SHADOW_ARGS(ShadowMap, sampler_ShadowMap), shadowCoord, samplingData);
  242. #elif defined(_SHADOWS_SOFT_MEDIUM)
  243. attenuation = SampleShadowmapFilteredMediumQuality(TEXTURE2D_SHADOW_ARGS(ShadowMap, sampler_ShadowMap), shadowCoord, samplingData);
  244. #elif defined(_SHADOWS_SOFT_HIGH)
  245. attenuation = SampleShadowmapFilteredHighQuality(TEXTURE2D_SHADOW_ARGS(ShadowMap, sampler_ShadowMap), shadowCoord, samplingData);
  246. #elif defined(_SHADOWS_SOFT)
  247. if (shadowParams.y > SOFT_SHADOW_QUALITY_OFF)
  248. {
  249. attenuation = SampleShadowmapFiltered(TEXTURE2D_SHADOW_ARGS(ShadowMap, sampler_ShadowMap), shadowCoord, samplingData);
  250. }
  251. else
  252. {
  253. attenuation = real(SAMPLE_TEXTURE2D_SHADOW(ShadowMap, sampler_ShadowMap, shadowCoord.xyz));
  254. }
  255. #else
  256. attenuation = real(SAMPLE_TEXTURE2D_SHADOW(ShadowMap, sampler_ShadowMap, shadowCoord.xyz));
  257. #endif
  258. attenuation = LerpWhiteTo(attenuation, shadowStrength);
  259. // Shadow coords that fall out of the light frustum volume must always return attenuation 1.0
  260. // TODO: We could use branch here to save some perf on some platforms.
  261. return BEYOND_SHADOW_FAR(shadowCoord) ? 1.0 : attenuation;
  262. }
  263. half ComputeCascadeIndex(float3 positionWS)
  264. {
  265. float3 fromCenter0 = positionWS - _CascadeShadowSplitSpheres0.xyz;
  266. float3 fromCenter1 = positionWS - _CascadeShadowSplitSpheres1.xyz;
  267. float3 fromCenter2 = positionWS - _CascadeShadowSplitSpheres2.xyz;
  268. float3 fromCenter3 = positionWS - _CascadeShadowSplitSpheres3.xyz;
  269. float4 distances2 = float4(dot(fromCenter0, fromCenter0), dot(fromCenter1, fromCenter1), dot(fromCenter2, fromCenter2), dot(fromCenter3, fromCenter3));
  270. half4 weights = half4(distances2 < _CascadeShadowSplitSphereRadii);
  271. weights.yzw = saturate(weights.yzw - weights.xyz);
  272. return half(4.0) - dot(weights, half4(4, 3, 2, 1));
  273. }
  274. float4 TransformWorldToShadowCoord(float3 positionWS)
  275. {
  276. #ifdef _MAIN_LIGHT_SHADOWS_CASCADE
  277. half cascadeIndex = ComputeCascadeIndex(positionWS);
  278. #else
  279. half cascadeIndex = half(0.0);
  280. #endif
  281. float4 shadowCoord = mul(_MainLightWorldToShadow[cascadeIndex], float4(positionWS, 1.0));
  282. return float4(shadowCoord.xyz, 0);
  283. }
  284. half MainLightRealtimeShadow(float4 shadowCoord)
  285. {
  286. #if !defined(MAIN_LIGHT_CALCULATE_SHADOWS)
  287. return half(1.0);
  288. #elif defined(_MAIN_LIGHT_SHADOWS_SCREEN) && !defined(_SURFACE_TYPE_TRANSPARENT)
  289. return SampleScreenSpaceShadowmap(shadowCoord);
  290. #else
  291. ShadowSamplingData shadowSamplingData = GetMainLightShadowSamplingData();
  292. half4 shadowParams = GetMainLightShadowParams();
  293. return SampleShadowmap(TEXTURE2D_ARGS(_MainLightShadowmapTexture, sampler_LinearClampCompare), shadowCoord, shadowSamplingData, shadowParams, false);
  294. #endif
  295. }
  296. // returns 0.0 if position is in light's shadow
  297. // returns 1.0 if position is in light
  298. half AdditionalLightRealtimeShadow(int lightIndex, float3 positionWS, half3 lightDirection)
  299. {
  300. #if defined(ADDITIONAL_LIGHT_CALCULATE_SHADOWS)
  301. ShadowSamplingData shadowSamplingData = GetAdditionalLightShadowSamplingData(lightIndex);
  302. half4 shadowParams = GetAdditionalLightShadowParams(lightIndex);
  303. int shadowSliceIndex = shadowParams.w;
  304. if (shadowSliceIndex < 0)
  305. return 1.0;
  306. half isPointLight = shadowParams.z;
  307. UNITY_BRANCH
  308. if (isPointLight)
  309. {
  310. // This is a point light, we have to find out which shadow slice to sample from
  311. float cubemapFaceId = CubeMapFaceID(-lightDirection);
  312. shadowSliceIndex += cubemapFaceId;
  313. }
  314. #if USE_STRUCTURED_BUFFER_FOR_LIGHT_DATA
  315. float4 shadowCoord = mul(_AdditionalLightsWorldToShadow_SSBO[shadowSliceIndex], float4(positionWS, 1.0));
  316. #else
  317. float4 shadowCoord = mul(_AdditionalLightsWorldToShadow[shadowSliceIndex], float4(positionWS, 1.0));
  318. #endif
  319. return SampleShadowmap(TEXTURE2D_ARGS(_AdditionalLightsShadowmapTexture, sampler_LinearClampCompare), shadowCoord, shadowSamplingData, shadowParams, true);
  320. #else
  321. return half(1.0);
  322. #endif
  323. }
  324. half GetMainLightShadowFade(float3 positionWS)
  325. {
  326. float3 camToPixel = positionWS - _WorldSpaceCameraPos;
  327. float distanceCamToPixel2 = dot(camToPixel, camToPixel);
  328. float fade = saturate(distanceCamToPixel2 * float(_MainLightShadowParams.z) + float(_MainLightShadowParams.w));
  329. return half(fade);
  330. }
  331. half GetAdditionalLightShadowFade(float3 positionWS)
  332. {
  333. #if defined(ADDITIONAL_LIGHT_CALCULATE_SHADOWS)
  334. float3 camToPixel = positionWS - _WorldSpaceCameraPos;
  335. float distanceCamToPixel2 = dot(camToPixel, camToPixel);
  336. float fade = saturate(distanceCamToPixel2 * float(_AdditionalShadowFadeParams.x) + float(_AdditionalShadowFadeParams.y));
  337. return half(fade);
  338. #else
  339. return half(1.0);
  340. #endif
  341. }
  342. half MixRealtimeAndBakedShadows(half realtimeShadow, half bakedShadow, half shadowFade)
  343. {
  344. #if defined(LIGHTMAP_SHADOW_MIXING)
  345. return min(lerp(realtimeShadow, 1, shadowFade), bakedShadow);
  346. #else
  347. return lerp(realtimeShadow, bakedShadow, shadowFade);
  348. #endif
  349. }
  350. half BakedShadow(half4 shadowMask, half4 occlusionProbeChannels)
  351. {
  352. // Here occlusionProbeChannels used as mask selector to select shadows in shadowMask
  353. // If occlusionProbeChannels all components are zero we use default baked shadow value 1.0
  354. // This code is optimized for mobile platforms:
  355. // half bakedShadow = any(occlusionProbeChannels) ? dot(shadowMask, occlusionProbeChannels) : 1.0h;
  356. half bakedShadow = half(1.0) + dot(shadowMask - half(1.0), occlusionProbeChannels);
  357. return bakedShadow;
  358. }
  359. half MainLightShadow(float4 shadowCoord, float3 positionWS, half4 shadowMask, half4 occlusionProbeChannels)
  360. {
  361. half realtimeShadow = MainLightRealtimeShadow(shadowCoord);
  362. #ifdef CALCULATE_BAKED_SHADOWS
  363. half bakedShadow = BakedShadow(shadowMask, occlusionProbeChannels);
  364. #else
  365. half bakedShadow = half(1.0);
  366. #endif
  367. #ifdef MAIN_LIGHT_CALCULATE_SHADOWS
  368. half shadowFade = GetMainLightShadowFade(positionWS);
  369. #else
  370. half shadowFade = half(1.0);
  371. #endif
  372. return MixRealtimeAndBakedShadows(realtimeShadow, bakedShadow, shadowFade);
  373. }
  374. half AdditionalLightShadow(int lightIndex, float3 positionWS, half3 lightDirection, half4 shadowMask, half4 occlusionProbeChannels)
  375. {
  376. half realtimeShadow = AdditionalLightRealtimeShadow(lightIndex, positionWS, lightDirection);
  377. #ifdef CALCULATE_BAKED_SHADOWS
  378. half bakedShadow = BakedShadow(shadowMask, occlusionProbeChannels);
  379. #else
  380. half bakedShadow = half(1.0);
  381. #endif
  382. #ifdef ADDITIONAL_LIGHT_CALCULATE_SHADOWS
  383. half shadowFade = GetAdditionalLightShadowFade(positionWS);
  384. #else
  385. half shadowFade = half(1.0);
  386. #endif
  387. return MixRealtimeAndBakedShadows(realtimeShadow, bakedShadow, shadowFade);
  388. }
  389. float4 GetShadowCoord(VertexPositionInputs vertexInput)
  390. {
  391. #if defined(_MAIN_LIGHT_SHADOWS_SCREEN) && !defined(_SURFACE_TYPE_TRANSPARENT)
  392. return ComputeScreenPos(vertexInput.positionCS);
  393. #else
  394. return TransformWorldToShadowCoord(vertexInput.positionWS);
  395. #endif
  396. }
  397. float3 ApplyShadowBias(float3 positionWS, float3 normalWS, float3 lightDirection)
  398. {
  399. float invNdotL = 1.0 - saturate(dot(lightDirection, normalWS));
  400. float scale = invNdotL * _ShadowBias.y;
  401. // normal bias is negative since we want to apply an inset normal offset
  402. positionWS = lightDirection * _ShadowBias.xxx + positionWS;
  403. positionWS = normalWS * scale.xxx + positionWS;
  404. return positionWS;
  405. }
  406. ///////////////////////////////////////////////////////////////////////////////
  407. // Deprecated /
  408. ///////////////////////////////////////////////////////////////////////////////
  409. // Renamed -> _MainLightShadowParams
  410. #define _MainLightShadowData _MainLightShadowParams
  411. // Deprecated: Use GetMainLightShadowFade or GetAdditionalLightShadowFade instead.
  412. float GetShadowFade(float3 positionWS)
  413. {
  414. float3 camToPixel = positionWS - _WorldSpaceCameraPos;
  415. float distanceCamToPixel2 = dot(camToPixel, camToPixel);
  416. float fade = saturate(distanceCamToPixel2 * float(_MainLightShadowParams.z) + float(_MainLightShadowParams.w));
  417. return fade * fade;
  418. }
  419. // Deprecated: Use GetShadowFade instead.
  420. float ApplyShadowFade(float shadowAttenuation, float3 positionWS)
  421. {
  422. float fade = GetShadowFade(positionWS);
  423. return shadowAttenuation + (1 - shadowAttenuation) * fade * fade;
  424. }
  425. // Deprecated: Use GetMainLightShadowParams instead.
  426. half GetMainLightShadowStrength()
  427. {
  428. return half(_MainLightShadowData.x);
  429. }
  430. // Deprecated: Use GetAdditionalLightShadowParams instead.
  431. half GetAdditionalLightShadowStrenth(int lightIndex)
  432. {
  433. #if defined(ADDITIONAL_LIGHT_CALCULATE_SHADOWS)
  434. #if USE_STRUCTURED_BUFFER_FOR_LIGHT_DATA
  435. return half(_AdditionalShadowParams_SSBO[lightIndex].x);
  436. #else
  437. return half(_AdditionalShadowParams[lightIndex].x);
  438. #endif
  439. #else
  440. return half(1.0);
  441. #endif
  442. }
  443. // Deprecated: Use SampleShadowmap that takes shadowParams instead of strength.
  444. real SampleShadowmap(float4 shadowCoord, TEXTURE2D_SHADOW_PARAM(ShadowMap, sampler_ShadowMap), ShadowSamplingData samplingData, half shadowStrength, bool isPerspectiveProjection = true)
  445. {
  446. half4 shadowParams = half4(shadowStrength, 1.0, 0.0, 0.0);
  447. return SampleShadowmap(TEXTURE2D_SHADOW_ARGS(ShadowMap, sampler_ShadowMap), shadowCoord, samplingData, shadowParams, isPerspectiveProjection);
  448. }
  449. // Deprecated: Use AdditionalLightRealtimeShadow(int lightIndex, float3 positionWS, half3 lightDirection) in Shadows.hlsl instead, as it supports Point Light shadows
  450. half AdditionalLightRealtimeShadow(int lightIndex, float3 positionWS)
  451. {
  452. return AdditionalLightRealtimeShadow(lightIndex, positionWS, half3(1, 0, 0));
  453. }
  454. #endif