Без опису
Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334
  1. using System;
  2. using System.Runtime.CompilerServices;
  3. using UnityEngine.Experimental.Rendering;
  4. using UnityEngine.Profiling;
  5. using Unity.Collections;
  6. using Unity.Jobs;
  7. using Unity.Mathematics;
  8. using UnityEngine.Rendering.RenderGraphModule;
  9. using static Unity.Mathematics.math;
  10. //#define URP_HAS_BURST
  11. // TODO SimpleLit material, make sure when variant is !defined(_SPECGLOSSMAP) && !defined(_SPECULAR_COLOR), specular is correctly silenced.
  12. // TODO use InitializeSimpleLitSurfaceData() in all shader code
  13. // TODO use InitializeParticleLitSurfaceData() in forward pass for ParticleLitForwardPass.hlsl ? Similar refactoring for ParticleSimpleLitForwardPass.hlsl
  14. // TODO Make sure GPU buffers are uploaded without copying into Unity CommandBuffer memory
  15. // TODO BakedLit.shader has a Universal2D pass, but Unlit.shader doesn't have?
  16. namespace UnityEngine.Rendering.Universal.Internal
  17. {
  18. // Customization per platform.
  19. static class DeferredConfig
  20. {
  21. internal static bool IsOpenGL { get; set; }
  22. // DX10 uses SM 4.0. However URP shaders requires SM 4.5 or will use fallback to SM 2.0 shaders otherwise.
  23. // We will consider deferred renderer is not available when SM 2.0 shaders run.
  24. internal static bool IsDX10 { get; set; }
  25. }
  26. internal enum LightFlag
  27. {
  28. // Keep in sync with kLightFlagSubtractiveMixedLighting.
  29. SubtractiveMixedLighting = 4
  30. }
  31. // Manages deferred lights.
  32. internal class DeferredLights
  33. {
  34. internal static class ShaderConstants
  35. {
  36. public static readonly int _LitStencilRef = Shader.PropertyToID("_LitStencilRef");
  37. public static readonly int _LitStencilReadMask = Shader.PropertyToID("_LitStencilReadMask");
  38. public static readonly int _LitStencilWriteMask = Shader.PropertyToID("_LitStencilWriteMask");
  39. public static readonly int _SimpleLitStencilRef = Shader.PropertyToID("_SimpleLitStencilRef");
  40. public static readonly int _SimpleLitStencilReadMask = Shader.PropertyToID("_SimpleLitStencilReadMask");
  41. public static readonly int _SimpleLitStencilWriteMask = Shader.PropertyToID("_SimpleLitStencilWriteMask");
  42. public static readonly int _StencilRef = Shader.PropertyToID("_StencilRef");
  43. public static readonly int _StencilReadMask = Shader.PropertyToID("_StencilReadMask");
  44. public static readonly int _StencilWriteMask = Shader.PropertyToID("_StencilWriteMask");
  45. public static readonly int _LitPunctualStencilRef = Shader.PropertyToID("_LitPunctualStencilRef");
  46. public static readonly int _LitPunctualStencilReadMask = Shader.PropertyToID("_LitPunctualStencilReadMask");
  47. public static readonly int _LitPunctualStencilWriteMask = Shader.PropertyToID("_LitPunctualStencilWriteMask");
  48. public static readonly int _SimpleLitPunctualStencilRef = Shader.PropertyToID("_SimpleLitPunctualStencilRef");
  49. public static readonly int _SimpleLitPunctualStencilReadMask = Shader.PropertyToID("_SimpleLitPunctualStencilReadMask");
  50. public static readonly int _SimpleLitPunctualStencilWriteMask = Shader.PropertyToID("_SimpleLitPunctualStencilWriteMask");
  51. public static readonly int _LitDirStencilRef = Shader.PropertyToID("_LitDirStencilRef");
  52. public static readonly int _LitDirStencilReadMask = Shader.PropertyToID("_LitDirStencilReadMask");
  53. public static readonly int _LitDirStencilWriteMask = Shader.PropertyToID("_LitDirStencilWriteMask");
  54. public static readonly int _SimpleLitDirStencilRef = Shader.PropertyToID("_SimpleLitDirStencilRef");
  55. public static readonly int _SimpleLitDirStencilReadMask = Shader.PropertyToID("_SimpleLitDirStencilReadMask");
  56. public static readonly int _SimpleLitDirStencilWriteMask = Shader.PropertyToID("_SimpleLitDirStencilWriteMask");
  57. public static readonly int _ClearStencilRef = Shader.PropertyToID("_ClearStencilRef");
  58. public static readonly int _ClearStencilReadMask = Shader.PropertyToID("_ClearStencilReadMask");
  59. public static readonly int _ClearStencilWriteMask = Shader.PropertyToID("_ClearStencilWriteMask");
  60. public static readonly int _ScreenToWorld = Shader.PropertyToID("_ScreenToWorld");
  61. 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
  62. 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
  63. 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
  64. public static int _SpotLightScale = Shader.PropertyToID("_SpotLightScale");
  65. public static int _SpotLightBias = Shader.PropertyToID("_SpotLightBias");
  66. public static int _SpotLightGuard = Shader.PropertyToID("_SpotLightGuard");
  67. public static int _LightPosWS = Shader.PropertyToID("_LightPosWS");
  68. public static int _LightColor = Shader.PropertyToID("_LightColor");
  69. public static int _LightAttenuation = Shader.PropertyToID("_LightAttenuation");
  70. public static int _LightOcclusionProbInfo = Shader.PropertyToID("_LightOcclusionProbInfo");
  71. public static int _LightDirection = Shader.PropertyToID("_LightDirection");
  72. public static int _LightFlags = Shader.PropertyToID("_LightFlags");
  73. public static int _ShadowLightIndex = Shader.PropertyToID("_ShadowLightIndex");
  74. public static int _LightLayerMask = Shader.PropertyToID("_LightLayerMask");
  75. public static int _CookieLightIndex = Shader.PropertyToID("_CookieLightIndex");
  76. }
  77. internal static readonly string[] k_GBufferNames = new string[]
  78. {
  79. "_GBuffer0",
  80. "_GBuffer1",
  81. "_GBuffer2",
  82. "_GBuffer3",
  83. "_GBuffer4",
  84. "_GBuffer5",
  85. "_GBuffer6"
  86. };
  87. internal static readonly int[] k_GBufferShaderPropertyIDs = new int[]
  88. {
  89. Shader.PropertyToID(k_GBufferNames[0]),
  90. Shader.PropertyToID(k_GBufferNames[1]),
  91. Shader.PropertyToID(k_GBufferNames[2]),
  92. Shader.PropertyToID(k_GBufferNames[3]),
  93. Shader.PropertyToID(k_GBufferNames[4]),
  94. Shader.PropertyToID(k_GBufferNames[5]),
  95. Shader.PropertyToID(k_GBufferNames[6]),
  96. };
  97. static readonly string[] k_StencilDeferredPassNames = new string[]
  98. {
  99. "Stencil Volume",
  100. "Deferred Punctual Light (Lit)",
  101. "Deferred Punctual Light (SimpleLit)",
  102. "Deferred Directional Light (Lit)",
  103. "Deferred Directional Light (SimpleLit)",
  104. "ClearStencilPartial",
  105. "Fog",
  106. "SSAOOnly"
  107. };
  108. internal enum StencilDeferredPasses
  109. {
  110. StencilVolume,
  111. PunctualLit,
  112. PunctualSimpleLit,
  113. DirectionalLit,
  114. DirectionalSimpleLit,
  115. ClearStencilPartial,
  116. Fog,
  117. SSAOOnly
  118. };
  119. static readonly ushort k_InvalidLightOffset = 0xFFFF;
  120. static readonly string k_SetupLights = "SetupLights";
  121. static readonly string k_DeferredPass = "Deferred Pass";
  122. static readonly string k_DeferredStencilPass = "Deferred Shading (Stencil)";
  123. static readonly string k_DeferredFogPass = "Deferred Fog";
  124. static readonly string k_ClearStencilPartial = "Clear Stencil Partial";
  125. static readonly string k_SetupLightConstants = "Setup Light Constants";
  126. static readonly float kStencilShapeGuard = 1.06067f; // stencil geometric shapes must be inflated to fit the analytic shapes.
  127. private static readonly ProfilingSampler m_ProfilingSetupLights = new ProfilingSampler(k_SetupLights);
  128. private static readonly ProfilingSampler m_ProfilingDeferredPass = new ProfilingSampler(k_DeferredPass);
  129. private static readonly ProfilingSampler m_ProfilingSetupLightConstants = new ProfilingSampler(k_SetupLightConstants);
  130. internal int GBufferAlbedoIndex { get { return 0; } }
  131. internal int GBufferSpecularMetallicIndex { get { return 1; } }
  132. internal int GBufferNormalSmoothnessIndex { get { return 2; } }
  133. internal int GBufferLightingIndex { get { return 3; } }
  134. internal int GbufferDepthIndex { get { return UseFramebufferFetch ? GBufferLightingIndex + 1 : -1; } }
  135. internal int GBufferRenderingLayers { get { return UseRenderingLayers ? GBufferLightingIndex + (UseFramebufferFetch ? 1 : 0) + 1 : -1; } }
  136. // Shadow Mask can change at runtime. Because of this it needs to come after the non-changing buffers.
  137. internal int GBufferShadowMask { get { return UseShadowMask ? GBufferLightingIndex + (UseFramebufferFetch ? 1 : 0) + (UseRenderingLayers ? 1 : 0) + 1 : -1; } }
  138. // Color buffer count (not including dephStencil).
  139. internal int GBufferSliceCount { get { return 4 + (UseFramebufferFetch ? 1 : 0) + (UseShadowMask ? 1 : 0) + (UseRenderingLayers ? 1 : 0); } }
  140. internal int GBufferInputAttachmentCount { get { return 4 + (UseShadowMask ? 1 : 0); } }
  141. internal GraphicsFormat GetGBufferFormat(int index)
  142. {
  143. if (index == GBufferAlbedoIndex) // sRGB albedo, materialFlags
  144. return QualitySettings.activeColorSpace == ColorSpace.Linear ? GraphicsFormat.R8G8B8A8_SRGB : GraphicsFormat.R8G8B8A8_UNorm;
  145. else if (index == GBufferSpecularMetallicIndex) // sRGB specular, [unused]
  146. return GraphicsFormat.R8G8B8A8_UNorm;
  147. else if (index == GBufferNormalSmoothnessIndex)
  148. return AccurateGbufferNormals ? GraphicsFormat.R8G8B8A8_UNorm : DepthNormalOnlyPass.GetGraphicsFormat(); // normal normal normal packedSmoothness
  149. else if (index == GBufferLightingIndex) // Emissive+baked: Most likely B10G11R11_UFloatPack32 or R16G16B16A16_SFloat
  150. return GraphicsFormat.None;
  151. else if (index == GbufferDepthIndex) // Render-pass on mobiles: reading back real depth-buffer is either inefficient (Arm Vulkan) or impossible (Metal).
  152. return GraphicsFormat.R32_SFloat;
  153. else if (index == GBufferShadowMask) // Optional: shadow mask is outputted in mixed lighting subtractive mode for non-static meshes only
  154. return GraphicsFormat.B8G8R8A8_UNorm;
  155. else if (index == GBufferRenderingLayers) // Optional: rendering layers is outputted when light layers are enabled (subset of rendering layers)
  156. return RenderingLayerUtils.GetFormat(RenderingLayerMaskSize);
  157. else
  158. return GraphicsFormat.None;
  159. }
  160. // This may return different values depending on what lights are rendered for a given frame.
  161. internal bool UseShadowMask { get { return this.MixedLightingSetup != MixedLightingSetup.None; } }
  162. //
  163. internal bool UseRenderingLayers { get { return UseLightLayers || UseDecalLayers; } }
  164. //
  165. internal RenderingLayerUtils.MaskSize RenderingLayerMaskSize { get; set; }
  166. //
  167. internal bool UseDecalLayers { get; set; }
  168. //
  169. internal bool UseLightLayers { get { return UniversalRenderPipeline.asset.useRenderingLayers; } }
  170. //
  171. internal bool UseFramebufferFetch { get; set; }
  172. //
  173. internal bool HasDepthPrepass { get; set; }
  174. //
  175. internal bool HasNormalPrepass { get; set; }
  176. internal bool HasRenderingLayerPrepass { get; set; }
  177. // This is an overlay camera being rendered.
  178. internal bool IsOverlay { get; set; }
  179. internal bool AccurateGbufferNormals { get; set; }
  180. // We browse all visible lights and found the mixed lighting setup every frame.
  181. internal MixedLightingSetup MixedLightingSetup { get; set; }
  182. //
  183. internal bool UseJobSystem { get; set; }
  184. //
  185. internal int RenderWidth { get; set; }
  186. //
  187. internal int RenderHeight { get; set; }
  188. // Output lighting result.
  189. internal RTHandle[] GbufferAttachments { get; set; }
  190. private RTHandle[] GbufferRTHandles;
  191. internal TextureHandle[] GbufferTextureHandles { get; set; }
  192. internal RTHandle[] DeferredInputAttachments { get; set; }
  193. internal bool[] DeferredInputIsTransient { get; set; }
  194. // Input depth texture, also bound as read-only RT
  195. internal RTHandle DepthAttachment { get; set; }
  196. //
  197. internal RTHandle DepthCopyTexture { get; set; }
  198. internal GraphicsFormat[] GbufferFormats { get; set; }
  199. internal RTHandle DepthAttachmentHandle { get; set; }
  200. // Visible lights indices rendered using stencil volumes.
  201. NativeArray<ushort> m_stencilVisLights;
  202. // Offset of each type of lights in m_stencilVisLights.
  203. NativeArray<ushort> m_stencilVisLightOffsets;
  204. // Needed to access light shadow index (can be null if the pass is not queued).
  205. AdditionalLightsShadowCasterPass m_AdditionalLightsShadowCasterPass;
  206. // For rendering stencil point lights.
  207. Mesh m_SphereMesh;
  208. // For rendering stencil spot lights.
  209. Mesh m_HemisphereMesh;
  210. // For rendering directional lights.
  211. Mesh m_FullscreenMesh;
  212. // Hold all shaders for stencil-volume deferred shading.
  213. Material m_StencilDeferredMaterial;
  214. // Pass indices.
  215. int[] m_StencilDeferredPasses;
  216. // Avoid memory allocations.
  217. Matrix4x4[] m_ScreenToWorld = new Matrix4x4[2];
  218. ProfilingSampler m_ProfilingSamplerDeferredStencilPass = new ProfilingSampler(k_DeferredStencilPass);
  219. ProfilingSampler m_ProfilingSamplerDeferredFogPass = new ProfilingSampler(k_DeferredFogPass);
  220. ProfilingSampler m_ProfilingSamplerClearStencilPartialPass = new ProfilingSampler(k_ClearStencilPartial);
  221. private LightCookieManager m_LightCookieManager;
  222. internal struct InitParams
  223. {
  224. public Material stencilDeferredMaterial;
  225. public LightCookieManager lightCookieManager;
  226. }
  227. internal DeferredLights(InitParams initParams, bool useNativeRenderPass = false)
  228. {
  229. // Cache result for GL platform here. SystemInfo properties are in C++ land so repeated access will be unecessary penalized.
  230. // They can also only be called from main thread!
  231. DeferredConfig.IsOpenGL = SystemInfo.graphicsDeviceType == GraphicsDeviceType.OpenGLCore || SystemInfo.graphicsDeviceType == GraphicsDeviceType.OpenGLES3;
  232. // Cachre result for DX10 platform too. Same reasons as above.
  233. DeferredConfig.IsDX10 = SystemInfo.graphicsDeviceType == GraphicsDeviceType.Direct3D11 && SystemInfo.graphicsShaderLevel <= 40;
  234. m_StencilDeferredMaterial = initParams.stencilDeferredMaterial;
  235. m_StencilDeferredPasses = new int[k_StencilDeferredPassNames.Length];
  236. InitStencilDeferredMaterial();
  237. this.AccurateGbufferNormals = true;
  238. this.UseJobSystem = true;
  239. this.UseFramebufferFetch = useNativeRenderPass;
  240. m_LightCookieManager = initParams.lightCookieManager;
  241. }
  242. static ProfilingSampler s_SetupDeferredLights = new ProfilingSampler("Setup Deferred lights");
  243. private class SetupLightPassData
  244. {
  245. internal UniversalCameraData cameraData;
  246. internal UniversalLightData lightData;
  247. internal DeferredLights deferredLights;
  248. // The size of the camera target changes during the frame so we must make a copy of it here to preserve its record-time value.
  249. internal Vector2Int cameraTargetSizeCopy;
  250. };
  251. /// <summary>
  252. /// Sets up the ForwardLight data for RenderGraph execution
  253. /// </summary>
  254. internal void SetupRenderGraphLights(RenderGraph renderGraph, UniversalCameraData cameraData, UniversalLightData lightData)
  255. {
  256. using (var builder = renderGraph.AddUnsafePass<SetupLightPassData>(s_SetupDeferredLights.name, out var passData,
  257. s_SetupDeferredLights))
  258. {
  259. passData.cameraData = cameraData;
  260. passData.cameraTargetSizeCopy = new Vector2Int(cameraData.cameraTargetDescriptor.width, cameraData.cameraTargetDescriptor.height);
  261. passData.lightData = lightData;
  262. passData.deferredLights = this;
  263. builder.AllowPassCulling(false);
  264. builder.SetRenderFunc((SetupLightPassData data, UnsafeGraphContext rgContext) =>
  265. {
  266. data.deferredLights.SetupLights(CommandBufferHelpers.GetNativeCommandBuffer(rgContext.cmd), data.cameraData, data.cameraTargetSizeCopy, data.lightData, true);
  267. });
  268. }
  269. }
  270. internal void SetupLights(CommandBuffer cmd, UniversalCameraData cameraData, Vector2Int cameraTargetSizeCopy, UniversalLightData lightData, bool isRenderGraph = false)
  271. {
  272. Profiler.BeginSample(k_SetupLights);
  273. Camera camera = cameraData.camera;
  274. // Support for dynamic resolution.
  275. this.RenderWidth = camera.allowDynamicResolution ? Mathf.CeilToInt(ScalableBufferManager.widthScaleFactor * cameraTargetSizeCopy.x) : cameraTargetSizeCopy.x;
  276. this.RenderHeight = camera.allowDynamicResolution ? Mathf.CeilToInt(ScalableBufferManager.heightScaleFactor * cameraTargetSizeCopy.y) : cameraTargetSizeCopy.y;
  277. // inspect lights in lightData.visibleLights and convert them to entries in m_stencilVisLights
  278. PrecomputeLights(
  279. out m_stencilVisLights,
  280. out m_stencilVisLightOffsets,
  281. ref lightData.visibleLights,
  282. lightData.additionalLightsCount != 0 || lightData.mainLightIndex >= 0
  283. );
  284. {
  285. using (new ProfilingScope(cmd, m_ProfilingSetupLightConstants))
  286. {
  287. // Shared uniform constants for all lights.
  288. SetupShaderLightConstants(cmd, lightData);
  289. #if UNITY_EDITOR
  290. // This flag is used to strip mixed lighting shader variants when a player is built.
  291. // All shader variants are available in the editor.
  292. bool supportsMixedLighting = true;
  293. #else
  294. bool supportsMixedLighting = lightData.supportsMixedLighting;
  295. #endif
  296. // Setup global keywords.
  297. cmd.SetKeyword(ShaderGlobalKeywords._GBUFFER_NORMALS_OCT, this.AccurateGbufferNormals);
  298. bool isShadowMask = supportsMixedLighting && this.MixedLightingSetup == MixedLightingSetup.ShadowMask;
  299. bool isShadowMaskAlways = isShadowMask && QualitySettings.shadowmaskMode == ShadowmaskMode.Shadowmask;
  300. bool isSubtractive = supportsMixedLighting && this.MixedLightingSetup == MixedLightingSetup.Subtractive;
  301. cmd.SetKeyword(ShaderGlobalKeywords.LightmapShadowMixing, isSubtractive || isShadowMaskAlways);
  302. cmd.SetKeyword(ShaderGlobalKeywords.ShadowsShadowMask, isShadowMask);
  303. cmd.SetKeyword(ShaderGlobalKeywords.MixedLightingSubtractive, isSubtractive); // Backward compatibility
  304. // This should be moved to a more global scope when framebuffer fetch is introduced to more passes
  305. cmd.SetKeyword(ShaderGlobalKeywords.RenderPassEnabled, this.UseFramebufferFetch && (cameraData.cameraType == CameraType.Game || camera.cameraType == CameraType.SceneView || isRenderGraph));
  306. cmd.SetKeyword(ShaderGlobalKeywords.LightLayers, UseLightLayers && !CoreUtils.IsSceneLightingDisabled(camera));
  307. RenderingLayerUtils.SetupProperties(cmd, RenderingLayerMaskSize);
  308. }
  309. }
  310. Profiler.EndSample();
  311. }
  312. internal void ResolveMixedLightingMode(UniversalLightData lightData)
  313. {
  314. // Find the mixed lighting mode. This is the same logic as ForwardLights.
  315. this.MixedLightingSetup = MixedLightingSetup.None;
  316. #if !UNITY_EDITOR
  317. // This flag is used to strip mixed lighting shader variants when a player is built.
  318. // All shader variants are available in the editor.
  319. if (lightData.supportsMixedLighting)
  320. #endif
  321. {
  322. NativeArray<VisibleLight> visibleLights = lightData.visibleLights;
  323. for (int lightIndex = 0; lightIndex < lightData.visibleLights.Length && this.MixedLightingSetup == MixedLightingSetup.None; ++lightIndex)
  324. {
  325. Light light = visibleLights.UnsafeElementAtMutable(lightIndex).light;
  326. if (light != null
  327. && light.bakingOutput.lightmapBakeType == LightmapBakeType.Mixed
  328. && light.shadows != LightShadows.None)
  329. {
  330. switch (light.bakingOutput.mixedLightingMode)
  331. {
  332. case MixedLightingMode.Subtractive:
  333. this.MixedLightingSetup = MixedLightingSetup.Subtractive;
  334. break;
  335. case MixedLightingMode.Shadowmask:
  336. this.MixedLightingSetup = MixedLightingSetup.ShadowMask;
  337. break;
  338. }
  339. }
  340. }
  341. }
  342. // Once the mixed lighting mode has been discovered, we know how many MRTs we need for the gbuffer.
  343. // Subtractive mixed lighting requires shadowMask output, which is actually used to store unity_ProbesOcclusion values.
  344. CreateGbufferResources();
  345. }
  346. // In cases when custom pass is injected between GBuffer and Deferred passes we need to fallback
  347. // To non-renderpass path in the middle of setup, which means recreating the gbuffer attachments as well due to GBuffer4 used for RenderPass
  348. internal void DisableFramebufferFetchInput()
  349. {
  350. this.UseFramebufferFetch = false;
  351. CreateGbufferResources();
  352. }
  353. internal void ReleaseGbufferResources()
  354. {
  355. if (this.GbufferRTHandles != null)
  356. {
  357. // Release the old handles before creating the new one
  358. for (int i = 0; i < this.GbufferRTHandles.Length; ++i)
  359. {
  360. if (i == GBufferLightingIndex) // Not on GBuffer to release
  361. continue;
  362. this.GbufferRTHandles[i].Release();
  363. this.GbufferAttachments[i].Release();
  364. }
  365. }
  366. }
  367. internal void ReAllocateGBufferIfNeeded(RenderTextureDescriptor gbufferSlice, int gbufferIndex)
  368. {
  369. if (this.GbufferRTHandles != null)
  370. {
  371. // In case DeferredLight does not own the RTHandle, we can skip realloc.
  372. if (this.GbufferRTHandles[gbufferIndex].GetInstanceID() != this.GbufferAttachments[gbufferIndex].GetInstanceID())
  373. return;
  374. gbufferSlice.depthBufferBits = 0; // make sure no depth surface is actually created
  375. gbufferSlice.stencilFormat = GraphicsFormat.None;
  376. gbufferSlice.graphicsFormat = GetGBufferFormat(gbufferIndex);
  377. RenderingUtils.ReAllocateHandleIfNeeded(ref GbufferRTHandles[gbufferIndex], gbufferSlice, FilterMode.Point, TextureWrapMode.Clamp, name: k_GBufferNames[gbufferIndex]);
  378. GbufferAttachments[gbufferIndex] = GbufferRTHandles[gbufferIndex];
  379. }
  380. }
  381. internal void CreateGbufferResources()
  382. {
  383. int gbufferSliceCount = this.GBufferSliceCount;
  384. if (this.GbufferRTHandles == null || this.GbufferRTHandles.Length != gbufferSliceCount)
  385. {
  386. ReleaseGbufferResources();
  387. this.GbufferAttachments = new RTHandle[gbufferSliceCount];
  388. this.GbufferRTHandles = new RTHandle[gbufferSliceCount];
  389. this.GbufferFormats = new GraphicsFormat[gbufferSliceCount];
  390. this.GbufferTextureHandles = new TextureHandle[gbufferSliceCount];
  391. for (int i = 0; i < gbufferSliceCount; ++i)
  392. {
  393. this.GbufferRTHandles[i] = RTHandles.Alloc(k_GBufferNames[i], name: k_GBufferNames[i]);
  394. this.GbufferAttachments[i] = this.GbufferRTHandles[i];
  395. this.GbufferFormats[i] = this.GetGBufferFormat(i);
  396. }
  397. }
  398. }
  399. internal void UpdateDeferredInputAttachments()
  400. {
  401. this.DeferredInputAttachments[0] = this.GbufferAttachments[0];
  402. this.DeferredInputAttachments[1] = this.GbufferAttachments[1];
  403. this.DeferredInputAttachments[2] = this.GbufferAttachments[2];
  404. this.DeferredInputAttachments[3] = this.GbufferAttachments[4];
  405. if (UseShadowMask && UseRenderingLayers)
  406. {
  407. this.DeferredInputAttachments[4] = this.GbufferAttachments[GBufferShadowMask];
  408. this.DeferredInputAttachments[5] = this.GbufferAttachments[GBufferRenderingLayers];
  409. }
  410. else if (UseShadowMask)
  411. {
  412. this.DeferredInputAttachments[4] = this.GbufferAttachments[GBufferShadowMask];
  413. }
  414. else if (UseRenderingLayers)
  415. {
  416. this.DeferredInputAttachments[4] = this.GbufferAttachments[GBufferRenderingLayers];
  417. }
  418. }
  419. internal bool IsRuntimeSupportedThisFrame()
  420. {
  421. // GBuffer slice count can change depending actual geometry/light being rendered.
  422. // For instance, we only bind shadowMask RT if the scene supports mix lighting and at least one visible light has subtractive mixed ligting mode.
  423. return this.GBufferSliceCount <= SystemInfo.supportedRenderTargetCount && !DeferredConfig.IsOpenGL && !DeferredConfig.IsDX10;
  424. }
  425. public void Setup(
  426. AdditionalLightsShadowCasterPass additionalLightsShadowCasterPass,
  427. bool hasDepthPrepass,
  428. bool hasNormalPrepass,
  429. bool hasRenderingLayerPrepass,
  430. RTHandle depthCopyTexture,
  431. RTHandle depthAttachment,
  432. RTHandle colorAttachment)
  433. {
  434. m_AdditionalLightsShadowCasterPass = additionalLightsShadowCasterPass;
  435. this.HasDepthPrepass = hasDepthPrepass;
  436. this.HasNormalPrepass = hasNormalPrepass;
  437. this.HasRenderingLayerPrepass = hasRenderingLayerPrepass;
  438. this.DepthCopyTexture = depthCopyTexture;
  439. this.GbufferAttachments[this.GBufferLightingIndex] = colorAttachment;
  440. this.DepthAttachment = depthAttachment;
  441. var inputCount = 4 + (UseShadowMask ? 1 : 0) + (UseRenderingLayers ? 1 : 0);
  442. if (this.DeferredInputAttachments == null && this.UseFramebufferFetch && this.GbufferAttachments.Length >= 3 ||
  443. (this.DeferredInputAttachments != null && inputCount != this.DeferredInputAttachments.Length))
  444. {
  445. this.DeferredInputAttachments = new RTHandle[inputCount];
  446. this.DeferredInputIsTransient = new bool[inputCount];
  447. int i, j = 0;
  448. for (i = 0; i < inputCount; i++, j++)
  449. {
  450. if (j == GBufferLightingIndex)
  451. j++;
  452. DeferredInputAttachments[i] = GbufferAttachments[j];
  453. DeferredInputIsTransient[i] = j != GbufferDepthIndex;
  454. }
  455. }
  456. this.DepthAttachmentHandle = this.DepthAttachment;
  457. }
  458. // Only used by RenderGraph now as the other Setup call requires providing target handles which isn't working on RG
  459. internal void Setup(AdditionalLightsShadowCasterPass additionalLightsShadowCasterPass)
  460. {
  461. m_AdditionalLightsShadowCasterPass = additionalLightsShadowCasterPass;
  462. }
  463. public void OnCameraCleanup(CommandBuffer cmd)
  464. {
  465. // Disable any global keywords setup in SetupLights().
  466. cmd.SetKeyword(ShaderGlobalKeywords._GBUFFER_NORMALS_OCT, false);
  467. if (m_stencilVisLights.IsCreated)
  468. m_stencilVisLights.Dispose();
  469. if (m_stencilVisLightOffsets.IsCreated)
  470. m_stencilVisLightOffsets.Dispose();
  471. }
  472. internal static StencilState OverwriteStencil(StencilState s, int stencilWriteMask)
  473. {
  474. if (!s.enabled)
  475. {
  476. return new StencilState(
  477. true,
  478. 0, (byte)stencilWriteMask,
  479. CompareFunction.Always, StencilOp.Replace, StencilOp.Keep, StencilOp.Keep,
  480. CompareFunction.Always, StencilOp.Replace, StencilOp.Keep, StencilOp.Keep
  481. );
  482. }
  483. CompareFunction funcFront = s.compareFunctionFront != CompareFunction.Disabled ? s.compareFunctionFront : CompareFunction.Always;
  484. CompareFunction funcBack = s.compareFunctionBack != CompareFunction.Disabled ? s.compareFunctionBack : CompareFunction.Always;
  485. StencilOp passFront = s.passOperationFront;
  486. StencilOp failFront = s.failOperationFront;
  487. StencilOp zfailFront = s.zFailOperationFront;
  488. StencilOp passBack = s.passOperationBack;
  489. StencilOp failBack = s.failOperationBack;
  490. StencilOp zfailBack = s.zFailOperationBack;
  491. return new StencilState(
  492. true,
  493. (byte)(s.readMask & 0x0F), (byte)(s.writeMask | stencilWriteMask),
  494. funcFront, passFront, failFront, zfailFront,
  495. funcBack, passBack, failBack, zfailBack
  496. );
  497. }
  498. internal static RenderStateBlock OverwriteStencil(RenderStateBlock block, int stencilWriteMask, int stencilRef)
  499. {
  500. if (!block.stencilState.enabled)
  501. {
  502. block.stencilState = new StencilState(
  503. true,
  504. 0, (byte)stencilWriteMask,
  505. CompareFunction.Always, StencilOp.Replace, StencilOp.Keep, StencilOp.Keep,
  506. CompareFunction.Always, StencilOp.Replace, StencilOp.Keep, StencilOp.Keep
  507. );
  508. }
  509. else
  510. {
  511. StencilState s = block.stencilState;
  512. CompareFunction funcFront = s.compareFunctionFront != CompareFunction.Disabled ? s.compareFunctionFront : CompareFunction.Always;
  513. CompareFunction funcBack = s.compareFunctionBack != CompareFunction.Disabled ? s.compareFunctionBack : CompareFunction.Always;
  514. StencilOp passFront = s.passOperationFront;
  515. StencilOp failFront = s.failOperationFront;
  516. StencilOp zfailFront = s.zFailOperationFront;
  517. StencilOp passBack = s.passOperationBack;
  518. StencilOp failBack = s.failOperationBack;
  519. StencilOp zfailBack = s.zFailOperationBack;
  520. block.stencilState = new StencilState(
  521. true,
  522. (byte)(s.readMask & 0x0F), (byte)(s.writeMask | stencilWriteMask),
  523. funcFront, passFront, failFront, zfailFront,
  524. funcBack, passBack, failBack, zfailBack
  525. );
  526. }
  527. block.mask |= RenderStateMask.Stencil;
  528. block.stencilReference = (block.stencilReference & (int)StencilUsage.UserMask) | stencilRef;
  529. return block;
  530. }
  531. internal void ClearStencilPartial(RasterCommandBuffer cmd)
  532. {
  533. if (m_FullscreenMesh == null)
  534. m_FullscreenMesh = CreateFullscreenMesh();
  535. using (new ProfilingScope(cmd, m_ProfilingSamplerClearStencilPartialPass))
  536. {
  537. cmd.DrawMesh(m_FullscreenMesh, Matrix4x4.identity, m_StencilDeferredMaterial, 0, m_StencilDeferredPasses[(int)StencilDeferredPasses.ClearStencilPartial]);
  538. }
  539. }
  540. internal void ExecuteDeferredPass(RasterCommandBuffer cmd, UniversalCameraData cameraData, UniversalLightData lightData, UniversalShadowData shadowData)
  541. {
  542. // Workaround for bug.
  543. // When changing the URP asset settings (ex: shadow cascade resolution), all ScriptableRenderers are recreated but
  544. // 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,
  545. // which prevents from resolving correct pass indices.
  546. if (m_StencilDeferredPasses[0] < 0)
  547. InitStencilDeferredMaterial();
  548. if (!UseFramebufferFetch)
  549. {
  550. for (int i = 0; i < GbufferTextureHandles.Length; i++)
  551. {
  552. if (i != GBufferLightingIndex)
  553. m_StencilDeferredMaterial.SetTexture(k_GBufferShaderPropertyIDs[i], GbufferTextureHandles[i]);
  554. }
  555. }
  556. using (new ProfilingScope(cmd, m_ProfilingDeferredPass))
  557. {
  558. // This does 2 things:
  559. // - baked geometry are skipped (do not receive dynamic lighting)
  560. // - non-baked geometry (== non-static geometry) use shadowMask/occlusionProbes to emulate baked shadows influences.
  561. cmd.SetKeyword(ShaderGlobalKeywords._DEFERRED_MIXED_LIGHTING, this.UseShadowMask);
  562. // This must be set for each eye in XR mode multipass.
  563. SetupMatrixConstants(cmd, cameraData);
  564. // First directional light will apply SSAO if possible, unless there is none.
  565. if (!HasStencilLightsOfType(LightType.Directional))
  566. RenderSSAOBeforeShading(cmd);
  567. RenderStencilLights(cmd, lightData, shadowData, cameraData.renderer.stripShadowsOffVariants);
  568. cmd.SetKeyword(ShaderGlobalKeywords._DEFERRED_MIXED_LIGHTING, false);
  569. // Legacy fog (Windows -> Rendering -> Lighting Settings -> Fog)
  570. RenderFog(cmd, cameraData.camera.orthographic);
  571. }
  572. // Restore shader keywords
  573. cmd.SetKeyword(ShaderGlobalKeywords.AdditionalLightShadows, shadowData.isKeywordAdditionalLightShadowsEnabled);
  574. ShadowUtils.SetSoftShadowQualityShaderKeywords(cmd, shadowData);
  575. cmd.SetKeyword(ShaderGlobalKeywords.LightCookies, m_LightCookieManager != null && m_LightCookieManager.IsKeywordLightCookieEnabled);
  576. }
  577. // adapted from ForwardLights.SetupShaderLightConstants
  578. void SetupShaderLightConstants(CommandBuffer cmd, UniversalLightData lightData)
  579. {
  580. // Main light has an optimized shader path for main light. This will benefit games that only care about a single light.
  581. // Universal Forward pipeline only supports a single shadow light, if available it will be the main light.
  582. SetupMainLightConstants(cmd, lightData);
  583. }
  584. // adapted from ForwardLights.SetupShaderLightConstants
  585. void SetupMainLightConstants(CommandBuffer cmd, UniversalLightData lightData)
  586. {
  587. if (lightData.mainLightIndex < 0)
  588. return;
  589. Vector4 lightPos, lightColor, lightAttenuation, lightSpotDir, lightOcclusionChannel;
  590. UniversalRenderPipeline.InitializeLightConstants_Common(lightData.visibleLights, lightData.mainLightIndex, out lightPos, out lightColor, out lightAttenuation, out lightSpotDir, out lightOcclusionChannel);
  591. if (lightData.supportsLightLayers)
  592. {
  593. Light light = lightData.visibleLights[lightData.mainLightIndex].light;
  594. SetRenderingLayersMask(CommandBufferHelpers.GetRasterCommandBuffer(cmd), light, ShaderConstants._MainLightLayerMask);
  595. }
  596. cmd.SetGlobalVector(ShaderConstants._MainLightPosition, lightPos);
  597. cmd.SetGlobalVector(ShaderConstants._MainLightColor, lightColor);
  598. }
  599. void SetupMatrixConstants(RasterCommandBuffer cmd, UniversalCameraData cameraData)
  600. {
  601. #if ENABLE_VR && ENABLE_XR_MODULE
  602. int eyeCount = cameraData.xr.enabled && cameraData.xr.singlePassEnabled ? 2 : 1;
  603. #else
  604. int eyeCount = 1;
  605. #endif
  606. Matrix4x4[] screenToWorld = m_ScreenToWorld; // deferred shaders expects 2 elements
  607. for (int eyeIndex = 0; eyeIndex < eyeCount; eyeIndex++)
  608. {
  609. Matrix4x4 proj = cameraData.GetProjectionMatrix(eyeIndex);
  610. Matrix4x4 view = cameraData.GetViewMatrix(eyeIndex);
  611. Matrix4x4 gpuProj = GL.GetGPUProjectionMatrix(proj, false);
  612. // xy coordinates in range [-1; 1] go to pixel coordinates.
  613. Matrix4x4 toScreen = new Matrix4x4(
  614. new Vector4(0.5f * this.RenderWidth, 0.0f, 0.0f, 0.0f),
  615. new Vector4(0.0f, 0.5f * this.RenderHeight, 0.0f, 0.0f),
  616. new Vector4(0.0f, 0.0f, 1.0f, 0.0f),
  617. new Vector4(0.5f * this.RenderWidth, 0.5f * this.RenderHeight, 0.0f, 1.0f)
  618. );
  619. Matrix4x4 zScaleBias = Matrix4x4.identity;
  620. if (DeferredConfig.IsOpenGL)
  621. {
  622. // We need to manunally adjust z in NDC space from [-1; 1] to [0; 1] (storage in depth texture).
  623. zScaleBias = new Matrix4x4(
  624. new Vector4(1.0f, 0.0f, 0.0f, 0.0f),
  625. new Vector4(0.0f, 1.0f, 0.0f, 0.0f),
  626. new Vector4(0.0f, 0.0f, 0.5f, 0.0f),
  627. new Vector4(0.0f, 0.0f, 0.5f, 1.0f)
  628. );
  629. }
  630. screenToWorld[eyeIndex] = Matrix4x4.Inverse(toScreen * zScaleBias * gpuProj * view);
  631. }
  632. cmd.SetGlobalMatrixArray(ShaderConstants._ScreenToWorld, screenToWorld);
  633. }
  634. void PrecomputeLights(
  635. out NativeArray<ushort> stencilVisLights,
  636. out NativeArray<ushort> stencilVisLightOffsets,
  637. ref NativeArray<VisibleLight> visibleLights,
  638. bool hasAdditionalLights)
  639. {
  640. const int lightTypeCount = (int)LightType.Tube + 1;
  641. if (!hasAdditionalLights)
  642. {
  643. stencilVisLights = new NativeArray<ushort>(0, Allocator.Temp, NativeArrayOptions.UninitializedMemory);
  644. stencilVisLightOffsets = new NativeArray<ushort>(lightTypeCount, Allocator.Temp, NativeArrayOptions.UninitializedMemory);
  645. for (int i = 0; i < lightTypeCount; ++i)
  646. stencilVisLightOffsets[i] = k_InvalidLightOffset;
  647. return;
  648. }
  649. NativeArray<int> stencilLightCounts = new NativeArray<int>(lightTypeCount, Allocator.Temp, NativeArrayOptions.ClearMemory);
  650. stencilVisLightOffsets = new NativeArray<ushort>(lightTypeCount, Allocator.Temp, NativeArrayOptions.ClearMemory);
  651. // Count the number of lights per type.
  652. int visibleLightCount = visibleLights.Length;
  653. for (ushort visLightIndex = 0; visLightIndex < visibleLightCount; ++visLightIndex)
  654. {
  655. ref VisibleLight vl = ref visibleLights.UnsafeElementAtMutable(visLightIndex);
  656. ++stencilVisLightOffsets[(int)vl.lightType];
  657. }
  658. int totalStencilLightCount = stencilVisLightOffsets[(int)LightType.Spot] + stencilVisLightOffsets[(int)LightType.Directional] + stencilVisLightOffsets[(int)LightType.Point];
  659. stencilVisLights = new NativeArray<ushort>(totalStencilLightCount, Allocator.Temp, NativeArrayOptions.UninitializedMemory);
  660. for (int i = 0, soffset = 0; i < stencilVisLightOffsets.Length; ++i)
  661. {
  662. if (stencilVisLightOffsets[i] == 0)
  663. stencilVisLightOffsets[i] = k_InvalidLightOffset;
  664. else
  665. {
  666. int c = stencilVisLightOffsets[i];
  667. stencilVisLightOffsets[i] = (ushort)soffset;
  668. soffset += c;
  669. }
  670. }
  671. for (ushort visLightIndex = 0; visLightIndex < visibleLightCount; ++visLightIndex)
  672. {
  673. ref VisibleLight vl = ref visibleLights.UnsafeElementAtMutable(visLightIndex);
  674. if (vl.lightType != LightType.Spot &&
  675. vl.lightType != LightType.Directional &&
  676. vl.lightType != LightType.Point)
  677. {
  678. // The light type is not supported. Skip the light.
  679. continue;
  680. }
  681. int i = stencilLightCounts[(int) vl.lightType]++;
  682. stencilVisLights[stencilVisLightOffsets[(int) vl.lightType] + i] = visLightIndex;
  683. }
  684. stencilLightCounts.Dispose();
  685. }
  686. bool HasStencilLightsOfType(LightType type)
  687. {
  688. return m_stencilVisLightOffsets[(int)type] != k_InvalidLightOffset;
  689. }
  690. void RenderStencilLights(RasterCommandBuffer cmd, UniversalLightData lightData, UniversalShadowData shadowData, bool stripShadowsOffVariants)
  691. {
  692. if (m_stencilVisLights.Length == 0)
  693. return;
  694. if (m_StencilDeferredMaterial == null)
  695. {
  696. Debug.LogErrorFormat("Missing {0}. {1} render pass will not execute. Check for missing reference in the renderer resources.", m_StencilDeferredMaterial, GetType().Name);
  697. return;
  698. }
  699. Profiler.BeginSample(k_DeferredStencilPass);
  700. using (new ProfilingScope(cmd, m_ProfilingSamplerDeferredStencilPass))
  701. {
  702. NativeArray<VisibleLight> visibleLights = lightData.visibleLights;
  703. bool hasLightCookieManager = m_LightCookieManager != null;
  704. bool hasAdditionalLightPass = m_AdditionalLightsShadowCasterPass != null;
  705. if (HasStencilLightsOfType(LightType.Directional))
  706. RenderStencilDirectionalLights(cmd, stripShadowsOffVariants, lightData, shadowData, visibleLights, hasAdditionalLightPass, hasLightCookieManager, lightData.mainLightIndex);
  707. if (lightData.supportsAdditionalLights)
  708. {
  709. if (HasStencilLightsOfType(LightType.Point))
  710. RenderStencilPointLights(cmd, stripShadowsOffVariants, lightData, shadowData, visibleLights, hasAdditionalLightPass, hasLightCookieManager);
  711. if (HasStencilLightsOfType(LightType.Spot))
  712. RenderStencilSpotLights(cmd, stripShadowsOffVariants, lightData, shadowData, visibleLights, hasAdditionalLightPass, hasLightCookieManager);
  713. }
  714. }
  715. Profiler.EndSample();
  716. }
  717. void RenderStencilDirectionalLights(RasterCommandBuffer cmd, bool stripShadowsOffVariants, UniversalLightData lightData, UniversalShadowData shadowData, NativeArray<VisibleLight> visibleLights, bool hasAdditionalLightPass, bool hasLightCookieManager, int mainLightIndex)
  718. {
  719. if (m_FullscreenMesh == null)
  720. m_FullscreenMesh = CreateFullscreenMesh();
  721. cmd.SetKeyword(ShaderGlobalKeywords._DIRECTIONAL, true);
  722. // TODO bundle extra directional lights rendering by batches of 8.
  723. // Also separate shadow caster lights from non-shadow caster.
  724. int lastLightCookieIndex = -1;
  725. bool isFirstLight = true;
  726. bool lastLightCookieKeywordState = false;
  727. bool lastShadowsKeywordState = false;
  728. bool lastSoftShadowsKeywordState = false;
  729. for (int soffset = m_stencilVisLightOffsets[(int)LightType.Directional]; soffset < m_stencilVisLights.Length; ++soffset)
  730. {
  731. ushort visLightIndex = m_stencilVisLights[soffset];
  732. ref VisibleLight vl = ref visibleLights.UnsafeElementAtMutable(visLightIndex);
  733. if (vl.lightType != LightType.Directional)
  734. break;
  735. // Avoid light find on every access.
  736. Light light = vl.light;
  737. Vector4 lightDir, lightColor, lightAttenuation, lightSpotDir, lightOcclusionChannel;
  738. UniversalRenderPipeline.InitializeLightConstants_Common(visibleLights, visLightIndex, out lightDir, out lightColor, out lightAttenuation, out lightSpotDir, out lightOcclusionChannel);
  739. int lightFlags = 0;
  740. if (light.bakingOutput.lightmapBakeType == LightmapBakeType.Mixed)
  741. lightFlags |= (int)LightFlag.SubtractiveMixedLighting;
  742. if (lightData.supportsLightLayers)
  743. SetRenderingLayersMask(cmd, light, ShaderConstants._LightLayerMask);
  744. // Setup shadow parameters:
  745. // - for the main light, they have already been setup globally, so nothing to do.
  746. // - for other directional lights, it is actually not supported by URP, but the code would look like this.
  747. bool hasDeferredShadows = light && light.shadows != LightShadows.None;
  748. bool isMainLight = visLightIndex == mainLightIndex;
  749. if (!isMainLight)
  750. {
  751. int shadowLightIndex = hasAdditionalLightPass ? m_AdditionalLightsShadowCasterPass.GetShadowLightIndexFromLightIndex(visLightIndex) : -1;
  752. hasDeferredShadows = light && light.shadows != LightShadows.None && shadowLightIndex >= 0;
  753. cmd.SetGlobalInt(ShaderConstants._ShadowLightIndex, shadowLightIndex);
  754. SetLightCookiesKeyword(cmd, visLightIndex, hasLightCookieManager, isFirstLight, ref lastLightCookieKeywordState, ref lastLightCookieIndex);
  755. }
  756. // Update keywords states
  757. SetAdditionalLightsShadowsKeyword(ref cmd, stripShadowsOffVariants, shadowData.additionalLightShadowsEnabled, hasDeferredShadows, isFirstLight, ref lastShadowsKeywordState);
  758. SetSoftShadowsKeyword(cmd, shadowData, light, hasDeferredShadows, isFirstLight, ref lastSoftShadowsKeywordState);
  759. cmd.SetKeyword(ShaderGlobalKeywords._DEFERRED_FIRST_LIGHT, isFirstLight); // First directional light applies SSAO
  760. cmd.SetKeyword(ShaderGlobalKeywords._DEFERRED_MAIN_LIGHT, isMainLight); // main directional light use different uniform constants from additional directional lights
  761. // Update Global properties
  762. cmd.SetGlobalVector(ShaderConstants._LightColor, lightColor); // VisibleLight.finalColor already returns color in active color space
  763. cmd.SetGlobalVector(ShaderConstants._LightDirection, lightDir);
  764. cmd.SetGlobalInt(ShaderConstants._LightFlags, lightFlags);
  765. // Lighting pass.
  766. cmd.DrawMesh(m_FullscreenMesh, Matrix4x4.identity, m_StencilDeferredMaterial, 0, m_StencilDeferredPasses[(int)StencilDeferredPasses.DirectionalLit]);
  767. cmd.DrawMesh(m_FullscreenMesh, Matrix4x4.identity, m_StencilDeferredMaterial, 0, m_StencilDeferredPasses[(int)StencilDeferredPasses.DirectionalSimpleLit]);
  768. isFirstLight = false;
  769. }
  770. cmd.SetKeyword(ShaderGlobalKeywords._DIRECTIONAL, false);
  771. }
  772. void RenderStencilPointLights(RasterCommandBuffer cmd, bool stripShadowsOffVariants, UniversalLightData lightData, UniversalShadowData shadowData, NativeArray<VisibleLight> visibleLights, bool hasAdditionalLightPass, bool hasLightCookieManager)
  773. {
  774. if (m_SphereMesh == null)
  775. m_SphereMesh = CreateSphereMesh();
  776. cmd.SetKeyword(ShaderGlobalKeywords._POINT, true);
  777. int lastLightCookieIndex = -1;
  778. bool isFirstLight = true;
  779. bool lastLightCookieKeywordState = false;
  780. bool lastShadowsKeywordState = false;
  781. bool lastSoftShadowsKeywordState = false;
  782. for (int soffset = m_stencilVisLightOffsets[(int)LightType.Point]; soffset < m_stencilVisLights.Length; ++soffset)
  783. {
  784. ushort visLightIndex = m_stencilVisLights[soffset];
  785. ref VisibleLight vl = ref visibleLights.UnsafeElementAtMutable(visLightIndex);
  786. if (vl.lightType != LightType.Point)
  787. break;
  788. // Avoid light find on every access.
  789. Light light = vl.light;
  790. Vector3 posWS = vl.localToWorldMatrix.GetColumn(3);
  791. Matrix4x4 transformMatrix = new Matrix4x4(
  792. new Vector4(vl.range, 0.0f, 0.0f, 0.0f),
  793. new Vector4(0.0f, vl.range, 0.0f, 0.0f),
  794. new Vector4(0.0f, 0.0f, vl.range, 0.0f),
  795. new Vector4(posWS.x, posWS.y, posWS.z, 1.0f)
  796. );
  797. Vector4 lightPos, lightColor, lightAttenuation, lightOcclusionChannel;
  798. UniversalRenderPipeline.InitializeLightConstants_Common(visibleLights, visLightIndex, out lightPos, out lightColor, out lightAttenuation, out _, out lightOcclusionChannel);
  799. if (lightData.supportsLightLayers)
  800. SetRenderingLayersMask(cmd, light, ShaderConstants._LightLayerMask);
  801. int lightFlags = 0;
  802. if (light.bakingOutput.lightmapBakeType == LightmapBakeType.Mixed)
  803. lightFlags |= (int)LightFlag.SubtractiveMixedLighting;
  804. // Determine whether the light is casting shadows and what the index it should use.
  805. int shadowLightIndex = hasAdditionalLightPass ? m_AdditionalLightsShadowCasterPass.GetShadowLightIndexFromLightIndex(visLightIndex) : -1;
  806. bool hasDeferredShadows = light && light.shadows != LightShadows.None && shadowLightIndex >= 0;
  807. // Update keywords states
  808. SetAdditionalLightsShadowsKeyword(ref cmd, stripShadowsOffVariants, shadowData.additionalLightShadowsEnabled, hasDeferredShadows, isFirstLight, ref lastShadowsKeywordState);
  809. SetSoftShadowsKeyword(cmd, shadowData, light, hasDeferredShadows, isFirstLight, ref lastSoftShadowsKeywordState);
  810. SetLightCookiesKeyword(cmd, visLightIndex, hasLightCookieManager, isFirstLight, ref lastLightCookieKeywordState, ref lastLightCookieIndex);
  811. // Update Global properties
  812. cmd.SetGlobalVector(ShaderConstants._LightPosWS, lightPos);
  813. cmd.SetGlobalVector(ShaderConstants._LightColor, lightColor);
  814. cmd.SetGlobalVector(ShaderConstants._LightAttenuation, lightAttenuation);
  815. cmd.SetGlobalVector(ShaderConstants._LightOcclusionProbInfo, lightOcclusionChannel);
  816. cmd.SetGlobalInt(ShaderConstants._LightFlags, lightFlags);
  817. cmd.SetGlobalInt(ShaderConstants._ShadowLightIndex, shadowLightIndex);
  818. // Stencil pass.
  819. cmd.DrawMesh(m_SphereMesh, transformMatrix, m_StencilDeferredMaterial, 0, m_StencilDeferredPasses[(int)StencilDeferredPasses.StencilVolume]);
  820. // Lighting pass.
  821. cmd.DrawMesh(m_SphereMesh, transformMatrix, m_StencilDeferredMaterial, 0, m_StencilDeferredPasses[(int)StencilDeferredPasses.PunctualLit]);
  822. cmd.DrawMesh(m_SphereMesh, transformMatrix, m_StencilDeferredMaterial, 0, m_StencilDeferredPasses[(int)StencilDeferredPasses.PunctualSimpleLit]);
  823. isFirstLight = false;
  824. }
  825. cmd.SetKeyword(ShaderGlobalKeywords._POINT, false);
  826. }
  827. void RenderStencilSpotLights(RasterCommandBuffer cmd, bool stripShadowsOffVariants, UniversalLightData lightData, UniversalShadowData shadowData, NativeArray<VisibleLight> visibleLights, bool hasAdditionalLightPass, bool hasLightCookieManager)
  828. {
  829. if (m_HemisphereMesh == null)
  830. m_HemisphereMesh = CreateHemisphereMesh();
  831. cmd.SetKeyword(ShaderGlobalKeywords._SPOT, true);
  832. int lastLightCookieIndex = -1;
  833. bool isFirstLight = true;
  834. bool lastLightCookieKeywordState = false;
  835. bool lastShadowsKeywordState = false;
  836. bool lastSoftShadowsKeywordState = false;
  837. for (int soffset = m_stencilVisLightOffsets[(int)LightType.Spot]; soffset < m_stencilVisLights.Length; ++soffset)
  838. {
  839. ushort visLightIndex = m_stencilVisLights[soffset];
  840. ref VisibleLight vl = ref visibleLights.UnsafeElementAtMutable(visLightIndex);
  841. if (vl.lightType != LightType.Spot)
  842. break;
  843. // Cache light to local, avoid light find on every access.
  844. Light light = vl.light;
  845. float alpha = Mathf.Deg2Rad * vl.spotAngle * 0.5f;
  846. float cosAlpha = Mathf.Cos(alpha);
  847. float sinAlpha = Mathf.Sin(alpha);
  848. // Artificially inflate the geometric shape to fit the analytic spot shape.
  849. // The tighter the spot shape, the lesser inflation is needed.
  850. float guard = Mathf.Lerp(1.0f, kStencilShapeGuard, sinAlpha);
  851. UniversalRenderPipeline.InitializeLightConstants_Common(visibleLights, visLightIndex, out Vector4 lightPos, out Vector4 lightColor, out Vector4 lightAttenuation, out Vector4 lightSpotDir, out Vector4 lightOcclusionChannel);
  852. if (lightData.supportsLightLayers)
  853. SetRenderingLayersMask(cmd, light, ShaderConstants._LightLayerMask);
  854. int lightFlags = 0;
  855. if (light.bakingOutput.lightmapBakeType == LightmapBakeType.Mixed)
  856. lightFlags |= (int)LightFlag.SubtractiveMixedLighting;
  857. // Determine whether the light is casting shadows and what the index it should use.
  858. int shadowLightIndex = hasAdditionalLightPass ? m_AdditionalLightsShadowCasterPass.GetShadowLightIndexFromLightIndex(visLightIndex) : -1;
  859. bool hasDeferredShadows = light && light.shadows != LightShadows.None && shadowLightIndex >= 0;
  860. // Update keywords states
  861. SetAdditionalLightsShadowsKeyword(ref cmd, stripShadowsOffVariants, shadowData.additionalLightShadowsEnabled, hasDeferredShadows, isFirstLight, ref lastShadowsKeywordState);
  862. SetSoftShadowsKeyword(cmd, shadowData, light, hasDeferredShadows, isFirstLight, ref lastSoftShadowsKeywordState);
  863. SetLightCookiesKeyword(cmd, visLightIndex, hasLightCookieManager, isFirstLight, ref lastLightCookieKeywordState, ref lastLightCookieIndex);
  864. // Update Global properties
  865. cmd.SetGlobalVector(ShaderConstants._SpotLightScale, new Vector4(sinAlpha, sinAlpha, 1.0f - cosAlpha, vl.range));
  866. cmd.SetGlobalVector(ShaderConstants._SpotLightBias, new Vector4(0.0f, 0.0f, cosAlpha, 0.0f));
  867. cmd.SetGlobalVector(ShaderConstants._SpotLightGuard, new Vector4(guard, guard, guard, cosAlpha * vl.range));
  868. cmd.SetGlobalVector(ShaderConstants._LightPosWS, lightPos);
  869. cmd.SetGlobalVector(ShaderConstants._LightColor, lightColor);
  870. cmd.SetGlobalVector(ShaderConstants._LightAttenuation, lightAttenuation);
  871. cmd.SetGlobalVector(ShaderConstants._LightDirection, new Vector3(lightSpotDir.x, lightSpotDir.y, lightSpotDir.z));
  872. cmd.SetGlobalVector(ShaderConstants._LightOcclusionProbInfo, lightOcclusionChannel);
  873. cmd.SetGlobalInt(ShaderConstants._LightFlags, lightFlags);
  874. cmd.SetGlobalInt(ShaderConstants._ShadowLightIndex, shadowLightIndex);
  875. // Stencil pass.
  876. cmd.DrawMesh(m_HemisphereMesh, vl.localToWorldMatrix, m_StencilDeferredMaterial, 0, m_StencilDeferredPasses[(int)StencilDeferredPasses.StencilVolume]);
  877. // Lighting pass.
  878. cmd.DrawMesh(m_HemisphereMesh, vl.localToWorldMatrix, m_StencilDeferredMaterial, 0, m_StencilDeferredPasses[(int)StencilDeferredPasses.PunctualLit]);
  879. cmd.DrawMesh(m_HemisphereMesh, vl.localToWorldMatrix, m_StencilDeferredMaterial, 0, m_StencilDeferredPasses[(int)StencilDeferredPasses.PunctualSimpleLit]);
  880. isFirstLight = false;
  881. }
  882. cmd.SetKeyword(ShaderGlobalKeywords._SPOT, false);
  883. }
  884. void RenderSSAOBeforeShading(RasterCommandBuffer cmd)
  885. {
  886. if (m_FullscreenMesh == null)
  887. m_FullscreenMesh = CreateFullscreenMesh();
  888. cmd.DrawMesh(m_FullscreenMesh, Matrix4x4.identity, m_StencilDeferredMaterial, 0, m_StencilDeferredPasses[(int)StencilDeferredPasses.SSAOOnly]);
  889. }
  890. void RenderFog(RasterCommandBuffer cmd, bool isOrthographic)
  891. {
  892. // Legacy fog does not work in orthographic mode.
  893. if (!RenderSettings.fog || isOrthographic)
  894. return;
  895. if (m_FullscreenMesh == null)
  896. m_FullscreenMesh = CreateFullscreenMesh();
  897. using (new ProfilingScope(cmd, m_ProfilingSamplerDeferredFogPass))
  898. {
  899. // Fog parameters and shader variant keywords are already set externally.
  900. cmd.DrawMesh(m_FullscreenMesh, Matrix4x4.identity, m_StencilDeferredMaterial, 0, m_StencilDeferredPasses[(int)StencilDeferredPasses.Fog]);
  901. }
  902. }
  903. void InitStencilDeferredMaterial()
  904. {
  905. if (m_StencilDeferredMaterial == null)
  906. return;
  907. // Pass indices can not be hardcoded because some platforms will strip out some passes, offset the index of later passes.
  908. for (int pass = 0; pass < k_StencilDeferredPassNames.Length; ++pass)
  909. m_StencilDeferredPasses[pass] = m_StencilDeferredMaterial.FindPass(k_StencilDeferredPassNames[pass]);
  910. m_StencilDeferredMaterial.SetFloat(ShaderConstants._StencilRef, (float)StencilUsage.MaterialUnlit);
  911. m_StencilDeferredMaterial.SetFloat(ShaderConstants._StencilReadMask, (float)StencilUsage.MaterialMask);
  912. m_StencilDeferredMaterial.SetFloat(ShaderConstants._StencilWriteMask, (float)StencilUsage.StencilLight);
  913. m_StencilDeferredMaterial.SetFloat(ShaderConstants._LitPunctualStencilRef, (float)((int)StencilUsage.StencilLight | (int)StencilUsage.MaterialLit));
  914. m_StencilDeferredMaterial.SetFloat(ShaderConstants._LitPunctualStencilReadMask, (float)((int)StencilUsage.StencilLight | (int)StencilUsage.MaterialMask));
  915. m_StencilDeferredMaterial.SetFloat(ShaderConstants._LitPunctualStencilWriteMask, (float)StencilUsage.StencilLight);
  916. m_StencilDeferredMaterial.SetFloat(ShaderConstants._SimpleLitPunctualStencilRef, (float)((int)StencilUsage.StencilLight | (int)StencilUsage.MaterialSimpleLit));
  917. m_StencilDeferredMaterial.SetFloat(ShaderConstants._SimpleLitPunctualStencilReadMask, (float)((int)StencilUsage.StencilLight | (int)StencilUsage.MaterialMask));
  918. m_StencilDeferredMaterial.SetFloat(ShaderConstants._SimpleLitPunctualStencilWriteMask, (float)StencilUsage.StencilLight);
  919. m_StencilDeferredMaterial.SetFloat(ShaderConstants._LitDirStencilRef, (float)StencilUsage.MaterialLit);
  920. m_StencilDeferredMaterial.SetFloat(ShaderConstants._LitDirStencilReadMask, (float)StencilUsage.MaterialMask);
  921. m_StencilDeferredMaterial.SetFloat(ShaderConstants._LitDirStencilWriteMask, 0.0f);
  922. m_StencilDeferredMaterial.SetFloat(ShaderConstants._SimpleLitDirStencilRef, (float)StencilUsage.MaterialSimpleLit);
  923. m_StencilDeferredMaterial.SetFloat(ShaderConstants._SimpleLitDirStencilReadMask, (float)StencilUsage.MaterialMask);
  924. m_StencilDeferredMaterial.SetFloat(ShaderConstants._SimpleLitDirStencilWriteMask, 0.0f);
  925. m_StencilDeferredMaterial.SetFloat(ShaderConstants._ClearStencilRef, 0.0f);
  926. m_StencilDeferredMaterial.SetFloat(ShaderConstants._ClearStencilReadMask, (float)StencilUsage.MaterialMask);
  927. m_StencilDeferredMaterial.SetFloat(ShaderConstants._ClearStencilWriteMask, (float)StencilUsage.MaterialMask);
  928. }
  929. static Mesh CreateSphereMesh()
  930. {
  931. // This icosaedron has been been slightly inflated to fit an unit sphere.
  932. // This is the same geometry as built-in deferred.
  933. Vector3[] positions =
  934. {
  935. new Vector3(0.000f, 0.000f, -1.070f), new Vector3(0.174f, -0.535f, -0.910f),
  936. new Vector3(-0.455f, -0.331f, -0.910f), new Vector3(0.562f, 0.000f, -0.910f),
  937. new Vector3(-0.455f, 0.331f, -0.910f), new Vector3(0.174f, 0.535f, -0.910f),
  938. new Vector3(-0.281f, -0.865f, -0.562f), new Vector3(0.736f, -0.535f, -0.562f),
  939. new Vector3(0.296f, -0.910f, -0.468f), new Vector3(-0.910f, 0.000f, -0.562f),
  940. new Vector3(-0.774f, -0.562f, -0.478f), new Vector3(0.000f, -1.070f, 0.000f),
  941. new Vector3(-0.629f, -0.865f, 0.000f), new Vector3(0.629f, -0.865f, 0.000f),
  942. new Vector3(-1.017f, -0.331f, 0.000f), new Vector3(0.957f, 0.000f, -0.478f),
  943. new Vector3(0.736f, 0.535f, -0.562f), new Vector3(1.017f, -0.331f, 0.000f),
  944. new Vector3(1.017f, 0.331f, 0.000f), new Vector3(-0.296f, -0.910f, 0.478f),
  945. new Vector3(0.281f, -0.865f, 0.562f), new Vector3(0.774f, -0.562f, 0.478f),
  946. new Vector3(-0.736f, -0.535f, 0.562f), new Vector3(0.910f, 0.000f, 0.562f),
  947. new Vector3(0.455f, -0.331f, 0.910f), new Vector3(-0.174f, -0.535f, 0.910f),
  948. new Vector3(0.629f, 0.865f, 0.000f), new Vector3(0.774f, 0.562f, 0.478f),
  949. new Vector3(0.455f, 0.331f, 0.910f), new Vector3(0.000f, 0.000f, 1.070f),
  950. new Vector3(-0.562f, 0.000f, 0.910f), new Vector3(-0.957f, 0.000f, 0.478f),
  951. new Vector3(0.281f, 0.865f, 0.562f), new Vector3(-0.174f, 0.535f, 0.910f),
  952. new Vector3(0.296f, 0.910f, -0.478f), new Vector3(-1.017f, 0.331f, 0.000f),
  953. new Vector3(-0.736f, 0.535f, 0.562f), new Vector3(-0.296f, 0.910f, 0.478f),
  954. new Vector3(0.000f, 1.070f, 0.000f), new Vector3(-0.281f, 0.865f, -0.562f),
  955. new Vector3(-0.774f, 0.562f, -0.478f), new Vector3(-0.629f, 0.865f, 0.000f),
  956. };
  957. int[] indices =
  958. {
  959. 0, 1, 2, 0, 3, 1, 2, 4, 0, 0, 5, 3, 0, 4, 5, 1, 6, 2,
  960. 3, 7, 1, 1, 8, 6, 1, 7, 8, 9, 4, 2, 2, 6, 10, 10, 9, 2,
  961. 8, 11, 6, 6, 12, 10, 11, 12, 6, 7, 13, 8, 8, 13, 11, 10, 14, 9,
  962. 10, 12, 14, 3, 15, 7, 5, 16, 3, 3, 16, 15, 15, 17, 7, 17, 13, 7,
  963. 16, 18, 15, 15, 18, 17, 11, 19, 12, 13, 20, 11, 11, 20, 19, 17, 21, 13,
  964. 13, 21, 20, 12, 19, 22, 12, 22, 14, 17, 23, 21, 18, 23, 17, 21, 24, 20,
  965. 23, 24, 21, 20, 25, 19, 19, 25, 22, 24, 25, 20, 26, 18, 16, 18, 27, 23,
  966. 26, 27, 18, 28, 24, 23, 27, 28, 23, 24, 29, 25, 28, 29, 24, 25, 30, 22,
  967. 25, 29, 30, 14, 22, 31, 22, 30, 31, 32, 28, 27, 26, 32, 27, 33, 29, 28,
  968. 30, 29, 33, 33, 28, 32, 34, 26, 16, 5, 34, 16, 14, 31, 35, 14, 35, 9,
  969. 31, 30, 36, 30, 33, 36, 35, 31, 36, 37, 33, 32, 36, 33, 37, 38, 32, 26,
  970. 34, 38, 26, 38, 37, 32, 5, 39, 34, 39, 38, 34, 4, 39, 5, 9, 40, 4,
  971. 9, 35, 40, 4, 40, 39, 35, 36, 41, 41, 36, 37, 41, 37, 38, 40, 35, 41,
  972. 40, 41, 39, 41, 38, 39,
  973. };
  974. Mesh mesh = new Mesh();
  975. mesh.indexFormat = IndexFormat.UInt16;
  976. mesh.vertices = positions;
  977. mesh.triangles = indices;
  978. return mesh;
  979. }
  980. static Mesh CreateHemisphereMesh()
  981. {
  982. // TODO reorder for pre&post-transform cache optimisation.
  983. // This capped hemisphere shape is in unit dimensions. It will be slightly inflated in the vertex shader
  984. // to fit the cone analytical shape.
  985. Vector3[] positions =
  986. {
  987. new Vector3(0.000000f, 0.000000f, 0.000000f), new Vector3(1.000000f, 0.000000f, 0.000000f),
  988. new Vector3(0.923880f, 0.382683f, 0.000000f), new Vector3(0.707107f, 0.707107f, 0.000000f),
  989. new Vector3(0.382683f, 0.923880f, 0.000000f), new Vector3(-0.000000f, 1.000000f, 0.000000f),
  990. new Vector3(-0.382684f, 0.923880f, 0.000000f), new Vector3(-0.707107f, 0.707107f, 0.000000f),
  991. new Vector3(-0.923880f, 0.382683f, 0.000000f), new Vector3(-1.000000f, -0.000000f, 0.000000f),
  992. new Vector3(-0.923880f, -0.382683f, 0.000000f), new Vector3(-0.707107f, -0.707107f, 0.000000f),
  993. new Vector3(-0.382683f, -0.923880f, 0.000000f), new Vector3(0.000000f, -1.000000f, 0.000000f),
  994. new Vector3(0.382684f, -0.923879f, 0.000000f), new Vector3(0.707107f, -0.707107f, 0.000000f),
  995. new Vector3(0.923880f, -0.382683f, 0.000000f), new Vector3(0.000000f, 0.000000f, 1.000000f),
  996. new Vector3(0.707107f, 0.000000f, 0.707107f), new Vector3(0.000000f, -0.707107f, 0.707107f),
  997. new Vector3(0.000000f, 0.707107f, 0.707107f), new Vector3(-0.707107f, 0.000000f, 0.707107f),
  998. new Vector3(0.816497f, -0.408248f, 0.408248f), new Vector3(0.408248f, -0.408248f, 0.816497f),
  999. new Vector3(0.408248f, -0.816497f, 0.408248f), new Vector3(0.408248f, 0.816497f, 0.408248f),
  1000. new Vector3(0.408248f, 0.408248f, 0.816497f), new Vector3(0.816497f, 0.408248f, 0.408248f),
  1001. new Vector3(-0.816497f, 0.408248f, 0.408248f), new Vector3(-0.408248f, 0.408248f, 0.816497f),
  1002. new Vector3(-0.408248f, 0.816497f, 0.408248f), new Vector3(-0.408248f, -0.816497f, 0.408248f),
  1003. new Vector3(-0.408248f, -0.408248f, 0.816497f), new Vector3(-0.816497f, -0.408248f, 0.408248f),
  1004. new Vector3(0.000000f, -0.923880f, 0.382683f), new Vector3(0.923880f, 0.000000f, 0.382683f),
  1005. new Vector3(0.000000f, -0.382683f, 0.923880f), new Vector3(0.382683f, 0.000000f, 0.923880f),
  1006. new Vector3(0.000000f, 0.923880f, 0.382683f), new Vector3(0.000000f, 0.382683f, 0.923880f),
  1007. new Vector3(-0.923880f, 0.000000f, 0.382683f), new Vector3(-0.382683f, 0.000000f, 0.923880f)
  1008. };
  1009. int[] indices =
  1010. {
  1011. 0, 2, 1, 0, 3, 2, 0, 4, 3, 0, 5, 4, 0, 6, 5, 0,
  1012. 7, 6, 0, 8, 7, 0, 9, 8, 0, 10, 9, 0, 11, 10, 0, 12,
  1013. 11, 0, 13, 12, 0, 14, 13, 0, 15, 14, 0, 16, 15, 0, 1, 16,
  1014. 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 14, 24, 34, 35,
  1015. 22, 16, 36, 23, 37, 2, 27, 35, 38, 25, 4, 37, 26, 39, 6, 30,
  1016. 38, 40, 28, 8, 39, 29, 41, 10, 33, 40, 34, 31, 12, 41, 32, 36,
  1017. 15, 22, 24, 18, 23, 22, 19, 24, 23, 3, 25, 27, 20, 26, 25, 18,
  1018. 27, 26, 7, 28, 30, 21, 29, 28, 20, 30, 29, 11, 31, 33, 19, 32,
  1019. 31, 21, 33, 32, 13, 14, 34, 15, 24, 14, 19, 34, 24, 1, 35, 16,
  1020. 18, 22, 35, 15, 16, 22, 17, 36, 37, 19, 23, 36, 18, 37, 23, 1,
  1021. 2, 35, 3, 27, 2, 18, 35, 27, 5, 38, 4, 20, 25, 38, 3, 4,
  1022. 25, 17, 37, 39, 18, 26, 37, 20, 39, 26, 5, 6, 38, 7, 30, 6,
  1023. 20, 38, 30, 9, 40, 8, 21, 28, 40, 7, 8, 28, 17, 39, 41, 20,
  1024. 29, 39, 21, 41, 29, 9, 10, 40, 11, 33, 10, 21, 40, 33, 13, 34,
  1025. 12, 19, 31, 34, 11, 12, 31, 17, 41, 36, 21, 32, 41, 19, 36, 32
  1026. };
  1027. Mesh mesh = new Mesh();
  1028. mesh.indexFormat = IndexFormat.UInt16;
  1029. mesh.vertices = positions;
  1030. mesh.triangles = indices;
  1031. return mesh;
  1032. }
  1033. static Mesh CreateFullscreenMesh()
  1034. {
  1035. // TODO reorder for pre&post-transform cache optimisation.
  1036. // Simple full-screen triangle.
  1037. Vector3[] positions =
  1038. {
  1039. new Vector3(-1.0f, 1.0f, 0.0f),
  1040. new Vector3(-1.0f, -3.0f, 0.0f),
  1041. new Vector3(3.0f, 1.0f, 0.0f)
  1042. };
  1043. int[] indices = { 0, 1, 2 };
  1044. Mesh mesh = new Mesh();
  1045. mesh.indexFormat = IndexFormat.UInt16;
  1046. mesh.vertices = positions;
  1047. mesh.triangles = indices;
  1048. return mesh;
  1049. }
  1050. // Sets the correct value for _MainLightLayerMask/_LightLayerMask
  1051. private void SetRenderingLayersMask(RasterCommandBuffer cmd, Light light, int shaderPropertyID)
  1052. {
  1053. var additionalLightData = light.GetUniversalAdditionalLightData();
  1054. uint lightLayerMask = RenderingLayerUtils.ToValidRenderingLayers(additionalLightData.renderingLayers);
  1055. cmd.SetGlobalInt(shaderPropertyID, (int)lightLayerMask);
  1056. }
  1057. // Enable/Disable the _ADDITIONAL_LIGHT_SHADOWS keyword if it has changed...
  1058. private void SetAdditionalLightsShadowsKeyword(ref RasterCommandBuffer cmd, bool stripShadowsOffVariants, bool additionalLightShadowsEnabled, bool hasDeferredShadows, bool shouldOverride, ref bool lastShadowsKeyword)
  1059. {
  1060. bool additionalLightShadowsEnabledInAsset = additionalLightShadowsEnabled;
  1061. bool hasOffVariant = !stripShadowsOffVariants;
  1062. // AdditionalLightShadows Keyword is enabled when:
  1063. // Shadows are enabled in Asset and
  1064. // a) the OFF variant has been stripped
  1065. // b) light is casting a shadow
  1066. bool shouldEnable = additionalLightShadowsEnabledInAsset && (!hasOffVariant || hasDeferredShadows);
  1067. // Return if the state hasn't changed...
  1068. if (!shouldOverride && lastShadowsKeyword == shouldEnable)
  1069. return;
  1070. // Update the keyword state
  1071. lastShadowsKeyword = shouldEnable;
  1072. cmd.SetKeyword(ShaderGlobalKeywords.AdditionalLightShadows, shouldEnable);
  1073. }
  1074. // Enable/Disable the _SHADOWS_SOFT keyword if it has changed...
  1075. private void SetSoftShadowsKeyword(RasterCommandBuffer cmd, UniversalShadowData shadowData, Light light, bool hasDeferredShadows, bool shouldOverride, ref bool lastHasSoftShadow)
  1076. {
  1077. bool hasSoftShadow = hasDeferredShadows && shadowData.supportsSoftShadows && light.shadows == LightShadows.Soft;
  1078. // Return if the state hasn't changed...
  1079. if (!shouldOverride && lastHasSoftShadow == hasSoftShadow)
  1080. return;
  1081. // Update the keyword state
  1082. lastHasSoftShadow = hasSoftShadow;
  1083. ShadowUtils.SetPerLightSoftShadowKeyword(cmd, hasSoftShadow);
  1084. }
  1085. // Enable/Disable the _LIGHT_COOKIES keyword if it has changed and the light cookie index
  1086. private void SetLightCookiesKeyword(RasterCommandBuffer cmd, int visLightIndex, bool hasLightCookieManager, bool shouldOverride, ref bool lastLightCookieState, ref int lastCookieLightIndex)
  1087. {
  1088. if (!hasLightCookieManager)
  1089. return;
  1090. int cookieLightIndex = m_LightCookieManager.GetLightCookieShaderDataIndex(visLightIndex);
  1091. bool newState = cookieLightIndex >= 0;
  1092. if (shouldOverride || newState != lastLightCookieState)
  1093. {
  1094. lastLightCookieState = newState;
  1095. cmd.SetKeyword(ShaderGlobalKeywords.LightCookies, newState);
  1096. }
  1097. if (shouldOverride || cookieLightIndex != lastCookieLightIndex)
  1098. {
  1099. lastCookieLightIndex = cookieLightIndex;
  1100. cmd.SetGlobalInt(ShaderConstants._CookieLightIndex, cookieLightIndex);
  1101. }
  1102. }
  1103. }
  1104. /*
  1105. struct BitArray : System.IDisposable
  1106. {
  1107. NativeArray<uint> m_Mem; // ulong not supported in il2cpp???
  1108. int m_BitCount;
  1109. int m_IntCount;
  1110. public BitArray(int bitCount, Allocator allocator, NativeArrayOptions options = NativeArrayOptions.ClearMemory)
  1111. {
  1112. m_BitCount = bitCount;
  1113. m_IntCount = (bitCount + 31) >> 5;
  1114. m_Mem = new NativeArray<uint>(m_IntCount, allocator, options);
  1115. }
  1116. public void Dispose()
  1117. {
  1118. m_Mem.Dispose();
  1119. }
  1120. public void Clear()
  1121. {
  1122. for (int i = 0; i < m_IntCount; ++i)
  1123. m_Mem[i] = 0;
  1124. }
  1125. public bool IsSet(int bitIndex)
  1126. {
  1127. return (m_Mem[bitIndex >> 5] & (1u << (bitIndex & 31))) != 0;
  1128. }
  1129. public void Set(int bitIndex, bool val)
  1130. {
  1131. if (val)
  1132. m_Mem[bitIndex >> 5] |= 1u << (bitIndex & 31);
  1133. else
  1134. m_Mem[bitIndex >> 5] &= ~(1u << (bitIndex & 31));
  1135. }
  1136. };
  1137. */
  1138. }