123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650 |
- using System;
- using UnityEngine.Rendering.RenderGraphModule;
-
- namespace UnityEngine.Rendering.Universal
- {
- // The Screen Space Ambient Occlusion (SSAO) Pass
- internal class ScreenSpaceAmbientOcclusionPass : ScriptableRenderPass
- {
- // Properties
- private bool isRendererDeferred => m_Renderer != null
- && m_Renderer is UniversalRenderer
- && ((UniversalRenderer)m_Renderer).renderingModeActual == RenderingMode.Deferred;
-
- // Private Variables
- private readonly bool m_SupportsR8RenderTextureFormat = SystemInfo.SupportsRenderTextureFormat(RenderTextureFormat.R8);
- private int m_BlueNoiseTextureIndex = 0;
- private Material m_Material;
- private SSAOPassData m_PassData;
- private Texture2D[] m_BlueNoiseTextures;
- private Vector4[] m_CameraTopLeftCorner = new Vector4[2];
- private Vector4[] m_CameraXExtent = new Vector4[2];
- private Vector4[] m_CameraYExtent = new Vector4[2];
- private Vector4[] m_CameraZExtent = new Vector4[2];
- private RTHandle[] m_SSAOTextures = new RTHandle[4];
- private BlurTypes m_BlurType = BlurTypes.Bilateral;
- private Matrix4x4[] m_CameraViewProjections = new Matrix4x4[2];
- private ProfilingSampler m_ProfilingSampler = ProfilingSampler.Get(URPProfileId.SSAO);
- private ScriptableRenderer m_Renderer = null;
- private RenderTextureDescriptor m_AOPassDescriptor;
- private ScreenSpaceAmbientOcclusionSettings m_CurrentSettings;
-
- // Constants
- private const string k_SSAOTextureName = "_ScreenSpaceOcclusionTexture";
- private const string k_AmbientOcclusionParamName = "_AmbientOcclusionParam";
-
- // Statics
- internal static readonly int s_AmbientOcclusionParamID = Shader.PropertyToID(k_AmbientOcclusionParamName);
- private static readonly int s_SSAOParamsID = Shader.PropertyToID("_SSAOParams");
- private static readonly int s_SSAOBlueNoiseParamsID = Shader.PropertyToID("_SSAOBlueNoiseParams");
- private static readonly int s_BlueNoiseTextureID = Shader.PropertyToID("_BlueNoiseTexture");
- private static readonly int s_SSAOFinalTextureID = Shader.PropertyToID(k_SSAOTextureName);
- private static readonly int s_CameraViewXExtentID = Shader.PropertyToID("_CameraViewXExtent");
- private static readonly int s_CameraViewYExtentID = Shader.PropertyToID("_CameraViewYExtent");
- private static readonly int s_CameraViewZExtentID = Shader.PropertyToID("_CameraViewZExtent");
- private static readonly int s_ProjectionParams2ID = Shader.PropertyToID("_ProjectionParams2");
- private static readonly int s_CameraViewProjectionsID = Shader.PropertyToID("_CameraViewProjections");
- private static readonly int s_CameraViewTopLeftCornerID = Shader.PropertyToID("_CameraViewTopLeftCorner");
- private static readonly int s_CameraDepthTextureID = Shader.PropertyToID("_CameraDepthTexture");
- private static readonly int s_CameraNormalsTextureID = Shader.PropertyToID("_CameraNormalsTexture");
-
- private static readonly int[] m_BilateralTexturesIndices = { 0, 1, 2, 3 };
- private static readonly ShaderPasses[] m_BilateralPasses = { ShaderPasses.BilateralBlurHorizontal, ShaderPasses.BilateralBlurVertical, ShaderPasses.BilateralBlurFinal };
- private static readonly ShaderPasses[] m_BilateralAfterOpaquePasses = { ShaderPasses.BilateralBlurHorizontal, ShaderPasses.BilateralBlurVertical, ShaderPasses.BilateralAfterOpaque };
-
- private static readonly int[] m_GaussianTexturesIndices = { 0, 1, 3, 3 };
- private static readonly ShaderPasses[] m_GaussianPasses = { ShaderPasses.GaussianBlurHorizontal, ShaderPasses.GaussianBlurVertical };
- private static readonly ShaderPasses[] m_GaussianAfterOpaquePasses = { ShaderPasses.GaussianBlurHorizontal, ShaderPasses.GaussianAfterOpaque };
-
- private static readonly int[] m_KawaseTexturesIndices = { 0, 3 };
- private static readonly ShaderPasses[] m_KawasePasses = { ShaderPasses.KawaseBlur };
- private static readonly ShaderPasses[] m_KawaseAfterOpaquePasses = { ShaderPasses.KawaseAfterOpaque };
-
- // Enums
- private enum BlurTypes
- {
- Bilateral,
- Gaussian,
- Kawase,
- }
-
- private enum ShaderPasses
- {
- AmbientOcclusion = 0,
-
- BilateralBlurHorizontal = 1,
- BilateralBlurVertical = 2,
- BilateralBlurFinal = 3,
- BilateralAfterOpaque = 4,
-
- GaussianBlurHorizontal = 5,
- GaussianBlurVertical = 6,
- GaussianAfterOpaque = 7,
-
- KawaseBlur = 8,
- KawaseAfterOpaque = 9,
- }
-
- // Structs
- private struct SSAOMaterialParams
- {
- internal bool orthographicCamera;
- internal bool aoBlueNoise;
- internal bool aoInterleavedGradient;
- internal bool sampleCountHigh;
- internal bool sampleCountMedium;
- internal bool sampleCountLow;
- internal bool sourceDepthNormals;
- internal bool sourceDepthHigh;
- internal bool sourceDepthMedium;
- internal bool sourceDepthLow;
- internal Vector4 ssaoParams;
-
- internal SSAOMaterialParams(ref ScreenSpaceAmbientOcclusionSettings settings, bool isOrthographic)
- {
- bool isUsingDepthNormals = settings.Source == ScreenSpaceAmbientOcclusionSettings.DepthSource.DepthNormals;
- float radiusMultiplier = settings.AOMethod == ScreenSpaceAmbientOcclusionSettings.AOMethodOptions.BlueNoise ? 1.5f : 1;
- orthographicCamera = isOrthographic;
- aoBlueNoise = settings.AOMethod == ScreenSpaceAmbientOcclusionSettings.AOMethodOptions.BlueNoise;
- aoInterleavedGradient = settings.AOMethod == ScreenSpaceAmbientOcclusionSettings.AOMethodOptions.InterleavedGradient;
- sampleCountHigh = settings.Samples == ScreenSpaceAmbientOcclusionSettings.AOSampleOption.High;
- sampleCountMedium = settings.Samples == ScreenSpaceAmbientOcclusionSettings.AOSampleOption.Medium;
- sampleCountLow = settings.Samples == ScreenSpaceAmbientOcclusionSettings.AOSampleOption.Low;
- sourceDepthNormals = settings.Source == ScreenSpaceAmbientOcclusionSettings.DepthSource.DepthNormals;
- sourceDepthHigh = !isUsingDepthNormals && settings.NormalSamples == ScreenSpaceAmbientOcclusionSettings.NormalQuality.High;
- sourceDepthMedium = !isUsingDepthNormals && settings.NormalSamples == ScreenSpaceAmbientOcclusionSettings.NormalQuality.Medium;
- sourceDepthLow = !isUsingDepthNormals && settings.NormalSamples == ScreenSpaceAmbientOcclusionSettings.NormalQuality.Low;
- ssaoParams = new Vector4(
- settings.Intensity, // Intensity
- settings.Radius * radiusMultiplier, // Radius
- 1.0f / (settings.Downsample ? 2 : 1), // Downsampling
- settings.Falloff // Falloff
- );
- }
-
- internal bool Equals(ref SSAOMaterialParams other)
- {
- return orthographicCamera == other.orthographicCamera
- && aoBlueNoise == other.aoBlueNoise
- && aoInterleavedGradient == other.aoInterleavedGradient
- && sampleCountHigh == other.sampleCountHigh
- && sampleCountMedium == other.sampleCountMedium
- && sampleCountLow == other.sampleCountLow
- && sourceDepthNormals == other.sourceDepthNormals
- && sourceDepthHigh == other.sourceDepthHigh
- && sourceDepthMedium == other.sourceDepthMedium
- && sourceDepthLow == other.sourceDepthLow
- && ssaoParams == other.ssaoParams
- ;
- }
- }
- private SSAOMaterialParams m_SSAOParamsPrev = new SSAOMaterialParams();
-
- internal ScreenSpaceAmbientOcclusionPass()
- {
- m_CurrentSettings = new ScreenSpaceAmbientOcclusionSettings();
- m_PassData = new SSAOPassData();
- }
-
- internal bool Setup(ref ScreenSpaceAmbientOcclusionSettings featureSettings, ref ScriptableRenderer renderer, ref Material material, ref Texture2D[] blueNoiseTextures)
- {
- m_BlueNoiseTextures = blueNoiseTextures;
- m_Material = material;
- m_Renderer = renderer;
- m_CurrentSettings = featureSettings;
-
- // RenderPass Event + Source Settings (Depth / Depth&Normals
- if (isRendererDeferred)
- {
- renderPassEvent = m_CurrentSettings.AfterOpaque ? RenderPassEvent.AfterRenderingOpaques : RenderPassEvent.AfterRenderingGbuffer;
-
- if (renderPassEvent == RenderPassEvent.AfterRenderingGbuffer)
- breakGBufferAndDeferredRenderPass = true;
-
- m_CurrentSettings.Source = ScreenSpaceAmbientOcclusionSettings.DepthSource.DepthNormals;
- }
- else
- {
- // Rendering after PrePasses is usually correct except when depth priming is in play:
- // then we rely on a depth resolve taking place after the PrePasses in order to have it ready for SSAO.
- // Hence we set the event to RenderPassEvent.AfterRenderingPrePasses + 1 at the earliest.
- renderPassEvent = m_CurrentSettings.AfterOpaque ? RenderPassEvent.BeforeRenderingTransparents : RenderPassEvent.AfterRenderingPrePasses + 1;
- }
-
- // Ask for a Depth or Depth + Normals textures
- switch (m_CurrentSettings.Source)
- {
- case ScreenSpaceAmbientOcclusionSettings.DepthSource.Depth:
- ConfigureInput(ScriptableRenderPassInput.Depth);
- break;
- case ScreenSpaceAmbientOcclusionSettings.DepthSource.DepthNormals:
- ConfigureInput(ScriptableRenderPassInput.Normal); // need depthNormal prepass for forward-only geometry
- break;
- default:
- throw new ArgumentOutOfRangeException();
- }
-
- // Blur settings
- switch (m_CurrentSettings.BlurQuality)
- {
- case ScreenSpaceAmbientOcclusionSettings.BlurQualityOptions.High:
- m_BlurType = BlurTypes.Bilateral;
- break;
- case ScreenSpaceAmbientOcclusionSettings.BlurQualityOptions.Medium:
- m_BlurType = BlurTypes.Gaussian;
- break;
- case ScreenSpaceAmbientOcclusionSettings.BlurQualityOptions.Low:
- m_BlurType = BlurTypes.Kawase;
- break;
- default:
- throw new ArgumentOutOfRangeException();
- }
-
- return m_Material != null
- && m_CurrentSettings.Intensity > 0.0f
- && m_CurrentSettings.Radius > 0.0f
- && m_CurrentSettings.Falloff > 0.0f;
- }
-
- private static bool IsAfterOpaquePass(ref ShaderPasses pass)
- {
- return pass == ShaderPasses.BilateralAfterOpaque
- || pass == ShaderPasses.GaussianAfterOpaque
- || pass == ShaderPasses.KawaseAfterOpaque;
- }
-
- private void SetupKeywordsAndParameters(ref ScreenSpaceAmbientOcclusionSettings settings, ref UniversalCameraData cameraData)
- {
- #if ENABLE_VR && ENABLE_XR_MODULE
- int eyeCount = cameraData.xr.enabled && cameraData.xr.singlePassEnabled ? 2 : 1;
- #else
- int eyeCount = 1;
- #endif
-
- for (int eyeIndex = 0; eyeIndex < eyeCount; eyeIndex++)
- {
- Matrix4x4 view = cameraData.GetViewMatrix(eyeIndex);
- Matrix4x4 proj = cameraData.GetProjectionMatrix(eyeIndex);
- m_CameraViewProjections[eyeIndex] = proj * view;
-
- // camera view space without translation, used by SSAO.hlsl ReconstructViewPos() to calculate view vector.
- Matrix4x4 cview = view;
- cview.SetColumn(3, new Vector4(0.0f, 0.0f, 0.0f, 1.0f));
- Matrix4x4 cviewProj = proj * cview;
- Matrix4x4 cviewProjInv = cviewProj.inverse;
-
- Vector4 topLeftCorner = cviewProjInv.MultiplyPoint(new Vector4(-1, 1, -1, 1));
- Vector4 topRightCorner = cviewProjInv.MultiplyPoint(new Vector4(1, 1, -1, 1));
- Vector4 bottomLeftCorner = cviewProjInv.MultiplyPoint(new Vector4(-1, -1, -1, 1));
- Vector4 farCentre = cviewProjInv.MultiplyPoint(new Vector4(0, 0, 1, 1));
- m_CameraTopLeftCorner[eyeIndex] = topLeftCorner;
- m_CameraXExtent[eyeIndex] = topRightCorner - topLeftCorner;
- m_CameraYExtent[eyeIndex] = bottomLeftCorner - topLeftCorner;
- m_CameraZExtent[eyeIndex] = farCentre;
- }
-
- m_Material.SetVector(s_ProjectionParams2ID, new Vector4(1.0f / cameraData.camera.nearClipPlane, 0.0f, 0.0f, 0.0f));
- m_Material.SetMatrixArray(s_CameraViewProjectionsID, m_CameraViewProjections);
- m_Material.SetVectorArray(s_CameraViewTopLeftCornerID, m_CameraTopLeftCorner);
- m_Material.SetVectorArray(s_CameraViewXExtentID, m_CameraXExtent);
- m_Material.SetVectorArray(s_CameraViewYExtentID, m_CameraYExtent);
- m_Material.SetVectorArray(s_CameraViewZExtentID, m_CameraZExtent);
-
- if (settings.AOMethod == ScreenSpaceAmbientOcclusionSettings.AOMethodOptions.BlueNoise)
- {
- m_BlueNoiseTextureIndex = (m_BlueNoiseTextureIndex + 1) % m_BlueNoiseTextures.Length;
- Texture2D noiseTexture = m_BlueNoiseTextures[m_BlueNoiseTextureIndex];
- Vector4 blueNoiseParams = new Vector4(
- cameraData.pixelWidth / (float)m_BlueNoiseTextures[m_BlueNoiseTextureIndex].width, // X Scale
- cameraData.pixelHeight / (float)m_BlueNoiseTextures[m_BlueNoiseTextureIndex].height, // Y Scale
- Random.value, // X Offset
- Random.value // Y Offset
- );
-
- // For testing we use a single blue noise texture and a single set of blue noise params.
- #if UNITY_INCLUDE_TESTS
- noiseTexture = m_BlueNoiseTextures[0];
- blueNoiseParams.z = 1;
- blueNoiseParams.w = 1;
- #endif
-
- m_Material.SetTexture(s_BlueNoiseTextureID, noiseTexture);
- m_Material.SetVector(s_SSAOBlueNoiseParamsID, blueNoiseParams);
- }
-
- // Setting keywords can be somewhat expensive on low-end platforms.
- // Previous params are cached to avoid setting the same keywords every frame.
- SSAOMaterialParams matParams = new SSAOMaterialParams(ref settings, cameraData.camera.orthographic);
- bool ssaoParamsDirty = !m_SSAOParamsPrev.Equals(ref matParams); // Checks if the parameters have changed.
- bool isParamsPropertySet = m_Material.HasProperty(s_SSAOParamsID); // Checks if the parameters have been set on the material.
- if (!ssaoParamsDirty && isParamsPropertySet)
- return;
-
- m_SSAOParamsPrev = matParams;
- CoreUtils.SetKeyword(m_Material, ScreenSpaceAmbientOcclusion.k_OrthographicCameraKeyword, matParams.orthographicCamera);
- CoreUtils.SetKeyword(m_Material, ScreenSpaceAmbientOcclusion.k_AOBlueNoiseKeyword, matParams.aoBlueNoise);
- CoreUtils.SetKeyword(m_Material, ScreenSpaceAmbientOcclusion.k_AOInterleavedGradientKeyword, matParams.aoInterleavedGradient);
- CoreUtils.SetKeyword(m_Material, ScreenSpaceAmbientOcclusion.k_SampleCountHighKeyword, matParams.sampleCountHigh);
- CoreUtils.SetKeyword(m_Material, ScreenSpaceAmbientOcclusion.k_SampleCountMediumKeyword, matParams.sampleCountMedium);
- CoreUtils.SetKeyword(m_Material, ScreenSpaceAmbientOcclusion.k_SampleCountLowKeyword, matParams.sampleCountLow);
- CoreUtils.SetKeyword(m_Material, ScreenSpaceAmbientOcclusion.k_SourceDepthNormalsKeyword, matParams.sourceDepthNormals);
- CoreUtils.SetKeyword(m_Material, ScreenSpaceAmbientOcclusion.k_SourceDepthHighKeyword, matParams.sourceDepthHigh);
- CoreUtils.SetKeyword(m_Material, ScreenSpaceAmbientOcclusion.k_SourceDepthMediumKeyword, matParams.sourceDepthMedium);
- CoreUtils.SetKeyword(m_Material, ScreenSpaceAmbientOcclusion.k_SourceDepthLowKeyword, matParams.sourceDepthLow);
- m_Material.SetVector(s_SSAOParamsID, matParams.ssaoParams);
- }
-
- /*----------------------------------------------------------------------------------------------------------------------------------------
- ------------------------------------------------------------- RENDER-GRAPH --------------------------------------------------------------
- ----------------------------------------------------------------------------------------------------------------------------------------*/
-
- private class SSAOPassData
- {
- internal bool afterOpaque;
- internal ScreenSpaceAmbientOcclusionSettings.BlurQualityOptions BlurQuality;
- internal Material material;
- internal float directLightingStrength;
- internal TextureHandle cameraColor;
- internal TextureHandle AOTexture;
- internal TextureHandle finalTexture;
- internal TextureHandle blurTexture;
- internal TextureHandle cameraDepthTexture;
- internal TextureHandle cameraNormalsTexture;
- }
-
- private void InitSSAOPassData(ref SSAOPassData data)
- {
- data.material = m_Material;
- data.BlurQuality = m_CurrentSettings.BlurQuality;
- data.afterOpaque = m_CurrentSettings.AfterOpaque;
- data.directLightingStrength = m_CurrentSettings.DirectLightingStrength;
- }
-
- public override void RecordRenderGraph(RenderGraph renderGraph, ContextContainer frameData)
- {
- UniversalCameraData cameraData = frameData.Get<UniversalCameraData>();
- UniversalResourceData resourceData = frameData.Get<UniversalResourceData>();
-
- // Create the texture handles...
- CreateRenderTextureHandles(renderGraph,
- resourceData,
- cameraData,
- out TextureHandle aoTexture,
- out TextureHandle blurTexture,
- out TextureHandle finalTexture);
-
- // Get the resources
- UniversalRenderer universalRenderer = cameraData.renderer as UniversalRenderer;
- bool isDeferred = universalRenderer != null && universalRenderer.renderingModeActual == RenderingMode.Deferred;
- TextureHandle cameraDepthTexture = isDeferred ? resourceData.activeDepthTexture : resourceData.cameraDepthTexture;
- TextureHandle cameraNormalsTexture = resourceData.cameraNormalsTexture;
-
- // Update keywords and other shader params
- SetupKeywordsAndParameters(ref m_CurrentSettings, ref cameraData);
-
- using (IUnsafeRenderGraphBuilder builder = renderGraph.AddUnsafePass<SSAOPassData>("Blit SSAO", out var passData, m_ProfilingSampler))
- {
- // Shader keyword changes are considered as global state modifications
- builder.AllowGlobalStateModification(true);
- builder.AllowPassCulling(false);
-
- // Fill in the Pass data...
- InitSSAOPassData(ref passData);
- passData.cameraColor = resourceData.cameraColor;
- passData.AOTexture = aoTexture;
- passData.finalTexture = finalTexture;
- passData.blurTexture = blurTexture;
- passData.cameraDepthTexture = isDeferred ? cameraDepthTexture : TextureHandle.nullHandle;
-
- // Declare input textures
- builder.UseTexture(passData.AOTexture, AccessFlags.ReadWrite);
-
- if (passData.BlurQuality != ScreenSpaceAmbientOcclusionSettings.BlurQualityOptions.Low)
- builder.UseTexture(passData.blurTexture, AccessFlags.ReadWrite);
-
- if (cameraDepthTexture.IsValid())
- builder.UseTexture(cameraDepthTexture, AccessFlags.Read);
-
- if (m_CurrentSettings.Source == ScreenSpaceAmbientOcclusionSettings.DepthSource.DepthNormals && cameraNormalsTexture.IsValid())
- {
- builder.UseTexture(cameraNormalsTexture, AccessFlags.Read);
- passData.cameraNormalsTexture = cameraNormalsTexture;
- }
-
- // The global SSAO texture only needs to be set if After Opaque is disabled...
- if (!passData.afterOpaque && finalTexture.IsValid())
- {
- builder.UseTexture(passData.finalTexture, AccessFlags.ReadWrite);
- builder.SetGlobalTextureAfterPass(finalTexture, s_SSAOFinalTextureID);
- }
-
- builder.SetRenderFunc((SSAOPassData data, UnsafeGraphContext rgContext) =>
- {
- if (data.cameraDepthTexture.IsValid())
- data.material.SetTexture(s_CameraDepthTextureID, data.cameraDepthTexture);
-
- CommandBuffer cmd = CommandBufferHelpers.GetNativeCommandBuffer(rgContext.cmd);
- RenderBufferLoadAction finalLoadAction = data.afterOpaque ? RenderBufferLoadAction.Load : RenderBufferLoadAction.DontCare;
-
- // Setup
- if (data.cameraColor.IsValid())
- PostProcessUtils.SetSourceSize(cmd, data.cameraColor);
-
- if (data.cameraDepthTexture.IsValid())
- data.material.SetTexture(s_CameraDepthTextureID, data.cameraDepthTexture);
-
- if (data.cameraNormalsTexture.IsValid())
- data.material.SetTexture(s_CameraNormalsTextureID, data.cameraNormalsTexture);
-
- // AO Pass
- Blitter.BlitCameraTexture(cmd, data.AOTexture, data.AOTexture, RenderBufferLoadAction.DontCare, RenderBufferStoreAction.Store, data.material, (int) ShaderPasses.AmbientOcclusion);
-
- // Blur passes
- switch (data.BlurQuality)
- {
- // Bilateral
- case ScreenSpaceAmbientOcclusionSettings.BlurQualityOptions.High:
- Blitter.BlitCameraTexture(cmd, data.AOTexture, data.blurTexture, RenderBufferLoadAction.DontCare, RenderBufferStoreAction.Store, data.material, (int) ShaderPasses.BilateralBlurHorizontal);
- Blitter.BlitCameraTexture(cmd, data.blurTexture, data.AOTexture, RenderBufferLoadAction.DontCare, RenderBufferStoreAction.Store, data.material, (int) ShaderPasses.BilateralBlurVertical);
- Blitter.BlitCameraTexture(cmd, data.AOTexture, data.finalTexture, finalLoadAction, RenderBufferStoreAction.Store, data.material, (int) (data.afterOpaque ? ShaderPasses.BilateralAfterOpaque : ShaderPasses.BilateralBlurFinal));
- break;
-
- // Gaussian
- case ScreenSpaceAmbientOcclusionSettings.BlurQualityOptions.Medium:
- Blitter.BlitCameraTexture(cmd, data.AOTexture, data.blurTexture, RenderBufferLoadAction.Load, RenderBufferStoreAction.Store, data.material, (int) ShaderPasses.GaussianBlurHorizontal);
- Blitter.BlitCameraTexture(cmd, data.blurTexture, data.finalTexture, finalLoadAction, RenderBufferStoreAction.Store, data.material, (int) (data.afterOpaque ? ShaderPasses.GaussianAfterOpaque : ShaderPasses.GaussianBlurVertical));
- break;
-
- // Kawase
- case ScreenSpaceAmbientOcclusionSettings.BlurQualityOptions.Low:
- Blitter.BlitCameraTexture(cmd, data.AOTexture, data.finalTexture, finalLoadAction, RenderBufferStoreAction.Store, data.material, (int) (data.afterOpaque ? ShaderPasses.KawaseAfterOpaque : ShaderPasses.KawaseBlur));
- break;
-
- default:
- throw new ArgumentOutOfRangeException();
- }
-
- // We only want URP shaders to sample SSAO if After Opaque is disabled...
- if (!data.afterOpaque)
- {
- rgContext.cmd.SetKeyword(ShaderGlobalKeywords.ScreenSpaceOcclusion, true);
- rgContext.cmd.SetGlobalVector(s_AmbientOcclusionParamID, new Vector4(1f, 0f, 0f, data.directLightingStrength));
- }
- });
- }
- }
-
- private void CreateRenderTextureHandles(RenderGraph renderGraph, UniversalResourceData resourceData,
- UniversalCameraData cameraData, out TextureHandle aoTexture, out TextureHandle blurTexture, out TextureHandle finalTexture)
- {
- // Descriptor for the final blur pass
- RenderTextureDescriptor finalTextureDescriptor = cameraData.cameraTargetDescriptor;
- finalTextureDescriptor.colorFormat = m_SupportsR8RenderTextureFormat ? RenderTextureFormat.R8 : RenderTextureFormat.ARGB32;
- finalTextureDescriptor.depthBufferBits = 0;
- finalTextureDescriptor.msaaSamples = 1;
-
- // Descriptor for the AO and Blur passes
- int downsampleDivider = m_CurrentSettings.Downsample ? 2 : 1;
- bool useRedComponentOnly = m_SupportsR8RenderTextureFormat && m_BlurType > BlurTypes.Bilateral;
-
- RenderTextureDescriptor aoBlurDescriptor = finalTextureDescriptor;
- aoBlurDescriptor.colorFormat = useRedComponentOnly ? RenderTextureFormat.R8 : RenderTextureFormat.ARGB32;
- aoBlurDescriptor.width /= downsampleDivider;
- aoBlurDescriptor.height /= downsampleDivider;
-
- // Handles
- aoTexture = UniversalRenderer.CreateRenderGraphTexture(renderGraph, aoBlurDescriptor, "_SSAO_OcclusionTexture0", false, FilterMode.Bilinear);
- finalTexture = m_CurrentSettings.AfterOpaque ? resourceData.activeColorTexture : UniversalRenderer.CreateRenderGraphTexture(renderGraph, finalTextureDescriptor, k_SSAOTextureName, false, FilterMode.Bilinear);
-
- if (m_CurrentSettings.BlurQuality != ScreenSpaceAmbientOcclusionSettings.BlurQualityOptions.Low)
- blurTexture = UniversalRenderer.CreateRenderGraphTexture(renderGraph, aoBlurDescriptor, "_SSAO_OcclusionTexture1", false, FilterMode.Bilinear);
- else
- blurTexture = TextureHandle.nullHandle;
-
- if (!m_CurrentSettings.AfterOpaque)
- resourceData.ssaoTexture = finalTexture;
- }
-
- /*----------------------------------------------------------------------------------------------------------------------------------------
- ------------------------------------------------------------- RENDER-GRAPH --------------------------------------------------------------
- ----------------------------------------------------------------------------------------------------------------------------------------*/
-
- /// <inheritdoc/>
- [Obsolete(DeprecationMessage.CompatibilityScriptingAPIObsolete, false)]
- public override void OnCameraSetup(CommandBuffer cmd, ref RenderingData renderingData)
- {
- ContextContainer frameData = renderingData.frameData;
- UniversalCameraData cameraData = frameData.Get<UniversalCameraData>();
-
- // Fill in the Pass data...
- InitSSAOPassData(ref m_PassData);
-
- // Update keywords and other shader params
- SetupKeywordsAndParameters(ref m_CurrentSettings, ref cameraData);
-
- // Set up the descriptors
- int downsampleDivider = m_CurrentSettings.Downsample ? 2 : 1;
- RenderTextureDescriptor descriptor = renderingData.cameraData.cameraTargetDescriptor;
- descriptor.msaaSamples = 1;
- descriptor.depthBufferBits = 0;
-
- // AO PAss
- m_AOPassDescriptor = descriptor;
- m_AOPassDescriptor.width /= downsampleDivider;
- m_AOPassDescriptor.height /= downsampleDivider;
- bool useRedComponentOnly = m_SupportsR8RenderTextureFormat && m_BlurType > BlurTypes.Bilateral;
- m_AOPassDescriptor.colorFormat = useRedComponentOnly ? RenderTextureFormat.R8 : RenderTextureFormat.ARGB32;
-
- // Allocate textures for the AO and blur
- RenderingUtils.ReAllocateHandleIfNeeded(ref m_SSAOTextures[0], m_AOPassDescriptor, FilterMode.Bilinear, TextureWrapMode.Clamp, name: "_SSAO_OcclusionTexture0");
- RenderingUtils.ReAllocateHandleIfNeeded(ref m_SSAOTextures[1], m_AOPassDescriptor, FilterMode.Bilinear, TextureWrapMode.Clamp, name: "_SSAO_OcclusionTexture1");
- RenderingUtils.ReAllocateHandleIfNeeded(ref m_SSAOTextures[2], m_AOPassDescriptor, FilterMode.Bilinear, TextureWrapMode.Clamp, name: "_SSAO_OcclusionTexture2");
-
- // Upsample setup
- m_AOPassDescriptor.width *= downsampleDivider;
- m_AOPassDescriptor.height *= downsampleDivider;
- m_AOPassDescriptor.colorFormat = m_SupportsR8RenderTextureFormat ? RenderTextureFormat.R8 : RenderTextureFormat.ARGB32;
-
- // Allocate texture for the final SSAO results
- RenderingUtils.ReAllocateHandleIfNeeded(ref m_SSAOTextures[3], m_AOPassDescriptor, FilterMode.Bilinear, TextureWrapMode.Clamp, name: "_SSAO_OcclusionTexture");
- PostProcessUtils.SetSourceSize(cmd, m_SSAOTextures[3]);
-
- // Disable obsolete warning for internal usage
- #pragma warning disable CS0618
- // Configure targets and clear color
- ConfigureTarget(m_CurrentSettings.AfterOpaque ? m_Renderer.cameraColorTargetHandle : m_SSAOTextures[3]);
- ConfigureClear(ClearFlag.None, Color.white);
- #pragma warning restore CS0618
- }
-
- /// <inheritdoc/>
- [Obsolete(DeprecationMessage.CompatibilityScriptingAPIObsolete, false)]
- public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
- {
- if (m_Material == null)
- {
- Debug.LogErrorFormat(
- "{0}.Execute(): Missing material. ScreenSpaceAmbientOcclusion pass will not execute. Check for missing reference in the renderer resources.",
- GetType().Name);
- return;
- }
-
- var cmd = renderingData.commandBuffer;
- using (new ProfilingScope(cmd, ProfilingSampler.Get(URPProfileId.SSAO)))
- {
- // We only want URP shaders to sample SSAO if After Opaque is off.
- if (!m_CurrentSettings.AfterOpaque)
- cmd.SetKeyword(ShaderGlobalKeywords.ScreenSpaceOcclusion, true);
-
- cmd.SetGlobalTexture(k_SSAOTextureName, m_SSAOTextures[3]);
-
- #if ENABLE_VR && ENABLE_XR_MODULE
- bool isFoveatedEnabled = false;
- if (renderingData.cameraData.xr.supportsFoveatedRendering)
- {
- // If we are downsampling we can't use the VRS texture
- // If it's a non uniform raster foveated rendering has to be turned off because it will keep applying non uniform for the other passes.
- // When calculating normals from depth, this causes artifacts that are amplified from VRS when going to say 4x4. Thus we disable foveated because of that
- if (m_CurrentSettings.Downsample || SystemInfo.foveatedRenderingCaps.HasFlag(FoveatedRenderingCaps.NonUniformRaster) ||
- (SystemInfo.foveatedRenderingCaps.HasFlag(FoveatedRenderingCaps.FoveationImage) && m_CurrentSettings.Source == ScreenSpaceAmbientOcclusionSettings.DepthSource.Depth))
- {
- cmd.SetFoveatedRenderingMode(FoveatedRenderingMode.Disabled);
- }
- // If we aren't downsampling and it's a VRS texture we can apply foveation in this case
- else if (SystemInfo.foveatedRenderingCaps.HasFlag(FoveatedRenderingCaps.FoveationImage))
- {
- cmd.SetFoveatedRenderingMode(FoveatedRenderingMode.Enabled);
- isFoveatedEnabled = true;
- }
- }
- #endif
-
- GetPassOrder(m_BlurType, m_CurrentSettings.AfterOpaque, out int[] textureIndices, out ShaderPasses[] shaderPasses);
-
- // Execute the SSAO Occlusion pass
- RTHandle cameraDepthTargetHandle = renderingData.cameraData.renderer.cameraDepthTargetHandle;
- RenderAndSetBaseMap(ref cmd, ref renderingData, ref renderingData.cameraData.renderer, ref m_Material, ref cameraDepthTargetHandle, ref m_SSAOTextures[0], ShaderPasses.AmbientOcclusion);
-
- // Execute the Blur Passes
- for (int i = 0; i < shaderPasses.Length; i++)
- {
- int baseMapIndex = textureIndices[i];
- int targetIndex = textureIndices[i + 1];
- RenderAndSetBaseMap(ref cmd, ref renderingData, ref renderingData.cameraData.renderer, ref m_Material, ref m_SSAOTextures[baseMapIndex], ref m_SSAOTextures[targetIndex], shaderPasses[i]);
- }
-
- // Set the global SSAO Params
- cmd.SetGlobalVector(s_AmbientOcclusionParamID, new Vector4(1f, 0f, 0f, m_CurrentSettings.DirectLightingStrength));
- #if ENABLE_VR && ENABLE_XR_MODULE
- // Cleanup, making sure it doesn't stay enabled for a pass after that should not have it on
- if (isFoveatedEnabled)
- cmd.SetFoveatedRenderingMode(FoveatedRenderingMode.Disabled);
- #endif
- }
- }
-
- private static void RenderAndSetBaseMap(ref CommandBuffer cmd, ref RenderingData renderingData, ref ScriptableRenderer renderer, ref Material mat, ref RTHandle baseMap, ref RTHandle target, ShaderPasses pass)
- {
- if (IsAfterOpaquePass(ref pass))
- {
- // Disable obsolete warning for internal usage
- #pragma warning disable CS0618
- Blitter.BlitCameraTexture(cmd, baseMap, renderer.cameraColorTargetHandle, RenderBufferLoadAction.Load, RenderBufferStoreAction.Store, mat, (int)pass);
- #pragma warning restore CS0618
- }
-
- else if (baseMap.rt == null)
- {
- // Obsolete usage of RTHandle aliasing a RenderTargetIdentifier
- Vector2 viewportScale = baseMap.useScaling ? new Vector2(baseMap.rtHandleProperties.rtHandleScale.x, baseMap.rtHandleProperties.rtHandleScale.y) : Vector2.one;
-
- // Will set the correct camera viewport as well.
- CoreUtils.SetRenderTarget(cmd, target);
- Blitter.BlitTexture(cmd, baseMap.nameID, viewportScale, mat, (int)pass);
- }
-
- else
- Blitter.BlitCameraTexture(cmd, baseMap, target, mat, (int)pass);
- }
-
- private static void GetPassOrder(BlurTypes blurType, bool isAfterOpaque, out int[] textureIndices, out ShaderPasses[] shaderPasses)
- {
- switch (blurType)
- {
- case BlurTypes.Bilateral:
- textureIndices = m_BilateralTexturesIndices;
- shaderPasses = isAfterOpaque ? m_BilateralAfterOpaquePasses : m_BilateralPasses;
- break;
- case BlurTypes.Gaussian:
- textureIndices = m_GaussianTexturesIndices;
- shaderPasses = isAfterOpaque ? m_GaussianAfterOpaquePasses : m_GaussianPasses;
- break;
- case BlurTypes.Kawase:
- textureIndices = m_KawaseTexturesIndices;
- shaderPasses = isAfterOpaque ? m_KawaseAfterOpaquePasses : m_KawasePasses;
- break;
- default:
- throw new ArgumentOutOfRangeException();
- }
- }
-
- /// <inheritdoc/>
- 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()
- {
- m_SSAOTextures[0]?.Release();
- m_SSAOTextures[1]?.Release();
- m_SSAOTextures[2]?.Release();
- m_SSAOTextures[3]?.Release();
- m_SSAOParamsPrev = default;
- }
- }
- }
|