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.

185 lines
7.3 KiB

  1. using UnityEngine.Rendering;
  2. namespace UnityEngine.PostProcessing
  3. {
  4. using DebugMode = BuiltinDebugViewsModel.Mode;
  5. public sealed class AmbientOcclusionComponent : PostProcessingComponentCommandBuffer<AmbientOcclusionModel>
  6. {
  7. static class Uniforms
  8. {
  9. internal static readonly int _Intensity = Shader.PropertyToID("_Intensity");
  10. internal static readonly int _Radius = Shader.PropertyToID("_Radius");
  11. internal static readonly int _FogParams = Shader.PropertyToID("_FogParams");
  12. internal static readonly int _Downsample = Shader.PropertyToID("_Downsample");
  13. internal static readonly int _SampleCount = Shader.PropertyToID("_SampleCount");
  14. internal static readonly int _OcclusionTexture1 = Shader.PropertyToID("_OcclusionTexture1");
  15. internal static readonly int _OcclusionTexture2 = Shader.PropertyToID("_OcclusionTexture2");
  16. internal static readonly int _OcclusionTexture = Shader.PropertyToID("_OcclusionTexture");
  17. internal static readonly int _MainTex = Shader.PropertyToID("_MainTex");
  18. internal static readonly int _TempRT = Shader.PropertyToID("_TempRT");
  19. }
  20. const string k_BlitShaderString = "Hidden/Post FX/Blit";
  21. const string k_ShaderString = "Hidden/Post FX/Ambient Occlusion";
  22. readonly RenderTargetIdentifier[] m_MRT =
  23. {
  24. BuiltinRenderTextureType.GBuffer0, // Albedo, Occ
  25. BuiltinRenderTextureType.CameraTarget // Ambient
  26. };
  27. enum OcclusionSource
  28. {
  29. DepthTexture,
  30. DepthNormalsTexture,
  31. GBuffer
  32. }
  33. OcclusionSource occlusionSource
  34. {
  35. get
  36. {
  37. if (context.isGBufferAvailable && !model.settings.forceForwardCompatibility)
  38. return OcclusionSource.GBuffer;
  39. if (model.settings.highPrecision && (!context.isGBufferAvailable || model.settings.forceForwardCompatibility))
  40. return OcclusionSource.DepthTexture;
  41. return OcclusionSource.DepthNormalsTexture;
  42. }
  43. }
  44. bool ambientOnlySupported
  45. {
  46. get { return context.isHdr && model.settings.ambientOnly && context.isGBufferAvailable && !model.settings.forceForwardCompatibility; }
  47. }
  48. public override bool active
  49. {
  50. get
  51. {
  52. return model.enabled
  53. && model.settings.intensity > 0f
  54. && !context.interrupted;
  55. }
  56. }
  57. public override DepthTextureMode GetCameraFlags()
  58. {
  59. var flags = DepthTextureMode.None;
  60. if (occlusionSource == OcclusionSource.DepthTexture)
  61. flags |= DepthTextureMode.Depth;
  62. if (occlusionSource != OcclusionSource.GBuffer)
  63. flags |= DepthTextureMode.DepthNormals;
  64. return flags;
  65. }
  66. public override string GetName()
  67. {
  68. return "Ambient Occlusion";
  69. }
  70. public override CameraEvent GetCameraEvent()
  71. {
  72. return ambientOnlySupported && !context.profile.debugViews.IsModeActive(DebugMode.AmbientOcclusion)
  73. ? CameraEvent.BeforeReflections
  74. : CameraEvent.BeforeImageEffectsOpaque;
  75. }
  76. public override void PopulateCommandBuffer(CommandBuffer cb)
  77. {
  78. var settings = model.settings;
  79. // Material setup
  80. var blitMaterial = context.materialFactory.Get(k_BlitShaderString);
  81. var material = context.materialFactory.Get(k_ShaderString);
  82. material.shaderKeywords = null;
  83. material.SetFloat(Uniforms._Intensity, settings.intensity);
  84. material.SetFloat(Uniforms._Radius, settings.radius);
  85. material.SetFloat(Uniforms._Downsample, settings.downsampling ? 0.5f : 1f);
  86. material.SetInt(Uniforms._SampleCount, (int)settings.sampleCount);
  87. if (!context.isGBufferAvailable && RenderSettings.fog)
  88. {
  89. material.SetVector(Uniforms._FogParams, new Vector3(RenderSettings.fogDensity, RenderSettings.fogStartDistance, RenderSettings.fogEndDistance));
  90. switch (RenderSettings.fogMode)
  91. {
  92. case FogMode.Linear:
  93. material.EnableKeyword("FOG_LINEAR");
  94. break;
  95. case FogMode.Exponential:
  96. material.EnableKeyword("FOG_EXP");
  97. break;
  98. case FogMode.ExponentialSquared:
  99. material.EnableKeyword("FOG_EXP2");
  100. break;
  101. }
  102. }
  103. else
  104. {
  105. material.EnableKeyword("FOG_OFF");
  106. }
  107. int tw = context.width;
  108. int th = context.height;
  109. int ts = settings.downsampling ? 2 : 1;
  110. const RenderTextureFormat kFormat = RenderTextureFormat.ARGB32;
  111. const RenderTextureReadWrite kRWMode = RenderTextureReadWrite.Linear;
  112. const FilterMode kFilter = FilterMode.Bilinear;
  113. // AO buffer
  114. var rtMask = Uniforms._OcclusionTexture1;
  115. cb.GetTemporaryRT(rtMask, tw / ts, th / ts, 0, kFilter, kFormat, kRWMode);
  116. // AO estimation
  117. cb.Blit((Texture)null, rtMask, material, (int)occlusionSource);
  118. // Blur buffer
  119. var rtBlur = Uniforms._OcclusionTexture2;
  120. // Separable blur (horizontal pass)
  121. cb.GetTemporaryRT(rtBlur, tw, th, 0, kFilter, kFormat, kRWMode);
  122. cb.SetGlobalTexture(Uniforms._MainTex, rtMask);
  123. cb.Blit(rtMask, rtBlur, material, occlusionSource == OcclusionSource.GBuffer ? 4 : 3);
  124. cb.ReleaseTemporaryRT(rtMask);
  125. // Separable blur (vertical pass)
  126. rtMask = Uniforms._OcclusionTexture;
  127. cb.GetTemporaryRT(rtMask, tw, th, 0, kFilter, kFormat, kRWMode);
  128. cb.SetGlobalTexture(Uniforms._MainTex, rtBlur);
  129. cb.Blit(rtBlur, rtMask, material, 5);
  130. cb.ReleaseTemporaryRT(rtBlur);
  131. if (context.profile.debugViews.IsModeActive(DebugMode.AmbientOcclusion))
  132. {
  133. cb.SetGlobalTexture(Uniforms._MainTex, rtMask);
  134. cb.Blit(rtMask, BuiltinRenderTextureType.CameraTarget, material, 8);
  135. context.Interrupt();
  136. }
  137. else if (ambientOnlySupported)
  138. {
  139. cb.SetRenderTarget(m_MRT, BuiltinRenderTextureType.CameraTarget);
  140. cb.DrawMesh(GraphicsUtils.quad, Matrix4x4.identity, material, 0, 7);
  141. }
  142. else
  143. {
  144. var fbFormat = context.isHdr ? RenderTextureFormat.DefaultHDR : RenderTextureFormat.Default;
  145. int tempRT = Uniforms._TempRT;
  146. cb.GetTemporaryRT(tempRT, context.width, context.height, 0, FilterMode.Bilinear, fbFormat);
  147. cb.Blit(BuiltinRenderTextureType.CameraTarget, tempRT, blitMaterial, 0);
  148. cb.SetGlobalTexture(Uniforms._MainTex, tempRT);
  149. cb.Blit(tempRT, BuiltinRenderTextureType.CameraTarget, material, 6);
  150. cb.ReleaseTemporaryRT(tempRT);
  151. }
  152. cb.ReleaseTemporaryRT(rtMask);
  153. }
  154. }
  155. }