DepthOfFieldComponent.cs 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. using UnityEngine.Rendering;
  2. namespace UnityEngine.PostProcessing
  3. {
  4. using DebugMode = BuiltinDebugViewsModel.Mode;
  5. public sealed class DepthOfFieldComponent : PostProcessingComponentRenderTexture<DepthOfFieldModel>
  6. {
  7. static class Uniforms
  8. {
  9. internal static readonly int _DepthOfFieldTex = Shader.PropertyToID("_DepthOfFieldTex");
  10. internal static readonly int _DepthOfFieldCoCTex = Shader.PropertyToID("_DepthOfFieldCoCTex");
  11. internal static readonly int _Distance = Shader.PropertyToID("_Distance");
  12. internal static readonly int _LensCoeff = Shader.PropertyToID("_LensCoeff");
  13. internal static readonly int _MaxCoC = Shader.PropertyToID("_MaxCoC");
  14. internal static readonly int _RcpMaxCoC = Shader.PropertyToID("_RcpMaxCoC");
  15. internal static readonly int _RcpAspect = Shader.PropertyToID("_RcpAspect");
  16. internal static readonly int _MainTex = Shader.PropertyToID("_MainTex");
  17. internal static readonly int _CoCTex = Shader.PropertyToID("_CoCTex");
  18. internal static readonly int _TaaParams = Shader.PropertyToID("_TaaParams");
  19. internal static readonly int _DepthOfFieldParams = Shader.PropertyToID("_DepthOfFieldParams");
  20. }
  21. const string k_ShaderString = "Hidden/Post FX/Depth Of Field";
  22. public override bool active
  23. {
  24. get
  25. {
  26. return model.enabled
  27. && SystemInfo.SupportsRenderTextureFormat(RenderTextureFormat.ARGBHalf)
  28. && !context.interrupted;
  29. }
  30. }
  31. public override DepthTextureMode GetCameraFlags()
  32. {
  33. return DepthTextureMode.Depth;
  34. }
  35. RenderTexture m_CoCHistory;
  36. // Height of the 35mm full-frame format (36mm x 24mm)
  37. const float k_FilmHeight = 0.024f;
  38. float CalculateFocalLength()
  39. {
  40. var settings = model.settings;
  41. if (!settings.useCameraFov)
  42. return settings.focalLength / 1000f;
  43. float fov = context.camera.fieldOfView * Mathf.Deg2Rad;
  44. return 0.5f * k_FilmHeight / Mathf.Tan(0.5f * fov);
  45. }
  46. float CalculateMaxCoCRadius(int screenHeight)
  47. {
  48. // Estimate the allowable maximum radius of CoC from the kernel
  49. // size (the equation below was empirically derived).
  50. float radiusInPixels = (float)model.settings.kernelSize * 4f + 6f;
  51. // Applying a 5% limit to the CoC radius to keep the size of
  52. // TileMax/NeighborMax small enough.
  53. return Mathf.Min(0.05f, radiusInPixels / screenHeight);
  54. }
  55. bool CheckHistory(int width, int height)
  56. {
  57. return m_CoCHistory != null && m_CoCHistory.IsCreated() &&
  58. m_CoCHistory.width == width && m_CoCHistory.height == height;
  59. }
  60. RenderTextureFormat SelectFormat(RenderTextureFormat primary, RenderTextureFormat secondary)
  61. {
  62. if (SystemInfo.SupportsRenderTextureFormat(primary)) return primary;
  63. if (SystemInfo.SupportsRenderTextureFormat(secondary)) return secondary;
  64. return RenderTextureFormat.Default;
  65. }
  66. public void Prepare(RenderTexture source, Material uberMaterial, bool antialiasCoC, Vector2 taaJitter, float taaBlending)
  67. {
  68. var settings = model.settings;
  69. var colorFormat = RenderTextureFormat.ARGBHalf;
  70. var cocFormat = SelectFormat(RenderTextureFormat.R8, RenderTextureFormat.RHalf);
  71. // Avoid using R8 on OSX with Metal. #896121, https://goo.gl/MgKqu6
  72. #if UNITY_EDITOR_OSX || UNITY_STANDALONE_OSX
  73. if (SystemInfo.graphicsDeviceType == GraphicsDeviceType.Metal)
  74. cocFormat = SelectFormat(RenderTextureFormat.RHalf, RenderTextureFormat.Default);
  75. #endif
  76. // Material setup
  77. var f = CalculateFocalLength();
  78. var s1 = Mathf.Max(settings.focusDistance, f);
  79. var aspect = (float)source.width / source.height;
  80. var coeff = f * f / (settings.aperture * (s1 - f) * k_FilmHeight * 2);
  81. var maxCoC = CalculateMaxCoCRadius(source.height);
  82. var material = context.materialFactory.Get(k_ShaderString);
  83. material.SetFloat(Uniforms._Distance, s1);
  84. material.SetFloat(Uniforms._LensCoeff, coeff);
  85. material.SetFloat(Uniforms._MaxCoC, maxCoC);
  86. material.SetFloat(Uniforms._RcpMaxCoC, 1f / maxCoC);
  87. material.SetFloat(Uniforms._RcpAspect, 1f / aspect);
  88. // CoC calculation pass
  89. var rtCoC = context.renderTextureFactory.Get(context.width, context.height, 0, cocFormat);
  90. Graphics.Blit(null, rtCoC, material, 0);
  91. if (antialiasCoC)
  92. {
  93. // CoC temporal filter pass
  94. material.SetTexture(Uniforms._CoCTex, rtCoC);
  95. var blend = CheckHistory(context.width, context.height) ? taaBlending : 0f;
  96. material.SetVector(Uniforms._TaaParams, new Vector3(taaJitter.x, taaJitter.y, blend));
  97. var rtFiltered = RenderTexture.GetTemporary(context.width, context.height, 0, cocFormat);
  98. Graphics.Blit(m_CoCHistory, rtFiltered, material, 1);
  99. context.renderTextureFactory.Release(rtCoC);
  100. if (m_CoCHistory != null) RenderTexture.ReleaseTemporary(m_CoCHistory);
  101. m_CoCHistory = rtCoC = rtFiltered;
  102. }
  103. // Downsampling and prefiltering pass
  104. var rt1 = context.renderTextureFactory.Get(context.width / 2, context.height / 2, 0, colorFormat);
  105. material.SetTexture(Uniforms._CoCTex, rtCoC);
  106. Graphics.Blit(source, rt1, material, 2);
  107. // Bokeh simulation pass
  108. var rt2 = context.renderTextureFactory.Get(context.width / 2, context.height / 2, 0, colorFormat);
  109. Graphics.Blit(rt1, rt2, material, 3 + (int)settings.kernelSize);
  110. // Postfilter pass
  111. Graphics.Blit(rt2, rt1, material, 7);
  112. // Give the results to the uber shader.
  113. uberMaterial.SetVector(Uniforms._DepthOfFieldParams, new Vector3(s1, coeff, maxCoC));
  114. if (context.profile.debugViews.IsModeActive(DebugMode.FocusPlane))
  115. {
  116. uberMaterial.EnableKeyword("DEPTH_OF_FIELD_COC_VIEW");
  117. context.Interrupt();
  118. }
  119. else
  120. {
  121. uberMaterial.SetTexture(Uniforms._DepthOfFieldTex, rt1);
  122. uberMaterial.SetTexture(Uniforms._DepthOfFieldCoCTex, rtCoC);
  123. uberMaterial.EnableKeyword("DEPTH_OF_FIELD");
  124. }
  125. context.renderTextureFactory.Release(rt2);
  126. }
  127. public override void OnDisable()
  128. {
  129. if (m_CoCHistory != null)
  130. RenderTexture.ReleaseTemporary(m_CoCHistory);
  131. m_CoCHistory = null;
  132. }
  133. }
  134. }