3 namespace UnityEngine
.Rendering
.PostProcessing
5 // Scalable ambient obscurance
6 #if UNITY_2017_1_OR_NEWER
7 [UnityEngine
.Scripting
.Preserve
]
10 internal sealed class ScalableAO
: IAmbientOcclusionMethod
12 RenderTexture m_Result
;
13 PropertySheet m_PropertySheet
;
14 AmbientOcclusion m_Settings
;
16 readonly RenderTargetIdentifier
[] m_MRT
=
18 BuiltinRenderTextureType
.GBuffer0
, // Albedo, Occ
19 BuiltinRenderTextureType
.CameraTarget
// Ambient
22 readonly int[] m_SampleCount
= { 4, 6, 10, 8, 12 }
;
26 OcclusionEstimationForward
,
27 OcclusionEstimationDeferred
,
28 HorizontalBlurForward
,
29 HorizontalBlurDeferred
,
36 public ScalableAO(AmbientOcclusion settings
)
38 m_Settings
= settings
;
41 public DepthTextureMode
GetCameraFlags()
43 return DepthTextureMode
.Depth
| DepthTextureMode
.DepthNormals
;
46 void DoLazyInitialization(PostProcessRenderContext context
)
48 m_PropertySheet
= context
.propertySheets
.Get(context
.resources
.shaders
.scalableAO
);
52 if (m_Result
== null || !m_Result
.IsCreated())
55 m_Result
= context
.GetScreenSpaceTemporaryRT(0, RenderTextureFormat
.ARGB32
, RenderTextureReadWrite
.Linear
);
56 m_Result
.hideFlags
= HideFlags
.DontSave
;
57 m_Result
.filterMode
= FilterMode
.Bilinear
;
61 else if (m_Result
.width
!= context
.width
|| m_Result
.height
!= context
.height
)
63 // Release and reallocate
65 m_Result
.width
= context
.width
;
66 m_Result
.height
= context
.height
;
74 void Render(PostProcessRenderContext context
, CommandBuffer cmd
, int occlusionSource
)
76 DoLazyInitialization(context
);
77 m_Settings
.radius
.value = Mathf
.Max(m_Settings
.radius
.value, 1e-4f
);
80 // Always use a quater-res AO buffer unless High/Ultra quality is set.
81 bool downsampling
= (int)m_Settings
.quality
.value < (int)AmbientOcclusionQuality
.High
;
82 float px
= m_Settings
.intensity
.value;
83 float py
= m_Settings
.radius
.value;
84 float pz
= downsampling
? 0.5f
: 1f
;
85 float pw
= m_SampleCount
[(int)m_Settings
.quality
.value];
87 var sheet
= m_PropertySheet
;
88 sheet
.ClearKeywords();
89 sheet
.properties
.SetVector(ShaderIDs
.AOParams
, new Vector4(px
, py
, pz
, pw
));
90 sheet
.properties
.SetVector(ShaderIDs
.AOColor
, Color
.white
- m_Settings
.color
.value);
92 // In forward fog is applied at the object level in the grometry pass so we need to
93 // apply it to AO as well or it'll drawn on top of the fog effect.
94 // Not needed in Deferred.
95 if (context
.camera
.actualRenderingPath
== RenderingPath
.Forward
&& RenderSettings
.fog
)
97 sheet
.EnableKeyword("APPLY_FORWARD_FOG");
98 sheet
.properties
.SetVector(
100 new Vector3(RenderSettings
.fogDensity
, RenderSettings
.fogStartDistance
, RenderSettings
.fogEndDistance
)
105 int ts
= downsampling
? 2 : 1;
106 const RenderTextureFormat kFormat
= RenderTextureFormat
.ARGB32
;
107 const RenderTextureReadWrite kRWMode
= RenderTextureReadWrite
.Linear
;
108 const FilterMode kFilter
= FilterMode
.Bilinear
;
111 var rtMask
= ShaderIDs
.OcclusionTexture1
;
112 int scaledWidth
= context
.width
/ ts
;
113 int scaledHeight
= context
.height
/ ts
;
114 context
.GetScreenSpaceTemporaryRT(cmd
, rtMask
, 0, kFormat
, kRWMode
, kFilter
, scaledWidth
, scaledHeight
);
117 cmd
.BlitFullscreenTriangle(BuiltinRenderTextureType
.None
, rtMask
, sheet
, (int)Pass
.OcclusionEstimationForward
+ occlusionSource
);
120 var rtBlur
= ShaderIDs
.OcclusionTexture2
;
121 context
.GetScreenSpaceTemporaryRT(cmd
, rtBlur
, 0, kFormat
, kRWMode
, kFilter
);
123 // Separable blur (horizontal pass)
124 cmd
.BlitFullscreenTriangle(rtMask
, rtBlur
, sheet
, (int)Pass
.HorizontalBlurForward
+ occlusionSource
);
125 cmd
.ReleaseTemporaryRT(rtMask
);
127 // Separable blur (vertical pass)
128 cmd
.BlitFullscreenTriangle(rtBlur
, m_Result
, sheet
, (int)Pass
.VerticalBlur
);
129 cmd
.ReleaseTemporaryRT(rtBlur
);
131 if (context
.IsDebugOverlayEnabled(DebugOverlay
.AmbientOcclusion
))
132 context
.PushDebugOverlay(cmd
, m_Result
, sheet
, (int)Pass
.DebugOverlay
);
135 public void RenderAfterOpaque(PostProcessRenderContext context
)
137 var cmd
= context
.command
;
138 cmd
.BeginSample("Ambient Occlusion");
139 Render(context
, cmd
, 0);
140 cmd
.SetGlobalTexture(ShaderIDs
.SAOcclusionTexture
, m_Result
);
141 cmd
.BlitFullscreenTriangle(BuiltinRenderTextureType
.None
, BuiltinRenderTextureType
.CameraTarget
, m_PropertySheet
, (int)Pass
.CompositionForward
, RenderBufferLoadAction
.Load
);
142 cmd
.EndSample("Ambient Occlusion");
145 public void RenderAmbientOnly(PostProcessRenderContext context
)
147 var cmd
= context
.command
;
148 cmd
.BeginSample("Ambient Occlusion Render");
149 Render(context
, cmd
, 1);
150 cmd
.EndSample("Ambient Occlusion Render");
153 public void CompositeAmbientOnly(PostProcessRenderContext context
)
155 var cmd
= context
.command
;
156 cmd
.BeginSample("Ambient Occlusion Composite");
157 cmd
.SetGlobalTexture(ShaderIDs
.SAOcclusionTexture
, m_Result
);
158 cmd
.BlitFullscreenTriangle(BuiltinRenderTextureType
.None
, m_MRT
, BuiltinRenderTextureType
.CameraTarget
, m_PropertySheet
, (int)Pass
.CompositionDeferred
);
159 cmd
.EndSample("Ambient Occlusion Composite");
162 public void Release()
164 RuntimeUtilities
.Destroy(m_Result
);