forked from ryanKeable/ShootySkiesOverDriveRenderPipeline
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathDelMarPostProcessingPass.cs
305 lines (235 loc) · 12.7 KB
/
DelMarPostProcessingPass.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
using System.Runtime.CompilerServices;
using UnityEngine.Experimental.Rendering;
namespace UnityEngine.Rendering.Universal.Internal
{
// TODO: TAA
// TODO: Motion blur
/// <summary>
/// Renders the post-processing effect stack.
/// </summary>
public class DelMarPostProcessingPass : ScriptableRenderPass
{
RenderTextureDescriptor m_Descriptor;
RenderTextureDescriptor m_FinalDescriptor;
RenderTargetHandle m_Source;
RenderTargetHandle m_Destination;
const string k_RenderPostProcessingTag = "Render PostProcessing Effects";
PostProcessData m_Data;
// Builtin effects settings
Bloom m_Bloom;
// Misc
const int k_MaxPyramidSize = 8;
readonly GraphicsFormat m_DefaultHDRFormat;
bool m_ResetHistory;
bool m_IsStereo;
Material m_BloomMaterial;
Material m_BlitMaterial;
int tw;
int th;
int maxSize;
int iterations;
int mipCount;
float threshold;
float thresholdKnee;
float thresholdNumerator;
float scatter;
const float bloomRenderSizeScalar = 0.5f;
public DelMarPostProcessingPass(RenderPassEvent evt, PostProcessData data, Material blitMaterial = null, Material bloomMaterial = null)
{
renderPassEvent = evt;
m_Data = data;
m_BlitMaterial = blitMaterial;
m_BloomMaterial = bloomMaterial;
m_DefaultHDRFormat = GraphicsFormat.R8G8B8A8_SRGB;
// Bloom pyramid shader ids - can't use a simple stackalloc in the bloom function as we
// unfortunately need to allocate strings
ShaderConstants._BloomMipUp = new int[k_MaxPyramidSize];
ShaderConstants._BloomMipDown = new int[k_MaxPyramidSize];
for (int i = 0; i < k_MaxPyramidSize; i++) {
ShaderConstants._BloomMipUp[i] = Shader.PropertyToID("_BloomMipUp" + i);
ShaderConstants._BloomMipDown[i] = Shader.PropertyToID("_BloomMipDown" + i);
}
m_ResetHistory = true;
}
public void Setup(in RenderTextureDescriptor baseDescriptor, in RenderTargetHandle source, in RenderTargetHandle destination)
{
m_Descriptor = baseDescriptor;
m_FinalDescriptor = baseDescriptor;
m_Source = source;
m_Destination = destination;
}
public override void Configure(CommandBuffer cmd, RenderTextureDescriptor cameraTextureDescriptor)
{
if (m_Destination == RenderTargetHandle.CameraTarget)
return;
// THIS IS MY MSAA DESCRIPTOR!!
var desc = cameraTextureDescriptor;
desc.msaaSamples = 1;
desc.depthBufferBits = 0;
cmd.GetTemporaryRT(m_Destination.id, desc, FilterMode.Point);
}
public void ResetHistory()
{
m_ResetHistory = true;
}
public bool CanRunOnTile()
{
// Check builtin & user effects here
return false;
}
/// <inheritdoc/>
public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
{
// Start by pre-fetching all builtin effect settings we need
// Some of the color-grading settings are only used in the color grading lut pass
var stack = VolumeManager.instance.stack;
m_Bloom = stack.GetComponent<Bloom>();
var cmd = CommandBufferPool.Get(k_RenderPostProcessingTag);
Render(cmd, ref renderingData);
context.ExecuteCommandBuffer(cmd);
CommandBufferPool.Release(cmd);
m_ResetHistory = false;
}
RenderTextureDescriptor GetStereoCompatibleDescriptor()
=> GetStereoCompatibleDescriptor(m_Descriptor.width, m_Descriptor.height, m_Descriptor.graphicsFormat, m_Descriptor.depthBufferBits);
RenderTextureDescriptor GetStereoCompatibleDescriptor(int width, int height, GraphicsFormat format, int depthBufferBits = 0)
{
// Inherit the VR setup from the camera descriptor
var desc = m_Descriptor;
desc.depthBufferBits = depthBufferBits;
desc.msaaSamples = 1;
desc.width = width;
desc.height = height;
desc.graphicsFormat = format;
return desc;
}
void Render(CommandBuffer cmd, ref RenderingData renderingData)
{
ref var cameraData = ref renderingData.cameraData;
m_IsStereo = renderingData.cameraData.isStereoEnabled;
// Don't use these directly unless you have a good reason to, use GetSource() and
// GetDestination() instead
int source = m_Source.id;
// Utilities to simplify intermediate target management
int GetSource() => source;
// Setup projection matrix for cmd.DrawMesh()
cmd.SetGlobalMatrix(ShaderConstants._FullscreenProjMat, GL.GetGPUProjectionMatrix(Matrix4x4.identity, true));
// Setup projection matrix for cmd.DrawMesh()
cmd.SetGlobalMatrix(ShaderConstants._FullscreenProjMat, GL.GetGPUProjectionMatrix(Matrix4x4.identity, true));
ProfilingSampler uberSampler = new ProfilingSampler("Uber Sampler");
ProfilingSampler bloomSampler = new ProfilingSampler("Bloom Sampler");
using (new ProfilingScope(cmd, uberSampler)) {
// Bloom goes second
using (new ProfilingScope(cmd, bloomSampler))
SetupBloom(cmd, GetSource());
// Done with Uber, blit it
cmd.SetGlobalTexture("_BlitTex", GetSource());
// we should never load or store our frame data as this is expensive on a tiled GPU.
// Note: We rendering to "camera target" we need to get the cameraData.targetTexture as this will get the targetTexture of the camera stack.
// Overlay cameras need to output to the target described in the base camera while doing camera stack.
RenderTargetIdentifier cameraTarget = m_Destination.Identifier(); // (m_Destination == RenderTargetHandle.CameraTarget) ? cameraTarget : m_Destination.Identifier();
cmd.SetRenderTarget(cameraTarget, RenderBufferLoadAction.DontCare, RenderBufferStoreAction.DontCare, RenderBufferLoadAction.DontCare, RenderBufferStoreAction.DontCare); //why are we storing?!
// With camera stacking we not always resolve post to final screen as we might run post-processing in the middle of the stack.
if (m_IsStereo) {
Blit(cmd, GetSource(), BuiltinRenderTextureType.CurrentActive, m_BlitMaterial);
} else {
cmd.SetViewProjectionMatrices(Matrix4x4.identity, Matrix4x4.identity);
cmd.SetViewport(cameraData.camera.pixelRect);
cmd.DrawMesh(RenderingUtils.fullscreenMesh, Matrix4x4.identity, m_BlitMaterial);
cmd.SetViewProjectionMatrices(cameraData.camera.worldToCameraMatrix, cameraData.camera.projectionMatrix);
}
// Cleanup
cmd.ReleaseTemporaryRT(ShaderConstants._BloomMipUp[0]);
}
}
private BuiltinRenderTextureType BlitDstDiscardContent(CommandBuffer cmd, RenderTargetIdentifier rt)
{
// I had always assumed we needed to store the frame data to access it later but this is incorrect.
// storing refers to a per framebuffer per frame write of the blit
// once the texture has been generated the colour is stored in the texture?
cmd.SetRenderTarget(new RenderTargetIdentifier(rt, 0, CubemapFace.Unknown, -1),
RenderBufferLoadAction.DontCare, RenderBufferStoreAction.DontCare,
RenderBufferLoadAction.DontCare, RenderBufferStoreAction.DontCare);
return BuiltinRenderTextureType.CurrentActive;
}
#region Bloom
void ConfigureBloom()
{
tw = m_Descriptor.width >> 1;
th = m_Descriptor.height >> 1;
// Determine the iteration count
maxSize = Mathf.Max(tw, th);
iterations = Mathf.FloorToInt(Mathf.Log(maxSize, 2f) - 1);
mipCount = Mathf.Clamp(iterations, 1, k_MaxPyramidSize);
// Pre-filtering parameters
threshold = Mathf.GammaToLinearSpace(m_Bloom.threshold.value);
thresholdKnee = threshold * 0.5f;
thresholdNumerator = 4.0f * thresholdKnee + 0.0001f;
scatter = Mathf.Lerp(0.05f, 0.95f, m_Bloom.scatter.value);
// Material setup
m_BloomMaterial.SetVector(ShaderConstants._Bloom_Params, new Vector4(scatter, threshold, thresholdKnee, thresholdNumerator));
m_BlitMaterial.SetFloat(ShaderConstants._Bloom_Intenisty, m_Bloom.intensity.value);
}
void SetupBloom(CommandBuffer cmd, int source)
{
ConfigureBloom();
var desc = GetStereoCompatibleDescriptor(tw, th, m_DefaultHDRFormat);
// bilinear performs first basic blur at half res
// this way we do not discard too many pixels before the blur passes
cmd.GetTemporaryRT(ShaderConstants._BloomMipDown[0], desc, FilterMode.Bilinear);
cmd.GetTemporaryRT(ShaderConstants._BloomMipUp[0], desc, FilterMode.Bilinear);
cmd.Blit(source, BlitDstDiscardContent(cmd, ShaderConstants._BloomMipDown[0]), m_BloomMaterial, 0);
// Downsample - gaussian pyramid
// we go down again before we blur
int lastDown = ShaderConstants._BloomMipDown[0];
for (int i = 1; i < mipCount - 1; i++) {
tw = Mathf.Max(1, tw >> 1);
th = Mathf.Max(1, th >> 1);
int mipDown = ShaderConstants._BloomMipDown[i];
int mipUp = ShaderConstants._BloomMipUp[i];
desc.width = tw;
desc.height = th;
cmd.GetTemporaryRT(mipDown, desc, FilterMode.Bilinear);
cmd.GetTemporaryRT(mipUp, desc, FilterMode.Bilinear);
// Classic two pass gaussian blur - use mipUp as a temporary target
// First pass does 2x downsampling + 9-tap gaussian using a 5-tap filter + bilinear filtering
// Second pass does 9-tap gaussian using a 5-tap filter + bilinear filtering
cmd.Blit(lastDown, BlitDstDiscardContent(cmd, mipUp), m_BloomMaterial, 1);
cmd.Blit(mipUp, BlitDstDiscardContent(cmd, mipDown), m_BloomMaterial, 2);
lastDown = mipDown;
}
for (int i = mipCount - 3; i >= 0; i--) {
int lowMip = (i == mipCount - 2) ? ShaderConstants._BloomMipDown[i + 1] : ShaderConstants._BloomMipUp[i + 1];
int highMip = ShaderConstants._BloomMipDown[i];
// int highMip = (i == 0) ? ShaderConstants._BloomMipDown[2] : ShaderConstants._BloomMipDown[i];
int dst = ShaderConstants._BloomMipUp[i];
cmd.SetGlobalTexture(ShaderConstants._MainTexLowMip, lowMip);
cmd.Blit(highMip, BlitDstDiscardContent(cmd, dst), m_BloomMaterial, 3);
}
// Cleanup
for (int i = 0; i < k_MaxPyramidSize; i++) {
cmd.ReleaseTemporaryRT(ShaderConstants._BloomMipDown[i]);
if (i > 0) cmd.ReleaseTemporaryRT(ShaderConstants._BloomMipUp[i]);
}
cmd.SetGlobalTexture(ShaderConstants._Bloom_Texture, ShaderConstants._BloomMipUp[0]);
}
#endregion
#region Internal utilities
// Precomputed shader ids to same some CPU cycles (mostly affects mobile)
static class ShaderConstants
{
public static readonly int _MainTexLowMip = Shader.PropertyToID("_MainTexLowMip");
public static readonly int _Bloom_Params = Shader.PropertyToID("_Bloom_Params");
public static readonly int _Bloom_Intenisty = Shader.PropertyToID("_Bloom_Intensity");
public static readonly int _Bloom_RGBM = Shader.PropertyToID("_Bloom_RGBM");
public static readonly int _Bloom_Texture = Shader.PropertyToID("_Bloom_Texture");
public static readonly int _TempNoMSAATex = Shader.PropertyToID("_TempNoMSAATex");
public static readonly int _FullscreenProjMat = Shader.PropertyToID("_FullscreenProjMat");
public static readonly int _MSAACopyString = Shader.PropertyToID("_MSAACopyString");
public static readonly int _BloomFilter = Shader.PropertyToID("_BloomFilter");
public static int[] _BloomMipUp;
public static int[] _BloomMipDown;
}
#endregion
}
}