3 namespace UnityEngine
.Rendering
.PostProcessing
6 /// This class holds settings for the Waveform monitor.
9 public sealed class WaveformMonitor
: Monitor
12 /// The exposure multiplier applied to the waveform values.
14 public float exposure
= 0.12f
;
17 /// The height of the rendered waveform.
20 /// Waveforms display localized values so the width is dynamic and depends on the current
23 public int height
= 256;
27 const int k_ThreadGroupSize
= 256;
28 const int k_ThreadGroupSizeX
= 16;
29 const int k_ThreadGroupSizeY
= 16;
31 internal override void OnDisable()
41 internal override bool NeedsHalfRes()
47 internal override bool ShaderResourcesAvailable(PostProcessRenderContext context
)
49 return context
.resources
.computeShaders
.waveform
;
52 internal override void Render(PostProcessRenderContext context
)
54 // Waveform show localized data, so width depends on the aspect ratio
55 float ratio
= (context
.width
/ 2f
) / (context
.height
/ 2f
);
56 int width
= Mathf
.FloorToInt(height
* ratio
);
58 CheckOutput(width
, height
);
59 exposure
= Mathf
.Max(0f
, exposure
);
61 int count
= width
* height
;
64 m_Data
= new ComputeBuffer(count
, sizeof(uint) << 2);
66 else if (m_Data
.count
< count
)
69 m_Data
= new ComputeBuffer(count
, sizeof(uint) << 2);
72 var compute
= context
.resources
.computeShaders
.waveform
;
73 var cmd
= context
.command
;
74 cmd
.BeginSample("Waveform");
76 var parameters
= new Vector4(
79 RuntimeUtilities
.isLinearColorSpace
? 1 : 0,
83 // Clear the buffer on every frame
84 int kernel
= compute
.FindKernel("KWaveformClear");
85 cmd
.SetComputeBufferParam(compute
, kernel
, "_WaveformBuffer", m_Data
);
86 cmd
.SetComputeVectorParam(compute
, "_Params", parameters
);
87 cmd
.DispatchCompute(compute
, kernel
, Mathf
.CeilToInt(width
/ (float)k_ThreadGroupSizeX
), Mathf
.CeilToInt(height
/ (float)k_ThreadGroupSizeY
), 1);
89 // For performance reasons, especially on consoles, we'll just downscale the source
90 // again to reduce VMEM stalls. Eventually the whole algorithm needs to be rewritten as
91 // it's currently pretty naive.
92 cmd
.GetTemporaryRT(ShaderIDs
.WaveformSource
, width
, height
, 0, FilterMode
.Bilinear
, context
.sourceFormat
);
93 cmd
.BlitFullscreenTriangle(ShaderIDs
.HalfResFinalCopy
, ShaderIDs
.WaveformSource
);
95 // Gather all pixels and fill in our waveform
96 kernel
= compute
.FindKernel("KWaveformGather");
97 cmd
.SetComputeBufferParam(compute
, kernel
, "_WaveformBuffer", m_Data
);
98 cmd
.SetComputeTextureParam(compute
, kernel
, "_Source", ShaderIDs
.WaveformSource
);
99 cmd
.SetComputeVectorParam(compute
, "_Params", parameters
);
100 cmd
.DispatchCompute(compute
, kernel
, width
, Mathf
.CeilToInt(height
/ (float)k_ThreadGroupSize
), 1);
101 cmd
.ReleaseTemporaryRT(ShaderIDs
.WaveformSource
);
103 // Generate the waveform texture
104 var sheet
= context
.propertySheets
.Get(context
.resources
.shaders
.waveform
);
105 sheet
.properties
.SetVector(ShaderIDs
.Params
, new Vector4(width
, height
, exposure
, 0f
));
106 sheet
.properties
.SetBuffer(ShaderIDs
.WaveformBuffer
, m_Data
);
107 cmd
.BlitFullscreenTriangle(BuiltinRenderTextureType
.None
, output
, sheet
, 0);
109 cmd
.EndSample("Waveform");