|
2 | 2 |
|
3 | 3 | namespace UnityEngine.Rendering.PostProcessing
|
4 | 4 | {
|
| 5 | + public interface IAmbientOcclusionMethod |
| 6 | + { |
| 7 | + DepthTextureMode GetCameraFlags(); |
| 8 | + bool IsSupported(PostProcessRenderContext context); |
| 9 | + void RenderAfterOpaque(PostProcessRenderContext context); |
| 10 | + void RenderAmbientOnly(PostProcessRenderContext context); |
| 11 | + void CompositeAmbientOnly(PostProcessRenderContext context); |
| 12 | + void Release(); |
| 13 | + } |
| 14 | + |
5 | 15 | [Serializable]
|
6 | 16 | public sealed class AmbientOcclusion
|
7 | 17 | {
|
8 |
| - // Unity sorts enums by value in the editor (and doesn't handle same-values enums very well |
9 |
| - // so we won't use enum values as sample counts this time |
10 |
| - public enum Quality |
| 18 | + public enum Mode |
11 | 19 | {
|
12 |
| - Lowest, |
13 |
| - Low, |
14 |
| - Medium, |
15 |
| - High, |
16 |
| - Ultra |
| 20 | + SAO, |
| 21 | + MSVO |
17 | 22 | }
|
18 | 23 |
|
19 | 24 | [Tooltip("Enables ambient occlusion.")]
|
20 | 25 | public bool enabled = false;
|
21 | 26 |
|
22 |
| - [Range(0f, 4f), Tooltip("Degree of darkness produced by the effect.")] |
23 |
| - public float intensity = 0.5f; |
24 |
| - |
25 |
| - [Tooltip("Radius of sample points, which affects extent of darkened areas.")] |
26 |
| - public float radius = 0.25f; |
27 |
| - |
28 |
| - [Tooltip("Number of sample points, which affects quality and performance. Lowest, Low & Medium passes are downsampled. High and Ultra are not and should only be used on high-end hardware.")] |
29 |
| - public Quality quality = Quality.Medium; |
| 27 | + public Mode mode = Mode.MSVO; |
30 | 28 |
|
31 | 29 | [Tooltip("Only affects ambient lighting. This mode is only available with the Deferred rendering path and HDR rendering. Objects rendered with the Forward rendering path won't get any ambient occlusion.")]
|
32 | 30 | public bool ambientOnly = false;
|
33 | 31 |
|
34 |
| - readonly RenderTargetIdentifier[] m_MRT = |
35 |
| - { |
36 |
| - BuiltinRenderTextureType.GBuffer0, // Albedo, Occ |
37 |
| - BuiltinRenderTextureType.CameraTarget // Ambient |
38 |
| - }; |
| 32 | + // Polymorphism doesn't play well with serialization in Unity so we have to keep explicit |
| 33 | + // references... Would be nice to have this more dynamic to allow user-custom AO methods. |
| 34 | + public ScalableAO scalableAO; |
| 35 | + public MultiScaleVO multiScaleVO; |
39 | 36 |
|
40 |
| - readonly int[] m_SampleCount = { 4, 6, 10, 8, 12 }; |
| 37 | + IAmbientOcclusionMethod[] m_Methods; |
41 | 38 |
|
42 |
| - enum Pass |
| 39 | + public AmbientOcclusion() |
43 | 40 | {
|
44 |
| - OcclusionEstimationForward, |
45 |
| - OcclusionEstimationDeferred, |
46 |
| - HorizontalBlurForward, |
47 |
| - HorizontalBlurDeferred, |
48 |
| - VerticalBlur, |
49 |
| - CompositionForward, |
50 |
| - CompositionDeferred |
| 41 | + if (scalableAO == null) scalableAO = new ScalableAO(); |
| 42 | + if (multiScaleVO == null) multiScaleVO = new MultiScaleVO(); |
| 43 | + |
| 44 | + m_Methods = new IAmbientOcclusionMethod[] { scalableAO, multiScaleVO }; |
51 | 45 | }
|
52 | 46 |
|
53 |
| - internal DepthTextureMode GetCameraFlags() |
| 47 | + public bool IsEnabledAndSupported(PostProcessRenderContext context) |
54 | 48 | {
|
55 |
| - return DepthTextureMode.Depth | DepthTextureMode.DepthNormals; |
| 49 | + return enabled && Get().IsSupported(context); |
56 | 50 | }
|
57 | 51 |
|
58 |
| - internal bool IsAmbientOnly(PostProcessRenderContext context) |
| 52 | + public bool IsAmbientOnly(PostProcessRenderContext context) |
59 | 53 | {
|
60 | 54 | var camera = context.camera;
|
61 | 55 | return ambientOnly
|
62 | 56 | && camera.actualRenderingPath == RenderingPath.DeferredShading
|
63 | 57 | && camera.allowHDR;
|
64 | 58 | }
|
65 | 59 |
|
66 |
| - internal bool IsEnabledAndSupported(PostProcessRenderContext context) |
67 |
| - { |
68 |
| - return enabled |
69 |
| - && intensity > 0f |
70 |
| - && !RuntimeUtilities.scriptableRenderPipelineActive; |
71 |
| - } |
72 |
| - |
73 |
| - PropertySheet PreRender(PostProcessRenderContext context, int occlusionSource) |
74 |
| - { |
75 |
| - radius = Mathf.Max(radius, 1e-4f); |
76 |
| - var cmd = context.command; |
77 |
| - |
78 |
| - // Material setup |
79 |
| - // Always use a quater-res AO buffer unless High/Ultra quality is set. |
80 |
| - bool downsampling = (int)quality < (int)Quality.High; |
81 |
| - float px = intensity; |
82 |
| - float py = radius; |
83 |
| - float pz = downsampling ? 0.5f : 1f; |
84 |
| - float pw = m_SampleCount[(int)quality]; |
85 |
| - |
86 |
| - var sheet = context.propertySheets.Get(context.resources.shaders.ambientOcclusion); |
87 |
| - sheet.ClearKeywords(); |
88 |
| - sheet.properties.SetVector(ShaderIDs.AOParams, new Vector4(px, py, pz, pw)); |
89 |
| - |
90 |
| - // In forward fog is applied at the object level in the grometry pass so we need to |
91 |
| - // apply it to AO as well or it'll drawn on top of the fog effect. |
92 |
| - // Not needed in Deferred. |
93 |
| - if (context.camera.actualRenderingPath == RenderingPath.Forward && RenderSettings.fog) |
94 |
| - { |
95 |
| - sheet.properties.SetVector(ShaderIDs.FogParams, new Vector3(RenderSettings.fogDensity, RenderSettings.fogStartDistance, RenderSettings.fogEndDistance)); |
96 |
| - |
97 |
| - switch (RenderSettings.fogMode) |
98 |
| - { |
99 |
| - case FogMode.Linear: |
100 |
| - sheet.EnableKeyword("FOG_LINEAR"); |
101 |
| - break; |
102 |
| - case FogMode.Exponential: |
103 |
| - sheet.EnableKeyword("FOG_EXP"); |
104 |
| - break; |
105 |
| - case FogMode.ExponentialSquared: |
106 |
| - sheet.EnableKeyword("FOG_EXP2"); |
107 |
| - break; |
108 |
| - } |
109 |
| - } |
110 |
| - |
111 |
| - // Texture setup |
112 |
| - int tw = context.width; |
113 |
| - int th = context.height; |
114 |
| - int ts = downsampling ? 2 : 1; |
115 |
| - const RenderTextureFormat kFormat = RenderTextureFormat.ARGB32; |
116 |
| - const RenderTextureReadWrite kRWMode = RenderTextureReadWrite.Linear; |
117 |
| - const FilterMode kFilter = FilterMode.Bilinear; |
118 |
| - |
119 |
| - // AO buffer |
120 |
| - var rtMask = ShaderIDs.OcclusionTexture1; |
121 |
| - cmd.GetTemporaryRT(rtMask, tw / ts, th / ts, 0, kFilter, kFormat, kRWMode); |
122 |
| - |
123 |
| - // AO estimation |
124 |
| - cmd.BlitFullscreenTriangle(BuiltinRenderTextureType.None, rtMask, sheet, (int)Pass.OcclusionEstimationForward + occlusionSource); |
125 |
| - |
126 |
| - // Blur buffer |
127 |
| - var rtBlur = ShaderIDs.OcclusionTexture2; |
128 |
| - |
129 |
| - // Separable blur (horizontal pass) |
130 |
| - cmd.GetTemporaryRT(rtBlur, tw, th, 0, kFilter, kFormat, kRWMode); |
131 |
| - cmd.BlitFullscreenTriangle(rtMask, rtBlur, sheet, (int)Pass.HorizontalBlurForward + occlusionSource); |
132 |
| - cmd.ReleaseTemporaryRT(rtMask); |
133 |
| - |
134 |
| - // Separable blur (vertical pass) |
135 |
| - rtMask = ShaderIDs.OcclusionTexture; |
136 |
| - cmd.GetTemporaryRT(rtMask, tw, th, 0, kFilter, kFormat, kRWMode); |
137 |
| - cmd.BlitFullscreenTriangle(rtBlur, rtMask, sheet, (int)Pass.VerticalBlur); |
138 |
| - cmd.ReleaseTemporaryRT(rtBlur); |
139 |
| - |
140 |
| - return sheet; |
141 |
| - } |
142 |
| - |
143 |
| - internal void RenderAfterOpaque(PostProcessRenderContext context) |
| 60 | + public IAmbientOcclusionMethod Get() |
144 | 61 | {
|
145 |
| - var cmd = context.command; |
146 |
| - cmd.BeginSample("Ambient Occlusion"); |
147 |
| - var sheet = PreRender(context, 0); // Forward |
148 |
| - cmd.BlitFullscreenTriangle(context.source, context.destination, sheet, (int)Pass.CompositionForward); |
149 |
| - cmd.EndSample("Ambient Occlusion"); |
| 62 | + return m_Methods[(int)mode]; |
150 | 63 | }
|
151 | 64 |
|
152 |
| - internal void RenderAmbientOnly(PostProcessRenderContext context) |
| 65 | + public void Release() |
153 | 66 | {
|
154 |
| - var cmd = context.command; |
155 |
| - cmd.BeginSample("Ambient Occlusion"); |
156 |
| - var sheet = PreRender(context, 1); // Deferred |
157 |
| - cmd.BlitFullscreenTriangle(BuiltinRenderTextureType.None, m_MRT, BuiltinRenderTextureType.CameraTarget, sheet, (int)Pass.CompositionDeferred); |
158 |
| - cmd.EndSample("Ambient Occlusion"); |
| 67 | + foreach (var m in m_Methods) |
| 68 | + m.Release(); |
159 | 69 | }
|
160 | 70 | }
|
161 | 71 | }
|
0 commit comments