Нема описа
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

ScreenSpaceAmbientOcclusionPass.cs 37KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650
  1. using System;
  2. using UnityEngine.Rendering.RenderGraphModule;
  3. namespace UnityEngine.Rendering.Universal
  4. {
  5. // The Screen Space Ambient Occlusion (SSAO) Pass
  6. internal class ScreenSpaceAmbientOcclusionPass : ScriptableRenderPass
  7. {
  8. // Properties
  9. private bool isRendererDeferred => m_Renderer != null
  10. && m_Renderer is UniversalRenderer
  11. && ((UniversalRenderer)m_Renderer).renderingModeActual == RenderingMode.Deferred;
  12. // Private Variables
  13. private readonly bool m_SupportsR8RenderTextureFormat = SystemInfo.SupportsRenderTextureFormat(RenderTextureFormat.R8);
  14. private int m_BlueNoiseTextureIndex = 0;
  15. private Material m_Material;
  16. private SSAOPassData m_PassData;
  17. private Texture2D[] m_BlueNoiseTextures;
  18. private Vector4[] m_CameraTopLeftCorner = new Vector4[2];
  19. private Vector4[] m_CameraXExtent = new Vector4[2];
  20. private Vector4[] m_CameraYExtent = new Vector4[2];
  21. private Vector4[] m_CameraZExtent = new Vector4[2];
  22. private RTHandle[] m_SSAOTextures = new RTHandle[4];
  23. private BlurTypes m_BlurType = BlurTypes.Bilateral;
  24. private Matrix4x4[] m_CameraViewProjections = new Matrix4x4[2];
  25. private ProfilingSampler m_ProfilingSampler = ProfilingSampler.Get(URPProfileId.SSAO);
  26. private ScriptableRenderer m_Renderer = null;
  27. private RenderTextureDescriptor m_AOPassDescriptor;
  28. private ScreenSpaceAmbientOcclusionSettings m_CurrentSettings;
  29. // Constants
  30. private const string k_SSAOTextureName = "_ScreenSpaceOcclusionTexture";
  31. private const string k_AmbientOcclusionParamName = "_AmbientOcclusionParam";
  32. // Statics
  33. internal static readonly int s_AmbientOcclusionParamID = Shader.PropertyToID(k_AmbientOcclusionParamName);
  34. private static readonly int s_SSAOParamsID = Shader.PropertyToID("_SSAOParams");
  35. private static readonly int s_SSAOBlueNoiseParamsID = Shader.PropertyToID("_SSAOBlueNoiseParams");
  36. private static readonly int s_BlueNoiseTextureID = Shader.PropertyToID("_BlueNoiseTexture");
  37. private static readonly int s_SSAOFinalTextureID = Shader.PropertyToID(k_SSAOTextureName);
  38. private static readonly int s_CameraViewXExtentID = Shader.PropertyToID("_CameraViewXExtent");
  39. private static readonly int s_CameraViewYExtentID = Shader.PropertyToID("_CameraViewYExtent");
  40. private static readonly int s_CameraViewZExtentID = Shader.PropertyToID("_CameraViewZExtent");
  41. private static readonly int s_ProjectionParams2ID = Shader.PropertyToID("_ProjectionParams2");
  42. private static readonly int s_CameraViewProjectionsID = Shader.PropertyToID("_CameraViewProjections");
  43. private static readonly int s_CameraViewTopLeftCornerID = Shader.PropertyToID("_CameraViewTopLeftCorner");
  44. private static readonly int s_CameraDepthTextureID = Shader.PropertyToID("_CameraDepthTexture");
  45. private static readonly int s_CameraNormalsTextureID = Shader.PropertyToID("_CameraNormalsTexture");
  46. private static readonly int[] m_BilateralTexturesIndices = { 0, 1, 2, 3 };
  47. private static readonly ShaderPasses[] m_BilateralPasses = { ShaderPasses.BilateralBlurHorizontal, ShaderPasses.BilateralBlurVertical, ShaderPasses.BilateralBlurFinal };
  48. private static readonly ShaderPasses[] m_BilateralAfterOpaquePasses = { ShaderPasses.BilateralBlurHorizontal, ShaderPasses.BilateralBlurVertical, ShaderPasses.BilateralAfterOpaque };
  49. private static readonly int[] m_GaussianTexturesIndices = { 0, 1, 3, 3 };
  50. private static readonly ShaderPasses[] m_GaussianPasses = { ShaderPasses.GaussianBlurHorizontal, ShaderPasses.GaussianBlurVertical };
  51. private static readonly ShaderPasses[] m_GaussianAfterOpaquePasses = { ShaderPasses.GaussianBlurHorizontal, ShaderPasses.GaussianAfterOpaque };
  52. private static readonly int[] m_KawaseTexturesIndices = { 0, 3 };
  53. private static readonly ShaderPasses[] m_KawasePasses = { ShaderPasses.KawaseBlur };
  54. private static readonly ShaderPasses[] m_KawaseAfterOpaquePasses = { ShaderPasses.KawaseAfterOpaque };
  55. // Enums
  56. private enum BlurTypes
  57. {
  58. Bilateral,
  59. Gaussian,
  60. Kawase,
  61. }
  62. private enum ShaderPasses
  63. {
  64. AmbientOcclusion = 0,
  65. BilateralBlurHorizontal = 1,
  66. BilateralBlurVertical = 2,
  67. BilateralBlurFinal = 3,
  68. BilateralAfterOpaque = 4,
  69. GaussianBlurHorizontal = 5,
  70. GaussianBlurVertical = 6,
  71. GaussianAfterOpaque = 7,
  72. KawaseBlur = 8,
  73. KawaseAfterOpaque = 9,
  74. }
  75. // Structs
  76. private struct SSAOMaterialParams
  77. {
  78. internal bool orthographicCamera;
  79. internal bool aoBlueNoise;
  80. internal bool aoInterleavedGradient;
  81. internal bool sampleCountHigh;
  82. internal bool sampleCountMedium;
  83. internal bool sampleCountLow;
  84. internal bool sourceDepthNormals;
  85. internal bool sourceDepthHigh;
  86. internal bool sourceDepthMedium;
  87. internal bool sourceDepthLow;
  88. internal Vector4 ssaoParams;
  89. internal SSAOMaterialParams(ref ScreenSpaceAmbientOcclusionSettings settings, bool isOrthographic)
  90. {
  91. bool isUsingDepthNormals = settings.Source == ScreenSpaceAmbientOcclusionSettings.DepthSource.DepthNormals;
  92. float radiusMultiplier = settings.AOMethod == ScreenSpaceAmbientOcclusionSettings.AOMethodOptions.BlueNoise ? 1.5f : 1;
  93. orthographicCamera = isOrthographic;
  94. aoBlueNoise = settings.AOMethod == ScreenSpaceAmbientOcclusionSettings.AOMethodOptions.BlueNoise;
  95. aoInterleavedGradient = settings.AOMethod == ScreenSpaceAmbientOcclusionSettings.AOMethodOptions.InterleavedGradient;
  96. sampleCountHigh = settings.Samples == ScreenSpaceAmbientOcclusionSettings.AOSampleOption.High;
  97. sampleCountMedium = settings.Samples == ScreenSpaceAmbientOcclusionSettings.AOSampleOption.Medium;
  98. sampleCountLow = settings.Samples == ScreenSpaceAmbientOcclusionSettings.AOSampleOption.Low;
  99. sourceDepthNormals = settings.Source == ScreenSpaceAmbientOcclusionSettings.DepthSource.DepthNormals;
  100. sourceDepthHigh = !isUsingDepthNormals && settings.NormalSamples == ScreenSpaceAmbientOcclusionSettings.NormalQuality.High;
  101. sourceDepthMedium = !isUsingDepthNormals && settings.NormalSamples == ScreenSpaceAmbientOcclusionSettings.NormalQuality.Medium;
  102. sourceDepthLow = !isUsingDepthNormals && settings.NormalSamples == ScreenSpaceAmbientOcclusionSettings.NormalQuality.Low;
  103. ssaoParams = new Vector4(
  104. settings.Intensity, // Intensity
  105. settings.Radius * radiusMultiplier, // Radius
  106. 1.0f / (settings.Downsample ? 2 : 1), // Downsampling
  107. settings.Falloff // Falloff
  108. );
  109. }
  110. internal bool Equals(ref SSAOMaterialParams other)
  111. {
  112. return orthographicCamera == other.orthographicCamera
  113. && aoBlueNoise == other.aoBlueNoise
  114. && aoInterleavedGradient == other.aoInterleavedGradient
  115. && sampleCountHigh == other.sampleCountHigh
  116. && sampleCountMedium == other.sampleCountMedium
  117. && sampleCountLow == other.sampleCountLow
  118. && sourceDepthNormals == other.sourceDepthNormals
  119. && sourceDepthHigh == other.sourceDepthHigh
  120. && sourceDepthMedium == other.sourceDepthMedium
  121. && sourceDepthLow == other.sourceDepthLow
  122. && ssaoParams == other.ssaoParams
  123. ;
  124. }
  125. }
  126. private SSAOMaterialParams m_SSAOParamsPrev = new SSAOMaterialParams();
  127. internal ScreenSpaceAmbientOcclusionPass()
  128. {
  129. m_CurrentSettings = new ScreenSpaceAmbientOcclusionSettings();
  130. m_PassData = new SSAOPassData();
  131. }
  132. internal bool Setup(ref ScreenSpaceAmbientOcclusionSettings featureSettings, ref ScriptableRenderer renderer, ref Material material, ref Texture2D[] blueNoiseTextures)
  133. {
  134. m_BlueNoiseTextures = blueNoiseTextures;
  135. m_Material = material;
  136. m_Renderer = renderer;
  137. m_CurrentSettings = featureSettings;
  138. // RenderPass Event + Source Settings (Depth / Depth&Normals
  139. if (isRendererDeferred)
  140. {
  141. renderPassEvent = m_CurrentSettings.AfterOpaque ? RenderPassEvent.AfterRenderingOpaques : RenderPassEvent.AfterRenderingGbuffer;
  142. if (renderPassEvent == RenderPassEvent.AfterRenderingGbuffer)
  143. breakGBufferAndDeferredRenderPass = true;
  144. m_CurrentSettings.Source = ScreenSpaceAmbientOcclusionSettings.DepthSource.DepthNormals;
  145. }
  146. else
  147. {
  148. // Rendering after PrePasses is usually correct except when depth priming is in play:
  149. // then we rely on a depth resolve taking place after the PrePasses in order to have it ready for SSAO.
  150. // Hence we set the event to RenderPassEvent.AfterRenderingPrePasses + 1 at the earliest.
  151. renderPassEvent = m_CurrentSettings.AfterOpaque ? RenderPassEvent.BeforeRenderingTransparents : RenderPassEvent.AfterRenderingPrePasses + 1;
  152. }
  153. // Ask for a Depth or Depth + Normals textures
  154. switch (m_CurrentSettings.Source)
  155. {
  156. case ScreenSpaceAmbientOcclusionSettings.DepthSource.Depth:
  157. ConfigureInput(ScriptableRenderPassInput.Depth);
  158. break;
  159. case ScreenSpaceAmbientOcclusionSettings.DepthSource.DepthNormals:
  160. ConfigureInput(ScriptableRenderPassInput.Normal); // need depthNormal prepass for forward-only geometry
  161. break;
  162. default:
  163. throw new ArgumentOutOfRangeException();
  164. }
  165. // Blur settings
  166. switch (m_CurrentSettings.BlurQuality)
  167. {
  168. case ScreenSpaceAmbientOcclusionSettings.BlurQualityOptions.High:
  169. m_BlurType = BlurTypes.Bilateral;
  170. break;
  171. case ScreenSpaceAmbientOcclusionSettings.BlurQualityOptions.Medium:
  172. m_BlurType = BlurTypes.Gaussian;
  173. break;
  174. case ScreenSpaceAmbientOcclusionSettings.BlurQualityOptions.Low:
  175. m_BlurType = BlurTypes.Kawase;
  176. break;
  177. default:
  178. throw new ArgumentOutOfRangeException();
  179. }
  180. return m_Material != null
  181. && m_CurrentSettings.Intensity > 0.0f
  182. && m_CurrentSettings.Radius > 0.0f
  183. && m_CurrentSettings.Falloff > 0.0f;
  184. }
  185. private static bool IsAfterOpaquePass(ref ShaderPasses pass)
  186. {
  187. return pass == ShaderPasses.BilateralAfterOpaque
  188. || pass == ShaderPasses.GaussianAfterOpaque
  189. || pass == ShaderPasses.KawaseAfterOpaque;
  190. }
  191. private void SetupKeywordsAndParameters(ref ScreenSpaceAmbientOcclusionSettings settings, ref UniversalCameraData cameraData)
  192. {
  193. #if ENABLE_VR && ENABLE_XR_MODULE
  194. int eyeCount = cameraData.xr.enabled && cameraData.xr.singlePassEnabled ? 2 : 1;
  195. #else
  196. int eyeCount = 1;
  197. #endif
  198. for (int eyeIndex = 0; eyeIndex < eyeCount; eyeIndex++)
  199. {
  200. Matrix4x4 view = cameraData.GetViewMatrix(eyeIndex);
  201. Matrix4x4 proj = cameraData.GetProjectionMatrix(eyeIndex);
  202. m_CameraViewProjections[eyeIndex] = proj * view;
  203. // camera view space without translation, used by SSAO.hlsl ReconstructViewPos() to calculate view vector.
  204. Matrix4x4 cview = view;
  205. cview.SetColumn(3, new Vector4(0.0f, 0.0f, 0.0f, 1.0f));
  206. Matrix4x4 cviewProj = proj * cview;
  207. Matrix4x4 cviewProjInv = cviewProj.inverse;
  208. Vector4 topLeftCorner = cviewProjInv.MultiplyPoint(new Vector4(-1, 1, -1, 1));
  209. Vector4 topRightCorner = cviewProjInv.MultiplyPoint(new Vector4(1, 1, -1, 1));
  210. Vector4 bottomLeftCorner = cviewProjInv.MultiplyPoint(new Vector4(-1, -1, -1, 1));
  211. Vector4 farCentre = cviewProjInv.MultiplyPoint(new Vector4(0, 0, 1, 1));
  212. m_CameraTopLeftCorner[eyeIndex] = topLeftCorner;
  213. m_CameraXExtent[eyeIndex] = topRightCorner - topLeftCorner;
  214. m_CameraYExtent[eyeIndex] = bottomLeftCorner - topLeftCorner;
  215. m_CameraZExtent[eyeIndex] = farCentre;
  216. }
  217. m_Material.SetVector(s_ProjectionParams2ID, new Vector4(1.0f / cameraData.camera.nearClipPlane, 0.0f, 0.0f, 0.0f));
  218. m_Material.SetMatrixArray(s_CameraViewProjectionsID, m_CameraViewProjections);
  219. m_Material.SetVectorArray(s_CameraViewTopLeftCornerID, m_CameraTopLeftCorner);
  220. m_Material.SetVectorArray(s_CameraViewXExtentID, m_CameraXExtent);
  221. m_Material.SetVectorArray(s_CameraViewYExtentID, m_CameraYExtent);
  222. m_Material.SetVectorArray(s_CameraViewZExtentID, m_CameraZExtent);
  223. if (settings.AOMethod == ScreenSpaceAmbientOcclusionSettings.AOMethodOptions.BlueNoise)
  224. {
  225. m_BlueNoiseTextureIndex = (m_BlueNoiseTextureIndex + 1) % m_BlueNoiseTextures.Length;
  226. Texture2D noiseTexture = m_BlueNoiseTextures[m_BlueNoiseTextureIndex];
  227. Vector4 blueNoiseParams = new Vector4(
  228. cameraData.pixelWidth / (float)m_BlueNoiseTextures[m_BlueNoiseTextureIndex].width, // X Scale
  229. cameraData.pixelHeight / (float)m_BlueNoiseTextures[m_BlueNoiseTextureIndex].height, // Y Scale
  230. Random.value, // X Offset
  231. Random.value // Y Offset
  232. );
  233. // For testing we use a single blue noise texture and a single set of blue noise params.
  234. #if UNITY_INCLUDE_TESTS
  235. noiseTexture = m_BlueNoiseTextures[0];
  236. blueNoiseParams.z = 1;
  237. blueNoiseParams.w = 1;
  238. #endif
  239. m_Material.SetTexture(s_BlueNoiseTextureID, noiseTexture);
  240. m_Material.SetVector(s_SSAOBlueNoiseParamsID, blueNoiseParams);
  241. }
  242. // Setting keywords can be somewhat expensive on low-end platforms.
  243. // Previous params are cached to avoid setting the same keywords every frame.
  244. SSAOMaterialParams matParams = new SSAOMaterialParams(ref settings, cameraData.camera.orthographic);
  245. bool ssaoParamsDirty = !m_SSAOParamsPrev.Equals(ref matParams); // Checks if the parameters have changed.
  246. bool isParamsPropertySet = m_Material.HasProperty(s_SSAOParamsID); // Checks if the parameters have been set on the material.
  247. if (!ssaoParamsDirty && isParamsPropertySet)
  248. return;
  249. m_SSAOParamsPrev = matParams;
  250. CoreUtils.SetKeyword(m_Material, ScreenSpaceAmbientOcclusion.k_OrthographicCameraKeyword, matParams.orthographicCamera);
  251. CoreUtils.SetKeyword(m_Material, ScreenSpaceAmbientOcclusion.k_AOBlueNoiseKeyword, matParams.aoBlueNoise);
  252. CoreUtils.SetKeyword(m_Material, ScreenSpaceAmbientOcclusion.k_AOInterleavedGradientKeyword, matParams.aoInterleavedGradient);
  253. CoreUtils.SetKeyword(m_Material, ScreenSpaceAmbientOcclusion.k_SampleCountHighKeyword, matParams.sampleCountHigh);
  254. CoreUtils.SetKeyword(m_Material, ScreenSpaceAmbientOcclusion.k_SampleCountMediumKeyword, matParams.sampleCountMedium);
  255. CoreUtils.SetKeyword(m_Material, ScreenSpaceAmbientOcclusion.k_SampleCountLowKeyword, matParams.sampleCountLow);
  256. CoreUtils.SetKeyword(m_Material, ScreenSpaceAmbientOcclusion.k_SourceDepthNormalsKeyword, matParams.sourceDepthNormals);
  257. CoreUtils.SetKeyword(m_Material, ScreenSpaceAmbientOcclusion.k_SourceDepthHighKeyword, matParams.sourceDepthHigh);
  258. CoreUtils.SetKeyword(m_Material, ScreenSpaceAmbientOcclusion.k_SourceDepthMediumKeyword, matParams.sourceDepthMedium);
  259. CoreUtils.SetKeyword(m_Material, ScreenSpaceAmbientOcclusion.k_SourceDepthLowKeyword, matParams.sourceDepthLow);
  260. m_Material.SetVector(s_SSAOParamsID, matParams.ssaoParams);
  261. }
  262. /*----------------------------------------------------------------------------------------------------------------------------------------
  263. ------------------------------------------------------------- RENDER-GRAPH --------------------------------------------------------------
  264. ----------------------------------------------------------------------------------------------------------------------------------------*/
  265. private class SSAOPassData
  266. {
  267. internal bool afterOpaque;
  268. internal ScreenSpaceAmbientOcclusionSettings.BlurQualityOptions BlurQuality;
  269. internal Material material;
  270. internal float directLightingStrength;
  271. internal TextureHandle cameraColor;
  272. internal TextureHandle AOTexture;
  273. internal TextureHandle finalTexture;
  274. internal TextureHandle blurTexture;
  275. internal TextureHandle cameraDepthTexture;
  276. internal TextureHandle cameraNormalsTexture;
  277. }
  278. private void InitSSAOPassData(ref SSAOPassData data)
  279. {
  280. data.material = m_Material;
  281. data.BlurQuality = m_CurrentSettings.BlurQuality;
  282. data.afterOpaque = m_CurrentSettings.AfterOpaque;
  283. data.directLightingStrength = m_CurrentSettings.DirectLightingStrength;
  284. }
  285. public override void RecordRenderGraph(RenderGraph renderGraph, ContextContainer frameData)
  286. {
  287. UniversalCameraData cameraData = frameData.Get<UniversalCameraData>();
  288. UniversalResourceData resourceData = frameData.Get<UniversalResourceData>();
  289. // Create the texture handles...
  290. CreateRenderTextureHandles(renderGraph,
  291. resourceData,
  292. cameraData,
  293. out TextureHandle aoTexture,
  294. out TextureHandle blurTexture,
  295. out TextureHandle finalTexture);
  296. // Get the resources
  297. UniversalRenderer universalRenderer = cameraData.renderer as UniversalRenderer;
  298. bool isDeferred = universalRenderer != null && universalRenderer.renderingModeActual == RenderingMode.Deferred;
  299. TextureHandle cameraDepthTexture = isDeferred ? resourceData.activeDepthTexture : resourceData.cameraDepthTexture;
  300. TextureHandle cameraNormalsTexture = resourceData.cameraNormalsTexture;
  301. // Update keywords and other shader params
  302. SetupKeywordsAndParameters(ref m_CurrentSettings, ref cameraData);
  303. using (IUnsafeRenderGraphBuilder builder = renderGraph.AddUnsafePass<SSAOPassData>("Blit SSAO", out var passData, m_ProfilingSampler))
  304. {
  305. // Shader keyword changes are considered as global state modifications
  306. builder.AllowGlobalStateModification(true);
  307. builder.AllowPassCulling(false);
  308. // Fill in the Pass data...
  309. InitSSAOPassData(ref passData);
  310. passData.cameraColor = resourceData.cameraColor;
  311. passData.AOTexture = aoTexture;
  312. passData.finalTexture = finalTexture;
  313. passData.blurTexture = blurTexture;
  314. passData.cameraDepthTexture = isDeferred ? cameraDepthTexture : TextureHandle.nullHandle;
  315. // Declare input textures
  316. builder.UseTexture(passData.AOTexture, AccessFlags.ReadWrite);
  317. if (passData.BlurQuality != ScreenSpaceAmbientOcclusionSettings.BlurQualityOptions.Low)
  318. builder.UseTexture(passData.blurTexture, AccessFlags.ReadWrite);
  319. if (cameraDepthTexture.IsValid())
  320. builder.UseTexture(cameraDepthTexture, AccessFlags.Read);
  321. if (m_CurrentSettings.Source == ScreenSpaceAmbientOcclusionSettings.DepthSource.DepthNormals && cameraNormalsTexture.IsValid())
  322. {
  323. builder.UseTexture(cameraNormalsTexture, AccessFlags.Read);
  324. passData.cameraNormalsTexture = cameraNormalsTexture;
  325. }
  326. // The global SSAO texture only needs to be set if After Opaque is disabled...
  327. if (!passData.afterOpaque && finalTexture.IsValid())
  328. {
  329. builder.UseTexture(passData.finalTexture, AccessFlags.ReadWrite);
  330. builder.SetGlobalTextureAfterPass(finalTexture, s_SSAOFinalTextureID);
  331. }
  332. builder.SetRenderFunc((SSAOPassData data, UnsafeGraphContext rgContext) =>
  333. {
  334. if (data.cameraDepthTexture.IsValid())
  335. data.material.SetTexture(s_CameraDepthTextureID, data.cameraDepthTexture);
  336. CommandBuffer cmd = CommandBufferHelpers.GetNativeCommandBuffer(rgContext.cmd);
  337. RenderBufferLoadAction finalLoadAction = data.afterOpaque ? RenderBufferLoadAction.Load : RenderBufferLoadAction.DontCare;
  338. // Setup
  339. if (data.cameraColor.IsValid())
  340. PostProcessUtils.SetSourceSize(cmd, data.cameraColor);
  341. if (data.cameraDepthTexture.IsValid())
  342. data.material.SetTexture(s_CameraDepthTextureID, data.cameraDepthTexture);
  343. if (data.cameraNormalsTexture.IsValid())
  344. data.material.SetTexture(s_CameraNormalsTextureID, data.cameraNormalsTexture);
  345. // AO Pass
  346. Blitter.BlitCameraTexture(cmd, data.AOTexture, data.AOTexture, RenderBufferLoadAction.DontCare, RenderBufferStoreAction.Store, data.material, (int) ShaderPasses.AmbientOcclusion);
  347. // Blur passes
  348. switch (data.BlurQuality)
  349. {
  350. // Bilateral
  351. case ScreenSpaceAmbientOcclusionSettings.BlurQualityOptions.High:
  352. Blitter.BlitCameraTexture(cmd, data.AOTexture, data.blurTexture, RenderBufferLoadAction.DontCare, RenderBufferStoreAction.Store, data.material, (int) ShaderPasses.BilateralBlurHorizontal);
  353. Blitter.BlitCameraTexture(cmd, data.blurTexture, data.AOTexture, RenderBufferLoadAction.DontCare, RenderBufferStoreAction.Store, data.material, (int) ShaderPasses.BilateralBlurVertical);
  354. Blitter.BlitCameraTexture(cmd, data.AOTexture, data.finalTexture, finalLoadAction, RenderBufferStoreAction.Store, data.material, (int) (data.afterOpaque ? ShaderPasses.BilateralAfterOpaque : ShaderPasses.BilateralBlurFinal));
  355. break;
  356. // Gaussian
  357. case ScreenSpaceAmbientOcclusionSettings.BlurQualityOptions.Medium:
  358. Blitter.BlitCameraTexture(cmd, data.AOTexture, data.blurTexture, RenderBufferLoadAction.Load, RenderBufferStoreAction.Store, data.material, (int) ShaderPasses.GaussianBlurHorizontal);
  359. Blitter.BlitCameraTexture(cmd, data.blurTexture, data.finalTexture, finalLoadAction, RenderBufferStoreAction.Store, data.material, (int) (data.afterOpaque ? ShaderPasses.GaussianAfterOpaque : ShaderPasses.GaussianBlurVertical));
  360. break;
  361. // Kawase
  362. case ScreenSpaceAmbientOcclusionSettings.BlurQualityOptions.Low:
  363. Blitter.BlitCameraTexture(cmd, data.AOTexture, data.finalTexture, finalLoadAction, RenderBufferStoreAction.Store, data.material, (int) (data.afterOpaque ? ShaderPasses.KawaseAfterOpaque : ShaderPasses.KawaseBlur));
  364. break;
  365. default:
  366. throw new ArgumentOutOfRangeException();
  367. }
  368. // We only want URP shaders to sample SSAO if After Opaque is disabled...
  369. if (!data.afterOpaque)
  370. {
  371. rgContext.cmd.SetKeyword(ShaderGlobalKeywords.ScreenSpaceOcclusion, true);
  372. rgContext.cmd.SetGlobalVector(s_AmbientOcclusionParamID, new Vector4(1f, 0f, 0f, data.directLightingStrength));
  373. }
  374. });
  375. }
  376. }
  377. private void CreateRenderTextureHandles(RenderGraph renderGraph, UniversalResourceData resourceData,
  378. UniversalCameraData cameraData, out TextureHandle aoTexture, out TextureHandle blurTexture, out TextureHandle finalTexture)
  379. {
  380. // Descriptor for the final blur pass
  381. RenderTextureDescriptor finalTextureDescriptor = cameraData.cameraTargetDescriptor;
  382. finalTextureDescriptor.colorFormat = m_SupportsR8RenderTextureFormat ? RenderTextureFormat.R8 : RenderTextureFormat.ARGB32;
  383. finalTextureDescriptor.depthBufferBits = 0;
  384. finalTextureDescriptor.msaaSamples = 1;
  385. // Descriptor for the AO and Blur passes
  386. int downsampleDivider = m_CurrentSettings.Downsample ? 2 : 1;
  387. bool useRedComponentOnly = m_SupportsR8RenderTextureFormat && m_BlurType > BlurTypes.Bilateral;
  388. RenderTextureDescriptor aoBlurDescriptor = finalTextureDescriptor;
  389. aoBlurDescriptor.colorFormat = useRedComponentOnly ? RenderTextureFormat.R8 : RenderTextureFormat.ARGB32;
  390. aoBlurDescriptor.width /= downsampleDivider;
  391. aoBlurDescriptor.height /= downsampleDivider;
  392. // Handles
  393. aoTexture = UniversalRenderer.CreateRenderGraphTexture(renderGraph, aoBlurDescriptor, "_SSAO_OcclusionTexture0", false, FilterMode.Bilinear);
  394. finalTexture = m_CurrentSettings.AfterOpaque ? resourceData.activeColorTexture : UniversalRenderer.CreateRenderGraphTexture(renderGraph, finalTextureDescriptor, k_SSAOTextureName, false, FilterMode.Bilinear);
  395. if (m_CurrentSettings.BlurQuality != ScreenSpaceAmbientOcclusionSettings.BlurQualityOptions.Low)
  396. blurTexture = UniversalRenderer.CreateRenderGraphTexture(renderGraph, aoBlurDescriptor, "_SSAO_OcclusionTexture1", false, FilterMode.Bilinear);
  397. else
  398. blurTexture = TextureHandle.nullHandle;
  399. if (!m_CurrentSettings.AfterOpaque)
  400. resourceData.ssaoTexture = finalTexture;
  401. }
  402. /*----------------------------------------------------------------------------------------------------------------------------------------
  403. ------------------------------------------------------------- RENDER-GRAPH --------------------------------------------------------------
  404. ----------------------------------------------------------------------------------------------------------------------------------------*/
  405. /// <inheritdoc/>
  406. [Obsolete(DeprecationMessage.CompatibilityScriptingAPIObsolete, false)]
  407. public override void OnCameraSetup(CommandBuffer cmd, ref RenderingData renderingData)
  408. {
  409. ContextContainer frameData = renderingData.frameData;
  410. UniversalCameraData cameraData = frameData.Get<UniversalCameraData>();
  411. // Fill in the Pass data...
  412. InitSSAOPassData(ref m_PassData);
  413. // Update keywords and other shader params
  414. SetupKeywordsAndParameters(ref m_CurrentSettings, ref cameraData);
  415. // Set up the descriptors
  416. int downsampleDivider = m_CurrentSettings.Downsample ? 2 : 1;
  417. RenderTextureDescriptor descriptor = renderingData.cameraData.cameraTargetDescriptor;
  418. descriptor.msaaSamples = 1;
  419. descriptor.depthBufferBits = 0;
  420. // AO PAss
  421. m_AOPassDescriptor = descriptor;
  422. m_AOPassDescriptor.width /= downsampleDivider;
  423. m_AOPassDescriptor.height /= downsampleDivider;
  424. bool useRedComponentOnly = m_SupportsR8RenderTextureFormat && m_BlurType > BlurTypes.Bilateral;
  425. m_AOPassDescriptor.colorFormat = useRedComponentOnly ? RenderTextureFormat.R8 : RenderTextureFormat.ARGB32;
  426. // Allocate textures for the AO and blur
  427. RenderingUtils.ReAllocateHandleIfNeeded(ref m_SSAOTextures[0], m_AOPassDescriptor, FilterMode.Bilinear, TextureWrapMode.Clamp, name: "_SSAO_OcclusionTexture0");
  428. RenderingUtils.ReAllocateHandleIfNeeded(ref m_SSAOTextures[1], m_AOPassDescriptor, FilterMode.Bilinear, TextureWrapMode.Clamp, name: "_SSAO_OcclusionTexture1");
  429. RenderingUtils.ReAllocateHandleIfNeeded(ref m_SSAOTextures[2], m_AOPassDescriptor, FilterMode.Bilinear, TextureWrapMode.Clamp, name: "_SSAO_OcclusionTexture2");
  430. // Upsample setup
  431. m_AOPassDescriptor.width *= downsampleDivider;
  432. m_AOPassDescriptor.height *= downsampleDivider;
  433. m_AOPassDescriptor.colorFormat = m_SupportsR8RenderTextureFormat ? RenderTextureFormat.R8 : RenderTextureFormat.ARGB32;
  434. // Allocate texture for the final SSAO results
  435. RenderingUtils.ReAllocateHandleIfNeeded(ref m_SSAOTextures[3], m_AOPassDescriptor, FilterMode.Bilinear, TextureWrapMode.Clamp, name: "_SSAO_OcclusionTexture");
  436. PostProcessUtils.SetSourceSize(cmd, m_SSAOTextures[3]);
  437. // Disable obsolete warning for internal usage
  438. #pragma warning disable CS0618
  439. // Configure targets and clear color
  440. ConfigureTarget(m_CurrentSettings.AfterOpaque ? m_Renderer.cameraColorTargetHandle : m_SSAOTextures[3]);
  441. ConfigureClear(ClearFlag.None, Color.white);
  442. #pragma warning restore CS0618
  443. }
  444. /// <inheritdoc/>
  445. [Obsolete(DeprecationMessage.CompatibilityScriptingAPIObsolete, false)]
  446. public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
  447. {
  448. if (m_Material == null)
  449. {
  450. Debug.LogErrorFormat(
  451. "{0}.Execute(): Missing material. ScreenSpaceAmbientOcclusion pass will not execute. Check for missing reference in the renderer resources.",
  452. GetType().Name);
  453. return;
  454. }
  455. var cmd = renderingData.commandBuffer;
  456. using (new ProfilingScope(cmd, ProfilingSampler.Get(URPProfileId.SSAO)))
  457. {
  458. // We only want URP shaders to sample SSAO if After Opaque is off.
  459. if (!m_CurrentSettings.AfterOpaque)
  460. cmd.SetKeyword(ShaderGlobalKeywords.ScreenSpaceOcclusion, true);
  461. cmd.SetGlobalTexture(k_SSAOTextureName, m_SSAOTextures[3]);
  462. #if ENABLE_VR && ENABLE_XR_MODULE
  463. bool isFoveatedEnabled = false;
  464. if (renderingData.cameraData.xr.supportsFoveatedRendering)
  465. {
  466. // If we are downsampling we can't use the VRS texture
  467. // If it's a non uniform raster foveated rendering has to be turned off because it will keep applying non uniform for the other passes.
  468. // When calculating normals from depth, this causes artifacts that are amplified from VRS when going to say 4x4. Thus we disable foveated because of that
  469. if (m_CurrentSettings.Downsample || SystemInfo.foveatedRenderingCaps.HasFlag(FoveatedRenderingCaps.NonUniformRaster) ||
  470. (SystemInfo.foveatedRenderingCaps.HasFlag(FoveatedRenderingCaps.FoveationImage) && m_CurrentSettings.Source == ScreenSpaceAmbientOcclusionSettings.DepthSource.Depth))
  471. {
  472. cmd.SetFoveatedRenderingMode(FoveatedRenderingMode.Disabled);
  473. }
  474. // If we aren't downsampling and it's a VRS texture we can apply foveation in this case
  475. else if (SystemInfo.foveatedRenderingCaps.HasFlag(FoveatedRenderingCaps.FoveationImage))
  476. {
  477. cmd.SetFoveatedRenderingMode(FoveatedRenderingMode.Enabled);
  478. isFoveatedEnabled = true;
  479. }
  480. }
  481. #endif
  482. GetPassOrder(m_BlurType, m_CurrentSettings.AfterOpaque, out int[] textureIndices, out ShaderPasses[] shaderPasses);
  483. // Execute the SSAO Occlusion pass
  484. RTHandle cameraDepthTargetHandle = renderingData.cameraData.renderer.cameraDepthTargetHandle;
  485. RenderAndSetBaseMap(ref cmd, ref renderingData, ref renderingData.cameraData.renderer, ref m_Material, ref cameraDepthTargetHandle, ref m_SSAOTextures[0], ShaderPasses.AmbientOcclusion);
  486. // Execute the Blur Passes
  487. for (int i = 0; i < shaderPasses.Length; i++)
  488. {
  489. int baseMapIndex = textureIndices[i];
  490. int targetIndex = textureIndices[i + 1];
  491. RenderAndSetBaseMap(ref cmd, ref renderingData, ref renderingData.cameraData.renderer, ref m_Material, ref m_SSAOTextures[baseMapIndex], ref m_SSAOTextures[targetIndex], shaderPasses[i]);
  492. }
  493. // Set the global SSAO Params
  494. cmd.SetGlobalVector(s_AmbientOcclusionParamID, new Vector4(1f, 0f, 0f, m_CurrentSettings.DirectLightingStrength));
  495. #if ENABLE_VR && ENABLE_XR_MODULE
  496. // Cleanup, making sure it doesn't stay enabled for a pass after that should not have it on
  497. if (isFoveatedEnabled)
  498. cmd.SetFoveatedRenderingMode(FoveatedRenderingMode.Disabled);
  499. #endif
  500. }
  501. }
  502. private static void RenderAndSetBaseMap(ref CommandBuffer cmd, ref RenderingData renderingData, ref ScriptableRenderer renderer, ref Material mat, ref RTHandle baseMap, ref RTHandle target, ShaderPasses pass)
  503. {
  504. if (IsAfterOpaquePass(ref pass))
  505. {
  506. // Disable obsolete warning for internal usage
  507. #pragma warning disable CS0618
  508. Blitter.BlitCameraTexture(cmd, baseMap, renderer.cameraColorTargetHandle, RenderBufferLoadAction.Load, RenderBufferStoreAction.Store, mat, (int)pass);
  509. #pragma warning restore CS0618
  510. }
  511. else if (baseMap.rt == null)
  512. {
  513. // Obsolete usage of RTHandle aliasing a RenderTargetIdentifier
  514. Vector2 viewportScale = baseMap.useScaling ? new Vector2(baseMap.rtHandleProperties.rtHandleScale.x, baseMap.rtHandleProperties.rtHandleScale.y) : Vector2.one;
  515. // Will set the correct camera viewport as well.
  516. CoreUtils.SetRenderTarget(cmd, target);
  517. Blitter.BlitTexture(cmd, baseMap.nameID, viewportScale, mat, (int)pass);
  518. }
  519. else
  520. Blitter.BlitCameraTexture(cmd, baseMap, target, mat, (int)pass);
  521. }
  522. private static void GetPassOrder(BlurTypes blurType, bool isAfterOpaque, out int[] textureIndices, out ShaderPasses[] shaderPasses)
  523. {
  524. switch (blurType)
  525. {
  526. case BlurTypes.Bilateral:
  527. textureIndices = m_BilateralTexturesIndices;
  528. shaderPasses = isAfterOpaque ? m_BilateralAfterOpaquePasses : m_BilateralPasses;
  529. break;
  530. case BlurTypes.Gaussian:
  531. textureIndices = m_GaussianTexturesIndices;
  532. shaderPasses = isAfterOpaque ? m_GaussianAfterOpaquePasses : m_GaussianPasses;
  533. break;
  534. case BlurTypes.Kawase:
  535. textureIndices = m_KawaseTexturesIndices;
  536. shaderPasses = isAfterOpaque ? m_KawaseAfterOpaquePasses : m_KawasePasses;
  537. break;
  538. default:
  539. throw new ArgumentOutOfRangeException();
  540. }
  541. }
  542. /// <inheritdoc/>
  543. public override void OnCameraCleanup(CommandBuffer cmd)
  544. {
  545. if (cmd == null)
  546. throw new ArgumentNullException("cmd");
  547. if (!m_CurrentSettings.AfterOpaque)
  548. cmd.SetKeyword(ShaderGlobalKeywords.ScreenSpaceOcclusion, false);
  549. }
  550. public void Dispose()
  551. {
  552. m_SSAOTextures[0]?.Release();
  553. m_SSAOTextures[1]?.Release();
  554. m_SSAOTextures[2]?.Release();
  555. m_SSAOTextures[3]?.Release();
  556. m_SSAOParamsPrev = default;
  557. }
  558. }
  559. }