RealtimeLights.hlsl 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349
  1. #ifndef UNIVERSAL_REALTIME_LIGHTS_INCLUDED
  2. #define UNIVERSAL_REALTIME_LIGHTS_INCLUDED
  3. #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/AmbientOcclusion.hlsl"
  4. #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Input.hlsl"
  5. #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Shadows.hlsl"
  6. #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/LightCookie/LightCookie.hlsl"
  7. #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Clustering.hlsl"
  8. ///////////////////////////////////////////////////////////////////////////////
  9. // Light Layers /
  10. ///////////////////////////////////////////////////////////////////////////////
  11. // Note: we need to mask out only 8bits of the layer mask before encoding it as otherwise any value > 255 will map to all layers active if save in a buffer
  12. uint GetMeshRenderingLightLayer()
  13. {
  14. #ifdef _LIGHT_LAYERS
  15. return (asuint(unity_RenderingLayer.x) & RENDERING_LIGHT_LAYERS_MASK) >> RENDERING_LIGHT_LAYERS_MASK_SHIFT;
  16. #else
  17. return DEFAULT_LIGHT_LAYERS;
  18. #endif
  19. }
  20. // Abstraction over Light shading data.
  21. struct Light
  22. {
  23. half3 direction;
  24. half3 color;
  25. half distanceAttenuation;
  26. half shadowAttenuation;
  27. uint layerMask;
  28. };
  29. // WebGL1 does not support the variable conditioned for loops used for additional lights
  30. #if !defined(_USE_WEBGL1_LIGHTS) && defined(UNITY_PLATFORM_WEBGL) && !defined(SHADER_API_GLES3)
  31. #define _USE_WEBGL1_LIGHTS 1
  32. #define _WEBGL1_MAX_LIGHTS 8
  33. #else
  34. #define _USE_WEBGL1_LIGHTS 0
  35. #endif
  36. #if USE_CLUSTERED_LIGHTING
  37. #define LIGHT_LOOP_BEGIN(lightCount) \
  38. ClusteredLightLoop cll = ClusteredLightLoopInit(inputData.normalizedScreenSpaceUV, inputData.positionWS); \
  39. while (ClusteredLightLoopNextWord(cll)) { while (ClusteredLightLoopNextLight(cll)) { \
  40. uint lightIndex = ClusteredLightLoopGetLightIndex(cll);
  41. #define LIGHT_LOOP_END } }
  42. #elif !_USE_WEBGL1_LIGHTS
  43. #define LIGHT_LOOP_BEGIN(lightCount) \
  44. for (uint lightIndex = 0u; lightIndex < lightCount; ++lightIndex) {
  45. #define LIGHT_LOOP_END }
  46. #else
  47. // WebGL 1 doesn't support variable for loop conditions
  48. #define LIGHT_LOOP_BEGIN(lightCount) \
  49. for (int lightIndex = 0; lightIndex < _WEBGL1_MAX_LIGHTS; ++lightIndex) { \
  50. if (lightIndex >= (int)lightCount) break;
  51. #define LIGHT_LOOP_END }
  52. #endif
  53. ///////////////////////////////////////////////////////////////////////////////
  54. // Attenuation Functions /
  55. ///////////////////////////////////////////////////////////////////////////////
  56. // Matches Unity Vanila attenuation
  57. // Attenuation smoothly decreases to light range.
  58. float DistanceAttenuation(float distanceSqr, half2 distanceAttenuation)
  59. {
  60. // We use a shared distance attenuation for additional directional and puctual lights
  61. // for directional lights attenuation will be 1
  62. float lightAtten = rcp(distanceSqr);
  63. float2 distanceAttenuationFloat = float2(distanceAttenuation);
  64. #if SHADER_HINT_NICE_QUALITY
  65. // Use the smoothing factor also used in the Unity lightmapper.
  66. half factor = half(distanceSqr * distanceAttenuationFloat.x);
  67. half smoothFactor = saturate(half(1.0) - factor * factor);
  68. smoothFactor = smoothFactor * smoothFactor;
  69. #else
  70. // We need to smoothly fade attenuation to light range. We start fading linearly at 80% of light range
  71. // Therefore:
  72. // fadeDistance = (0.8 * 0.8 * lightRangeSq)
  73. // smoothFactor = (lightRangeSqr - distanceSqr) / (lightRangeSqr - fadeDistance)
  74. // We can rewrite that to fit a MAD by doing
  75. // distanceSqr * (1.0 / (fadeDistanceSqr - lightRangeSqr)) + (-lightRangeSqr / (fadeDistanceSqr - lightRangeSqr)
  76. // distanceSqr * distanceAttenuation.y + distanceAttenuation.z
  77. half smoothFactor = half(saturate(distanceSqr * distanceAttenuationFloat.x + distanceAttenuationFloat.y));
  78. #endif
  79. return lightAtten * smoothFactor;
  80. }
  81. half AngleAttenuation(half3 spotDirection, half3 lightDirection, half2 spotAttenuation)
  82. {
  83. // Spot Attenuation with a linear falloff can be defined as
  84. // (SdotL - cosOuterAngle) / (cosInnerAngle - cosOuterAngle)
  85. // This can be rewritten as
  86. // invAngleRange = 1.0 / (cosInnerAngle - cosOuterAngle)
  87. // SdotL * invAngleRange + (-cosOuterAngle * invAngleRange)
  88. // SdotL * spotAttenuation.x + spotAttenuation.y
  89. // If we precompute the terms in a MAD instruction
  90. half SdotL = dot(spotDirection, lightDirection);
  91. half atten = saturate(SdotL * spotAttenuation.x + spotAttenuation.y);
  92. return atten * atten;
  93. }
  94. ///////////////////////////////////////////////////////////////////////////////
  95. // Light Abstraction //
  96. ///////////////////////////////////////////////////////////////////////////////
  97. Light GetMainLight()
  98. {
  99. Light light;
  100. light.direction = half3(_MainLightPosition.xyz);
  101. #if USE_CLUSTERED_LIGHTING
  102. light.distanceAttenuation = 1.0;
  103. #else
  104. light.distanceAttenuation = unity_LightData.z; // unity_LightData.z is 1 when not culled by the culling mask, otherwise 0.
  105. #endif
  106. light.shadowAttenuation = 1.0;
  107. light.color = _MainLightColor.rgb;
  108. #ifdef _LIGHT_LAYERS
  109. light.layerMask = _MainLightLayerMask;
  110. #else
  111. light.layerMask = DEFAULT_LIGHT_LAYERS;
  112. #endif
  113. return light;
  114. }
  115. Light GetMainLight(float4 shadowCoord)
  116. {
  117. Light light = GetMainLight();
  118. light.shadowAttenuation = MainLightRealtimeShadow(shadowCoord);
  119. return light;
  120. }
  121. Light GetMainLight(float4 shadowCoord, float3 positionWS, half4 shadowMask)
  122. {
  123. Light light = GetMainLight();
  124. light.shadowAttenuation = MainLightShadow(shadowCoord, positionWS, shadowMask, _MainLightOcclusionProbes);
  125. #if defined(_LIGHT_COOKIES)
  126. real3 cookieColor = SampleMainLightCookie(positionWS);
  127. light.color *= cookieColor;
  128. #endif
  129. return light;
  130. }
  131. Light GetMainLight(InputData inputData, half4 shadowMask, AmbientOcclusionFactor aoFactor)
  132. {
  133. Light light = GetMainLight(inputData.shadowCoord, inputData.positionWS, shadowMask);
  134. #if defined(_SCREEN_SPACE_OCCLUSION) && !defined(_SURFACE_TYPE_TRANSPARENT)
  135. if (IsLightingFeatureEnabled(DEBUGLIGHTINGFEATUREFLAGS_AMBIENT_OCCLUSION))
  136. {
  137. light.color *= aoFactor.directAmbientOcclusion;
  138. }
  139. #endif
  140. return light;
  141. }
  142. // Fills a light struct given a perObjectLightIndex
  143. Light GetAdditionalPerObjectLight(int perObjectLightIndex, float3 positionWS)
  144. {
  145. // Abstraction over Light input constants
  146. #if USE_STRUCTURED_BUFFER_FOR_LIGHT_DATA
  147. float4 lightPositionWS = _AdditionalLightsBuffer[perObjectLightIndex].position;
  148. half3 color = _AdditionalLightsBuffer[perObjectLightIndex].color.rgb;
  149. half4 distanceAndSpotAttenuation = _AdditionalLightsBuffer[perObjectLightIndex].attenuation;
  150. half4 spotDirection = _AdditionalLightsBuffer[perObjectLightIndex].spotDirection;
  151. #ifdef _LIGHT_LAYERS
  152. uint lightLayerMask = _AdditionalLightsBuffer[perObjectLightIndex].layerMask;
  153. #else
  154. uint lightLayerMask = DEFAULT_LIGHT_LAYERS;
  155. #endif
  156. #else
  157. float4 lightPositionWS = _AdditionalLightsPosition[perObjectLightIndex];
  158. half3 color = _AdditionalLightsColor[perObjectLightIndex].rgb;
  159. half4 distanceAndSpotAttenuation = _AdditionalLightsAttenuation[perObjectLightIndex];
  160. half4 spotDirection = _AdditionalLightsSpotDir[perObjectLightIndex];
  161. #ifdef _LIGHT_LAYERS
  162. uint lightLayerMask = asuint(_AdditionalLightsLayerMasks[perObjectLightIndex]);
  163. #else
  164. uint lightLayerMask = DEFAULT_LIGHT_LAYERS;
  165. #endif
  166. #endif
  167. // Directional lights store direction in lightPosition.xyz and have .w set to 0.0.
  168. // This way the following code will work for both directional and punctual lights.
  169. float3 lightVector = lightPositionWS.xyz - positionWS * lightPositionWS.w;
  170. float distanceSqr = max(dot(lightVector, lightVector), HALF_MIN);
  171. half3 lightDirection = half3(lightVector * rsqrt(distanceSqr));
  172. half attenuation = half(DistanceAttenuation(distanceSqr, distanceAndSpotAttenuation.xy) * AngleAttenuation(spotDirection.xyz, lightDirection, distanceAndSpotAttenuation.zw));
  173. Light light;
  174. light.direction = lightDirection;
  175. light.distanceAttenuation = attenuation;
  176. light.shadowAttenuation = 1.0; // This value can later be overridden in GetAdditionalLight(uint i, float3 positionWS, half4 shadowMask)
  177. light.color = color;
  178. light.layerMask = lightLayerMask;
  179. return light;
  180. }
  181. uint GetPerObjectLightIndexOffset()
  182. {
  183. #if USE_STRUCTURED_BUFFER_FOR_LIGHT_DATA
  184. return uint(unity_LightData.x);
  185. #else
  186. return 0;
  187. #endif
  188. }
  189. // Returns a per-object index given a loop index.
  190. // This abstract the underlying data implementation for storing lights/light indices
  191. int GetPerObjectLightIndex(uint index)
  192. {
  193. /////////////////////////////////////////////////////////////////////////////////////////////
  194. // Structured Buffer Path /
  195. // /
  196. // Lights and light indices are stored in StructuredBuffer. We can just index them. /
  197. // Currently all non-mobile platforms take this path :( /
  198. // There are limitation in mobile GPUs to use SSBO (performance / no vertex shader support) /
  199. /////////////////////////////////////////////////////////////////////////////////////////////
  200. #if USE_STRUCTURED_BUFFER_FOR_LIGHT_DATA
  201. uint offset = uint(unity_LightData.x);
  202. return _AdditionalLightsIndices[offset + index];
  203. /////////////////////////////////////////////////////////////////////////////////////////////
  204. // UBO path /
  205. // /
  206. // We store 8 light indices in half4 unity_LightIndices[2]; /
  207. // Due to memory alignment unity doesn't support int[] or float[] /
  208. // Even trying to reinterpret cast the unity_LightIndices to float[] won't work /
  209. // it will cast to float4[] and create extra register pressure. :( /
  210. /////////////////////////////////////////////////////////////////////////////////////////////
  211. #elif !defined(SHADER_API_GLES)
  212. // since index is uint shader compiler will implement
  213. // div & mod as bitfield ops (shift and mask).
  214. // TODO: Can we index a float4? Currently compiler is
  215. // replacing unity_LightIndicesX[i] with a dp4 with identity matrix.
  216. // u_xlat16_40 = dot(unity_LightIndices[int(u_xlatu13)], ImmCB_0_0_0[u_xlati1]);
  217. // This increases both arithmetic and register pressure.
  218. //
  219. // NOTE: min16float4 bug workaround.
  220. // Take the "vec4" part into float4 tmp variable in order to force float4 math.
  221. // It appears indexing half4 as min16float4 on DX11 can fail. (dp4 {min16f})
  222. float4 tmp = unity_LightIndices[index / 4];
  223. return int(tmp[index % 4]);
  224. #else
  225. // Fallback to GLES2. No bitfield magic here :(.
  226. // We limit to 4 indices per object and only sample unity_4LightIndices0.
  227. // Conditional moves are branch free even on mali-400
  228. // small arithmetic cost but no extra register pressure from ImmCB_0_0_0 matrix.
  229. half indexHalf = half(index);
  230. half2 lightIndex2 = (indexHalf < half(2.0)) ? unity_LightIndices[0].xy : unity_LightIndices[0].zw;
  231. half i_rem = (indexHalf < half(2.0)) ? indexHalf : indexHalf - half(2.0);
  232. return int((i_rem < half(1.0)) ? lightIndex2.x : lightIndex2.y);
  233. #endif
  234. }
  235. // Fills a light struct given a loop i index. This will convert the i
  236. // index to a perObjectLightIndex
  237. Light GetAdditionalLight(uint i, float3 positionWS)
  238. {
  239. #if USE_CLUSTERED_LIGHTING
  240. int lightIndex = i;
  241. #else
  242. int lightIndex = GetPerObjectLightIndex(i);
  243. #endif
  244. return GetAdditionalPerObjectLight(lightIndex, positionWS);
  245. }
  246. Light GetAdditionalLight(uint i, float3 positionWS, half4 shadowMask)
  247. {
  248. #if USE_CLUSTERED_LIGHTING
  249. int lightIndex = i;
  250. #else
  251. int lightIndex = GetPerObjectLightIndex(i);
  252. #endif
  253. Light light = GetAdditionalPerObjectLight(lightIndex, positionWS);
  254. #if USE_STRUCTURED_BUFFER_FOR_LIGHT_DATA
  255. half4 occlusionProbeChannels = _AdditionalLightsBuffer[lightIndex].occlusionProbeChannels;
  256. #else
  257. half4 occlusionProbeChannels = _AdditionalLightsOcclusionProbes[lightIndex];
  258. #endif
  259. light.shadowAttenuation = AdditionalLightShadow(lightIndex, positionWS, light.direction, shadowMask, occlusionProbeChannels);
  260. #if defined(_LIGHT_COOKIES)
  261. real3 cookieColor = SampleAdditionalLightCookie(lightIndex, positionWS);
  262. light.color *= cookieColor;
  263. #endif
  264. return light;
  265. }
  266. Light GetAdditionalLight(uint i, InputData inputData, half4 shadowMask, AmbientOcclusionFactor aoFactor)
  267. {
  268. Light light = GetAdditionalLight(i, inputData.positionWS, shadowMask);
  269. #if defined(_SCREEN_SPACE_OCCLUSION) && !defined(_SURFACE_TYPE_TRANSPARENT)
  270. if (IsLightingFeatureEnabled(DEBUGLIGHTINGFEATUREFLAGS_AMBIENT_OCCLUSION))
  271. {
  272. light.color *= aoFactor.directAmbientOcclusion;
  273. }
  274. #endif
  275. return light;
  276. }
  277. int GetAdditionalLightsCount()
  278. {
  279. #if USE_CLUSTERED_LIGHTING
  280. // Counting the number of lights in clustered requires traversing the bit list, and is not needed up front.
  281. return 0;
  282. #else
  283. // TODO: we need to expose in SRP api an ability for the pipeline cap the amount of lights
  284. // in the culling. This way we could do the loop branch with an uniform
  285. // This would be helpful to support baking exceeding lights in SH as well
  286. return int(min(_AdditionalLightsCount.x, unity_LightData.y));
  287. #endif
  288. }
  289. half4 CalculateShadowMask(InputData inputData)
  290. {
  291. // To ensure backward compatibility we have to avoid using shadowMask input, as it is not present in older shaders
  292. #if defined(SHADOWS_SHADOWMASK) && defined(LIGHTMAP_ON)
  293. half4 shadowMask = inputData.shadowMask;
  294. #elif !defined (LIGHTMAP_ON)
  295. half4 shadowMask = unity_ProbesOcclusion;
  296. #else
  297. half4 shadowMask = half4(1, 1, 1, 1);
  298. #endif
  299. return shadowMask;
  300. }
  301. #endif