HistogramMonitor.cs 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. using System;
  2. namespace UnityEngine.Rendering.PostProcessing
  3. {
  4. /// <summary>
  5. /// This class holds settings for the Histogram monitor.
  6. /// </summary>
  7. [Serializable]
  8. public sealed class HistogramMonitor : Monitor
  9. {
  10. /// <summary>
  11. /// Displayable channels.
  12. /// </summary>
  13. public enum Channel
  14. {
  15. /// <summary>
  16. /// The red channel.
  17. /// </summary>
  18. Red,
  19. /// <summary>
  20. /// The green channel.
  21. /// </summary>
  22. Green,
  23. /// <summary>
  24. /// The blue channel.
  25. /// </summary>
  26. Blue,
  27. /// <summary>
  28. /// The master (luminance) channel.
  29. /// </summary>
  30. Master
  31. }
  32. /// <summary>
  33. /// The width of the rendered histogram.
  34. /// </summary>
  35. public int width = 512;
  36. /// <summary>
  37. /// The height of the rendered histogram.
  38. /// </summary>
  39. public int height = 256;
  40. /// <summary>
  41. /// The channel to render.
  42. /// </summary>
  43. public Channel channel = Channel.Master;
  44. ComputeBuffer m_Data;
  45. const int k_NumBins = 256;
  46. const int k_ThreadGroupSizeX = 16;
  47. const int k_ThreadGroupSizeY = 16;
  48. internal override void OnDisable()
  49. {
  50. base.OnDisable();
  51. if (m_Data != null)
  52. m_Data.Release();
  53. m_Data = null;
  54. }
  55. internal override bool NeedsHalfRes()
  56. {
  57. return true;
  58. }
  59. internal override bool ShaderResourcesAvailable(PostProcessRenderContext context)
  60. {
  61. return context.resources.computeShaders.gammaHistogram;
  62. }
  63. internal override void Render(PostProcessRenderContext context)
  64. {
  65. CheckOutput(width, height);
  66. if (m_Data == null)
  67. m_Data = new ComputeBuffer(k_NumBins, sizeof(uint));
  68. var compute = context.resources.computeShaders.gammaHistogram;
  69. var cmd = context.command;
  70. cmd.BeginSample("GammaHistogram");
  71. // Clear the buffer on every frame as we use it to accumulate values on every frame
  72. int kernel = compute.FindKernel("KHistogramClear");
  73. cmd.SetComputeBufferParam(compute, kernel, "_HistogramBuffer", m_Data);
  74. cmd.DispatchCompute(compute, kernel, Mathf.CeilToInt(k_NumBins / (float)k_ThreadGroupSizeX), 1, 1);
  75. // Gather all pixels and fill in our histogram
  76. kernel = compute.FindKernel("KHistogramGather");
  77. var parameters = new Vector4(
  78. context.width / 2,
  79. context.height / 2,
  80. RuntimeUtilities.isLinearColorSpace ? 1 : 0,
  81. (int)channel
  82. );
  83. cmd.SetComputeVectorParam(compute, "_Params", parameters);
  84. cmd.SetComputeTextureParam(compute, kernel, "_Source", ShaderIDs.HalfResFinalCopy);
  85. cmd.SetComputeBufferParam(compute, kernel, "_HistogramBuffer", m_Data);
  86. cmd.DispatchCompute(compute, kernel,
  87. Mathf.CeilToInt(parameters.x / k_ThreadGroupSizeX),
  88. Mathf.CeilToInt(parameters.y / k_ThreadGroupSizeY),
  89. 1
  90. );
  91. // Generate the histogram texture
  92. var sheet = context.propertySheets.Get(context.resources.shaders.gammaHistogram);
  93. sheet.properties.SetVector(ShaderIDs.Params, new Vector4(width, height, 0f, 0f));
  94. sheet.properties.SetBuffer(ShaderIDs.HistogramBuffer, m_Data);
  95. cmd.BlitFullscreenTriangle(BuiltinRenderTextureType.None, output, sheet, 0);
  96. cmd.EndSample("GammaHistogram");
  97. }
  98. }
  99. }