DeferredLights.cs 116 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131
  1. using System.Runtime.CompilerServices;
  2. using UnityEngine.Experimental.Rendering;
  3. using UnityEngine.Profiling;
  4. using Unity.Collections;
  5. using Unity.Jobs;
  6. using Unity.Mathematics;
  7. using static Unity.Mathematics.math;
  8. //#define URP_HAS_BURST
  9. // TODO SimpleLit material, make sure when variant is !defined(_SPECGLOSSMAP) && !defined(_SPECULAR_COLOR), specular is correctly silenced.
  10. // TODO use InitializeSimpleLitSurfaceData() in all shader code
  11. // TODO use InitializeParticleLitSurfaceData() in forward pass for ParticleLitForwardPass.hlsl ? Similar refactoring for ParticleSimpleLitForwardPass.hlsl
  12. // TODO Make sure GPU buffers are uploaded without copying into Unity CommandBuffer memory
  13. // TODO BakedLit.shader has a Universal2D pass, but Unlit.shader doesn't have?
  14. namespace UnityEngine.Rendering.Universal.Internal
  15. {
  16. // Customization per platform.
  17. static class DeferredConfig
  18. {
  19. // Keep in sync with shader define USE_CBUFFER_FOR_DEPTHRANGE
  20. // Keep in sync with shader define USE_CBUFFER_FOR_TILELIST
  21. // Keep in sync with shader define USE_CBUFFER_FOR_LIGHTDATA
  22. // Keep in sync with shader define USE_CBUFFER_FOR_LIGHTLIST
  23. internal static bool IsOpenGL { get; set; }
  24. // DX10 uses SM 4.0. However URP shaders requires SM 4.5 or will use fallback to SM 2.0 shaders otherwise.
  25. // We will consider deferred renderer is not available when SM 2.0 shaders run.
  26. internal static bool IsDX10 { get; set; }
  27. // Constant buffers are used for data that a repeatedly fetched by shaders.
  28. // Structured buffers are used for data only consumed once.
  29. internal static bool UseCBufferForDepthRange
  30. {
  31. get
  32. {
  33. #if !UNITY_EDITOR && UNITY_SWITCH
  34. return false;
  35. #else
  36. return IsOpenGL;
  37. #endif
  38. }
  39. }
  40. internal static bool UseCBufferForTileList
  41. {
  42. get
  43. {
  44. #if !UNITY_EDITOR && UNITY_SWITCH
  45. return false;
  46. #else
  47. return IsOpenGL;
  48. #endif
  49. }
  50. }
  51. internal static bool UseCBufferForLightData
  52. {
  53. get
  54. {
  55. return true;
  56. }
  57. }
  58. internal static bool UseCBufferForLightList
  59. {
  60. get
  61. {
  62. #if !UNITY_EDITOR && UNITY_SWITCH
  63. return false;
  64. #else
  65. return IsOpenGL;
  66. #endif
  67. }
  68. }
  69. // Keep in sync with PREFERRED_CBUFFER_SIZE.
  70. public const int kPreferredCBufferSize = 64 * 1024;
  71. public const int kPreferredStructuredBufferSize = 128 * 1024;
  72. public const int kTilePixelWidth = 16;
  73. public const int kTilePixelHeight = 16;
  74. // Levels of hierarchical tiling. Each level process 4x4 finer tiles. For example:
  75. // For platforms using 16x16 px tiles, we use a 16x16px tiles grid, a 64x64px tiles grid, and a 256x256px tiles grid
  76. // For platforms using 8x8 px tiles, we use a 8x8px tiles grid, a 32x32px tiles grid, and a 128x128px tiles grid
  77. public const int kTilerDepth = 3;
  78. public const int kTilerSubdivisions = 4;
  79. public const int kAvgLightPerTile = 32;
  80. // On platforms where the tile dimensions is large (16x16), it may be faster to generate tileDepthInfo texture
  81. // with an intermediate mip level, as this allows spawning more pixel shaders (avoid GPU starvation).
  82. // Set to -1 to disable.
  83. #if UNITY_SWITCH || UNITY_IOS
  84. public const int kTileDepthInfoIntermediateLevel = 1;
  85. #else
  86. public const int kTileDepthInfoIntermediateLevel = -1;
  87. #endif
  88. #if !UNITY_EDITOR && UNITY_SWITCH
  89. public const bool kHasNativeQuadSupport = true;
  90. #else
  91. public const bool kHasNativeQuadSupport = false;
  92. #endif
  93. }
  94. internal enum LightFlag
  95. {
  96. // Keep in sync with kLightFlagSubtractiveMixedLighting.
  97. SubtractiveMixedLighting = 4
  98. }
  99. // Manages tiled-based deferred lights.
  100. internal class DeferredLights
  101. {
  102. internal static class ShaderConstants
  103. {
  104. public static readonly int _LitStencilRef = Shader.PropertyToID("_LitStencilRef");
  105. public static readonly int _LitStencilReadMask = Shader.PropertyToID("_LitStencilReadMask");
  106. public static readonly int _LitStencilWriteMask = Shader.PropertyToID("_LitStencilWriteMask");
  107. public static readonly int _SimpleLitStencilRef = Shader.PropertyToID("_SimpleLitStencilRef");
  108. public static readonly int _SimpleLitStencilReadMask = Shader.PropertyToID("_SimpleLitStencilReadMask");
  109. public static readonly int _SimpleLitStencilWriteMask = Shader.PropertyToID("_SimpleLitStencilWriteMask");
  110. public static readonly int _StencilRef = Shader.PropertyToID("_StencilRef");
  111. public static readonly int _StencilReadMask = Shader.PropertyToID("_StencilReadMask");
  112. public static readonly int _StencilWriteMask = Shader.PropertyToID("_StencilWriteMask");
  113. public static readonly int _LitPunctualStencilRef = Shader.PropertyToID("_LitPunctualStencilRef");
  114. public static readonly int _LitPunctualStencilReadMask = Shader.PropertyToID("_LitPunctualStencilReadMask");
  115. public static readonly int _LitPunctualStencilWriteMask = Shader.PropertyToID("_LitPunctualStencilWriteMask");
  116. public static readonly int _SimpleLitPunctualStencilRef = Shader.PropertyToID("_SimpleLitPunctualStencilRef");
  117. public static readonly int _SimpleLitPunctualStencilReadMask = Shader.PropertyToID("_SimpleLitPunctualStencilReadMask");
  118. public static readonly int _SimpleLitPunctualStencilWriteMask = Shader.PropertyToID("_SimpleLitPunctualStencilWriteMask");
  119. public static readonly int _LitDirStencilRef = Shader.PropertyToID("_LitDirStencilRef");
  120. public static readonly int _LitDirStencilReadMask = Shader.PropertyToID("_LitDirStencilReadMask");
  121. public static readonly int _LitDirStencilWriteMask = Shader.PropertyToID("_LitDirStencilWriteMask");
  122. public static readonly int _SimpleLitDirStencilRef = Shader.PropertyToID("_SimpleLitDirStencilRef");
  123. public static readonly int _SimpleLitDirStencilReadMask = Shader.PropertyToID("_SimpleLitDirStencilReadMask");
  124. public static readonly int _SimpleLitDirStencilWriteMask = Shader.PropertyToID("_SimpleLitDirStencilWriteMask");
  125. public static readonly int _ClearStencilRef = Shader.PropertyToID("_ClearStencilRef");
  126. public static readonly int _ClearStencilReadMask = Shader.PropertyToID("_ClearStencilReadMask");
  127. public static readonly int _ClearStencilWriteMask = Shader.PropertyToID("_ClearStencilWriteMask");
  128. public static readonly int UDepthRanges = Shader.PropertyToID("UDepthRanges");
  129. public static readonly int _DepthRanges = Shader.PropertyToID("_DepthRanges");
  130. public static readonly int _DownsamplingWidth = Shader.PropertyToID("_DownsamplingWidth");
  131. public static readonly int _DownsamplingHeight = Shader.PropertyToID("_DownsamplingHeight");
  132. public static readonly int _SourceShiftX = Shader.PropertyToID("_SourceShiftX");
  133. public static readonly int _SourceShiftY = Shader.PropertyToID("_SourceShiftY");
  134. public static readonly int _TileShiftX = Shader.PropertyToID("_TileShiftX");
  135. public static readonly int _TileShiftY = Shader.PropertyToID("_TileShiftY");
  136. public static readonly int _tileXCount = Shader.PropertyToID("_tileXCount");
  137. public static readonly int _DepthRangeOffset = Shader.PropertyToID("_DepthRangeOffset");
  138. public static readonly int _BitmaskTex = Shader.PropertyToID("_BitmaskTex");
  139. public static readonly int UTileList = Shader.PropertyToID("UTileList");
  140. public static readonly int _TileList = Shader.PropertyToID("_TileList");
  141. public static readonly int UPunctualLightBuffer = Shader.PropertyToID("UPunctualLightBuffer");
  142. public static readonly int _PunctualLightBuffer = Shader.PropertyToID("_PunctualLightBuffer");
  143. public static readonly int URelLightList = Shader.PropertyToID("URelLightList");
  144. public static readonly int _RelLightList = Shader.PropertyToID("_RelLightList");
  145. public static readonly int _TilePixelWidth = Shader.PropertyToID("_TilePixelWidth");
  146. public static readonly int _TilePixelHeight = Shader.PropertyToID("_TilePixelHeight");
  147. public static readonly int _InstanceOffset = Shader.PropertyToID("_InstanceOffset");
  148. public static readonly int _DepthTex = Shader.PropertyToID("_DepthTex");
  149. public static readonly int _DepthTexSize = Shader.PropertyToID("_DepthTexSize");
  150. public static readonly int _ScreenToWorld = Shader.PropertyToID("_ScreenToWorld");
  151. public static readonly int _unproject0 = Shader.PropertyToID("_unproject0");
  152. public static readonly int _unproject1 = Shader.PropertyToID("_unproject1");
  153. public static int _MainLightPosition = Shader.PropertyToID("_MainLightPosition"); // ForwardLights.LightConstantBuffer also refers to the same ShaderPropertyID - TODO: move this definition to a common location shared by other UniversalRP classes
  154. public static int _MainLightColor = Shader.PropertyToID("_MainLightColor"); // ForwardLights.LightConstantBuffer also refers to the same ShaderPropertyID - TODO: move this definition to a common location shared by other UniversalRP classes
  155. public static int _MainLightLayerMask = Shader.PropertyToID("_MainLightLayerMask"); // ForwardLights.LightConstantBuffer also refers to the same ShaderPropertyID - TODO: move this definition to a common location shared by other UniversalRP classes
  156. public static int _SpotLightScale = Shader.PropertyToID("_SpotLightScale");
  157. public static int _SpotLightBias = Shader.PropertyToID("_SpotLightBias");
  158. public static int _SpotLightGuard = Shader.PropertyToID("_SpotLightGuard");
  159. public static int _LightPosWS = Shader.PropertyToID("_LightPosWS");
  160. public static int _LightColor = Shader.PropertyToID("_LightColor");
  161. public static int _LightAttenuation = Shader.PropertyToID("_LightAttenuation");
  162. public static int _LightOcclusionProbInfo = Shader.PropertyToID("_LightOcclusionProbInfo");
  163. public static int _LightDirection = Shader.PropertyToID("_LightDirection");
  164. public static int _LightFlags = Shader.PropertyToID("_LightFlags");
  165. public static int _ShadowLightIndex = Shader.PropertyToID("_ShadowLightIndex");
  166. public static int _LightLayerMask = Shader.PropertyToID("_LightLayerMask");
  167. public static int _CookieLightIndex = Shader.PropertyToID("_CookieLightIndex");
  168. }
  169. // Disable Burst for now since there are issues on macos builds.
  170. #if URP_HAS_BURST
  171. [Unity.Burst.BurstCompile(CompileSynchronously = true)]
  172. #endif
  173. struct CullLightsJob : IJob
  174. {
  175. public DeferredTiler tiler;
  176. [ReadOnly]
  177. [Unity.Collections.LowLevel.Unsafe.NativeDisableContainerSafetyRestriction]
  178. public NativeArray<DeferredTiler.PrePunctualLight> prePunctualLights;
  179. [ReadOnly]
  180. [Unity.Collections.LowLevel.Unsafe.NativeDisableContainerSafetyRestriction]
  181. public NativeArray<ushort> coarseTiles;
  182. [ReadOnly]
  183. [Unity.Collections.LowLevel.Unsafe.NativeDisableContainerSafetyRestriction]
  184. public NativeArray<uint> coarseTileHeaders;
  185. public int coarseHeaderOffset;
  186. public int istart;
  187. public int iend;
  188. public int jstart;
  189. public int jend;
  190. public void Execute()
  191. {
  192. int coarseTileOffset = (int)coarseTileHeaders[coarseHeaderOffset + 0];
  193. int coarseVisLightCount = (int)coarseTileHeaders[coarseHeaderOffset + 1];
  194. if (tiler.TilerLevel != 0)
  195. {
  196. tiler.CullIntermediateLights(
  197. ref prePunctualLights,
  198. ref coarseTiles, coarseTileOffset, coarseVisLightCount,
  199. istart, iend, jstart, jend
  200. );
  201. }
  202. else
  203. {
  204. tiler.CullFinalLights(
  205. ref prePunctualLights,
  206. ref coarseTiles, coarseTileOffset, coarseVisLightCount,
  207. istart, iend, jstart, jend
  208. );
  209. }
  210. }
  211. }
  212. struct DrawCall
  213. {
  214. public ComputeBuffer tileList;
  215. public ComputeBuffer punctualLightBuffer;
  216. public ComputeBuffer relLightList;
  217. public int tileListSize;
  218. public int punctualLightBufferSize;
  219. public int relLightListSize;
  220. public int instanceOffset;
  221. public int instanceCount;
  222. }
  223. static readonly string[] k_GBufferNames = new string[]
  224. {
  225. "_GBuffer0",
  226. "_GBuffer1",
  227. "_GBuffer2",
  228. "_GBuffer3",
  229. "_GBuffer4",
  230. "_GBuffer5",
  231. "_GBuffer6"
  232. };
  233. static readonly string[] k_TileDeferredPassNames = new string[]
  234. {
  235. "Tiled Deferred Punctual Light (Lit)",
  236. "Tiled Deferred Punctual Light (SimpleLit)"
  237. };
  238. static readonly string[] k_StencilDeferredPassNames = new string[]
  239. {
  240. "Stencil Volume",
  241. "Deferred Punctual Light (Lit)",
  242. "Deferred Punctual Light (SimpleLit)",
  243. "Deferred Directional Light (Lit)",
  244. "Deferred Directional Light (SimpleLit)",
  245. "ClearStencilPartial",
  246. "Fog",
  247. "SSAOOnly"
  248. };
  249. internal enum TileDeferredPasses
  250. {
  251. PunctualLit,
  252. PunctualSimpleLit,
  253. };
  254. internal enum StencilDeferredPasses
  255. {
  256. StencilVolume,
  257. PunctualLit,
  258. PunctualSimpleLit,
  259. DirectionalLit,
  260. DirectionalSimpleLit,
  261. ClearStencilPartial,
  262. Fog,
  263. SSAOOnly
  264. };
  265. static readonly ushort k_InvalidLightOffset = 0xFFFF;
  266. static readonly string k_SetupLights = "SetupLights";
  267. static readonly string k_DeferredPass = "Deferred Pass";
  268. static readonly string k_TileDepthInfo = "Tile Depth Info";
  269. static readonly string k_DeferredTiledPass = "Deferred Shading (Tile-Based)";
  270. static readonly string k_DeferredStencilPass = "Deferred Shading (Stencil)";
  271. static readonly string k_DeferredFogPass = "Deferred Fog";
  272. static readonly string k_ClearStencilPartial = "Clear Stencil Partial";
  273. static readonly string k_SetupLightConstants = "Setup Light Constants";
  274. static readonly float kStencilShapeGuard = 1.06067f; // stencil geometric shapes must be inflated to fit the analytic shapes.
  275. private static readonly ProfilingSampler m_ProfilingSetupLights = new ProfilingSampler(k_SetupLights);
  276. private static readonly ProfilingSampler m_ProfilingDeferredPass = new ProfilingSampler(k_DeferredPass);
  277. private static readonly ProfilingSampler m_ProfilingTileDepthInfo = new ProfilingSampler(k_TileDepthInfo);
  278. private static readonly ProfilingSampler m_ProfilingSetupLightConstants = new ProfilingSampler(k_SetupLightConstants);
  279. internal int GBufferAlbedoIndex { get { return 0; } }
  280. internal int GBufferSpecularMetallicIndex { get { return 1; } }
  281. internal int GBufferNormalSmoothnessIndex { get { return 2; } }
  282. internal int GBufferLightingIndex { get { return 3; } }
  283. internal int GbufferDepthIndex { get { return UseRenderPass ? GBufferLightingIndex + 1 : -1; } }
  284. internal int GBufferShadowMask { get { return UseShadowMask ? GBufferLightingIndex + (UseRenderPass ? 1 : 0) + 1 : -1; } }
  285. internal int GBufferRenderingLayers { get { return UseRenderingLayers ? GBufferLightingIndex + (UseRenderPass ? 1 : 0) + (UseShadowMask ? 1 : 0) + 1 : -1; } }
  286. // Color buffer count (not including dephStencil).
  287. internal int GBufferSliceCount { get { return 4 + (UseRenderPass ? 1 : 0) + (UseShadowMask ? 1 : 0) + (UseRenderingLayers ? 1 : 0); } }
  288. internal GraphicsFormat GetGBufferFormat(int index)
  289. {
  290. if (index == GBufferAlbedoIndex) // sRGB albedo, materialFlags
  291. return QualitySettings.activeColorSpace == ColorSpace.Linear ? GraphicsFormat.R8G8B8A8_SRGB : GraphicsFormat.R8G8B8A8_UNorm;
  292. else if (index == GBufferSpecularMetallicIndex) // sRGB specular, [unused]
  293. return GraphicsFormat.R8G8B8A8_UNorm;
  294. else if (index == GBufferNormalSmoothnessIndex)
  295. return this.AccurateGbufferNormals ? GraphicsFormat.R8G8B8A8_UNorm : GraphicsFormat.R8G8B8A8_SNorm; // normal normal normal packedSmoothness
  296. else if (index == GBufferLightingIndex) // Emissive+baked: Most likely B10G11R11_UFloatPack32 or R16G16B16A16_SFloat
  297. return GraphicsFormat.None;
  298. else if (index == GbufferDepthIndex) // Render-pass on mobiles: reading back real depth-buffer is either inefficient (Arm Vulkan) or impossible (Metal).
  299. return GraphicsFormat.R32_SFloat;
  300. else if (index == GBufferShadowMask) // Optional: shadow mask is outputed in mixed lighting subtractive mode for non-static meshes only
  301. return GraphicsFormat.R8G8B8A8_UNorm;
  302. else if (index == GBufferRenderingLayers) // Optional: rendering layers is outputed when light layers are enabled (subset of rendering layers)
  303. return GraphicsFormat.R8_UNorm;
  304. else
  305. return GraphicsFormat.None;
  306. }
  307. // This may return different values depending on what lights are rendered for a given frame.
  308. internal bool UseShadowMask { get { return this.MixedLightingSetup != MixedLightingSetup.None; } }
  309. //
  310. internal bool UseRenderingLayers { get { return UniversalRenderPipeline.asset.supportsLightLayers; } }
  311. //
  312. internal bool UseRenderPass { get; set; }
  313. //
  314. internal bool HasDepthPrepass { get; set; }
  315. //
  316. internal bool HasNormalPrepass { get; set; }
  317. // This is an overlay camera being rendered.
  318. internal bool IsOverlay { get; set; }
  319. // Not all platforms support R8G8B8A8_SNorm, so we need to check for the support and force accurate GBuffer normals and relevant shader variants
  320. private bool m_AccurateGbufferNormals;
  321. internal bool AccurateGbufferNormals
  322. {
  323. get { return m_AccurateGbufferNormals; }
  324. set { m_AccurateGbufferNormals = value || !RenderingUtils.SupportsGraphicsFormat(GraphicsFormat.R8G8B8A8_SNorm, FormatUsage.Render); }
  325. }
  326. // true: TileDeferred.shader used for some lights (currently: point/spot lights without shadows) - false: use StencilDeferred.shader for all lights
  327. internal bool TiledDeferredShading { get; set; }
  328. // We browse all visible lights and found the mixed lighting setup every frame.
  329. internal MixedLightingSetup MixedLightingSetup { get; set; }
  330. //
  331. internal bool UseJobSystem { get; set; }
  332. //
  333. internal int RenderWidth { get; set; }
  334. //
  335. internal int RenderHeight { get; set; }
  336. // Output lighting result.
  337. internal RenderTargetHandle[] GbufferAttachments { get; set; }
  338. internal RenderTargetIdentifier[] DeferredInputAttachments { get; set; }
  339. internal bool[] DeferredInputIsTransient { get; set; }
  340. // Input depth texture, also bound as read-only RT
  341. internal RenderTargetHandle DepthAttachment { get; set; }
  342. //
  343. internal RenderTargetHandle DepthCopyTexture { get; set; }
  344. // Intermediate depth info texture.
  345. internal RenderTargetHandle DepthInfoTexture { get; set; }
  346. // Per-tile depth info texture.
  347. internal RenderTargetHandle TileDepthInfoTexture { get; set; }
  348. internal RenderTargetIdentifier[] GbufferAttachmentIdentifiers { get; set; }
  349. internal GraphicsFormat[] GbufferFormats { get; set; }
  350. internal RenderTargetIdentifier DepthAttachmentIdentifier { get; set; }
  351. internal RenderTargetIdentifier DepthCopyTextureIdentifier { get; set; }
  352. internal RenderTargetIdentifier DepthInfoTextureIdentifier { get; set; }
  353. internal RenderTargetIdentifier TileDepthInfoTextureIdentifier { get; set; }
  354. // Cached.
  355. int m_CachedRenderWidth = 0;
  356. // Cached.
  357. int m_CachedRenderHeight = 0;
  358. // Cached.
  359. Matrix4x4 m_CachedProjectionMatrix;
  360. // Hierarchical tilers.
  361. DeferredTiler[] m_Tilers;
  362. int[] m_TileDataCapacities;
  363. // Should any visible lights be rendered as tile?
  364. bool m_HasTileVisLights;
  365. // Visible lights indices rendered using stencil volumes.
  366. NativeArray<ushort> m_stencilVisLights;
  367. // Offset of each type of lights in m_stencilVisLights.
  368. NativeArray<ushort> m_stencilVisLightOffsets;
  369. // Needed to access light shadow index (can be null if the pass is not queued).
  370. AdditionalLightsShadowCasterPass m_AdditionalLightsShadowCasterPass;
  371. // For rendering stencil point lights.
  372. Mesh m_SphereMesh;
  373. // For rendering stencil spot lights.
  374. Mesh m_HemisphereMesh;
  375. // For rendering directional lights.
  376. Mesh m_FullscreenMesh;
  377. // Max number of tile depth range data that can be referenced per draw call.
  378. int m_MaxDepthRangePerBatch;
  379. // Max numer of instanced tile that can be referenced per draw call.
  380. int m_MaxTilesPerBatch;
  381. // Max number of punctual lights that can be referenced per draw call.
  382. int m_MaxPunctualLightPerBatch;
  383. // Max number of relative light indices that can be referenced per draw call.
  384. int m_MaxRelLightIndicesPerBatch;
  385. // Generate per-tile depth information.
  386. Material m_TileDepthInfoMaterial;
  387. // Hold all shaders for tiled-based deferred shading.
  388. Material m_TileDeferredMaterial;
  389. // Hold all shaders for stencil-volume deferred shading.
  390. Material m_StencilDeferredMaterial;
  391. // Pass indices.
  392. int[] m_StencilDeferredPasses;
  393. // Pass indices.
  394. int[] m_TileDeferredPasses;
  395. // Avoid memory allocations.
  396. Matrix4x4[] m_ScreenToWorld = new Matrix4x4[2];
  397. ProfilingSampler m_ProfilingSamplerDeferredTiledPass = new ProfilingSampler(k_DeferredTiledPass);
  398. ProfilingSampler m_ProfilingSamplerDeferredStencilPass = new ProfilingSampler(k_DeferredStencilPass);
  399. ProfilingSampler m_ProfilingSamplerDeferredFogPass = new ProfilingSampler(k_DeferredFogPass);
  400. ProfilingSampler m_ProfilingSamplerClearStencilPartialPass = new ProfilingSampler(k_ClearStencilPartial);
  401. private LightCookieManager m_LightCookieManager;
  402. internal struct InitParams
  403. {
  404. public Material tileDepthInfoMaterial;
  405. public Material tileDeferredMaterial;
  406. public Material stencilDeferredMaterial;
  407. public LightCookieManager lightCookieManager;
  408. }
  409. internal DeferredLights(InitParams initParams, bool useNativeRenderPass = false)
  410. {
  411. // Cache result for GL platform here. SystemInfo properties are in C++ land so repeated access will be unecessary penalized.
  412. // They can also only be called from main thread!
  413. DeferredConfig.IsOpenGL = SystemInfo.graphicsDeviceType == GraphicsDeviceType.OpenGLCore
  414. || SystemInfo.graphicsDeviceType == GraphicsDeviceType.OpenGLES2
  415. || SystemInfo.graphicsDeviceType == GraphicsDeviceType.OpenGLES3;
  416. // Cachre result for DX10 platform too. Same reasons as above.
  417. DeferredConfig.IsDX10 = SystemInfo.graphicsDeviceType == GraphicsDeviceType.Direct3D11 && SystemInfo.graphicsShaderLevel <= 40;
  418. m_TileDepthInfoMaterial = initParams.tileDepthInfoMaterial;
  419. m_TileDeferredMaterial = initParams.tileDeferredMaterial;
  420. m_StencilDeferredMaterial = initParams.stencilDeferredMaterial;
  421. m_TileDeferredPasses = new int[k_TileDeferredPassNames.Length];
  422. InitTileDeferredMaterial();
  423. m_StencilDeferredPasses = new int[k_StencilDeferredPassNames.Length];
  424. InitStencilDeferredMaterial();
  425. // Compute some platform limits (for deferred tiling).
  426. m_MaxDepthRangePerBatch = (DeferredConfig.UseCBufferForDepthRange ? DeferredConfig.kPreferredCBufferSize : DeferredConfig.kPreferredStructuredBufferSize) / sizeof(uint);
  427. m_MaxTilesPerBatch = (DeferredConfig.UseCBufferForTileList ? DeferredConfig.kPreferredCBufferSize : DeferredConfig.kPreferredStructuredBufferSize) / System.Runtime.InteropServices.Marshal.SizeOf(typeof(TileData));
  428. m_MaxPunctualLightPerBatch = (DeferredConfig.UseCBufferForLightData ? DeferredConfig.kPreferredCBufferSize : DeferredConfig.kPreferredStructuredBufferSize) / System.Runtime.InteropServices.Marshal.SizeOf(typeof(PunctualLightData));
  429. m_MaxRelLightIndicesPerBatch = (DeferredConfig.UseCBufferForLightList ? DeferredConfig.kPreferredCBufferSize : DeferredConfig.kPreferredStructuredBufferSize) / sizeof(uint);
  430. m_Tilers = new DeferredTiler[DeferredConfig.kTilerDepth];
  431. m_TileDataCapacities = new int[DeferredConfig.kTilerDepth];
  432. // Initialize hierarchical tilers. Next tiler processes 4x4 of the tiles of the previous tiler.
  433. // Tiler 0 has finest tiles, coarser tilers follow.
  434. for (int tilerLevel = 0; tilerLevel < DeferredConfig.kTilerDepth; ++tilerLevel)
  435. {
  436. int scale = (int)Mathf.Pow(DeferredConfig.kTilerSubdivisions, tilerLevel);
  437. m_Tilers[tilerLevel] = new DeferredTiler(
  438. DeferredConfig.kTilePixelWidth * scale,
  439. DeferredConfig.kTilePixelHeight * scale,
  440. DeferredConfig.kAvgLightPerTile * scale * scale,
  441. tilerLevel
  442. );
  443. m_TileDataCapacities[tilerLevel] = 0; // not known yet
  444. }
  445. this.AccurateGbufferNormals = true;
  446. this.TiledDeferredShading = true;
  447. this.UseJobSystem = true;
  448. m_HasTileVisLights = false;
  449. this.UseRenderPass = useNativeRenderPass;
  450. m_LightCookieManager = initParams.lightCookieManager;
  451. }
  452. internal ref DeferredTiler GetTiler(int i)
  453. {
  454. return ref m_Tilers[i];
  455. }
  456. internal void SetupLights(ScriptableRenderContext context, ref RenderingData renderingData)
  457. {
  458. Profiler.BeginSample(k_SetupLights);
  459. DeferredShaderData.instance.ResetBuffers();
  460. Camera camera = renderingData.cameraData.camera;
  461. // Support for dynamic resolution.
  462. this.RenderWidth = camera.allowDynamicResolution ? Mathf.CeilToInt(ScalableBufferManager.widthScaleFactor * renderingData.cameraData.cameraTargetDescriptor.width) : renderingData.cameraData.cameraTargetDescriptor.width;
  463. this.RenderHeight = camera.allowDynamicResolution ? Mathf.CeilToInt(ScalableBufferManager.heightScaleFactor * renderingData.cameraData.cameraTargetDescriptor.height) : renderingData.cameraData.cameraTargetDescriptor.height;
  464. if (this.TiledDeferredShading)
  465. {
  466. // Precompute tile data again if the camera projection or the screen resolution has changed.
  467. if (m_CachedRenderWidth != this.RenderWidth
  468. || m_CachedRenderHeight != this.RenderHeight
  469. || m_CachedProjectionMatrix != renderingData.cameraData.camera.projectionMatrix)
  470. {
  471. m_CachedRenderWidth = this.RenderWidth;
  472. m_CachedRenderHeight = this.RenderHeight;
  473. m_CachedProjectionMatrix = renderingData.cameraData.camera.projectionMatrix;
  474. for (int tilerIndex = 0; tilerIndex < m_Tilers.Length; ++tilerIndex)
  475. {
  476. m_Tilers[tilerIndex].PrecomputeTiles(renderingData.cameraData.camera.projectionMatrix,
  477. renderingData.cameraData.camera.orthographic, m_CachedRenderWidth, m_CachedRenderHeight);
  478. }
  479. }
  480. // Allocate temporary resources for each hierarchical tiler.
  481. for (int tilerIndex = 0; tilerIndex < m_Tilers.Length; ++tilerIndex)
  482. m_Tilers[tilerIndex].Setup(m_TileDataCapacities[tilerIndex]);
  483. }
  484. // Will hold punctual lights that will be rendered using tiles.
  485. NativeArray<DeferredTiler.PrePunctualLight> prePunctualLights;
  486. // inspect lights in renderingData.lightData.visibleLights and convert them to entries in prePunctualLights OR m_stencilVisLights
  487. // currently we store point lights and spot lights that can be rendered by TiledDeferred, in the same prePunctualLights list
  488. PrecomputeLights(
  489. out prePunctualLights,
  490. out m_stencilVisLights,
  491. out m_stencilVisLightOffsets,
  492. ref renderingData.lightData.visibleLights,
  493. renderingData.lightData.additionalLightsCount != 0 || renderingData.lightData.mainLightIndex >= 0,
  494. renderingData.cameraData.camera.worldToCameraMatrix,
  495. renderingData.cameraData.camera.orthographic,
  496. renderingData.cameraData.camera.nearClipPlane
  497. );
  498. {
  499. CommandBuffer cmd = CommandBufferPool.Get();
  500. using (new ProfilingScope(cmd, m_ProfilingSetupLightConstants))
  501. {
  502. // Shared uniform constants for all lights.
  503. SetupShaderLightConstants(cmd, ref renderingData);
  504. #if UNITY_EDITOR
  505. // This flag is used to strip mixed lighting shader variants when a player is built.
  506. // All shader variants are available in the editor.
  507. bool supportsMixedLighting = true;
  508. #else
  509. bool supportsMixedLighting = renderingData.lightData.supportsMixedLighting;
  510. #endif
  511. // Setup global keywords.
  512. CoreUtils.SetKeyword(cmd, ShaderKeywordStrings._GBUFFER_NORMALS_OCT, this.AccurateGbufferNormals);
  513. bool isShadowMask = supportsMixedLighting && this.MixedLightingSetup == MixedLightingSetup.ShadowMask;
  514. bool isShadowMaskAlways = isShadowMask && QualitySettings.shadowmaskMode == ShadowmaskMode.Shadowmask;
  515. bool isSubtractive = supportsMixedLighting && this.MixedLightingSetup == MixedLightingSetup.Subtractive;
  516. CoreUtils.SetKeyword(cmd, ShaderKeywordStrings.LightmapShadowMixing, isSubtractive || isShadowMaskAlways);
  517. CoreUtils.SetKeyword(cmd, ShaderKeywordStrings.ShadowsShadowMask, isShadowMask);
  518. CoreUtils.SetKeyword(cmd, ShaderKeywordStrings.MixedLightingSubtractive, isSubtractive); // Backward compatibility
  519. // This should be moved to a more global scope when framebuffer fetch is introduced to more passes
  520. CoreUtils.SetKeyword(cmd, ShaderKeywordStrings.RenderPassEnabled, this.UseRenderPass && renderingData.cameraData.cameraType == CameraType.Game);
  521. }
  522. context.ExecuteCommandBuffer(cmd);
  523. CommandBufferPool.Release(cmd);
  524. }
  525. if (this.TiledDeferredShading)
  526. {
  527. // Sort lights front to back.
  528. // This allows a further optimisation where per-tile light lists can be more easily trimmed on both ends in the vertex shading instancing the tiles.
  529. SortLights(ref prePunctualLights);
  530. NativeArray<ushort> defaultIndices = new NativeArray<ushort>(prePunctualLights.Length, Allocator.Temp, NativeArrayOptions.UninitializedMemory);
  531. for (int i = 0; i < prePunctualLights.Length; ++i)
  532. defaultIndices[i] = (ushort)i;
  533. NativeArray<uint> defaultHeaders = new NativeArray<uint>(2, Allocator.Temp, NativeArrayOptions.UninitializedMemory);
  534. defaultHeaders[0] = 0; // tileHeaders offset
  535. defaultHeaders[1] = (uint)prePunctualLights.Length; // tileHeaders count
  536. // Cull tile-friendly lights into the coarse tile structure.
  537. ref DeferredTiler coarsestTiler = ref m_Tilers[m_Tilers.Length - 1];
  538. if (m_Tilers.Length != 1)
  539. {
  540. NativeArray<JobHandle> jobHandles = new NativeArray<JobHandle>();
  541. int jobOffset = 0;
  542. int jobCount = 0;
  543. if (this.UseJobSystem)
  544. {
  545. int totalJobCount = 1;
  546. for (int t = m_Tilers.Length - 1; t > 0; --t)
  547. {
  548. ref DeferredTiler coarseTiler = ref m_Tilers[t];
  549. totalJobCount += coarseTiler.TileXCount * coarseTiler.TileYCount;
  550. }
  551. jobHandles = new NativeArray<JobHandle>(totalJobCount, Allocator.Temp, NativeArrayOptions.UninitializedMemory);
  552. }
  553. // Fill coarsestTiler.m_Tiles with for each tile, a list of lightIndices from prePunctualLights that intersect the tile
  554. CullLightsJob coarsestJob = new CullLightsJob
  555. {
  556. tiler = coarsestTiler,
  557. prePunctualLights = prePunctualLights,
  558. coarseTiles = defaultIndices,
  559. coarseTileHeaders = defaultHeaders,
  560. coarseHeaderOffset = 0,
  561. istart = 0,
  562. iend = coarsestTiler.TileXCount,
  563. jstart = 0,
  564. jend = coarsestTiler.TileYCount,
  565. };
  566. if (this.UseJobSystem)
  567. {
  568. jobHandles[jobCount++] = coarsestJob.Schedule();
  569. // Start this job now, as the main thread will be busy setting up all the dependent jobs.
  570. JobHandle.ScheduleBatchedJobs();
  571. }
  572. else
  573. coarsestJob.Execute();
  574. // Filter to fine tile structure.
  575. for (int t = m_Tilers.Length - 1; t > 0; --t)
  576. {
  577. ref DeferredTiler fineTiler = ref m_Tilers[t - 1];
  578. ref DeferredTiler coarseTiler = ref m_Tilers[t];
  579. int fineTileXCount = fineTiler.TileXCount;
  580. int fineTileYCount = fineTiler.TileYCount;
  581. int coarseTileXCount = coarseTiler.TileXCount;
  582. int coarseTileYCount = coarseTiler.TileYCount;
  583. int subdivX = (t == m_Tilers.Length - 1) ? coarseTileXCount : DeferredConfig.kTilerSubdivisions;
  584. int subdivY = (t == m_Tilers.Length - 1) ? coarseTileYCount : DeferredConfig.kTilerSubdivisions;
  585. int superCoarseTileXCount = (coarseTileXCount + subdivX - 1) / subdivX;
  586. int superCoarseTileYCount = (coarseTileYCount + subdivY - 1) / subdivY;
  587. NativeArray<ushort> coarseTiles = coarseTiler.Tiles;
  588. NativeArray<uint> coarseTileHeaders = coarseTiler.TileHeaders;
  589. int fineStepX = coarseTiler.TilePixelWidth / fineTiler.TilePixelWidth;
  590. int fineStepY = coarseTiler.TilePixelHeight / fineTiler.TilePixelHeight;
  591. for (int j = 0; j < coarseTileYCount; ++j)
  592. for (int i = 0; i < coarseTileXCount; ++i)
  593. {
  594. int fine_istart = i * fineStepX;
  595. int fine_jstart = j * fineStepY;
  596. int fine_iend = Mathf.Min(fine_istart + fineStepX, fineTileXCount);
  597. int fine_jend = Mathf.Min(fine_jstart + fineStepY, fineTileYCount);
  598. int coarseHeaderOffset = coarseTiler.GetTileHeaderOffset(i, j);
  599. CullLightsJob job = new CullLightsJob
  600. {
  601. tiler = m_Tilers[t - 1],
  602. prePunctualLights = prePunctualLights,
  603. coarseTiles = coarseTiles,
  604. coarseTileHeaders = coarseTileHeaders,
  605. coarseHeaderOffset = coarseHeaderOffset,
  606. istart = fine_istart,
  607. iend = fine_iend,
  608. jstart = fine_jstart,
  609. jend = fine_jend,
  610. };
  611. if (this.UseJobSystem)
  612. jobHandles[jobCount++] = job.Schedule(jobHandles[jobOffset + (i / subdivX) + (j / subdivY) * superCoarseTileXCount]);
  613. else
  614. job.Execute();
  615. }
  616. jobOffset += superCoarseTileXCount * superCoarseTileYCount;
  617. }
  618. if (this.UseJobSystem)
  619. {
  620. JobHandle.CompleteAll(jobHandles);
  621. jobHandles.Dispose();
  622. }
  623. }
  624. else
  625. {
  626. coarsestTiler.CullFinalLights(
  627. ref prePunctualLights,
  628. ref defaultIndices, 0, prePunctualLights.Length,
  629. 0, coarsestTiler.TileXCount, 0, coarsestTiler.TileYCount
  630. );
  631. }
  632. defaultIndices.Dispose();
  633. defaultHeaders.Dispose();
  634. }
  635. // We don't need this array anymore as all the lights have been inserted into the tile-grid structures.
  636. if (prePunctualLights.IsCreated)
  637. prePunctualLights.Dispose();
  638. Profiler.EndSample();
  639. }
  640. internal void ResolveMixedLightingMode(ref RenderingData renderingData)
  641. {
  642. // Find the mixed lighting mode. This is the same logic as ForwardLights.
  643. this.MixedLightingSetup = MixedLightingSetup.None;
  644. #if !UNITY_EDITOR
  645. // This flag is used to strip mixed lighting shader variants when a player is built.
  646. // All shader variants are available in the editor.
  647. if (renderingData.lightData.supportsMixedLighting)
  648. #endif
  649. {
  650. NativeArray<VisibleLight> visibleLights = renderingData.lightData.visibleLights;
  651. for (int lightIndex = 0; lightIndex < renderingData.lightData.visibleLights.Length && this.MixedLightingSetup == MixedLightingSetup.None; ++lightIndex)
  652. {
  653. Light light = visibleLights[lightIndex].light;
  654. if (light != null
  655. && light.bakingOutput.lightmapBakeType == LightmapBakeType.Mixed
  656. && light.shadows != LightShadows.None)
  657. {
  658. switch (light.bakingOutput.mixedLightingMode)
  659. {
  660. case MixedLightingMode.Subtractive:
  661. this.MixedLightingSetup = MixedLightingSetup.Subtractive;
  662. break;
  663. case MixedLightingMode.Shadowmask:
  664. this.MixedLightingSetup = MixedLightingSetup.ShadowMask;
  665. break;
  666. }
  667. }
  668. }
  669. }
  670. // Once the mixed lighting mode has been discovered, we know how many MRTs we need for the gbuffer.
  671. // Subtractive mixed lighting requires shadowMask output, which is actually used to store unity_ProbesOcclusion values.
  672. CreateGbufferAttachments();
  673. }
  674. // In cases when custom pass is injected between GBuffer and Deferred passes we need to fallback
  675. // To non-renderpass path in the middle of setup, which means recreating the gbuffer attachments as well due to GBuffer4 used for RenderPass
  676. internal void DisableFramebufferFetchInput()
  677. {
  678. this.UseRenderPass = false;
  679. CreateGbufferAttachments();
  680. }
  681. internal void CreateGbufferAttachments()
  682. {
  683. int gbufferSliceCount = this.GBufferSliceCount;
  684. if (this.GbufferAttachments == null || this.GbufferAttachments.Length != gbufferSliceCount)
  685. {
  686. this.GbufferAttachments = new RenderTargetHandle[gbufferSliceCount];
  687. for (int i = 0; i < gbufferSliceCount; ++i)
  688. this.GbufferAttachments[i].Init(k_GBufferNames[i]);
  689. }
  690. }
  691. internal bool IsRuntimeSupportedThisFrame()
  692. {
  693. // GBuffer slice count can change depending actual geometry/light being rendered.
  694. // For instance, we only bind shadowMask RT if the scene supports mix lighting and at least one visible light has subtractive mixed ligting mode.
  695. return this.GBufferSliceCount <= SystemInfo.supportedRenderTargetCount && !DeferredConfig.IsOpenGL && !DeferredConfig.IsDX10;
  696. }
  697. public void Setup(ref RenderingData renderingData,
  698. AdditionalLightsShadowCasterPass additionalLightsShadowCasterPass,
  699. bool hasDepthPrepass,
  700. bool hasNormalPrepass,
  701. RenderTargetHandle depthCopyTexture,
  702. RenderTargetHandle depthInfoTexture,
  703. RenderTargetHandle tileDepthInfoTexture,
  704. RenderTargetHandle depthAttachment,
  705. RenderTargetHandle colorAttachment)
  706. {
  707. m_AdditionalLightsShadowCasterPass = additionalLightsShadowCasterPass;
  708. this.HasDepthPrepass = hasDepthPrepass;
  709. this.HasNormalPrepass = hasNormalPrepass;
  710. this.DepthCopyTexture = depthCopyTexture;
  711. this.DepthInfoTexture = depthInfoTexture;
  712. this.TileDepthInfoTexture = tileDepthInfoTexture;
  713. this.GbufferAttachments[this.GBufferLightingIndex] = colorAttachment;
  714. this.DepthAttachment = depthAttachment;
  715. this.DepthCopyTextureIdentifier = this.DepthCopyTexture.Identifier();
  716. this.DepthInfoTextureIdentifier = this.DepthInfoTexture.Identifier();
  717. this.TileDepthInfoTextureIdentifier = this.TileDepthInfoTexture.Identifier();
  718. if (this.GbufferAttachmentIdentifiers == null || this.GbufferAttachmentIdentifiers.Length != this.GbufferAttachments.Length)
  719. {
  720. this.GbufferAttachmentIdentifiers = new RenderTargetIdentifier[this.GbufferAttachments.Length];
  721. this.GbufferFormats = new GraphicsFormat[this.GbufferAttachments.Length];
  722. }
  723. for (int i = 0; i < this.GbufferAttachments.Length; ++i)
  724. {
  725. this.GbufferAttachmentIdentifiers[i] = this.GbufferAttachments[i].Identifier();
  726. this.GbufferFormats[i] = this.GetGBufferFormat(i);
  727. }
  728. if (this.DeferredInputAttachments == null && this.UseRenderPass && this.GbufferAttachments.Length >= 5)
  729. {
  730. this.DeferredInputAttachments = new RenderTargetIdentifier[4]
  731. {
  732. this.GbufferAttachmentIdentifiers[0], this.GbufferAttachmentIdentifiers[1],
  733. this.GbufferAttachmentIdentifiers[2], this.GbufferAttachmentIdentifiers[4]
  734. };
  735. this.DeferredInputIsTransient = new bool[4]
  736. {
  737. true, true, true, false
  738. };
  739. }
  740. this.DepthAttachmentIdentifier = depthAttachment.Identifier();
  741. #if ENABLE_VR && ENABLE_XR_MODULE
  742. // In XR SinglePassInstance mode, the RTs are texture-array and all slices must be bound.
  743. if (renderingData.cameraData.xr.enabled)
  744. {
  745. this.DepthCopyTextureIdentifier = new RenderTargetIdentifier(this.DepthCopyTextureIdentifier, 0, CubemapFace.Unknown, -1);
  746. this.DepthInfoTextureIdentifier = new RenderTargetIdentifier(this.DepthInfoTextureIdentifier, 0, CubemapFace.Unknown, -1);
  747. this.TileDepthInfoTextureIdentifier = new RenderTargetIdentifier(this.TileDepthInfoTextureIdentifier, 0, CubemapFace.Unknown, -1);
  748. for (int i = 0; i < this.GbufferAttachmentIdentifiers.Length; ++i)
  749. this.GbufferAttachmentIdentifiers[i] = new RenderTargetIdentifier(this.GbufferAttachmentIdentifiers[i], 0, CubemapFace.Unknown, -1);
  750. this.DepthAttachmentIdentifier = new RenderTargetIdentifier(this.DepthAttachmentIdentifier, 0, CubemapFace.Unknown, -1);
  751. }
  752. #endif
  753. m_HasTileVisLights = this.TiledDeferredShading && CheckHasTileLights(ref renderingData.lightData.visibleLights);
  754. }
  755. public void OnCameraCleanup(CommandBuffer cmd)
  756. {
  757. // Disable any global keywords setup in SetupLights().
  758. CoreUtils.SetKeyword(cmd, ShaderKeywordStrings._GBUFFER_NORMALS_OCT, false);
  759. for (int tilerIndex = 0; tilerIndex < m_Tilers.Length; ++tilerIndex)
  760. {
  761. m_TileDataCapacities[tilerIndex] = max(m_TileDataCapacities[tilerIndex], m_Tilers[tilerIndex].TileDataCapacity);
  762. m_Tilers[tilerIndex].OnCameraCleanup();
  763. }
  764. if (m_stencilVisLights.IsCreated)
  765. m_stencilVisLights.Dispose();
  766. if (m_stencilVisLightOffsets.IsCreated)
  767. m_stencilVisLightOffsets.Dispose();
  768. }
  769. internal static StencilState OverwriteStencil(StencilState s, int stencilWriteMask)
  770. {
  771. if (!s.enabled)
  772. {
  773. return new StencilState(
  774. true,
  775. 0, (byte)stencilWriteMask,
  776. CompareFunction.Always, StencilOp.Replace, StencilOp.Keep, StencilOp.Keep,
  777. CompareFunction.Always, StencilOp.Replace, StencilOp.Keep, StencilOp.Keep
  778. );
  779. }
  780. CompareFunction funcFront = s.compareFunctionFront != CompareFunction.Disabled ? s.compareFunctionFront : CompareFunction.Always;
  781. CompareFunction funcBack = s.compareFunctionBack != CompareFunction.Disabled ? s.compareFunctionBack : CompareFunction.Always;
  782. StencilOp passFront = s.passOperationFront;
  783. StencilOp failFront = s.failOperationFront;
  784. StencilOp zfailFront = s.zFailOperationFront;
  785. StencilOp passBack = s.passOperationBack;
  786. StencilOp failBack = s.failOperationBack;
  787. StencilOp zfailBack = s.zFailOperationBack;
  788. return new StencilState(
  789. true,
  790. (byte)(s.readMask & 0x0F), (byte)(s.writeMask | stencilWriteMask),
  791. funcFront, passFront, failFront, zfailFront,
  792. funcBack, passBack, failBack, zfailBack
  793. );
  794. }
  795. internal static RenderStateBlock OverwriteStencil(RenderStateBlock block, int stencilWriteMask, int stencilRef)
  796. {
  797. if (!block.stencilState.enabled)
  798. {
  799. block.stencilState = new StencilState(
  800. true,
  801. 0, (byte)stencilWriteMask,
  802. CompareFunction.Always, StencilOp.Replace, StencilOp.Keep, StencilOp.Keep,
  803. CompareFunction.Always, StencilOp.Replace, StencilOp.Keep, StencilOp.Keep
  804. );
  805. }
  806. else
  807. {
  808. StencilState s = block.stencilState;
  809. CompareFunction funcFront = s.compareFunctionFront != CompareFunction.Disabled ? s.compareFunctionFront : CompareFunction.Always;
  810. CompareFunction funcBack = s.compareFunctionBack != CompareFunction.Disabled ? s.compareFunctionBack : CompareFunction.Always;
  811. StencilOp passFront = s.passOperationFront;
  812. StencilOp failFront = s.failOperationFront;
  813. StencilOp zfailFront = s.zFailOperationFront;
  814. StencilOp passBack = s.passOperationBack;
  815. StencilOp failBack = s.failOperationBack;
  816. StencilOp zfailBack = s.zFailOperationBack;
  817. block.stencilState = new StencilState(
  818. true,
  819. (byte)(s.readMask & 0x0F), (byte)(s.writeMask | stencilWriteMask),
  820. funcFront, passFront, failFront, zfailFront,
  821. funcBack, passBack, failBack, zfailBack
  822. );
  823. }
  824. block.mask |= RenderStateMask.Stencil;
  825. block.stencilReference = (block.stencilReference & (int)StencilUsage.UserMask) | stencilRef;
  826. return block;
  827. }
  828. internal bool HasTileLights()
  829. {
  830. return m_HasTileVisLights;
  831. }
  832. internal bool HasTileDepthRangeExtraPass()
  833. {
  834. ref DeferredTiler tiler = ref m_Tilers[0];
  835. int tilePixelWidth = tiler.TilePixelWidth;
  836. int tilePixelHeight = tiler.TilePixelHeight;
  837. int tileMipLevel = (int)Mathf.Log(Mathf.Min(tilePixelWidth, tilePixelHeight), 2);
  838. return DeferredConfig.kTileDepthInfoIntermediateLevel >= 0 && DeferredConfig.kTileDepthInfoIntermediateLevel < tileMipLevel;
  839. }
  840. internal void ExecuteTileDepthInfoPass(ScriptableRenderContext context, ref RenderingData renderingData)
  841. {
  842. if (m_TileDepthInfoMaterial == null)
  843. {
  844. Debug.LogErrorFormat("Missing {0}. {1} render pass will not execute. Check for missing reference in the renderer resources.", m_TileDepthInfoMaterial, GetType().Name);
  845. return;
  846. }
  847. Assertions.Assert.IsTrue(
  848. m_Tilers[0].TilePixelWidth == m_Tilers[0].TilePixelHeight || DeferredConfig.kTileDepthInfoIntermediateLevel <= 0,
  849. "for non square tiles, cannot use intermediate mip level for TileDepthInfo texture generation (todo)"
  850. );
  851. uint invalidDepthRange = (uint)Mathf.FloatToHalf(-2.0f) | (((uint)Mathf.FloatToHalf(-1.0f)) << 16);
  852. ref DeferredTiler tiler = ref m_Tilers[0];
  853. int tileXCount = tiler.TileXCount;
  854. int tileYCount = tiler.TileYCount;
  855. int tilePixelWidth = tiler.TilePixelWidth;
  856. int tilePixelHeight = tiler.TilePixelHeight;
  857. int tileMipLevel = (int)Mathf.Log(Mathf.Min(tilePixelWidth, tilePixelHeight), 2);
  858. int intermediateMipLevel = DeferredConfig.kTileDepthInfoIntermediateLevel >= 0 && DeferredConfig.kTileDepthInfoIntermediateLevel < tileMipLevel ? DeferredConfig.kTileDepthInfoIntermediateLevel : tileMipLevel;
  859. int tileShiftMipLevel = tileMipLevel - intermediateMipLevel;
  860. int alignment = 1 << intermediateMipLevel;
  861. int depthInfoWidth = (this.RenderWidth + alignment - 1) >> intermediateMipLevel;
  862. int depthInfoHeight = (this.RenderHeight + alignment - 1) >> intermediateMipLevel;
  863. NativeArray<ushort> tiles = tiler.Tiles;
  864. NativeArray<uint> tileHeaders = tiler.TileHeaders;
  865. NativeArray<uint> depthRanges = new NativeArray<uint>(m_MaxDepthRangePerBatch, Allocator.Temp, NativeArrayOptions.UninitializedMemory);
  866. CommandBuffer cmd = CommandBufferPool.Get();
  867. using (new ProfilingScope(cmd, m_ProfilingTileDepthInfo))
  868. {
  869. RenderTargetIdentifier depthSurface = this.DepthAttachmentIdentifier;
  870. RenderTargetIdentifier depthInfoSurface = (tileMipLevel == intermediateMipLevel) ? this.TileDepthInfoTextureIdentifier : this.DepthInfoTextureIdentifier;
  871. cmd.SetGlobalTexture(ShaderConstants._DepthTex, depthSurface);
  872. cmd.SetGlobalVector(ShaderConstants._DepthTexSize, new Vector4(this.RenderWidth, this.RenderHeight, 1.0f / this.RenderWidth, 1.0f / this.RenderHeight));
  873. cmd.SetGlobalInt(ShaderConstants._DownsamplingWidth, tilePixelWidth);
  874. cmd.SetGlobalInt(ShaderConstants._DownsamplingHeight, tilePixelHeight);
  875. cmd.SetGlobalInt(ShaderConstants._SourceShiftX, intermediateMipLevel);
  876. cmd.SetGlobalInt(ShaderConstants._SourceShiftY, intermediateMipLevel);
  877. cmd.SetGlobalInt(ShaderConstants._TileShiftX, tileShiftMipLevel);
  878. cmd.SetGlobalInt(ShaderConstants._TileShiftY, tileShiftMipLevel);
  879. Matrix4x4 proj = renderingData.cameraData.camera.projectionMatrix;
  880. Matrix4x4 clip = new Matrix4x4(new Vector4(1, 0, 0, 0), new Vector4(0, 1, 0, 0), new Vector4(0, 0, 0.5f, 0), new Vector4(0, 0, 0.5f, 1));
  881. Matrix4x4 projScreenInv = Matrix4x4.Inverse(clip * proj);
  882. cmd.SetGlobalVector(ShaderConstants._unproject0, projScreenInv.GetRow(2));
  883. cmd.SetGlobalVector(ShaderConstants._unproject1, projScreenInv.GetRow(3));
  884. string shaderVariant = null;
  885. if (tilePixelWidth == tilePixelHeight)
  886. {
  887. if (intermediateMipLevel == 1)
  888. shaderVariant = ShaderKeywordStrings.DOWNSAMPLING_SIZE_2;
  889. else if (intermediateMipLevel == 2)
  890. shaderVariant = ShaderKeywordStrings.DOWNSAMPLING_SIZE_4;
  891. else if (intermediateMipLevel == 3)
  892. shaderVariant = ShaderKeywordStrings.DOWNSAMPLING_SIZE_8;
  893. else if (intermediateMipLevel == 4)
  894. shaderVariant = ShaderKeywordStrings.DOWNSAMPLING_SIZE_16;
  895. }
  896. if (shaderVariant != null)
  897. cmd.EnableShaderKeyword(shaderVariant);
  898. int tileY = 0;
  899. int tileYIncrement = (DeferredConfig.UseCBufferForDepthRange ? DeferredConfig.kPreferredCBufferSize : DeferredConfig.kPreferredStructuredBufferSize) / (tileXCount * 4);
  900. while (tileY < tileYCount)
  901. {
  902. int tileYEnd = Mathf.Min(tileYCount, tileY + tileYIncrement);
  903. for (int j = tileY; j < tileYEnd; ++j)
  904. {
  905. for (int i = 0; i < tileXCount; ++i)
  906. {
  907. int headerOffset = tiler.GetTileHeaderOffset(i, j);
  908. int tileLightCount = (int)tileHeaders[headerOffset + 1];
  909. uint listDepthRange = tileLightCount == 0 ? invalidDepthRange : tileHeaders[headerOffset + 2];
  910. depthRanges[i + (j - tileY) * tileXCount] = listDepthRange;
  911. }
  912. }
  913. ComputeBuffer _depthRanges = DeferredShaderData.instance.ReserveBuffer<uint>(m_MaxDepthRangePerBatch, DeferredConfig.UseCBufferForDepthRange);
  914. _depthRanges.SetData(depthRanges, 0, 0, depthRanges.Length);
  915. if (DeferredConfig.UseCBufferForDepthRange)
  916. cmd.SetGlobalConstantBuffer(_depthRanges, ShaderConstants.UDepthRanges, 0, m_MaxDepthRangePerBatch * 4);
  917. else
  918. cmd.SetGlobalBuffer(ShaderConstants._DepthRanges, _depthRanges);
  919. cmd.SetGlobalInt(ShaderConstants._tileXCount, tileXCount);
  920. cmd.SetGlobalInt(ShaderConstants._DepthRangeOffset, tileY * tileXCount);
  921. cmd.EnableScissorRect(new Rect(0, tileY << tileShiftMipLevel, depthInfoWidth, (tileYEnd - tileY) << tileShiftMipLevel));
  922. cmd.Blit(depthSurface, depthInfoSurface, m_TileDepthInfoMaterial, 0);
  923. tileY = tileYEnd;
  924. }
  925. cmd.DisableScissorRect();
  926. if (shaderVariant != null)
  927. cmd.DisableShaderKeyword(shaderVariant);
  928. }
  929. context.ExecuteCommandBuffer(cmd);
  930. CommandBufferPool.Release(cmd);
  931. depthRanges.Dispose();
  932. }
  933. internal void ExecuteDownsampleBitmaskPass(ScriptableRenderContext context, ref RenderingData renderingData)
  934. {
  935. if (m_TileDepthInfoMaterial == null)
  936. {
  937. Debug.LogErrorFormat("Missing {0}. {1} render pass will not execute. Check for missing reference in the renderer resources.", m_TileDepthInfoMaterial, GetType().Name);
  938. return;
  939. }
  940. CommandBuffer cmd = CommandBufferPool.Get();
  941. using (new ProfilingScope(cmd, m_ProfilingTileDepthInfo))
  942. {
  943. RenderTargetIdentifier depthInfoSurface = this.DepthInfoTextureIdentifier;
  944. RenderTargetIdentifier tileDepthInfoSurface = this.TileDepthInfoTextureIdentifier;
  945. ref DeferredTiler tiler = ref m_Tilers[0];
  946. int tilePixelWidth = tiler.TilePixelWidth;
  947. int tilePixelHeight = tiler.TilePixelHeight;
  948. int tileWidthLevel = (int)Mathf.Log(tilePixelWidth, 2);
  949. int tileHeightLevel = (int)Mathf.Log(tilePixelHeight, 2);
  950. int intermediateMipLevel = DeferredConfig.kTileDepthInfoIntermediateLevel;
  951. int diffWidthLevel = tileWidthLevel - intermediateMipLevel;
  952. int diffHeightLevel = tileHeightLevel - intermediateMipLevel;
  953. cmd.SetGlobalTexture(ShaderConstants._BitmaskTex, depthInfoSurface);
  954. cmd.SetGlobalInt(ShaderConstants._DownsamplingWidth, tilePixelWidth);
  955. cmd.SetGlobalInt(ShaderConstants._DownsamplingHeight, tilePixelHeight);
  956. int alignment = 1 << DeferredConfig.kTileDepthInfoIntermediateLevel;
  957. int depthInfoWidth = (this.RenderWidth + alignment - 1) >> DeferredConfig.kTileDepthInfoIntermediateLevel;
  958. int depthInfoHeight = (this.RenderHeight + alignment - 1) >> DeferredConfig.kTileDepthInfoIntermediateLevel;
  959. cmd.SetGlobalVector("_BitmaskTexSize", new Vector4(depthInfoWidth, depthInfoHeight, 1.0f / depthInfoWidth, 1.0f / depthInfoHeight));
  960. string shaderVariant = null;
  961. if (diffWidthLevel == 1 && diffHeightLevel == 1)
  962. shaderVariant = ShaderKeywordStrings.DOWNSAMPLING_SIZE_2;
  963. else if (diffWidthLevel == 2 && diffHeightLevel == 2)
  964. shaderVariant = ShaderKeywordStrings.DOWNSAMPLING_SIZE_4;
  965. else if (diffWidthLevel == 3 && diffHeightLevel == 3)
  966. shaderVariant = ShaderKeywordStrings.DOWNSAMPLING_SIZE_8;
  967. if (shaderVariant != null)
  968. cmd.EnableShaderKeyword(shaderVariant);
  969. cmd.Blit(depthInfoSurface, tileDepthInfoSurface, m_TileDepthInfoMaterial, 1);
  970. if (shaderVariant != null)
  971. cmd.DisableShaderKeyword(shaderVariant);
  972. }
  973. context.ExecuteCommandBuffer(cmd);
  974. CommandBufferPool.Release(cmd);
  975. }
  976. internal void ClearStencilPartial(CommandBuffer cmd)
  977. {
  978. if (m_FullscreenMesh == null)
  979. m_FullscreenMesh = CreateFullscreenMesh();
  980. using (new ProfilingScope(cmd, m_ProfilingSamplerClearStencilPartialPass))
  981. {
  982. cmd.DrawMesh(m_FullscreenMesh, Matrix4x4.identity, m_StencilDeferredMaterial, 0, m_StencilDeferredPasses[(int)StencilDeferredPasses.ClearStencilPartial]);
  983. }
  984. }
  985. internal void ExecuteDeferredPass(ScriptableRenderContext context, ref RenderingData renderingData)
  986. {
  987. // Workaround for bug.
  988. // When changing the URP asset settings (ex: shadow cascade resolution), all ScriptableRenderers are recreated but
  989. // materials passed in have not finished initializing at that point if they have fallback shader defined. In particular deferred shaders only have 1 pass available,
  990. // which prevents from resolving correct pass indices.
  991. if (m_StencilDeferredPasses[0] < 0)
  992. InitStencilDeferredMaterial();
  993. CommandBuffer cmd = CommandBufferPool.Get();
  994. using (new ProfilingScope(cmd, m_ProfilingDeferredPass))
  995. {
  996. // This does 2 things:
  997. // - baked geometry are skipped (do not receive dynamic lighting)
  998. // - non-baked geometry (== non-static geometry) use shadowMask/occlusionProbes to emulate baked shadows influences.
  999. CoreUtils.SetKeyword(cmd, ShaderKeywordStrings._DEFERRED_MIXED_LIGHTING, this.UseShadowMask);
  1000. // This must be set for each eye in XR mode multipass.
  1001. SetupMatrixConstants(cmd, ref renderingData);
  1002. // Firt directional light will apply SSAO if possible, unless there is none.
  1003. if (!HasStencilLightsOfType(LightType.Directional))
  1004. RenderSSAOBeforeShading(cmd, ref renderingData);
  1005. // Stencil lights must be applied before tile light because main directional light may require to overwrite lighting buffer for SSAO.
  1006. RenderStencilLights(context, cmd, ref renderingData);
  1007. RenderTileLights(context, cmd, ref renderingData);
  1008. CoreUtils.SetKeyword(cmd, ShaderKeywordStrings._DEFERRED_MIXED_LIGHTING, false);
  1009. // Legacy fog (Windows -> Rendering -> Lighting Settings -> Fog)
  1010. RenderFog(context, cmd, ref renderingData);
  1011. }
  1012. // Restore shader keywords
  1013. CoreUtils.SetKeyword(cmd, ShaderKeywordStrings.AdditionalLightShadows, renderingData.shadowData.isKeywordAdditionalLightShadowsEnabled);
  1014. CoreUtils.SetKeyword(cmd, ShaderKeywordStrings.SoftShadows, renderingData.shadowData.isKeywordSoftShadowsEnabled);
  1015. CoreUtils.SetKeyword(cmd, ShaderKeywordStrings.LightCookies, m_LightCookieManager.IsKeywordLightCookieEnabled);
  1016. context.ExecuteCommandBuffer(cmd);
  1017. CommandBufferPool.Release(cmd);
  1018. }
  1019. // adapted from ForwardLights.SetupShaderLightConstants
  1020. void SetupShaderLightConstants(CommandBuffer cmd, ref RenderingData renderingData)
  1021. {
  1022. // Main light has an optimized shader path for main light. This will benefit games that only care about a single light.
  1023. // Universal Forward pipeline only supports a single shadow light, if available it will be the main light.
  1024. SetupMainLightConstants(cmd, ref renderingData.lightData);
  1025. }
  1026. // adapted from ForwardLights.SetupShaderLightConstants
  1027. void SetupMainLightConstants(CommandBuffer cmd, ref LightData lightData)
  1028. {
  1029. if (lightData.mainLightIndex < 0)
  1030. return;
  1031. Vector4 lightPos, lightColor, lightAttenuation, lightSpotDir, lightOcclusionChannel;
  1032. UniversalRenderPipeline.InitializeLightConstants_Common(lightData.visibleLights, lightData.mainLightIndex, out lightPos, out lightColor, out lightAttenuation, out lightSpotDir, out lightOcclusionChannel);
  1033. var additionalLightData = lightData.visibleLights[lightData.mainLightIndex].light.GetUniversalAdditionalLightData();
  1034. uint lightLayerMask = (uint)additionalLightData.lightLayerMask;
  1035. cmd.SetGlobalVector(ShaderConstants._MainLightPosition, lightPos);
  1036. cmd.SetGlobalVector(ShaderConstants._MainLightColor, lightColor);
  1037. cmd.SetGlobalInt(ShaderConstants._MainLightLayerMask, (int)lightLayerMask);
  1038. }
  1039. void SetupMatrixConstants(CommandBuffer cmd, ref RenderingData renderingData)
  1040. {
  1041. ref CameraData cameraData = ref renderingData.cameraData;
  1042. #if ENABLE_VR && ENABLE_XR_MODULE
  1043. int eyeCount = cameraData.xr.enabled && cameraData.xr.singlePassEnabled ? 2 : 1;
  1044. #else
  1045. int eyeCount = 1;
  1046. #endif
  1047. Matrix4x4[] screenToWorld = m_ScreenToWorld; // deferred shaders expects 2 elements
  1048. for (int eyeIndex = 0; eyeIndex < eyeCount; eyeIndex++)
  1049. {
  1050. Matrix4x4 proj = cameraData.GetProjectionMatrix(eyeIndex);
  1051. Matrix4x4 view = cameraData.GetViewMatrix(eyeIndex);
  1052. Matrix4x4 gpuProj = GL.GetGPUProjectionMatrix(proj, false);
  1053. // xy coordinates in range [-1; 1] go to pixel coordinates.
  1054. Matrix4x4 toScreen = new Matrix4x4(
  1055. new Vector4(0.5f * this.RenderWidth, 0.0f, 0.0f, 0.0f),
  1056. new Vector4(0.0f, 0.5f * this.RenderHeight, 0.0f, 0.0f),
  1057. new Vector4(0.0f, 0.0f, 1.0f, 0.0f),
  1058. new Vector4(0.5f * this.RenderWidth, 0.5f * this.RenderHeight, 0.0f, 1.0f)
  1059. );
  1060. Matrix4x4 zScaleBias = Matrix4x4.identity;
  1061. if (DeferredConfig.IsOpenGL)
  1062. {
  1063. // We need to manunally adjust z in NDC space from [-1; 1] to [0; 1] (storage in depth texture).
  1064. zScaleBias = new Matrix4x4(
  1065. new Vector4(1.0f, 0.0f, 0.0f, 0.0f),
  1066. new Vector4(0.0f, 1.0f, 0.0f, 0.0f),
  1067. new Vector4(0.0f, 0.0f, 0.5f, 0.0f),
  1068. new Vector4(0.0f, 0.0f, 0.5f, 1.0f)
  1069. );
  1070. }
  1071. screenToWorld[eyeIndex] = Matrix4x4.Inverse(toScreen * zScaleBias * gpuProj * view);
  1072. }
  1073. cmd.SetGlobalMatrixArray(ShaderConstants._ScreenToWorld, screenToWorld);
  1074. }
  1075. void SortLights(ref NativeArray<DeferredTiler.PrePunctualLight> prePunctualLights)
  1076. {
  1077. DeferredTiler.PrePunctualLight[] array = prePunctualLights.ToArray(); // TODO Use NativeArrayExtensions and avoid dynamic memory allocation.
  1078. System.Array.Sort<DeferredTiler.PrePunctualLight>(array, new SortPrePunctualLight());
  1079. prePunctualLights.CopyFrom(array);
  1080. }
  1081. bool CheckHasTileLights(ref NativeArray<VisibleLight> visibleLights)
  1082. {
  1083. for (int visLightIndex = 0; visLightIndex < visibleLights.Length; ++visLightIndex)
  1084. {
  1085. if (IsTileLight(visibleLights[visLightIndex]))
  1086. return true;
  1087. }
  1088. return false;
  1089. }
  1090. void PrecomputeLights(out NativeArray<DeferredTiler.PrePunctualLight> prePunctualLights,
  1091. out NativeArray<ushort> stencilVisLights,
  1092. out NativeArray<ushort> stencilVisLightOffsets,
  1093. ref NativeArray<VisibleLight> visibleLights,
  1094. bool hasAdditionalLights,
  1095. Matrix4x4 view,
  1096. bool isOrthographic,
  1097. float zNear)
  1098. {
  1099. const int lightTypeCount = (int)LightType.Disc + 1;
  1100. if (!hasAdditionalLights)
  1101. {
  1102. prePunctualLights = new NativeArray<DeferredTiler.PrePunctualLight>(0, Allocator.Temp, NativeArrayOptions.UninitializedMemory);
  1103. stencilVisLights = new NativeArray<ushort>(0, Allocator.Temp, NativeArrayOptions.UninitializedMemory);
  1104. stencilVisLightOffsets = new NativeArray<ushort>(lightTypeCount, Allocator.Temp, NativeArrayOptions.UninitializedMemory);
  1105. for (int i = 0; i < lightTypeCount; ++i)
  1106. stencilVisLightOffsets[i] = k_InvalidLightOffset;
  1107. return;
  1108. }
  1109. // number of supported lights rendered by the TileDeferred system, for each light type (Spot, Directional, Point, Area, Rectangle, Disc, plus one slot at the end)
  1110. NativeArray<int> tileLightOffsets = new NativeArray<int>(lightTypeCount, Allocator.Temp, NativeArrayOptions.ClearMemory);
  1111. NativeArray<int> tileLightCounts = new NativeArray<int>(lightTypeCount, Allocator.Temp, NativeArrayOptions.ClearMemory);
  1112. NativeArray<int> stencilLightCounts = new NativeArray<int>(lightTypeCount, Allocator.Temp, NativeArrayOptions.ClearMemory);
  1113. stencilVisLightOffsets = new NativeArray<ushort>(lightTypeCount, Allocator.Temp, NativeArrayOptions.ClearMemory);
  1114. // Count the number of lights per type.
  1115. for (ushort visLightIndex = 0; visLightIndex < visibleLights.Length; ++visLightIndex)
  1116. {
  1117. VisibleLight vl = visibleLights[visLightIndex];
  1118. if (this.TiledDeferredShading && IsTileLight(vl))
  1119. ++tileLightOffsets[(int)vl.lightType];
  1120. else // All remaining lights are processed as stencil volumes.
  1121. ++stencilVisLightOffsets[(int)vl.lightType];
  1122. }
  1123. int totalTileLightCount = tileLightOffsets[(int)LightType.Point] + tileLightOffsets[(int)LightType.Spot];
  1124. int totalStencilLightCount = stencilVisLightOffsets[(int)LightType.Spot] + stencilVisLightOffsets[(int)LightType.Directional] + stencilVisLightOffsets[(int)LightType.Point];
  1125. prePunctualLights = new NativeArray<DeferredTiler.PrePunctualLight>(totalTileLightCount, Allocator.Temp, NativeArrayOptions.UninitializedMemory);
  1126. stencilVisLights = new NativeArray<ushort>(totalStencilLightCount, Allocator.Temp, NativeArrayOptions.UninitializedMemory);
  1127. // Calculate correct offsets now.
  1128. for (int i = 0, toffset = 0; i < tileLightOffsets.Length; ++i)
  1129. {
  1130. int c = tileLightOffsets[i];
  1131. tileLightOffsets[i] = toffset;
  1132. toffset += c;
  1133. }
  1134. for (int i = 0, soffset = 0; i < stencilVisLightOffsets.Length; ++i)
  1135. {
  1136. if (stencilVisLightOffsets[i] == 0)
  1137. stencilVisLightOffsets[i] = k_InvalidLightOffset;
  1138. else
  1139. {
  1140. int c = stencilVisLightOffsets[i];
  1141. stencilVisLightOffsets[i] = (ushort)soffset;
  1142. soffset += c;
  1143. }
  1144. }
  1145. // Precompute punctual light data.
  1146. for (ushort visLightIndex = 0; visLightIndex < visibleLights.Length; ++visLightIndex)
  1147. {
  1148. VisibleLight vl = visibleLights[visLightIndex];
  1149. if (this.TiledDeferredShading && IsTileLight(vl))
  1150. {
  1151. DeferredTiler.PrePunctualLight ppl;
  1152. ppl.posVS = view.MultiplyPoint(vl.localToWorldMatrix.GetColumn(3)); // By convention, OpenGL RH coordinate space
  1153. ppl.radius = vl.range;
  1154. ppl.minDist = max(0.0f, length(ppl.posVS) - ppl.radius);
  1155. ppl.screenPos = new Vector2(ppl.posVS.x, ppl.posVS.y);
  1156. // Project on screen for perspective projections.
  1157. if (!isOrthographic && ppl.posVS.z <= zNear)
  1158. ppl.screenPos = ppl.screenPos * (-zNear / ppl.posVS.z);
  1159. ppl.visLightIndex = visLightIndex;
  1160. int i = tileLightCounts[(int)vl.lightType]++;
  1161. prePunctualLights[tileLightOffsets[(int)vl.lightType] + i] = ppl;
  1162. }
  1163. else
  1164. {
  1165. // All remaining lights are processed as stencil volumes.
  1166. int i = stencilLightCounts[(int)vl.lightType]++;
  1167. stencilVisLights[stencilVisLightOffsets[(int)vl.lightType] + i] = visLightIndex;
  1168. }
  1169. }
  1170. tileLightOffsets.Dispose();
  1171. tileLightCounts.Dispose();
  1172. stencilLightCounts.Dispose();
  1173. }
  1174. void RenderTileLights(ScriptableRenderContext context, CommandBuffer cmd, ref RenderingData renderingData)
  1175. {
  1176. if (!m_HasTileVisLights)
  1177. return;
  1178. if (m_TileDeferredMaterial == null)
  1179. {
  1180. Debug.LogErrorFormat("Missing {0}. {1} render pass will not execute. Check for missing reference in the renderer resources.", m_TileDeferredMaterial, GetType().Name);
  1181. return;
  1182. }
  1183. // Workaround for bug.
  1184. // When changing the URP asset settings (ex: shadow cascade resolution), all ScriptableRenderers are recreated but
  1185. // materials passed in have not finished initializing at that point if they have fallback shader defined. In particular deferred shaders only have 1 pass available,
  1186. // which prevents from resolving correct pass indices.
  1187. if (m_TileDeferredPasses[0] < 0)
  1188. InitTileDeferredMaterial();
  1189. Profiler.BeginSample(k_DeferredTiledPass);
  1190. // Allow max 256 draw calls for rendering all the batches of tiles
  1191. DrawCall[] drawCalls = new DrawCall[256];
  1192. int drawCallCount = 0;
  1193. {
  1194. ref DeferredTiler tiler = ref m_Tilers[0];
  1195. int sizeof_TileData = 16;
  1196. int sizeof_vec4_TileData = sizeof_TileData >> 4;
  1197. int sizeof_PunctualLightData = System.Runtime.InteropServices.Marshal.SizeOf(typeof(PunctualLightData));
  1198. int sizeof_vec4_PunctualLightData = sizeof_PunctualLightData >> 4;
  1199. int tileXCount = tiler.TileXCount;
  1200. int tileYCount = tiler.TileYCount;
  1201. int maxLightPerTile = tiler.MaxLightPerTile;
  1202. NativeArray<ushort> tiles = tiler.Tiles;
  1203. NativeArray<uint> tileHeaders = tiler.TileHeaders;
  1204. int instanceOffset = 0;
  1205. int tileCount = 0;
  1206. int lightCount = 0;
  1207. int relLightIndices = 0;
  1208. ComputeBuffer _tileList = DeferredShaderData.instance.ReserveBuffer<TileData>(m_MaxTilesPerBatch, DeferredConfig.UseCBufferForTileList);
  1209. ComputeBuffer _punctualLightBuffer = DeferredShaderData.instance.ReserveBuffer<PunctualLightData>(m_MaxPunctualLightPerBatch, DeferredConfig.UseCBufferForLightData);
  1210. ComputeBuffer _relLightList = DeferredShaderData.instance.ReserveBuffer<uint>(m_MaxRelLightIndicesPerBatch, DeferredConfig.UseCBufferForLightList);
  1211. NativeArray<uint4> tileList = new NativeArray<uint4>(m_MaxTilesPerBatch * sizeof_vec4_TileData, Allocator.Temp, NativeArrayOptions.UninitializedMemory);
  1212. NativeArray<uint4> punctualLightBuffer = new NativeArray<uint4>(m_MaxPunctualLightPerBatch * sizeof_vec4_PunctualLightData, Allocator.Temp, NativeArrayOptions.UninitializedMemory);
  1213. NativeArray<uint> relLightList = new NativeArray<uint>(m_MaxRelLightIndicesPerBatch, Allocator.Temp, NativeArrayOptions.UninitializedMemory);
  1214. // Acceleration structure to quickly find if a light has already been added to the uniform block data for the current draw call.
  1215. NativeArray<ushort> trimmedLights = new NativeArray<ushort>(maxLightPerTile, Allocator.Temp, NativeArrayOptions.UninitializedMemory);
  1216. NativeArray<ushort> visLightToRelLights = new NativeArray<ushort>(renderingData.lightData.visibleLights.Length, Allocator.Temp, NativeArrayOptions.UninitializedMemory);
  1217. BitArray usedLights = new BitArray(renderingData.lightData.visibleLights.Length, Allocator.Temp, NativeArrayOptions.ClearMemory);
  1218. for (int j = 0; j < tileYCount; ++j)
  1219. {
  1220. for (int i = 0; i < tileXCount; ++i)
  1221. {
  1222. int tileOffset;
  1223. int tileLightCount;
  1224. tiler.GetTileOffsetAndCount(i, j, out tileOffset, out tileLightCount);
  1225. if (tileLightCount == 0) // empty tile
  1226. continue;
  1227. // Find lights that are not in the batch yet.
  1228. int trimmedLightCount = TrimLights(ref trimmedLights, ref tiles, tileOffset, tileLightCount, ref usedLights);
  1229. Assertions.Assert.IsTrue(trimmedLightCount <= maxLightPerTile); // too many lights overlaps a tile
  1230. // Checks whether one of the GPU buffers is reaching max capacity.
  1231. // In that case, the draw call must be flushed and new GPU buffer(s) be allocated.
  1232. bool tileListIsFull = (tileCount == m_MaxTilesPerBatch);
  1233. bool lightBufferIsFull = (lightCount + trimmedLightCount > m_MaxPunctualLightPerBatch);
  1234. bool relLightListIsFull = (relLightIndices + tileLightCount > m_MaxRelLightIndicesPerBatch);
  1235. if (tileListIsFull || lightBufferIsFull || relLightListIsFull)
  1236. {
  1237. drawCalls[drawCallCount++] = new DrawCall
  1238. {
  1239. tileList = _tileList,
  1240. punctualLightBuffer = _punctualLightBuffer,
  1241. relLightList = _relLightList,
  1242. tileListSize = tileCount * sizeof_TileData,
  1243. punctualLightBufferSize = lightCount * sizeof_PunctualLightData,
  1244. relLightListSize = Align(relLightIndices, 4) * 4,
  1245. instanceOffset = instanceOffset,
  1246. instanceCount = tileCount - instanceOffset
  1247. };
  1248. if (tileListIsFull)
  1249. {
  1250. _tileList.SetData(tileList, 0, 0, tileList.Length); // Must pass complete array (restriction for binding Unity Constant Buffers)
  1251. _tileList = DeferredShaderData.instance.ReserveBuffer<TileData>(m_MaxTilesPerBatch, DeferredConfig.UseCBufferForTileList);
  1252. tileCount = 0;
  1253. }
  1254. if (lightBufferIsFull)
  1255. {
  1256. _punctualLightBuffer.SetData(punctualLightBuffer, 0, 0, punctualLightBuffer.Length);
  1257. _punctualLightBuffer = DeferredShaderData.instance.ReserveBuffer<PunctualLightData>(m_MaxPunctualLightPerBatch, DeferredConfig.UseCBufferForLightData);
  1258. lightCount = 0;
  1259. // If punctualLightBuffer was reset, then all lights in the current tile must be added.
  1260. trimmedLightCount = tileLightCount;
  1261. for (int l = 0; l < tileLightCount; ++l)
  1262. trimmedLights[l] = tiles[tileOffset + l];
  1263. usedLights.Clear();
  1264. }
  1265. if (relLightListIsFull)
  1266. {
  1267. _relLightList.SetData(relLightList, 0, 0, relLightList.Length);
  1268. _relLightList = DeferredShaderData.instance.ReserveBuffer<uint>(m_MaxRelLightIndicesPerBatch, DeferredConfig.UseCBufferForLightList);
  1269. relLightIndices = 0;
  1270. }
  1271. instanceOffset = tileCount;
  1272. }
  1273. // Add TileData.
  1274. int headerOffset = tiler.GetTileHeaderOffset(i, j);
  1275. uint listBitMask = tileHeaders[headerOffset + 3];
  1276. StoreTileData(ref tileList, tileCount, PackTileID((uint)i, (uint)j), listBitMask, (ushort)relLightIndices, (ushort)tileLightCount);
  1277. ++tileCount;
  1278. // Add newly discovered lights.
  1279. for (int l = 0; l < trimmedLightCount; ++l)
  1280. {
  1281. int visLightIndex = trimmedLights[l];
  1282. StorePunctualLightData(ref punctualLightBuffer, lightCount, ref renderingData.lightData.visibleLights, visLightIndex);
  1283. visLightToRelLights[visLightIndex] = (ushort)lightCount;
  1284. ++lightCount;
  1285. usedLights.Set(visLightIndex, true);
  1286. }
  1287. // Add light list for the tile.
  1288. for (int l = 0; l < tileLightCount; ++l)
  1289. {
  1290. ushort visLightIndex = tiles[tileOffset + l];
  1291. ushort relLightBitRange = tiles[tileOffset + tileLightCount + l];
  1292. ushort relLightIndex = visLightToRelLights[visLightIndex];
  1293. relLightList[relLightIndices++] = (uint)relLightIndex | (uint)(relLightBitRange << 16);
  1294. }
  1295. }
  1296. }
  1297. int instanceCount = tileCount - instanceOffset;
  1298. if (instanceCount > 0)
  1299. {
  1300. _tileList.SetData(tileList, 0, 0, tileList.Length); // Must pass complete array (restriction for binding Unity Constant Buffers)
  1301. _punctualLightBuffer.SetData(punctualLightBuffer, 0, 0, punctualLightBuffer.Length);
  1302. _relLightList.SetData(relLightList, 0, 0, relLightList.Length);
  1303. drawCalls[drawCallCount++] = new DrawCall
  1304. {
  1305. tileList = _tileList,
  1306. punctualLightBuffer = _punctualLightBuffer,
  1307. relLightList = _relLightList,
  1308. tileListSize = tileCount * sizeof_TileData,
  1309. punctualLightBufferSize = lightCount * sizeof_PunctualLightData,
  1310. relLightListSize = Align(relLightIndices, 4) * 4,
  1311. instanceOffset = instanceOffset,
  1312. instanceCount = instanceCount
  1313. };
  1314. }
  1315. tileList.Dispose();
  1316. punctualLightBuffer.Dispose();
  1317. relLightList.Dispose();
  1318. trimmedLights.Dispose();
  1319. visLightToRelLights.Dispose();
  1320. usedLights.Dispose();
  1321. }
  1322. // Now draw all tile batches.
  1323. using (new ProfilingScope(cmd, m_ProfilingSamplerDeferredTiledPass))
  1324. {
  1325. MeshTopology topology = DeferredConfig.kHasNativeQuadSupport ? MeshTopology.Quads : MeshTopology.Triangles;
  1326. int vertexCount = DeferredConfig.kHasNativeQuadSupport ? 4 : 6;
  1327. int tileWidth = m_Tilers[0].TilePixelWidth;
  1328. int tileHeight = m_Tilers[0].TilePixelHeight;
  1329. cmd.SetGlobalInt(ShaderConstants._TilePixelWidth, tileWidth);
  1330. cmd.SetGlobalInt(ShaderConstants._TilePixelHeight, tileHeight);
  1331. cmd.SetGlobalTexture(this.TileDepthInfoTexture.id, this.TileDepthInfoTextureIdentifier);
  1332. for (int i = 0; i < drawCallCount; ++i)
  1333. {
  1334. DrawCall dc = drawCalls[i];
  1335. if (DeferredConfig.UseCBufferForTileList)
  1336. cmd.SetGlobalConstantBuffer(dc.tileList, ShaderConstants.UTileList, 0, dc.tileListSize);
  1337. else
  1338. cmd.SetGlobalBuffer(ShaderConstants._TileList, dc.tileList);
  1339. if (DeferredConfig.UseCBufferForLightData)
  1340. cmd.SetGlobalConstantBuffer(dc.punctualLightBuffer, ShaderConstants.UPunctualLightBuffer, 0, dc.punctualLightBufferSize);
  1341. else
  1342. cmd.SetGlobalBuffer(ShaderConstants._PunctualLightBuffer, dc.punctualLightBuffer);
  1343. if (DeferredConfig.UseCBufferForLightList)
  1344. cmd.SetGlobalConstantBuffer(dc.relLightList, ShaderConstants.URelLightList, 0, dc.relLightListSize);
  1345. else
  1346. cmd.SetGlobalBuffer(ShaderConstants._RelLightList, dc.relLightList);
  1347. cmd.SetGlobalInt(ShaderConstants._InstanceOffset, dc.instanceOffset);
  1348. cmd.DrawProcedural(Matrix4x4.identity, m_TileDeferredMaterial, m_TileDeferredPasses[(int)TileDeferredPasses.PunctualLit], topology, vertexCount, dc.instanceCount);
  1349. cmd.DrawProcedural(Matrix4x4.identity, m_TileDeferredMaterial, m_TileDeferredPasses[(int)TileDeferredPasses.PunctualSimpleLit], topology, vertexCount, dc.instanceCount);
  1350. }
  1351. }
  1352. Profiler.EndSample();
  1353. }
  1354. bool HasStencilLightsOfType(LightType type)
  1355. {
  1356. return m_stencilVisLightOffsets[(int)type] != k_InvalidLightOffset;
  1357. }
  1358. void RenderStencilLights(ScriptableRenderContext context, CommandBuffer cmd, ref RenderingData renderingData)
  1359. {
  1360. if (m_stencilVisLights.Length == 0)
  1361. return;
  1362. if (m_StencilDeferredMaterial == null)
  1363. {
  1364. Debug.LogErrorFormat("Missing {0}. {1} render pass will not execute. Check for missing reference in the renderer resources.", m_StencilDeferredMaterial, GetType().Name);
  1365. return;
  1366. }
  1367. Profiler.BeginSample(k_DeferredStencilPass);
  1368. using (new ProfilingScope(cmd, m_ProfilingSamplerDeferredStencilPass))
  1369. {
  1370. NativeArray<VisibleLight> visibleLights = renderingData.lightData.visibleLights;
  1371. if (HasStencilLightsOfType(LightType.Directional))
  1372. RenderStencilDirectionalLights(cmd, ref renderingData, visibleLights, renderingData.lightData.mainLightIndex);
  1373. if (HasStencilLightsOfType(LightType.Point))
  1374. RenderStencilPointLights(cmd, ref renderingData, visibleLights);
  1375. if (HasStencilLightsOfType(LightType.Spot))
  1376. RenderStencilSpotLights(cmd, ref renderingData, visibleLights);
  1377. }
  1378. Profiler.EndSample();
  1379. }
  1380. void RenderStencilDirectionalLights(CommandBuffer cmd, ref RenderingData renderingData, NativeArray<VisibleLight> visibleLights, int mainLightIndex)
  1381. {
  1382. if (m_FullscreenMesh == null)
  1383. m_FullscreenMesh = CreateFullscreenMesh();
  1384. cmd.EnableShaderKeyword(ShaderKeywordStrings._DIRECTIONAL);
  1385. // Directional lights.
  1386. bool isFirstLight = true;
  1387. // TODO bundle extra directional lights rendering by batches of 8.
  1388. // Also separate shadow caster lights from non-shadow caster.
  1389. for (int soffset = m_stencilVisLightOffsets[(int)LightType.Directional]; soffset < m_stencilVisLights.Length; ++soffset)
  1390. {
  1391. ushort visLightIndex = m_stencilVisLights[soffset];
  1392. VisibleLight vl = visibleLights[visLightIndex];
  1393. if (vl.lightType != LightType.Directional)
  1394. break;
  1395. Vector4 lightDir, lightColor, lightAttenuation, lightSpotDir, lightOcclusionChannel;
  1396. UniversalRenderPipeline.InitializeLightConstants_Common(visibleLights, visLightIndex, out lightDir, out lightColor, out lightAttenuation, out lightSpotDir, out lightOcclusionChannel);
  1397. int lightFlags = 0;
  1398. if (vl.light.bakingOutput.lightmapBakeType == LightmapBakeType.Mixed)
  1399. lightFlags |= (int)LightFlag.SubtractiveMixedLighting;
  1400. var additionalLightData = vl.light.GetUniversalAdditionalLightData();
  1401. uint lightLayerMask = (uint)additionalLightData.lightLayerMask;
  1402. // Setup shadow paramters:
  1403. // - for the main light, they have already been setup globally, so nothing to do.
  1404. // - for other directional lights, it is actually not supported by URP, but the code would look like this.
  1405. bool hasDeferredShadows;
  1406. if (visLightIndex == mainLightIndex)
  1407. {
  1408. hasDeferredShadows = vl.light && vl.light.shadows != LightShadows.None;
  1409. CoreUtils.SetKeyword(cmd, ShaderKeywordStrings.AdditionalLightShadows, false);
  1410. }
  1411. else
  1412. {
  1413. int shadowLightIndex = m_AdditionalLightsShadowCasterPass != null ? m_AdditionalLightsShadowCasterPass.GetShadowLightIndexFromLightIndex(visLightIndex) : -1;
  1414. hasDeferredShadows = vl.light && vl.light.shadows != LightShadows.None && shadowLightIndex >= 0;
  1415. CoreUtils.SetKeyword(cmd, ShaderKeywordStrings.AdditionalLightShadows, hasDeferredShadows);
  1416. cmd.SetGlobalInt(ShaderConstants._ShadowLightIndex, shadowLightIndex);
  1417. }
  1418. bool hasSoftShadow = hasDeferredShadows && renderingData.shadowData.supportsSoftShadows && vl.light.shadows == LightShadows.Soft;
  1419. CoreUtils.SetKeyword(cmd, ShaderKeywordStrings.SoftShadows, hasSoftShadow);
  1420. CoreUtils.SetKeyword(cmd, ShaderKeywordStrings._DEFERRED_FIRST_LIGHT, isFirstLight); // First directional light applies SSAO
  1421. CoreUtils.SetKeyword(cmd, ShaderKeywordStrings._DEFERRED_MAIN_LIGHT, visLightIndex == mainLightIndex); // main directional light use different uniform constants from additional directional lights
  1422. cmd.SetGlobalVector(ShaderConstants._LightColor, lightColor); // VisibleLight.finalColor already returns color in active color space
  1423. cmd.SetGlobalVector(ShaderConstants._LightDirection, lightDir);
  1424. cmd.SetGlobalInt(ShaderConstants._LightFlags, lightFlags);
  1425. cmd.SetGlobalInt(ShaderConstants._LightLayerMask, (int)lightLayerMask);
  1426. // Lighting pass.
  1427. cmd.DrawMesh(m_FullscreenMesh, Matrix4x4.identity, m_StencilDeferredMaterial, 0, m_StencilDeferredPasses[(int)StencilDeferredPasses.DirectionalLit]);
  1428. cmd.DrawMesh(m_FullscreenMesh, Matrix4x4.identity, m_StencilDeferredMaterial, 0, m_StencilDeferredPasses[(int)StencilDeferredPasses.DirectionalSimpleLit]);
  1429. isFirstLight = false;
  1430. }
  1431. cmd.DisableShaderKeyword(ShaderKeywordStrings._DIRECTIONAL);
  1432. }
  1433. void RenderStencilPointLights(CommandBuffer cmd, ref RenderingData renderingData, NativeArray<VisibleLight> visibleLights)
  1434. {
  1435. if (m_SphereMesh == null)
  1436. m_SphereMesh = CreateSphereMesh();
  1437. cmd.EnableShaderKeyword(ShaderKeywordStrings._POINT);
  1438. for (int soffset = m_stencilVisLightOffsets[(int)LightType.Point]; soffset < m_stencilVisLights.Length; ++soffset)
  1439. {
  1440. ushort visLightIndex = m_stencilVisLights[soffset];
  1441. VisibleLight vl = visibleLights[visLightIndex];
  1442. if (vl.lightType != LightType.Point)
  1443. break;
  1444. Vector3 posWS = vl.localToWorldMatrix.GetColumn(3);
  1445. Matrix4x4 transformMatrix = new Matrix4x4(
  1446. new Vector4(vl.range, 0.0f, 0.0f, 0.0f),
  1447. new Vector4(0.0f, vl.range, 0.0f, 0.0f),
  1448. new Vector4(0.0f, 0.0f, vl.range, 0.0f),
  1449. new Vector4(posWS.x, posWS.y, posWS.z, 1.0f)
  1450. );
  1451. Vector4 lightPos, lightColor, lightAttenuation, lightSpotDir, lightOcclusionChannel;
  1452. UniversalRenderPipeline.InitializeLightConstants_Common(visibleLights, visLightIndex, out lightPos, out lightColor, out lightAttenuation, out lightSpotDir, out lightOcclusionChannel);
  1453. var additionalLightData = vl.light.GetUniversalAdditionalLightData();
  1454. uint lightLayerMask = (uint)additionalLightData.lightLayerMask;
  1455. int lightFlags = 0;
  1456. if (vl.light.bakingOutput.lightmapBakeType == LightmapBakeType.Mixed)
  1457. lightFlags |= (int)LightFlag.SubtractiveMixedLighting;
  1458. int shadowLightIndex = m_AdditionalLightsShadowCasterPass != null ? m_AdditionalLightsShadowCasterPass.GetShadowLightIndexFromLightIndex(visLightIndex) : -1;
  1459. bool hasDeferredLightShadows = vl.light && vl.light.shadows != LightShadows.None && shadowLightIndex >= 0;
  1460. bool hasSoftShadow = hasDeferredLightShadows && renderingData.shadowData.supportsSoftShadows && vl.light.shadows == LightShadows.Soft;
  1461. CoreUtils.SetKeyword(cmd, ShaderKeywordStrings.AdditionalLightShadows, hasDeferredLightShadows);
  1462. CoreUtils.SetKeyword(cmd, ShaderKeywordStrings.SoftShadows, hasSoftShadow);
  1463. int cookieLightIndex = m_LightCookieManager.GetLightCookieShaderDataIndex(visLightIndex);
  1464. // We could test this in shader (static if) a variant (shader change) is undesirable. Same for spot light.
  1465. CoreUtils.SetKeyword(cmd, ShaderKeywordStrings.LightCookies, cookieLightIndex >= 0);
  1466. cmd.SetGlobalVector(ShaderConstants._LightPosWS, lightPos);
  1467. cmd.SetGlobalVector(ShaderConstants._LightColor, lightColor);
  1468. cmd.SetGlobalVector(ShaderConstants._LightAttenuation, lightAttenuation);
  1469. cmd.SetGlobalVector(ShaderConstants._LightOcclusionProbInfo, lightOcclusionChannel);
  1470. cmd.SetGlobalInt(ShaderConstants._LightFlags, lightFlags);
  1471. cmd.SetGlobalInt(ShaderConstants._ShadowLightIndex, shadowLightIndex);
  1472. cmd.SetGlobalInt(ShaderConstants._LightLayerMask, (int)lightLayerMask);
  1473. cmd.SetGlobalInt(ShaderConstants._CookieLightIndex, cookieLightIndex);
  1474. // Stencil pass.
  1475. cmd.DrawMesh(m_SphereMesh, transformMatrix, m_StencilDeferredMaterial, 0, m_StencilDeferredPasses[(int)StencilDeferredPasses.StencilVolume]);
  1476. // Lighting pass.
  1477. cmd.DrawMesh(m_SphereMesh, transformMatrix, m_StencilDeferredMaterial, 0, m_StencilDeferredPasses[(int)StencilDeferredPasses.PunctualLit]);
  1478. cmd.DrawMesh(m_SphereMesh, transformMatrix, m_StencilDeferredMaterial, 0, m_StencilDeferredPasses[(int)StencilDeferredPasses.PunctualSimpleLit]);
  1479. }
  1480. cmd.DisableShaderKeyword(ShaderKeywordStrings._POINT);
  1481. }
  1482. void RenderStencilSpotLights(CommandBuffer cmd, ref RenderingData renderingData, NativeArray<VisibleLight> visibleLights)
  1483. {
  1484. if (m_HemisphereMesh == null)
  1485. m_HemisphereMesh = CreateHemisphereMesh();
  1486. cmd.EnableShaderKeyword(ShaderKeywordStrings._SPOT);
  1487. for (int soffset = m_stencilVisLightOffsets[(int)LightType.Spot]; soffset < m_stencilVisLights.Length; ++soffset)
  1488. {
  1489. ushort visLightIndex = m_stencilVisLights[soffset];
  1490. VisibleLight vl = visibleLights[visLightIndex];
  1491. if (vl.lightType != LightType.Spot)
  1492. break;
  1493. float alpha = Mathf.Deg2Rad * vl.spotAngle * 0.5f;
  1494. float cosAlpha = Mathf.Cos(alpha);
  1495. float sinAlpha = Mathf.Sin(alpha);
  1496. // Artificially inflate the geometric shape to fit the analytic spot shape.
  1497. // The tighter the spot shape, the lesser inflation is needed.
  1498. float guard = Mathf.Lerp(1.0f, kStencilShapeGuard, sinAlpha);
  1499. Vector4 lightPos, lightColor, lightAttenuation, lightSpotDir, lightOcclusionChannel;
  1500. UniversalRenderPipeline.InitializeLightConstants_Common(visibleLights, visLightIndex, out lightPos, out lightColor, out lightAttenuation, out lightSpotDir, out lightOcclusionChannel);
  1501. var additionalLightData = vl.light.GetUniversalAdditionalLightData();
  1502. uint lightLayerMask = (uint)additionalLightData.lightLayerMask;
  1503. int lightFlags = 0;
  1504. if (vl.light.bakingOutput.lightmapBakeType == LightmapBakeType.Mixed)
  1505. lightFlags |= (int)LightFlag.SubtractiveMixedLighting;
  1506. int shadowLightIndex = m_AdditionalLightsShadowCasterPass != null ? m_AdditionalLightsShadowCasterPass.GetShadowLightIndexFromLightIndex(visLightIndex) : -1;
  1507. bool hasDeferredLightShadows = vl.light && vl.light.shadows != LightShadows.None && shadowLightIndex >= 0;
  1508. bool hasSoftShadow = hasDeferredLightShadows && renderingData.shadowData.supportsSoftShadows && vl.light.shadows == LightShadows.Soft;
  1509. CoreUtils.SetKeyword(cmd, ShaderKeywordStrings.AdditionalLightShadows, hasDeferredLightShadows);
  1510. CoreUtils.SetKeyword(cmd, ShaderKeywordStrings.SoftShadows, hasSoftShadow);
  1511. int cookieLightIndex = m_LightCookieManager.GetLightCookieShaderDataIndex(visLightIndex);
  1512. CoreUtils.SetKeyword(cmd, ShaderKeywordStrings.LightCookies, cookieLightIndex >= 0);
  1513. cmd.SetGlobalVector(ShaderConstants._SpotLightScale, new Vector4(sinAlpha, sinAlpha, 1.0f - cosAlpha, vl.range));
  1514. cmd.SetGlobalVector(ShaderConstants._SpotLightBias, new Vector4(0.0f, 0.0f, cosAlpha, 0.0f));
  1515. cmd.SetGlobalVector(ShaderConstants._SpotLightGuard, new Vector4(guard, guard, guard, cosAlpha * vl.range));
  1516. cmd.SetGlobalVector(ShaderConstants._LightPosWS, lightPos);
  1517. cmd.SetGlobalVector(ShaderConstants._LightColor, lightColor);
  1518. cmd.SetGlobalVector(ShaderConstants._LightAttenuation, lightAttenuation);
  1519. cmd.SetGlobalVector(ShaderConstants._LightDirection, new Vector3(lightSpotDir.x, lightSpotDir.y, lightSpotDir.z));
  1520. cmd.SetGlobalVector(ShaderConstants._LightOcclusionProbInfo, lightOcclusionChannel);
  1521. cmd.SetGlobalInt(ShaderConstants._LightFlags, lightFlags);
  1522. cmd.SetGlobalInt(ShaderConstants._ShadowLightIndex, shadowLightIndex);
  1523. cmd.SetGlobalInt(ShaderConstants._LightLayerMask, (int)lightLayerMask);
  1524. cmd.SetGlobalInt(ShaderConstants._CookieLightIndex, cookieLightIndex);
  1525. // Stencil pass.
  1526. cmd.DrawMesh(m_HemisphereMesh, vl.localToWorldMatrix, m_StencilDeferredMaterial, 0, m_StencilDeferredPasses[(int)StencilDeferredPasses.StencilVolume]);
  1527. // Lighting pass.
  1528. cmd.DrawMesh(m_HemisphereMesh, vl.localToWorldMatrix, m_StencilDeferredMaterial, 0, m_StencilDeferredPasses[(int)StencilDeferredPasses.PunctualLit]);
  1529. cmd.DrawMesh(m_HemisphereMesh, vl.localToWorldMatrix, m_StencilDeferredMaterial, 0, m_StencilDeferredPasses[(int)StencilDeferredPasses.PunctualSimpleLit]);
  1530. }
  1531. cmd.DisableShaderKeyword(ShaderKeywordStrings._SPOT);
  1532. }
  1533. void RenderSSAOBeforeShading(CommandBuffer cmd, ref RenderingData renderingData)
  1534. {
  1535. if (m_FullscreenMesh == null)
  1536. m_FullscreenMesh = CreateFullscreenMesh();
  1537. cmd.DrawMesh(m_FullscreenMesh, Matrix4x4.identity, m_StencilDeferredMaterial, 0, m_StencilDeferredPasses[(int)StencilDeferredPasses.SSAOOnly]);
  1538. }
  1539. void RenderFog(ScriptableRenderContext context, CommandBuffer cmd, ref RenderingData renderingData)
  1540. {
  1541. // Legacy fog does not work in orthographic mode.
  1542. if (!RenderSettings.fog || renderingData.cameraData.camera.orthographic)
  1543. return;
  1544. if (m_FullscreenMesh == null)
  1545. m_FullscreenMesh = CreateFullscreenMesh();
  1546. using (new ProfilingScope(cmd, m_ProfilingSamplerDeferredFogPass))
  1547. {
  1548. // Fog parameters and shader variant keywords are already set externally.
  1549. cmd.DrawMesh(m_FullscreenMesh, Matrix4x4.identity, m_StencilDeferredMaterial, 0, m_StencilDeferredPasses[(int)StencilDeferredPasses.Fog]);
  1550. }
  1551. }
  1552. int TrimLights(ref NativeArray<ushort> trimmedLights, ref NativeArray<ushort> tiles, int offset, int lightCount, ref BitArray usedLights)
  1553. {
  1554. int trimCount = 0;
  1555. for (int i = 0; i < lightCount; ++i)
  1556. {
  1557. ushort visLightIndex = tiles[offset + i];
  1558. if (usedLights.IsSet(visLightIndex))
  1559. continue;
  1560. trimmedLights[trimCount++] = visLightIndex;
  1561. }
  1562. return trimCount;
  1563. }
  1564. void StorePunctualLightData(ref NativeArray<uint4> punctualLightBuffer, int storeIndex, ref NativeArray<VisibleLight> visibleLights, int index)
  1565. {
  1566. int lightFlags = 0;
  1567. if (visibleLights[index].light.bakingOutput.lightmapBakeType == LightmapBakeType.Mixed)
  1568. lightFlags |= (int)LightFlag.SubtractiveMixedLighting;
  1569. // tile lights do not support shadows, so shadowLightIndex is -1.
  1570. //int shadowLightIndex = -1;
  1571. Vector4 lightPos, lightColor, lightAttenuation, lightSpotDir, lightOcclusionChannel;
  1572. UniversalRenderPipeline.InitializeLightConstants_Common(visibleLights, index, out lightPos, out lightColor, out lightAttenuation, out lightSpotDir, out lightOcclusionChannel);
  1573. var additionalLightData = visibleLights[index].light.GetUniversalAdditionalLightData();
  1574. uint lightLayerMask = (uint)additionalLightData.lightLayerMask;
  1575. punctualLightBuffer[storeIndex * 6 + 0] = new uint4(FloatToUInt(lightPos.x), FloatToUInt(lightPos.y), FloatToUInt(lightPos.z), FloatToUInt(visibleLights[index].range * visibleLights[index].range));
  1576. punctualLightBuffer[storeIndex * 6 + 1] = new uint4(FloatToUInt(lightColor.x), FloatToUInt(lightColor.y), FloatToUInt(lightColor.z), 0);
  1577. punctualLightBuffer[storeIndex * 6 + 2] = new uint4(FloatToUInt(lightAttenuation.x), FloatToUInt(lightAttenuation.y), FloatToUInt(lightAttenuation.z), FloatToUInt(lightAttenuation.w));
  1578. punctualLightBuffer[storeIndex * 6 + 3] = new uint4(FloatToUInt(lightSpotDir.x), FloatToUInt(lightSpotDir.y), FloatToUInt(lightSpotDir.z), (uint)lightFlags);
  1579. punctualLightBuffer[storeIndex * 6 + 4] = new uint4(FloatToUInt(lightOcclusionChannel.x), FloatToUInt(lightOcclusionChannel.y), FloatToUInt(lightOcclusionChannel.z), FloatToUInt(lightOcclusionChannel.w));
  1580. punctualLightBuffer[storeIndex * 6 + 5] = new uint4(lightLayerMask, 0, 0, 0);
  1581. }
  1582. void StoreTileData(ref NativeArray<uint4> tileList, int storeIndex, uint tileID, uint listBitMask, ushort relLightOffset, ushort lightCount)
  1583. {
  1584. // See struct TileData in TileDeferred.shader.
  1585. tileList[storeIndex] = new uint4 { x = tileID, y = listBitMask, z = relLightOffset | ((uint)lightCount << 16), w = 0 };
  1586. }
  1587. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  1588. bool IsTileLight(VisibleLight visibleLight)
  1589. {
  1590. // tileDeferred might render a lot of point lights in the same draw call.
  1591. // point light shadows require generating cube shadow maps in real-time, requiring extra CPU/GPU resources ; which can become expensive quickly
  1592. return (visibleLight.lightType == LightType.Point && (visibleLight.light == null || visibleLight.light.shadows == LightShadows.None))
  1593. || (visibleLight.lightType == LightType.Spot && (visibleLight.light == null || visibleLight.light.shadows == LightShadows.None));
  1594. }
  1595. void InitTileDeferredMaterial()
  1596. {
  1597. if (m_TileDeferredMaterial == null)
  1598. return;
  1599. for (int pass = 0; pass < k_TileDeferredPassNames.Length; ++pass)
  1600. m_TileDeferredPasses[pass] = m_TileDeferredMaterial.FindPass(k_TileDeferredPassNames[pass]);
  1601. m_TileDeferredMaterial.SetFloat(ShaderConstants._LitStencilRef, (float)StencilUsage.MaterialLit);
  1602. m_TileDeferredMaterial.SetFloat(ShaderConstants._LitStencilReadMask, (float)StencilUsage.MaterialMask);
  1603. m_TileDeferredMaterial.SetFloat(ShaderConstants._LitStencilWriteMask, 0.0f);
  1604. m_TileDeferredMaterial.SetFloat(ShaderConstants._SimpleLitStencilRef, (float)StencilUsage.MaterialSimpleLit);
  1605. m_TileDeferredMaterial.SetFloat(ShaderConstants._SimpleLitStencilReadMask, (float)StencilUsage.MaterialMask);
  1606. m_TileDeferredMaterial.SetFloat(ShaderConstants._SimpleLitStencilWriteMask, 0.0f);
  1607. }
  1608. void InitStencilDeferredMaterial()
  1609. {
  1610. if (m_StencilDeferredMaterial == null)
  1611. return;
  1612. // Pass indices can not be hardcoded because some platforms will strip out some passes, offset the index of later passes.
  1613. for (int pass = 0; pass < k_StencilDeferredPassNames.Length; ++pass)
  1614. m_StencilDeferredPasses[pass] = m_StencilDeferredMaterial.FindPass(k_StencilDeferredPassNames[pass]);
  1615. m_StencilDeferredMaterial.SetFloat(ShaderConstants._StencilRef, (float)StencilUsage.MaterialUnlit);
  1616. m_StencilDeferredMaterial.SetFloat(ShaderConstants._StencilReadMask, (float)StencilUsage.MaterialMask);
  1617. m_StencilDeferredMaterial.SetFloat(ShaderConstants._StencilWriteMask, (float)StencilUsage.StencilLight);
  1618. m_StencilDeferredMaterial.SetFloat(ShaderConstants._LitPunctualStencilRef, (float)((int)StencilUsage.StencilLight | (int)StencilUsage.MaterialLit));
  1619. m_StencilDeferredMaterial.SetFloat(ShaderConstants._LitPunctualStencilReadMask, (float)((int)StencilUsage.StencilLight | (int)StencilUsage.MaterialMask));
  1620. m_StencilDeferredMaterial.SetFloat(ShaderConstants._LitPunctualStencilWriteMask, (float)StencilUsage.StencilLight);
  1621. m_StencilDeferredMaterial.SetFloat(ShaderConstants._SimpleLitPunctualStencilRef, (float)((int)StencilUsage.StencilLight | (int)StencilUsage.MaterialSimpleLit));
  1622. m_StencilDeferredMaterial.SetFloat(ShaderConstants._SimpleLitPunctualStencilReadMask, (float)((int)StencilUsage.StencilLight | (int)StencilUsage.MaterialMask));
  1623. m_StencilDeferredMaterial.SetFloat(ShaderConstants._SimpleLitPunctualStencilWriteMask, (float)StencilUsage.StencilLight);
  1624. m_StencilDeferredMaterial.SetFloat(ShaderConstants._LitDirStencilRef, (float)StencilUsage.MaterialLit);
  1625. m_StencilDeferredMaterial.SetFloat(ShaderConstants._LitDirStencilReadMask, (float)StencilUsage.MaterialMask);
  1626. m_StencilDeferredMaterial.SetFloat(ShaderConstants._LitDirStencilWriteMask, 0.0f);
  1627. m_StencilDeferredMaterial.SetFloat(ShaderConstants._SimpleLitDirStencilRef, (float)StencilUsage.MaterialSimpleLit);
  1628. m_StencilDeferredMaterial.SetFloat(ShaderConstants._SimpleLitDirStencilReadMask, (float)StencilUsage.MaterialMask);
  1629. m_StencilDeferredMaterial.SetFloat(ShaderConstants._SimpleLitDirStencilWriteMask, 0.0f);
  1630. m_StencilDeferredMaterial.SetFloat(ShaderConstants._ClearStencilRef, 0.0f);
  1631. m_StencilDeferredMaterial.SetFloat(ShaderConstants._ClearStencilReadMask, (float)StencilUsage.MaterialMask);
  1632. m_StencilDeferredMaterial.SetFloat(ShaderConstants._ClearStencilWriteMask, (float)StencilUsage.MaterialMask);
  1633. }
  1634. static Mesh CreateSphereMesh()
  1635. {
  1636. // This icosaedron has been been slightly inflated to fit an unit sphere.
  1637. // This is the same geometry as built-in deferred.
  1638. Vector3[] positions =
  1639. {
  1640. new Vector3(0.000f, 0.000f, -1.070f), new Vector3(0.174f, -0.535f, -0.910f),
  1641. new Vector3(-0.455f, -0.331f, -0.910f), new Vector3(0.562f, 0.000f, -0.910f),
  1642. new Vector3(-0.455f, 0.331f, -0.910f), new Vector3(0.174f, 0.535f, -0.910f),
  1643. new Vector3(-0.281f, -0.865f, -0.562f), new Vector3(0.736f, -0.535f, -0.562f),
  1644. new Vector3(0.296f, -0.910f, -0.468f), new Vector3(-0.910f, 0.000f, -0.562f),
  1645. new Vector3(-0.774f, -0.562f, -0.478f), new Vector3(0.000f, -1.070f, 0.000f),
  1646. new Vector3(-0.629f, -0.865f, 0.000f), new Vector3(0.629f, -0.865f, 0.000f),
  1647. new Vector3(-1.017f, -0.331f, 0.000f), new Vector3(0.957f, 0.000f, -0.478f),
  1648. new Vector3(0.736f, 0.535f, -0.562f), new Vector3(1.017f, -0.331f, 0.000f),
  1649. new Vector3(1.017f, 0.331f, 0.000f), new Vector3(-0.296f, -0.910f, 0.478f),
  1650. new Vector3(0.281f, -0.865f, 0.562f), new Vector3(0.774f, -0.562f, 0.478f),
  1651. new Vector3(-0.736f, -0.535f, 0.562f), new Vector3(0.910f, 0.000f, 0.562f),
  1652. new Vector3(0.455f, -0.331f, 0.910f), new Vector3(-0.174f, -0.535f, 0.910f),
  1653. new Vector3(0.629f, 0.865f, 0.000f), new Vector3(0.774f, 0.562f, 0.478f),
  1654. new Vector3(0.455f, 0.331f, 0.910f), new Vector3(0.000f, 0.000f, 1.070f),
  1655. new Vector3(-0.562f, 0.000f, 0.910f), new Vector3(-0.957f, 0.000f, 0.478f),
  1656. new Vector3(0.281f, 0.865f, 0.562f), new Vector3(-0.174f, 0.535f, 0.910f),
  1657. new Vector3(0.296f, 0.910f, -0.478f), new Vector3(-1.017f, 0.331f, 0.000f),
  1658. new Vector3(-0.736f, 0.535f, 0.562f), new Vector3(-0.296f, 0.910f, 0.478f),
  1659. new Vector3(0.000f, 1.070f, 0.000f), new Vector3(-0.281f, 0.865f, -0.562f),
  1660. new Vector3(-0.774f, 0.562f, -0.478f), new Vector3(-0.629f, 0.865f, 0.000f),
  1661. };
  1662. int[] indices =
  1663. {
  1664. 0, 1, 2, 0, 3, 1, 2, 4, 0, 0, 5, 3, 0, 4, 5, 1, 6, 2,
  1665. 3, 7, 1, 1, 8, 6, 1, 7, 8, 9, 4, 2, 2, 6, 10, 10, 9, 2,
  1666. 8, 11, 6, 6, 12, 10, 11, 12, 6, 7, 13, 8, 8, 13, 11, 10, 14, 9,
  1667. 10, 12, 14, 3, 15, 7, 5, 16, 3, 3, 16, 15, 15, 17, 7, 17, 13, 7,
  1668. 16, 18, 15, 15, 18, 17, 11, 19, 12, 13, 20, 11, 11, 20, 19, 17, 21, 13,
  1669. 13, 21, 20, 12, 19, 22, 12, 22, 14, 17, 23, 21, 18, 23, 17, 21, 24, 20,
  1670. 23, 24, 21, 20, 25, 19, 19, 25, 22, 24, 25, 20, 26, 18, 16, 18, 27, 23,
  1671. 26, 27, 18, 28, 24, 23, 27, 28, 23, 24, 29, 25, 28, 29, 24, 25, 30, 22,
  1672. 25, 29, 30, 14, 22, 31, 22, 30, 31, 32, 28, 27, 26, 32, 27, 33, 29, 28,
  1673. 30, 29, 33, 33, 28, 32, 34, 26, 16, 5, 34, 16, 14, 31, 35, 14, 35, 9,
  1674. 31, 30, 36, 30, 33, 36, 35, 31, 36, 37, 33, 32, 36, 33, 37, 38, 32, 26,
  1675. 34, 38, 26, 38, 37, 32, 5, 39, 34, 39, 38, 34, 4, 39, 5, 9, 40, 4,
  1676. 9, 35, 40, 4, 40, 39, 35, 36, 41, 41, 36, 37, 41, 37, 38, 40, 35, 41,
  1677. 40, 41, 39, 41, 38, 39,
  1678. };
  1679. Mesh mesh = new Mesh();
  1680. mesh.indexFormat = IndexFormat.UInt16;
  1681. mesh.vertices = positions;
  1682. mesh.triangles = indices;
  1683. return mesh;
  1684. }
  1685. static Mesh CreateHemisphereMesh()
  1686. {
  1687. // TODO reorder for pre&post-transform cache optimisation.
  1688. // This capped hemisphere shape is in unit dimensions. It will be slightly inflated in the vertex shader
  1689. // to fit the cone analytical shape.
  1690. Vector3[] positions =
  1691. {
  1692. new Vector3(0.000000f, 0.000000f, 0.000000f), new Vector3(1.000000f, 0.000000f, 0.000000f),
  1693. new Vector3(0.923880f, 0.382683f, 0.000000f), new Vector3(0.707107f, 0.707107f, 0.000000f),
  1694. new Vector3(0.382683f, 0.923880f, 0.000000f), new Vector3(-0.000000f, 1.000000f, 0.000000f),
  1695. new Vector3(-0.382684f, 0.923880f, 0.000000f), new Vector3(-0.707107f, 0.707107f, 0.000000f),
  1696. new Vector3(-0.923880f, 0.382683f, 0.000000f), new Vector3(-1.000000f, -0.000000f, 0.000000f),
  1697. new Vector3(-0.923880f, -0.382683f, 0.000000f), new Vector3(-0.707107f, -0.707107f, 0.000000f),
  1698. new Vector3(-0.382683f, -0.923880f, 0.000000f), new Vector3(0.000000f, -1.000000f, 0.000000f),
  1699. new Vector3(0.382684f, -0.923879f, 0.000000f), new Vector3(0.707107f, -0.707107f, 0.000000f),
  1700. new Vector3(0.923880f, -0.382683f, 0.000000f), new Vector3(0.000000f, 0.000000f, 1.000000f),
  1701. new Vector3(0.707107f, 0.000000f, 0.707107f), new Vector3(0.000000f, -0.707107f, 0.707107f),
  1702. new Vector3(0.000000f, 0.707107f, 0.707107f), new Vector3(-0.707107f, 0.000000f, 0.707107f),
  1703. new Vector3(0.816497f, -0.408248f, 0.408248f), new Vector3(0.408248f, -0.408248f, 0.816497f),
  1704. new Vector3(0.408248f, -0.816497f, 0.408248f), new Vector3(0.408248f, 0.816497f, 0.408248f),
  1705. new Vector3(0.408248f, 0.408248f, 0.816497f), new Vector3(0.816497f, 0.408248f, 0.408248f),
  1706. new Vector3(-0.816497f, 0.408248f, 0.408248f), new Vector3(-0.408248f, 0.408248f, 0.816497f),
  1707. new Vector3(-0.408248f, 0.816497f, 0.408248f), new Vector3(-0.408248f, -0.816497f, 0.408248f),
  1708. new Vector3(-0.408248f, -0.408248f, 0.816497f), new Vector3(-0.816497f, -0.408248f, 0.408248f),
  1709. new Vector3(0.000000f, -0.923880f, 0.382683f), new Vector3(0.923880f, 0.000000f, 0.382683f),
  1710. new Vector3(0.000000f, -0.382683f, 0.923880f), new Vector3(0.382683f, 0.000000f, 0.923880f),
  1711. new Vector3(0.000000f, 0.923880f, 0.382683f), new Vector3(0.000000f, 0.382683f, 0.923880f),
  1712. new Vector3(-0.923880f, 0.000000f, 0.382683f), new Vector3(-0.382683f, 0.000000f, 0.923880f)
  1713. };
  1714. int[] indices =
  1715. {
  1716. 0, 2, 1, 0, 3, 2, 0, 4, 3, 0, 5, 4, 0, 6, 5, 0,
  1717. 7, 6, 0, 8, 7, 0, 9, 8, 0, 10, 9, 0, 11, 10, 0, 12,
  1718. 11, 0, 13, 12, 0, 14, 13, 0, 15, 14, 0, 16, 15, 0, 1, 16,
  1719. 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 14, 24, 34, 35,
  1720. 22, 16, 36, 23, 37, 2, 27, 35, 38, 25, 4, 37, 26, 39, 6, 30,
  1721. 38, 40, 28, 8, 39, 29, 41, 10, 33, 40, 34, 31, 12, 41, 32, 36,
  1722. 15, 22, 24, 18, 23, 22, 19, 24, 23, 3, 25, 27, 20, 26, 25, 18,
  1723. 27, 26, 7, 28, 30, 21, 29, 28, 20, 30, 29, 11, 31, 33, 19, 32,
  1724. 31, 21, 33, 32, 13, 14, 34, 15, 24, 14, 19, 34, 24, 1, 35, 16,
  1725. 18, 22, 35, 15, 16, 22, 17, 36, 37, 19, 23, 36, 18, 37, 23, 1,
  1726. 2, 35, 3, 27, 2, 18, 35, 27, 5, 38, 4, 20, 25, 38, 3, 4,
  1727. 25, 17, 37, 39, 18, 26, 37, 20, 39, 26, 5, 6, 38, 7, 30, 6,
  1728. 20, 38, 30, 9, 40, 8, 21, 28, 40, 7, 8, 28, 17, 39, 41, 20,
  1729. 29, 39, 21, 41, 29, 9, 10, 40, 11, 33, 10, 21, 40, 33, 13, 34,
  1730. 12, 19, 31, 34, 11, 12, 31, 17, 41, 36, 21, 32, 41, 19, 36, 32
  1731. };
  1732. Mesh mesh = new Mesh();
  1733. mesh.indexFormat = IndexFormat.UInt16;
  1734. mesh.vertices = positions;
  1735. mesh.triangles = indices;
  1736. return mesh;
  1737. }
  1738. static Mesh CreateFullscreenMesh()
  1739. {
  1740. // TODO reorder for pre&post-transform cache optimisation.
  1741. // Simple full-screen triangle.
  1742. Vector3[] positions =
  1743. {
  1744. new Vector3(-1.0f, 1.0f, 0.0f),
  1745. new Vector3(-1.0f, -3.0f, 0.0f),
  1746. new Vector3(3.0f, 1.0f, 0.0f)
  1747. };
  1748. int[] indices = { 0, 1, 2 };
  1749. Mesh mesh = new Mesh();
  1750. mesh.indexFormat = IndexFormat.UInt16;
  1751. mesh.vertices = positions;
  1752. mesh.triangles = indices;
  1753. return mesh;
  1754. }
  1755. static int Align(int s, int alignment)
  1756. {
  1757. return ((s + alignment - 1) / alignment) * alignment;
  1758. }
  1759. // Keep in sync with UnpackTileID().
  1760. static uint PackTileID(uint i, uint j)
  1761. {
  1762. return i | (j << 16);
  1763. }
  1764. static uint FloatToUInt(float val)
  1765. {
  1766. // TODO different order for little-endian and big-endian platforms.
  1767. byte[] bytes = System.BitConverter.GetBytes(val);
  1768. return bytes[0] | (((uint)bytes[1]) << 8) | (((uint)bytes[2]) << 16) | (((uint)bytes[3]) << 24);
  1769. //return bytes[3] | (((uint)bytes[2]) << 8) | (((uint)bytes[1]) << 16) | (((uint)bytes[0]) << 24);
  1770. }
  1771. static uint Half2ToUInt(float x, float y)
  1772. {
  1773. uint hx = Mathf.FloatToHalf(x);
  1774. uint hy = Mathf.FloatToHalf(y);
  1775. return hx | (hy << 16);
  1776. }
  1777. }
  1778. class SortPrePunctualLight : System.Collections.Generic.IComparer<DeferredTiler.PrePunctualLight>
  1779. {
  1780. public int Compare(DeferredTiler.PrePunctualLight a, DeferredTiler.PrePunctualLight b)
  1781. {
  1782. if (a.minDist < b.minDist)
  1783. return -1;
  1784. else if (a.minDist > b.minDist)
  1785. return 1;
  1786. else
  1787. return 0;
  1788. }
  1789. }
  1790. struct BitArray : System.IDisposable
  1791. {
  1792. NativeArray<uint> m_Mem; // ulong not supported in il2cpp???
  1793. int m_BitCount;
  1794. int m_IntCount;
  1795. public BitArray(int bitCount, Allocator allocator, NativeArrayOptions options = NativeArrayOptions.ClearMemory)
  1796. {
  1797. m_BitCount = bitCount;
  1798. m_IntCount = (bitCount + 31) >> 5;
  1799. m_Mem = new NativeArray<uint>(m_IntCount, allocator, options);
  1800. }
  1801. public void Dispose()
  1802. {
  1803. m_Mem.Dispose();
  1804. }
  1805. public void Clear()
  1806. {
  1807. for (int i = 0; i < m_IntCount; ++i)
  1808. m_Mem[i] = 0;
  1809. }
  1810. public bool IsSet(int bitIndex)
  1811. {
  1812. return (m_Mem[bitIndex >> 5] & (1u << (bitIndex & 31))) != 0;
  1813. }
  1814. public void Set(int bitIndex, bool val)
  1815. {
  1816. if (val)
  1817. m_Mem[bitIndex >> 5] |= 1u << (bitIndex & 31);
  1818. else
  1819. m_Mem[bitIndex >> 5] &= ~(1u << (bitIndex & 31));
  1820. }
  1821. };
  1822. }