post processing
[WindSway-HDRP.git] / Library / PackageCache / com.unity.postprocessing@2.1.6 / PostProcessing / Runtime / Effects / MultiScaleVO.cs
blobb7fb45f5192b6eaf63dcf3c844a28f7d33195de3
1 using System;
3 namespace UnityEngine.Rendering.PostProcessing
5 // Multi-scale volumetric obscurance
6 // TODO: Fix VR support
8 #if UNITY_2017_1_OR_NEWER
9 [UnityEngine.Scripting.Preserve]
10 [Serializable]
11 internal sealed class MultiScaleVO : IAmbientOcclusionMethod
13 internal enum MipLevel { Original, L1, L2, L3, L4, L5, L6 }
15 enum Pass
17 DepthCopy,
18 CompositionDeferred,
19 CompositionForward,
20 DebugOverlay
23 // The arrays below are reused between frames to reduce GC allocation.
24 readonly float[] m_SampleThickness =
26 Mathf.Sqrt(1f - 0.2f * 0.2f),
27 Mathf.Sqrt(1f - 0.4f * 0.4f),
28 Mathf.Sqrt(1f - 0.6f * 0.6f),
29 Mathf.Sqrt(1f - 0.8f * 0.8f),
30 Mathf.Sqrt(1f - 0.2f * 0.2f - 0.2f * 0.2f),
31 Mathf.Sqrt(1f - 0.2f * 0.2f - 0.4f * 0.4f),
32 Mathf.Sqrt(1f - 0.2f * 0.2f - 0.6f * 0.6f),
33 Mathf.Sqrt(1f - 0.2f * 0.2f - 0.8f * 0.8f),
34 Mathf.Sqrt(1f - 0.4f * 0.4f - 0.4f * 0.4f),
35 Mathf.Sqrt(1f - 0.4f * 0.4f - 0.6f * 0.6f),
36 Mathf.Sqrt(1f - 0.4f * 0.4f - 0.8f * 0.8f),
37 Mathf.Sqrt(1f - 0.6f * 0.6f - 0.6f * 0.6f)
40 readonly float[] m_InvThicknessTable = new float[12];
41 readonly float[] m_SampleWeightTable = new float[12];
43 readonly int[] m_Widths = new int[7];
44 readonly int[] m_Heights = new int[7];
46 AmbientOcclusion m_Settings;
47 PropertySheet m_PropertySheet;
48 PostProcessResources m_Resources;
50 // Can't use a temporary because we need to share it between cmdbuffers - also fixes a weird
51 // command buffer warning
52 RenderTexture m_AmbientOnlyAO;
54 readonly RenderTargetIdentifier[] m_MRT =
56 BuiltinRenderTextureType.GBuffer0, // Albedo, Occ
57 BuiltinRenderTextureType.CameraTarget // Ambient
60 public MultiScaleVO(AmbientOcclusion settings)
62 m_Settings = settings;
65 public DepthTextureMode GetCameraFlags()
67 return DepthTextureMode.Depth;
70 // Special case for AO [because SRPs], please don't do this in other effects, it's bad
71 // practice in this framework
72 public void SetResources(PostProcessResources resources)
74 m_Resources = resources;
77 void Alloc(CommandBuffer cmd, int id, MipLevel size, RenderTextureFormat format, bool uav)
79 int sizeId = (int)size;
80 cmd.GetTemporaryRT(id, new RenderTextureDescriptor
82 width = m_Widths[sizeId],
83 height = m_Heights[sizeId],
84 colorFormat = format,
85 depthBufferBits = 0,
86 volumeDepth = 1,
87 autoGenerateMips = false,
88 msaaSamples = 1,
89 enableRandomWrite = uav,
90 dimension = TextureDimension.Tex2D,
91 sRGB = false
92 }, FilterMode.Point);
95 void AllocArray(CommandBuffer cmd, int id, MipLevel size, RenderTextureFormat format, bool uav)
97 int sizeId = (int)size;
98 cmd.GetTemporaryRT(id, new RenderTextureDescriptor
100 width = m_Widths[sizeId],
101 height = m_Heights[sizeId],
102 colorFormat = format,
103 depthBufferBits = 0,
104 volumeDepth = 16,
105 autoGenerateMips = false,
106 msaaSamples = 1,
107 enableRandomWrite = uav,
108 dimension = TextureDimension.Tex2DArray,
109 sRGB = false
110 }, FilterMode.Point);
113 void Release(CommandBuffer cmd, int id)
115 cmd.ReleaseTemporaryRT(id);
118 // Calculate values in _ZBuferParams (built-in shader variable)
119 // We can't use _ZBufferParams in compute shaders, so this function is
120 // used to give the values in it to compute shaders.
121 Vector4 CalculateZBufferParams(Camera camera)
123 float fpn = camera.farClipPlane / camera.nearClipPlane;
125 if (SystemInfo.usesReversedZBuffer)
126 return new Vector4(fpn - 1f, 1f, 0f, 0f);
128 return new Vector4(1f - fpn, fpn, 0f, 0f);
131 float CalculateTanHalfFovHeight(Camera camera)
133 return 1f / camera.projectionMatrix[0, 0];
136 Vector2 GetSize(MipLevel mip)
138 return new Vector2(m_Widths[(int)mip], m_Heights[(int)mip]);
141 Vector3 GetSizeArray(MipLevel mip)
143 return new Vector3(m_Widths[(int)mip], m_Heights[(int)mip], 16);
146 public void GenerateAOMap(CommandBuffer cmd, Camera camera, RenderTargetIdentifier destination, RenderTargetIdentifier? depthMap, bool invert, bool isMSAA)
148 // Base size
149 m_Widths[0] = camera.pixelWidth * (RuntimeUtilities.isSinglePassStereoEnabled ? 2 : 1);
150 m_Heights[0] = camera.pixelHeight;
152 // L1 -> L6 sizes
153 for (int i = 1; i < 7; i++)
155 int div = 1 << i;
156 m_Widths[i] = (m_Widths[0] + (div - 1)) / div;
157 m_Heights[i] = (m_Heights[0] + (div - 1)) / div;
160 // Allocate temporary textures
161 PushAllocCommands(cmd, isMSAA);
163 // Render logic
164 PushDownsampleCommands(cmd, camera, depthMap, isMSAA);
166 float tanHalfFovH = CalculateTanHalfFovHeight(camera);
167 PushRenderCommands(cmd, ShaderIDs.TiledDepth1, ShaderIDs.Occlusion1, GetSizeArray(MipLevel.L3), tanHalfFovH, isMSAA);
168 PushRenderCommands(cmd, ShaderIDs.TiledDepth2, ShaderIDs.Occlusion2, GetSizeArray(MipLevel.L4), tanHalfFovH, isMSAA);
169 PushRenderCommands(cmd, ShaderIDs.TiledDepth3, ShaderIDs.Occlusion3, GetSizeArray(MipLevel.L5), tanHalfFovH, isMSAA);
170 PushRenderCommands(cmd, ShaderIDs.TiledDepth4, ShaderIDs.Occlusion4, GetSizeArray(MipLevel.L6), tanHalfFovH, isMSAA);
172 PushUpsampleCommands(cmd, ShaderIDs.LowDepth4, ShaderIDs.Occlusion4, ShaderIDs.LowDepth3, ShaderIDs.Occlusion3, ShaderIDs.Combined3, GetSize(MipLevel.L4), GetSize(MipLevel.L3), isMSAA);
173 PushUpsampleCommands(cmd, ShaderIDs.LowDepth3, ShaderIDs.Combined3, ShaderIDs.LowDepth2, ShaderIDs.Occlusion2, ShaderIDs.Combined2, GetSize(MipLevel.L3), GetSize(MipLevel.L2), isMSAA);
174 PushUpsampleCommands(cmd, ShaderIDs.LowDepth2, ShaderIDs.Combined2, ShaderIDs.LowDepth1, ShaderIDs.Occlusion1, ShaderIDs.Combined1, GetSize(MipLevel.L2), GetSize(MipLevel.L1), isMSAA);
175 PushUpsampleCommands(cmd, ShaderIDs.LowDepth1, ShaderIDs.Combined1, ShaderIDs.LinearDepth, null, destination, GetSize(MipLevel.L1), GetSize(MipLevel.Original), isMSAA, invert);
177 // Cleanup
178 PushReleaseCommands(cmd);
181 void PushAllocCommands(CommandBuffer cmd, bool isMSAA)
183 if(isMSAA)
185 Alloc(cmd, ShaderIDs.LinearDepth, MipLevel.Original, RenderTextureFormat.RGHalf, true);
187 Alloc(cmd, ShaderIDs.LowDepth1, MipLevel.L1, RenderTextureFormat.RGFloat, true);
188 Alloc(cmd, ShaderIDs.LowDepth2, MipLevel.L2, RenderTextureFormat.RGFloat, true);
189 Alloc(cmd, ShaderIDs.LowDepth3, MipLevel.L3, RenderTextureFormat.RGFloat, true);
190 Alloc(cmd, ShaderIDs.LowDepth4, MipLevel.L4, RenderTextureFormat.RGFloat, true);
192 AllocArray(cmd, ShaderIDs.TiledDepth1, MipLevel.L3, RenderTextureFormat.RGHalf, true);
193 AllocArray(cmd, ShaderIDs.TiledDepth2, MipLevel.L4, RenderTextureFormat.RGHalf, true);
194 AllocArray(cmd, ShaderIDs.TiledDepth3, MipLevel.L5, RenderTextureFormat.RGHalf, true);
195 AllocArray(cmd, ShaderIDs.TiledDepth4, MipLevel.L6, RenderTextureFormat.RGHalf, true);
197 Alloc(cmd, ShaderIDs.Occlusion1, MipLevel.L1, RenderTextureFormat.RG16, true);
198 Alloc(cmd, ShaderIDs.Occlusion2, MipLevel.L2, RenderTextureFormat.RG16, true);
199 Alloc(cmd, ShaderIDs.Occlusion3, MipLevel.L3, RenderTextureFormat.RG16, true);
200 Alloc(cmd, ShaderIDs.Occlusion4, MipLevel.L4, RenderTextureFormat.RG16, true);
202 Alloc(cmd, ShaderIDs.Combined1, MipLevel.L1, RenderTextureFormat.RG16, true);
203 Alloc(cmd, ShaderIDs.Combined2, MipLevel.L2, RenderTextureFormat.RG16, true);
204 Alloc(cmd, ShaderIDs.Combined3, MipLevel.L3, RenderTextureFormat.RG16, true);
206 else
208 Alloc(cmd, ShaderIDs.LinearDepth, MipLevel.Original, RenderTextureFormat.RHalf, true);
210 Alloc(cmd, ShaderIDs.LowDepth1, MipLevel.L1, RenderTextureFormat.RFloat, true);
211 Alloc(cmd, ShaderIDs.LowDepth2, MipLevel.L2, RenderTextureFormat.RFloat, true);
212 Alloc(cmd, ShaderIDs.LowDepth3, MipLevel.L3, RenderTextureFormat.RFloat, true);
213 Alloc(cmd, ShaderIDs.LowDepth4, MipLevel.L4, RenderTextureFormat.RFloat, true);
215 AllocArray(cmd, ShaderIDs.TiledDepth1, MipLevel.L3, RenderTextureFormat.RHalf, true);
216 AllocArray(cmd, ShaderIDs.TiledDepth2, MipLevel.L4, RenderTextureFormat.RHalf, true);
217 AllocArray(cmd, ShaderIDs.TiledDepth3, MipLevel.L5, RenderTextureFormat.RHalf, true);
218 AllocArray(cmd, ShaderIDs.TiledDepth4, MipLevel.L6, RenderTextureFormat.RHalf, true);
220 Alloc(cmd, ShaderIDs.Occlusion1, MipLevel.L1, RenderTextureFormat.R8, true);
221 Alloc(cmd, ShaderIDs.Occlusion2, MipLevel.L2, RenderTextureFormat.R8, true);
222 Alloc(cmd, ShaderIDs.Occlusion3, MipLevel.L3, RenderTextureFormat.R8, true);
223 Alloc(cmd, ShaderIDs.Occlusion4, MipLevel.L4, RenderTextureFormat.R8, true);
225 Alloc(cmd, ShaderIDs.Combined1, MipLevel.L1, RenderTextureFormat.R8, true);
226 Alloc(cmd, ShaderIDs.Combined2, MipLevel.L2, RenderTextureFormat.R8, true);
227 Alloc(cmd, ShaderIDs.Combined3, MipLevel.L3, RenderTextureFormat.R8, true);
231 void PushDownsampleCommands(CommandBuffer cmd, Camera camera, RenderTargetIdentifier? depthMap, bool isMSAA)
233 RenderTargetIdentifier depthMapId;
234 bool needDepthMapRelease = false;
236 if (depthMap != null)
238 depthMapId = depthMap.Value;
240 else
242 // Make a copy of the depth texture, or reuse the resolved depth
243 // buffer (it's only available in some specific situations).
244 if (!RuntimeUtilities.IsResolvedDepthAvailable(camera))
246 Alloc(cmd, ShaderIDs.DepthCopy, MipLevel.Original, RenderTextureFormat.RFloat, false);
247 depthMapId = new RenderTargetIdentifier(ShaderIDs.DepthCopy);
248 cmd.BlitFullscreenTriangle(BuiltinRenderTextureType.None, depthMapId, m_PropertySheet, (int)Pass.DepthCopy);
249 needDepthMapRelease = true;
251 else
253 depthMapId = BuiltinRenderTextureType.ResolvedDepth;
257 // 1st downsampling pass.
258 var cs = m_Resources.computeShaders.multiScaleAODownsample1;
259 int kernel = cs.FindKernel(isMSAA ? "MultiScaleVODownsample1_MSAA" : "MultiScaleVODownsample1");
261 cmd.SetComputeTextureParam(cs, kernel, "LinearZ", ShaderIDs.LinearDepth);
262 cmd.SetComputeTextureParam(cs, kernel, "DS2x", ShaderIDs.LowDepth1);
263 cmd.SetComputeTextureParam(cs, kernel, "DS4x", ShaderIDs.LowDepth2);
264 cmd.SetComputeTextureParam(cs, kernel, "DS2xAtlas", ShaderIDs.TiledDepth1);
265 cmd.SetComputeTextureParam(cs, kernel, "DS4xAtlas", ShaderIDs.TiledDepth2);
266 cmd.SetComputeVectorParam(cs, "ZBufferParams", CalculateZBufferParams(camera));
267 cmd.SetComputeTextureParam(cs, kernel, "Depth", depthMapId);
269 cmd.DispatchCompute(cs, kernel, m_Widths[(int)MipLevel.L4], m_Heights[(int)MipLevel.L4], 1);
271 if (needDepthMapRelease)
272 Release(cmd, ShaderIDs.DepthCopy);
274 // 2nd downsampling pass.
275 cs = m_Resources.computeShaders.multiScaleAODownsample2;
276 kernel = isMSAA ? cs.FindKernel("MultiScaleVODownsample2_MSAA") : cs.FindKernel("MultiScaleVODownsample2");
278 cmd.SetComputeTextureParam(cs, kernel, "DS4x", ShaderIDs.LowDepth2);
279 cmd.SetComputeTextureParam(cs, kernel, "DS8x", ShaderIDs.LowDepth3);
280 cmd.SetComputeTextureParam(cs, kernel, "DS16x", ShaderIDs.LowDepth4);
281 cmd.SetComputeTextureParam(cs, kernel, "DS8xAtlas", ShaderIDs.TiledDepth3);
282 cmd.SetComputeTextureParam(cs, kernel, "DS16xAtlas", ShaderIDs.TiledDepth4);
284 cmd.DispatchCompute(cs, kernel, m_Widths[(int)MipLevel.L6], m_Heights[(int)MipLevel.L6], 1);
287 void PushRenderCommands(CommandBuffer cmd, int source, int destination, Vector3 sourceSize, float tanHalfFovH, bool isMSAA)
289 // Here we compute multipliers that convert the center depth value into (the reciprocal
290 // of) sphere thicknesses at each sample location. This assumes a maximum sample radius
291 // of 5 units, but since a sphere has no thickness at its extent, we don't need to
292 // sample that far out. Only samples whole integer offsets with distance less than 25
293 // are used. This means that there is no sample at (3, 4) because its distance is
294 // exactly 25 (and has a thickness of 0.)
296 // The shaders are set up to sample a circular region within a 5-pixel radius.
297 const float kScreenspaceDiameter = 10f;
299 // SphereDiameter = CenterDepth * ThicknessMultiplier. This will compute the thickness
300 // of a sphere centered at a specific depth. The ellipsoid scale can stretch a sphere
301 // into an ellipsoid, which changes the characteristics of the AO.
302 // TanHalfFovH: Radius of sphere in depth units if its center lies at Z = 1
303 // ScreenspaceDiameter: Diameter of sample sphere in pixel units
304 // ScreenspaceDiameter / BufferWidth: Ratio of the screen width that the sphere actually covers
305 float thicknessMultiplier = 2f * tanHalfFovH * kScreenspaceDiameter / sourceSize.x;
306 if (RuntimeUtilities.isSinglePassStereoEnabled)
307 thicknessMultiplier *= 2f;
309 // This will transform a depth value from [0, thickness] to [0, 1].
310 float inverseRangeFactor = 1f / thicknessMultiplier;
312 // The thicknesses are smaller for all off-center samples of the sphere. Compute
313 // thicknesses relative to the center sample.
314 for (int i = 0; i < 12; i++)
315 m_InvThicknessTable[i] = inverseRangeFactor / m_SampleThickness[i];
317 // These are the weights that are multiplied against the samples because not all samples
318 // are equally important. The farther the sample is from the center location, the less
319 // they matter. We use the thickness of the sphere to determine the weight. The scalars
320 // in front are the number of samples with this weight because we sum the samples
321 // together before multiplying by the weight, so as an aggregate all of those samples
322 // matter more. After generating this table, the weights are normalized.
323 m_SampleWeightTable[ 0] = 4 * m_SampleThickness[ 0]; // Axial
324 m_SampleWeightTable[ 1] = 4 * m_SampleThickness[ 1]; // Axial
325 m_SampleWeightTable[ 2] = 4 * m_SampleThickness[ 2]; // Axial
326 m_SampleWeightTable[ 3] = 4 * m_SampleThickness[ 3]; // Axial
327 m_SampleWeightTable[ 4] = 4 * m_SampleThickness[ 4]; // Diagonal
328 m_SampleWeightTable[ 5] = 8 * m_SampleThickness[ 5]; // L-shaped
329 m_SampleWeightTable[ 6] = 8 * m_SampleThickness[ 6]; // L-shaped
330 m_SampleWeightTable[ 7] = 8 * m_SampleThickness[ 7]; // L-shaped
331 m_SampleWeightTable[ 8] = 4 * m_SampleThickness[ 8]; // Diagonal
332 m_SampleWeightTable[ 9] = 8 * m_SampleThickness[ 9]; // L-shaped
333 m_SampleWeightTable[10] = 8 * m_SampleThickness[10]; // L-shaped
334 m_SampleWeightTable[11] = 4 * m_SampleThickness[11]; // Diagonal
336 // Zero out the unused samples.
337 // FIXME: should we support SAMPLE_EXHAUSTIVELY mode?
338 m_SampleWeightTable[0] = 0;
339 m_SampleWeightTable[2] = 0;
340 m_SampleWeightTable[5] = 0;
341 m_SampleWeightTable[7] = 0;
342 m_SampleWeightTable[9] = 0;
344 // Normalize the weights by dividing by the sum of all weights
345 var totalWeight = 0f;
347 foreach (float w in m_SampleWeightTable)
348 totalWeight += w;
350 for (int i = 0; i < m_SampleWeightTable.Length; i++)
351 m_SampleWeightTable[i] /= totalWeight;
353 // Set the arguments for the render kernel.
354 var cs = m_Resources.computeShaders.multiScaleAORender;
355 int kernel = isMSAA ? cs.FindKernel("MultiScaleVORender_MSAA_interleaved") : cs.FindKernel("MultiScaleVORender_interleaved");
357 cmd.SetComputeFloatParams(cs, "gInvThicknessTable", m_InvThicknessTable);
358 cmd.SetComputeFloatParams(cs, "gSampleWeightTable", m_SampleWeightTable);
359 cmd.SetComputeVectorParam(cs, "gInvSliceDimension", new Vector2(1f / sourceSize.x, 1f / sourceSize.y));
360 cmd.SetComputeVectorParam(cs, "AdditionalParams", new Vector2(-1f / m_Settings.thicknessModifier.value, m_Settings.intensity.value));
361 cmd.SetComputeTextureParam(cs, kernel, "DepthTex", source);
362 cmd.SetComputeTextureParam(cs, kernel, "Occlusion", destination);
364 // Calculate the thread group count and add a dispatch command with them.
365 uint xsize, ysize, zsize;
366 cs.GetKernelThreadGroupSizes(kernel, out xsize, out ysize, out zsize);
368 cmd.DispatchCompute(
369 cs, kernel,
370 ((int)sourceSize.x + (int)xsize - 1) / (int)xsize,
371 ((int)sourceSize.y + (int)ysize - 1) / (int)ysize,
372 ((int)sourceSize.z + (int)zsize - 1) / (int)zsize
376 void PushUpsampleCommands(CommandBuffer cmd, int lowResDepth, int interleavedAO, int highResDepth, int? highResAO, RenderTargetIdentifier dest, Vector3 lowResDepthSize, Vector2 highResDepthSize, bool isMSAA, bool invert = false)
378 var cs = m_Resources.computeShaders.multiScaleAOUpsample;
379 int kernel = 0;
380 if (!isMSAA)
382 kernel = cs.FindKernel(highResAO == null ? invert
383 ? "MultiScaleVOUpSample_invert"
384 : "MultiScaleVOUpSample"
385 : "MultiScaleVOUpSample_blendout");
387 else
389 kernel = cs.FindKernel(highResAO == null ? invert
390 ? "MultiScaleVOUpSample_MSAA_invert"
391 : "MultiScaleVOUpSample_MSAA"
392 : "MultiScaleVOUpSample_MSAA_blendout");
396 float stepSize = 1920f / lowResDepthSize.x;
397 float bTolerance = 1f - Mathf.Pow(10f, m_Settings.blurTolerance.value) * stepSize;
398 bTolerance *= bTolerance;
399 float uTolerance = Mathf.Pow(10f, m_Settings.upsampleTolerance.value);
400 float noiseFilterWeight = 1f / (Mathf.Pow(10f, m_Settings.noiseFilterTolerance.value) + uTolerance);
402 cmd.SetComputeVectorParam(cs, "InvLowResolution", new Vector2(1f / lowResDepthSize.x, 1f / lowResDepthSize.y));
403 cmd.SetComputeVectorParam(cs, "InvHighResolution", new Vector2(1f / highResDepthSize.x, 1f / highResDepthSize.y));
404 cmd.SetComputeVectorParam(cs, "AdditionalParams", new Vector4(noiseFilterWeight, stepSize, bTolerance, uTolerance));
406 cmd.SetComputeTextureParam(cs, kernel, "LoResDB", lowResDepth);
407 cmd.SetComputeTextureParam(cs, kernel, "HiResDB", highResDepth);
408 cmd.SetComputeTextureParam(cs, kernel, "LoResAO1", interleavedAO);
410 if (highResAO != null)
411 cmd.SetComputeTextureParam(cs, kernel, "HiResAO", highResAO.Value);
413 cmd.SetComputeTextureParam(cs, kernel, "AoResult", dest);
415 int xcount = ((int)highResDepthSize.x + 17) / 16;
416 int ycount = ((int)highResDepthSize.y + 17) / 16;
417 cmd.DispatchCompute(cs, kernel, xcount, ycount, 1);
420 void PushReleaseCommands(CommandBuffer cmd)
422 Release(cmd, ShaderIDs.LinearDepth);
424 Release(cmd, ShaderIDs.LowDepth1);
425 Release(cmd, ShaderIDs.LowDepth2);
426 Release(cmd, ShaderIDs.LowDepth3);
427 Release(cmd, ShaderIDs.LowDepth4);
429 Release(cmd, ShaderIDs.TiledDepth1);
430 Release(cmd, ShaderIDs.TiledDepth2);
431 Release(cmd, ShaderIDs.TiledDepth3);
432 Release(cmd, ShaderIDs.TiledDepth4);
434 Release(cmd, ShaderIDs.Occlusion1);
435 Release(cmd, ShaderIDs.Occlusion2);
436 Release(cmd, ShaderIDs.Occlusion3);
437 Release(cmd, ShaderIDs.Occlusion4);
439 Release(cmd, ShaderIDs.Combined1);
440 Release(cmd, ShaderIDs.Combined2);
441 Release(cmd, ShaderIDs.Combined3);
444 void PreparePropertySheet(PostProcessRenderContext context)
446 var sheet = context.propertySheets.Get(m_Resources.shaders.multiScaleAO);
447 sheet.ClearKeywords();
448 sheet.properties.SetVector(ShaderIDs.AOColor, Color.white - m_Settings.color.value);
449 m_PropertySheet = sheet;
452 void CheckAOTexture(PostProcessRenderContext context)
454 if (m_AmbientOnlyAO == null || !m_AmbientOnlyAO.IsCreated() || m_AmbientOnlyAO.width != context.width || m_AmbientOnlyAO.height != context.height)
456 RuntimeUtilities.Destroy(m_AmbientOnlyAO);
458 m_AmbientOnlyAO = new RenderTexture(context.width, context.height, 0, RenderTextureFormat.R8, RenderTextureReadWrite.Linear)
460 hideFlags = HideFlags.DontSave,
461 filterMode = FilterMode.Point,
462 enableRandomWrite = true
464 m_AmbientOnlyAO.Create();
468 void PushDebug(PostProcessRenderContext context)
470 if (context.IsDebugOverlayEnabled(DebugOverlay.AmbientOcclusion))
471 context.PushDebugOverlay(context.command, m_AmbientOnlyAO, m_PropertySheet, (int)Pass.DebugOverlay);
474 public void RenderAfterOpaque(PostProcessRenderContext context)
476 var cmd = context.command;
477 cmd.BeginSample("Ambient Occlusion");
478 SetResources(context.resources);
479 PreparePropertySheet(context);
480 CheckAOTexture(context);
482 // In Forward mode, fog is applied at the object level in the grometry pass so we need
483 // to apply it to AO as well or it'll drawn on top of the fog effect.
484 if (context.camera.actualRenderingPath == RenderingPath.Forward && RenderSettings.fog)
486 m_PropertySheet.EnableKeyword("APPLY_FORWARD_FOG");
487 m_PropertySheet.properties.SetVector(
488 ShaderIDs.FogParams,
489 new Vector3(RenderSettings.fogDensity, RenderSettings.fogStartDistance, RenderSettings.fogEndDistance)
493 GenerateAOMap(cmd, context.camera, m_AmbientOnlyAO, null, false, false);
494 PushDebug(context);
495 cmd.SetGlobalTexture(ShaderIDs.MSVOcclusionTexture, m_AmbientOnlyAO);
496 cmd.BlitFullscreenTriangle(BuiltinRenderTextureType.None, BuiltinRenderTextureType.CameraTarget, m_PropertySheet, (int)Pass.CompositionForward, RenderBufferLoadAction.Load);
497 cmd.EndSample("Ambient Occlusion");
500 public void RenderAmbientOnly(PostProcessRenderContext context)
502 var cmd = context.command;
503 cmd.BeginSample("Ambient Occlusion Render");
504 SetResources(context.resources);
505 PreparePropertySheet(context);
506 CheckAOTexture(context);
507 GenerateAOMap(cmd, context.camera, m_AmbientOnlyAO, null, false, false);
508 PushDebug(context);
509 cmd.EndSample("Ambient Occlusion Render");
512 public void CompositeAmbientOnly(PostProcessRenderContext context)
514 var cmd = context.command;
515 cmd.BeginSample("Ambient Occlusion Composite");
516 cmd.SetGlobalTexture(ShaderIDs.MSVOcclusionTexture, m_AmbientOnlyAO);
517 cmd.BlitFullscreenTriangle(BuiltinRenderTextureType.None, m_MRT, BuiltinRenderTextureType.CameraTarget, m_PropertySheet, (int)Pass.CompositionDeferred);
518 cmd.EndSample("Ambient Occlusion Composite");
521 public void Release()
523 RuntimeUtilities.Destroy(m_AmbientOnlyAO);
524 m_AmbientOnlyAO = null;
527 #else
528 [Serializable]
529 public sealed class MultiScaleVO : IAmbientOcclusionMethod
531 public MultiScaleVO(AmbientOcclusion settings)
535 public void SetResources(PostProcessResources resources)
539 public DepthTextureMode GetCameraFlags()
541 return DepthTextureMode.None;
544 public void GenerateAOMap(CommandBuffer cmd, Camera camera, RenderTargetIdentifier destination, RenderTargetIdentifier? depthMap, bool invert, bool isMSAA)
548 public void RenderAfterOpaque(PostProcessRenderContext context)
552 public void RenderAmbientOnly(PostProcessRenderContext context)
556 public void CompositeAmbientOnly(PostProcessRenderContext context)
560 public void Release()
564 #endif