ScalableAO.cs 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. using System;
  2. namespace UnityEngine.Rendering.PostProcessing
  3. {
  4. // Scalable ambient obscurance
  5. [Serializable]
  6. internal sealed class ScalableAO : IAmbientOcclusionMethod
  7. {
  8. RenderTexture m_Result;
  9. PropertySheet m_PropertySheet;
  10. AmbientOcclusion m_Settings;
  11. readonly RenderTargetIdentifier[] m_MRT =
  12. {
  13. BuiltinRenderTextureType.GBuffer0, // Albedo, Occ
  14. BuiltinRenderTextureType.CameraTarget // Ambient
  15. };
  16. readonly int[] m_SampleCount = { 4, 6, 10, 8, 12 };
  17. enum Pass
  18. {
  19. OcclusionEstimationForward,
  20. OcclusionEstimationDeferred,
  21. HorizontalBlurForward,
  22. HorizontalBlurDeferred,
  23. VerticalBlur,
  24. CompositionForward,
  25. CompositionDeferred,
  26. DebugOverlay
  27. }
  28. public ScalableAO(AmbientOcclusion settings)
  29. {
  30. m_Settings = settings;
  31. }
  32. public DepthTextureMode GetCameraFlags()
  33. {
  34. return DepthTextureMode.Depth | DepthTextureMode.DepthNormals;
  35. }
  36. void DoLazyInitialization(PostProcessRenderContext context)
  37. {
  38. m_PropertySheet = context.propertySheets.Get(context.resources.shaders.scalableAO);
  39. bool reset = false;
  40. if (m_Result == null || !m_Result.IsCreated())
  41. {
  42. // Initial allocation
  43. m_Result = context.GetScreenSpaceTemporaryRT(0, RenderTextureFormat.ARGB32, RenderTextureReadWrite.Linear);
  44. m_Result.hideFlags = HideFlags.DontSave;
  45. m_Result.filterMode = FilterMode.Bilinear;
  46. reset = true;
  47. }
  48. else if (m_Result.width != context.width || m_Result.height != context.height)
  49. {
  50. // Release and reallocate
  51. m_Result.Release();
  52. m_Result.width = context.width;
  53. m_Result.height = context.height;
  54. reset = true;
  55. }
  56. if (reset)
  57. m_Result.Create();
  58. }
  59. void Render(PostProcessRenderContext context, CommandBuffer cmd, int occlusionSource)
  60. {
  61. DoLazyInitialization(context);
  62. m_Settings.radius.value = Mathf.Max(m_Settings.radius.value, 1e-4f);
  63. // Material setup
  64. // Always use a quater-res AO buffer unless High/Ultra quality is set.
  65. bool downsampling = (int)m_Settings.quality.value < (int)AmbientOcclusionQuality.High;
  66. float px = m_Settings.intensity.value;
  67. float py = m_Settings.radius.value;
  68. float pz = downsampling ? 0.5f : 1f;
  69. float pw = m_SampleCount[(int)m_Settings.quality.value];
  70. var sheet = m_PropertySheet;
  71. sheet.ClearKeywords();
  72. sheet.properties.SetVector(ShaderIDs.AOParams, new Vector4(px, py, pz, pw));
  73. sheet.properties.SetVector(ShaderIDs.AOColor, Color.white - m_Settings.color.value);
  74. // In forward fog is applied at the object level in the grometry pass so we need to
  75. // apply it to AO as well or it'll drawn on top of the fog effect.
  76. // Not needed in Deferred.
  77. if (context.camera.actualRenderingPath == RenderingPath.Forward && RenderSettings.fog)
  78. {
  79. sheet.EnableKeyword("APPLY_FORWARD_FOG");
  80. sheet.properties.SetVector(
  81. ShaderIDs.FogParams,
  82. new Vector3(RenderSettings.fogDensity, RenderSettings.fogStartDistance, RenderSettings.fogEndDistance)
  83. );
  84. }
  85. // Texture setup
  86. int ts = downsampling ? 2 : 1;
  87. const RenderTextureFormat kFormat = RenderTextureFormat.ARGB32;
  88. const RenderTextureReadWrite kRWMode = RenderTextureReadWrite.Linear;
  89. const FilterMode kFilter = FilterMode.Bilinear;
  90. // AO buffer
  91. var rtMask = ShaderIDs.OcclusionTexture1;
  92. int scaledWidth = context.width / ts;
  93. int scaledHeight = context.height / ts;
  94. context.GetScreenSpaceTemporaryRT(cmd, rtMask, 0, kFormat, kRWMode, kFilter, scaledWidth, scaledHeight);
  95. // AO estimation
  96. cmd.BlitFullscreenTriangle(BuiltinRenderTextureType.None, rtMask, sheet, (int)Pass.OcclusionEstimationForward + occlusionSource);
  97. // Blur buffer
  98. var rtBlur = ShaderIDs.OcclusionTexture2;
  99. context.GetScreenSpaceTemporaryRT(cmd, rtBlur, 0, kFormat, kRWMode, kFilter);
  100. // Separable blur (horizontal pass)
  101. cmd.BlitFullscreenTriangle(rtMask, rtBlur, sheet, (int)Pass.HorizontalBlurForward + occlusionSource);
  102. cmd.ReleaseTemporaryRT(rtMask);
  103. // Separable blur (vertical pass)
  104. cmd.BlitFullscreenTriangle(rtBlur, m_Result, sheet, (int)Pass.VerticalBlur);
  105. cmd.ReleaseTemporaryRT(rtBlur);
  106. if (context.IsDebugOverlayEnabled(DebugOverlay.AmbientOcclusion))
  107. context.PushDebugOverlay(cmd, m_Result, sheet, (int)Pass.DebugOverlay);
  108. }
  109. public void RenderAfterOpaque(PostProcessRenderContext context)
  110. {
  111. var cmd = context.command;
  112. cmd.BeginSample("Ambient Occlusion");
  113. Render(context, cmd, 0);
  114. cmd.SetGlobalTexture(ShaderIDs.SAOcclusionTexture, m_Result);
  115. cmd.BlitFullscreenTriangle(BuiltinRenderTextureType.None, BuiltinRenderTextureType.CameraTarget, m_PropertySheet, (int)Pass.CompositionForward, RenderBufferLoadAction.Load);
  116. cmd.EndSample("Ambient Occlusion");
  117. }
  118. public void RenderAmbientOnly(PostProcessRenderContext context)
  119. {
  120. var cmd = context.command;
  121. cmd.BeginSample("Ambient Occlusion Render");
  122. Render(context, cmd, 1);
  123. cmd.EndSample("Ambient Occlusion Render");
  124. }
  125. public void CompositeAmbientOnly(PostProcessRenderContext context)
  126. {
  127. var cmd = context.command;
  128. cmd.BeginSample("Ambient Occlusion Composite");
  129. cmd.SetGlobalTexture(ShaderIDs.SAOcclusionTexture, m_Result);
  130. cmd.BlitFullscreenTriangle(BuiltinRenderTextureType.None, m_MRT, BuiltinRenderTextureType.CameraTarget, m_PropertySheet, (int)Pass.CompositionDeferred);
  131. cmd.EndSample("Ambient Occlusion Composite");
  132. }
  133. public void Release()
  134. {
  135. RuntimeUtilities.Destroy(m_Result);
  136. m_Result = null;
  137. }
  138. }
  139. }