Files
2026-11-01 23:39:55 +02:00

145 lines
8.1 KiB
C#

using System;
using UnityEngine.Rendering.RenderGraphModule;
namespace UnityEngine.Rendering.Universal
{
// Alchemy Ambient Occlusion (AAO) Pass - Standard SSAO mode using raster shaders.
internal class AAOPass : ScriptableRenderPass, IDisposable
{
private readonly bool m_SupportsR8RenderTextureFormat = SystemInfo.SupportsRenderTextureFormat(RenderTextureFormat.R8);
private int m_BlueNoiseTextureIndex = 0;
private Material m_Material;
private Texture2D[] m_BlueNoiseTextures;
private SSAOUtils.CameraViewData m_CameraViewData = SSAOUtils.CameraViewData.Create();
private SSAOUtils.BlurTypes m_BlurType = SSAOUtils.BlurTypes.Bilateral;
private ProfilingSampler m_ProfilingSampler = URPProfilingSamplers.SSAO;
private ScreenSpaceAmbientOcclusionSettings m_CurrentSettings;
private SSAOUtils.SSAOMaterialParams m_SSAOParamsPrev = new SSAOUtils.SSAOMaterialParams();
private bool m_WarnedMissingTextures;
internal AAOPass(Shader shader, Texture2D[] blueNoiseTextures)
{
m_CurrentSettings = new ScreenSpaceAmbientOcclusionSettings();
m_Material = CoreUtils.CreateEngineMaterial(shader);
Debug.Assert(m_Material != null, "AAOPass: Failed to create material from shader.");
m_BlueNoiseTextures = blueNoiseTextures;
}
// Sets up AAO pass using renderer feature settings. Returns false if the pass should be skipped.
internal bool Setup(ScreenSpaceAmbientOcclusionSettings featureSettings, ScreenSpaceAmbientOcclusionSettings.DepthSource depthSource)
{
m_CurrentSettings = featureSettings;
m_CurrentSettings.Source = depthSource;
#if MODERN_SSAO
m_CurrentSettings.Mode = ScreenSpaceAmbientOcclusionMode.Standard;
#endif
m_BlurType = SSAOUtils.GetBlurType(m_CurrentSettings.BlurQuality);
return m_CurrentSettings.Intensity > 0.0f
&& m_CurrentSettings.Radius > 0.0f
&& m_CurrentSettings.Falloff > 0.0f;
}
#if MODERN_SSAO
// Sets up AAO pass using active volume for Standard mode. Returns false if the pass should be skipped.
internal bool Setup(ScreenSpaceAmbientOcclusionVolumeOverride ssaoVolume, bool usesDeferredLighting)
{
ApplyVolumeSettings(m_CurrentSettings, ssaoVolume, usesDeferredLighting);
m_BlurType = SSAOUtils.GetBlurType(m_CurrentSettings.BlurQuality);
return ssaoVolume.IsActive();
}
private static void ApplyVolumeSettings(ScreenSpaceAmbientOcclusionSettings settings, ScreenSpaceAmbientOcclusionVolumeOverride volume, bool usesDeferredLighting)
{
settings.Mode = ScreenSpaceAmbientOcclusionMode.Standard;
settings.Intensity = volume.intensity;
settings.Radius = volume.radius;
settings.DirectLightingStrength = volume.directLightingStrength;
settings.Falloff = volume.falloffDistance;
settings.Downsample = volume.downsample;
settings.AfterOpaque = volume.afterOpaque;
settings.AOMethod = volume.method == ScreenSpaceAmbientOcclusionNoiseMethod.BlueNoise ? ScreenSpaceAmbientOcclusionSettings.AOMethodOptions.BlueNoise : ScreenSpaceAmbientOcclusionSettings.AOMethodOptions.InterleavedGradient;
settings.Samples = volume.sampleCount switch
{
ScreenSpaceAmbientOcclusionSampleCount.Low => ScreenSpaceAmbientOcclusionSettings.AOSampleOption.Low,
ScreenSpaceAmbientOcclusionSampleCount.High => ScreenSpaceAmbientOcclusionSettings.AOSampleOption.High,
_ => ScreenSpaceAmbientOcclusionSettings.AOSampleOption.Medium
};
settings.Source = volume.depthSource == ScreenSpaceAmbientOcclusionDepthSource.Depth ? ScreenSpaceAmbientOcclusionSettings.DepthSource.Depth : ScreenSpaceAmbientOcclusionSettings.DepthSource.DepthNormals;
settings.NormalSamples = volume.normalQuality switch
{
ScreenSpaceAmbientOcclusionNormalQuality.Low => ScreenSpaceAmbientOcclusionSettings.NormalQuality.Low,
ScreenSpaceAmbientOcclusionNormalQuality.High => ScreenSpaceAmbientOcclusionSettings.NormalQuality.High,
_ => ScreenSpaceAmbientOcclusionSettings.NormalQuality.Medium
};
settings.BlurQuality = volume.blurQuality switch
{
ScreenSpaceAmbientOcclusionBlurQuality.Low => ScreenSpaceAmbientOcclusionSettings.BlurQualityOptions.Low,
ScreenSpaceAmbientOcclusionBlurQuality.High => ScreenSpaceAmbientOcclusionSettings.BlurQualityOptions.High,
_ => ScreenSpaceAmbientOcclusionSettings.BlurQualityOptions.Medium
};
// Force to use Depth + Normals textures if deferred rendering
if (usesDeferredLighting)
settings.Source = ScreenSpaceAmbientOcclusionSettings.DepthSource.DepthNormals;
}
#endif
public override void RecordRenderGraph(RenderGraph renderGraph, ContextContainer frameData)
{
UniversalCameraData cameraData = frameData.Get<UniversalCameraData>();
UniversalResourceData resourceData = frameData.Get<UniversalResourceData>();
TextureHandle cameraDepthTexture = resourceData.cameraDepthTexture;
TextureHandle cameraNormalsTexture = resourceData.cameraNormalsTexture;
if (!cameraDepthTexture.IsValid() || (m_CurrentSettings.Source == ScreenSpaceAmbientOcclusionSettings.DepthSource.DepthNormals && !cameraNormalsTexture.IsValid()))
{
if (Debug.isDebugBuild && !m_WarnedMissingTextures)
{
m_WarnedMissingTextures = true;
Debug.LogWarning("Screen Space Ambient Occlusion: skipped because the active renderer does not provide the required camera depth/normals textures.");
}
return;
}
if (Debug.isDebugBuild) // Saw valid textures: reset so a later renderer without them warns again.
m_WarnedMissingTextures = false;
// Builds a TextureDesc compatible with the active camera color target, safe for both intermediate render textures and imported back-buffer handles.
TextureDesc cameraColorDesc = SSAOUtils.GetCameraColorDescriptor(renderGraph, resourceData.activeColorTexture, cameraData.camera.allowDynamicResolution);
SSAOUtils.CreateRenderTextureHandles(renderGraph, resourceData, cameraColorDesc,
m_CurrentSettings, m_SupportsR8RenderTextureFormat, m_BlurType, enableRandomWrite: false,
out TextureHandle aoTexture, out TextureHandle blurTexture, out TextureHandle temporalTexture, out TextureHandle finalTexture);
SSAOUtils.SetupCameraViewMatrices(cameraData, ref m_CameraViewData);
m_BlueNoiseTextureIndex = SSAOUtils.AdvanceBlueNoiseIndex(m_CurrentSettings, m_BlueNoiseTextures, m_BlueNoiseTextureIndex);
SSAOUtils.SetupKeywordsAndParameters(m_Material, m_CurrentSettings, cameraData, cameraColorDesc, ref m_CameraViewData, m_BlueNoiseTextures, m_BlueNoiseTextureIndex, ref m_SSAOParamsPrev);
SSAOUtils.RecordRasterAOPass(renderGraph, m_ProfilingSampler, m_Material, m_CurrentSettings, aoTexture, cameraDepthTexture, cameraNormalsTexture, cameraColorDesc);
SSAOUtils.RecordBlurChain(renderGraph, m_ProfilingSampler, m_Material, m_CurrentSettings, cameraData, aoTexture, blurTexture, finalTexture);
if (!m_CurrentSettings.AfterOpaque)
SSAOUtils.RecordCleanupPass(renderGraph, m_ProfilingSampler, m_CurrentSettings.DirectLightingStrength, finalTexture);
}
public override void OnCameraCleanup(CommandBuffer cmd)
{
if (cmd == null)
throw new ArgumentNullException("cmd");
if (!m_CurrentSettings.AfterOpaque)
cmd.SetKeyword(ShaderGlobalKeywords.ScreenSpaceOcclusion, false);
}
public void Dispose()
{
CoreUtils.Destroy(m_Material);
m_Material = null;
m_SSAOParamsPrev = default;
}
}
}