640 lines
		
	
	
		
			36 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
		
		
			
		
	
	
			640 lines
		
	
	
		
			36 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
|  | using System; | ||
|  | using UnityEngine.Experimental.Rendering; | ||
|  | using UnityEngine.Rendering.RenderGraphModule; | ||
|  | 
 | ||
|  | namespace UnityEngine.Rendering.Universal | ||
|  | { | ||
|  |     // The Screen Space Ambient Occlusion (SSAO) Pass | ||
|  |     internal class ScreenSpaceAmbientOcclusionPass : ScriptableRenderPass | ||
|  |     { | ||
|  |         // 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 (renderer is UniversalRenderer { usesDeferredLighting: true }) | ||
|  |             { | ||
|  |                 renderPassEvent = m_CurrentSettings.AfterOpaque ? RenderPassEvent.AfterRenderingOpaques : RenderPassEvent.AfterRenderingGbuffer; | ||
|  | 
 | ||
|  |                 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.Depth | 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 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 | ||
|  |             TextureHandle cameraDepthTexture = 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); | ||
|  | 
 | ||
|  |                 // Fill in the Pass data... | ||
|  |                 InitSSAOPassData(ref passData); | ||
|  |                 passData.cameraColor = resourceData.cameraColor; | ||
|  |                 passData.AOTexture = aoTexture; | ||
|  |                 passData.finalTexture = finalTexture; | ||
|  |                 passData.blurTexture = blurTexture; | ||
|  | 
 | ||
|  |                 // Declare input textures | ||
|  |                 builder.UseTexture(passData.AOTexture, AccessFlags.ReadWrite); | ||
|  | 
 | ||
|  |                 // TODO: Refactor to eliminate the need for 'UseTexture'. | ||
|  |                 // Currently required only because 'PostProcessUtils.SetSourceSize' allocates an RTHandle, | ||
|  |                 // which expects a valid graphicsResource. Without this call, 'cameraColor.graphicsResource' | ||
|  |                 // may be null if it wasn't initialized in an earlier pass (e.g., DrawOpaque). | ||
|  |                 if (resourceData.cameraColor.IsValid()) | ||
|  |                     builder.UseTexture(resourceData.cameraColor, AccessFlags.Read); | ||
|  | 
 | ||
|  |                 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) => | ||
|  |                 { | ||
|  |                     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.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.depthStencilFormat = GraphicsFormat.None; | ||
|  |             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.depthStencilFormat = GraphicsFormat.None; | ||
|  | 
 | ||
|  |             // 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; | ||
|  |         } | ||
|  |     } | ||
|  | } |