803 lines
45 KiB
C#
803 lines
45 KiB
C#
#if MODERN_SSAO
|
|
using System;
|
|
using UnityEngine.Experimental.Rendering;
|
|
using UnityEngine.Rendering.RenderGraphModule;
|
|
|
|
namespace UnityEngine.Rendering.Universal
|
|
{
|
|
// Ground Truth Ambient Occlusion (GTAO) Pass - Handles GTAO mode with compute shader and raster-fragment fallback.
|
|
internal class GTAOPass : ScriptableRenderPass, IDisposable
|
|
{
|
|
// Shared state
|
|
private readonly bool m_SupportsR8RenderTextureFormat = SystemInfo.SupportsRenderTextureFormat(RenderTextureFormat.R8);
|
|
private readonly bool m_SupportsComputeShader = SystemInfo.supportsComputeShaders;
|
|
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 bool m_WarnedMissingTextures;
|
|
|
|
// Raster path state
|
|
private SSAOUtils.SSAOMaterialParams m_SSAOParamsPrev = new SSAOUtils.SSAOMaterialParams();
|
|
|
|
// Compute path state
|
|
private ComputePathState m_ComputePathState;
|
|
|
|
// Constants
|
|
private const float k_DegreesPerRotation = 360.0f;
|
|
private const int k_TemporalOffsetCount = 4;
|
|
|
|
// GTAO-only Shader Property IDs
|
|
internal static class ShaderIDs
|
|
{
|
|
// Compute kernel I/O bindings
|
|
public static readonly int _CameraDepthTexture = Shader.PropertyToID("_CameraDepthTexture");
|
|
public static readonly int _AOOutput = Shader.PropertyToID("_AOOutput");
|
|
public static readonly int _BlurOutput = Shader.PropertyToID("_BlurOutput");
|
|
public static readonly int _OcclusionTexture = Shader.PropertyToID("_OcclusionTexture");
|
|
public static readonly int _AOOutputHistory = Shader.PropertyToID("_AOOutputHistory");
|
|
public static readonly int _FinalOutput = Shader.PropertyToID("_FinalOutput");
|
|
|
|
// Temporal filter
|
|
public static readonly int _AOPackedHistory = Shader.PropertyToID("_AOPackedHistory");
|
|
public static readonly int _MotionVectorTexture = Shader.PropertyToID("_MotionVectorTexture");
|
|
public static readonly int _SSAOHistoryLength = Shader.PropertyToID("_SSAOHistoryLength");
|
|
public static readonly int _SSAOGhostingMitigation = Shader.PropertyToID("_SSAOGhostingMitigation");
|
|
public static readonly int _SSAOTemporalRotation = Shader.PropertyToID("_SSAOTemporalRotation");
|
|
public static readonly int _SSAOTemporalOffset = Shader.PropertyToID("_SSAOTemporalOffset");
|
|
|
|
// GTAO compute parameters
|
|
public static readonly int _GTAODirectionCount = Shader.PropertyToID("_GTAODirectionCount");
|
|
public static readonly int _GTAOStepCount = Shader.PropertyToID("_GTAOStepCount");
|
|
public static readonly int _GTAOSpatialFilter = Shader.PropertyToID("_GTAOSpatialFilter");
|
|
public static readonly int _GTAOBoxFilterStep = Shader.PropertyToID("_GTAOBoxFilterStep");
|
|
}
|
|
|
|
// Temporal rotation/offset arrays for GTAO temporal filtering
|
|
private static readonly float[] s_TemporalRotations = { 60.0f, 300.0f, 180.0f, 240.0f, 120.0f, 0.0f };
|
|
|
|
// Structs
|
|
private struct LocalKeywordSet
|
|
{
|
|
public LocalKeyword blueNoise;
|
|
public LocalKeyword interleavedGradient;
|
|
public LocalKeyword temporalFiltering;
|
|
public LocalKeyword orthographic;
|
|
|
|
public void Init(ComputeShader cs)
|
|
{
|
|
blueNoise = new(cs, ScreenSpaceAmbientOcclusionKeywords.k_AOBlueNoiseKeyword);
|
|
interleavedGradient = new(cs, ScreenSpaceAmbientOcclusionKeywords.k_AOInterleavedGradientKeyword);
|
|
temporalFiltering = new(cs, ScreenSpaceAmbientOcclusionKeywords.k_TemporalFilteringKeyword);
|
|
orthographic = new(cs, ScreenSpaceAmbientOcclusionKeywords.k_OrthographicCameraKeyword);
|
|
}
|
|
}
|
|
|
|
private struct ComputePathState
|
|
{
|
|
public ComputeShader shader;
|
|
public int gtaoKernel;
|
|
public int blurHKernel;
|
|
public int blurVKernel;
|
|
public int boxSpatialFilterKernel;
|
|
public int temporalKernel;
|
|
public int copyHistoryKernel;
|
|
public int finalBlitKernel;
|
|
public LocalKeywordSet keywords;
|
|
public RTHandle blueNoiseRTHandle;
|
|
|
|
public void Init(ComputeShader cs)
|
|
{
|
|
Debug.Assert(SystemInfo.supportsComputeShaders, "ComputePathState must not be initialized when the platform does not support compute shaders.");
|
|
|
|
shader = cs;
|
|
|
|
if (shader == null)
|
|
return;
|
|
|
|
Debug.Assert(
|
|
shader.HasKernel("ComputeAO") &&
|
|
shader.HasKernel("BilateralBlurH") &&
|
|
shader.HasKernel("BilateralBlurV") &&
|
|
shader.HasKernel("BoxSpatialFilter") &&
|
|
shader.HasKernel("TemporalFilter") &&
|
|
shader.HasKernel("CopyHistory") &&
|
|
shader.HasKernel("FinalBlit"),
|
|
"The GTAO compute shader does not have the expected kernels.");
|
|
|
|
gtaoKernel = shader.FindKernel("ComputeAO");
|
|
blurHKernel = shader.FindKernel("BilateralBlurH");
|
|
blurVKernel = shader.FindKernel("BilateralBlurV");
|
|
boxSpatialFilterKernel = shader.FindKernel("BoxSpatialFilter");
|
|
temporalKernel = shader.FindKernel("TemporalFilter");
|
|
copyHistoryKernel = shader.FindKernel("CopyHistory");
|
|
finalBlitKernel = shader.FindKernel("FinalBlit");
|
|
keywords.Init(shader);
|
|
}
|
|
|
|
public void Release()
|
|
{
|
|
blueNoiseRTHandle?.Release();
|
|
blueNoiseRTHandle = null;
|
|
}
|
|
}
|
|
|
|
private struct GTAOComputeParams
|
|
{
|
|
public Vector4 ssaoParams;
|
|
public Vector4 ssaoParams2;
|
|
public Vector4 depthToViewParams;
|
|
public Vector4 sourceSize;
|
|
public Vector4 blueNoiseParams;
|
|
public float historyLength;
|
|
public float ghostingMitigation;
|
|
public Vector4 projectionParams2;
|
|
public bool orthographicCamera;
|
|
public float temporalRotation;
|
|
public int temporalOffset;
|
|
}
|
|
|
|
private struct TemporalHistoryState
|
|
{
|
|
public TextureHandle historyReadTexture;
|
|
public TextureHandle historyWriteTexture;
|
|
public SSAOHistory ssaoHistory;
|
|
public bool historyReady;
|
|
public bool isNewFrame;
|
|
}
|
|
|
|
// Pass Data Classes
|
|
private class GTAOComputePassData
|
|
{
|
|
public ComputeShader cs;
|
|
public int kernel;
|
|
public Vector2Int dispatchSize;
|
|
public bool useBlueNoise;
|
|
public LocalKeywordSet localKeywords;
|
|
public bool willRunTemporalFilter;
|
|
public int directionCount;
|
|
public int stepCount;
|
|
public ScreenSpaceAmbientOcclusionSpatialFilter spatialFilter;
|
|
public GTAOComputeParams computeParams;
|
|
public Matrix4x4[] cameraViewProjections = new Matrix4x4[2];
|
|
public Vector4[] cameraTopLeftCorner = new Vector4[2];
|
|
public Vector4[] cameraXExtent = new Vector4[2];
|
|
public Vector4[] cameraYExtent = new Vector4[2];
|
|
public Vector4[] cameraZExtent = new Vector4[2];
|
|
public TextureHandle depthTexture;
|
|
public TextureHandle normalsTexture;
|
|
public TextureHandle blueNoiseTexture;
|
|
public TextureHandle aoTexture;
|
|
}
|
|
|
|
private class GTAOSingleDispatchPassData
|
|
{
|
|
public ComputeShader cs;
|
|
public int kernel;
|
|
public int dstPropertyId;
|
|
public Vector2Int dispatchSize;
|
|
public TextureHandle srcTexture;
|
|
public TextureHandle depthTexture;
|
|
public TextureHandle dstTexture;
|
|
public float boxFilterStep;
|
|
}
|
|
|
|
private class GTAOCopyHistoryPassData
|
|
{
|
|
public ComputeShader cs;
|
|
public int kernel;
|
|
public Vector2Int dispatchSize;
|
|
public TextureHandle srcTexture;
|
|
public TextureHandle depthTexture;
|
|
public TextureHandle historyTexture;
|
|
}
|
|
|
|
private class GTAOTemporalPassData
|
|
{
|
|
public ComputeShader cs;
|
|
public int kernel;
|
|
public Vector2Int dispatchSize;
|
|
public TextureHandle aoTexture;
|
|
public TextureHandle depthTexture;
|
|
public TextureHandle historyReadTexture;
|
|
public TextureHandle historyWriteTexture;
|
|
public TextureHandle motionVectorTexture;
|
|
public TextureHandle temporalTexture;
|
|
public ScreenSpaceAmbientOcclusionSpatialFilter spatialFilter;
|
|
}
|
|
|
|
private class GTAOFinalBlitPassData
|
|
{
|
|
public ComputeShader cs;
|
|
public int kernel;
|
|
public Vector2Int dispatchSize;
|
|
public float directLightingStrength;
|
|
public TextureHandle srcTexture;
|
|
public TextureHandle finalTexture;
|
|
}
|
|
|
|
private class GTAOAfterOpaqueBlitPassData
|
|
{
|
|
public Material material;
|
|
public Vector4 sourceSize;
|
|
public Vector4 ssaoParams;
|
|
public int shaderPass;
|
|
public TextureHandle sourceTexture;
|
|
public TextureHandle targetTexture;
|
|
}
|
|
|
|
internal GTAOPass(Shader shader, Texture2D[] blueNoiseTextures)
|
|
{
|
|
m_CurrentSettings = new ScreenSpaceAmbientOcclusionSettings();
|
|
m_Material = CoreUtils.CreateEngineMaterial(shader);
|
|
m_BlueNoiseTextures = blueNoiseTextures;
|
|
|
|
if (m_SupportsComputeShader && GraphicsSettings.TryGetRenderPipelineSettings<ScreenSpaceAmbientOcclusionCoreResources>(out var ssaoCoreResources))
|
|
m_ComputePathState.Init(ssaoCoreResources.GTAOComputeShader);
|
|
}
|
|
|
|
// Sets up GTAO pass using active volume. Returns false if SSAO should be skipped.
|
|
internal bool Setup(ScreenSpaceAmbientOcclusionVolumeOverride ssaoVolume)
|
|
{
|
|
ApplyVolumeSettings(m_CurrentSettings, ssaoVolume);
|
|
m_BlurType = SSAOUtils.GetBlurType(m_CurrentSettings.BlurQuality);
|
|
return ssaoVolume.IsActive();
|
|
}
|
|
|
|
private static void ApplyVolumeSettings(ScreenSpaceAmbientOcclusionSettings settings, ScreenSpaceAmbientOcclusionVolumeOverride volume)
|
|
{
|
|
// Common parameters
|
|
settings.Mode = ScreenSpaceAmbientOcclusionMode.GTAO;
|
|
settings.UseComputeShader = volume.useComputeShader;
|
|
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
|
|
};
|
|
|
|
// GTAO mode parameters
|
|
settings.GTAOMinimumRadiusInPixels = volume.minimumRadiusInPixels;
|
|
settings.Source = ScreenSpaceAmbientOcclusionSettings.DepthSource.DepthNormals;
|
|
settings.BlurQuality = ScreenSpaceAmbientOcclusionSettings.BlurQualityOptions.High;
|
|
settings.NormalSamples = ScreenSpaceAmbientOcclusionSettings.NormalQuality.High;
|
|
|
|
if (volume.useComputeShader)
|
|
{
|
|
settings.GTAODirectionCount = volume.directionCount;
|
|
settings.GTAOStepCount = volume.stepCount;
|
|
settings.GTAOSpatialFilter = volume.spatialFilter;
|
|
settings.GTAOTemporalFilterEnabled = volume.temporalFilter;
|
|
settings.GTAOGhostingMitigation = volume.ghostingMitigation;
|
|
settings.GTAOHistoryLength = volume.historyLength;
|
|
}
|
|
}
|
|
|
|
// ---- GTAO-specific helpers ----
|
|
|
|
internal static void CalculateGTAOViewParams(ScreenSpaceAmbientOcclusionSettings settings, UniversalCameraData cameraData,
|
|
bool orthographicCamera, float radius, in TextureDesc cameraColorDesc, out Vector4 ssaoParams2, out Vector4 depthToViewParams)
|
|
{
|
|
if (settings.Mode == ScreenSpaceAmbientOcclusionMode.Standard)
|
|
{
|
|
ssaoParams2 = Vector4.zero;
|
|
depthToViewParams = Vector4.zero;
|
|
return;
|
|
}
|
|
|
|
float invHalfTanFOV = cameraData.camera.projectionMatrix.m11;
|
|
float downsampleMultiplier = 1.0f / (settings.Downsample ? 2 : 1);
|
|
Vector2 runningRes = new Vector2(cameraColorDesc.width, cameraColorDesc.height) * downsampleMultiplier;
|
|
float aspectRatio = runningRes.y / runningRes.x;
|
|
float fovCorrection = runningRes.y * invHalfTanFOV * 0.5f;
|
|
|
|
ssaoParams2 = new Vector4(settings.GTAOMinimumRadiusInPixels * downsampleMultiplier, 0.0f, fovCorrection, 0.0f);
|
|
depthToViewParams = new Vector4(
|
|
2.0f / (invHalfTanFOV * aspectRatio * runningRes.x),
|
|
2.0f / (invHalfTanFOV * runningRes.y),
|
|
1.0f / (invHalfTanFOV * aspectRatio),
|
|
1.0f / invHalfTanFOV
|
|
);
|
|
}
|
|
|
|
private static void CalculateTemporalParams(ScreenSpaceAmbientOcclusionSettings settings, out float temporalRotation, out int temporalOffset)
|
|
{
|
|
temporalRotation = 0.0f;
|
|
temporalOffset = 0;
|
|
|
|
if (!settings.IsTemporalFilterActive)
|
|
return;
|
|
|
|
uint temporalRotationCount = (uint)s_TemporalRotations.Length;
|
|
temporalRotation = s_TemporalRotations[(uint)Time.frameCount % temporalRotationCount] / k_DegreesPerRotation;
|
|
temporalOffset = (int)(((uint)Time.frameCount / temporalRotationCount) % k_TemporalOffsetCount);
|
|
}
|
|
|
|
private static Vector2Int CalculateDispatchSize(Vector2Int textureSize, ComputeShader cs, int kernelIndex)
|
|
{
|
|
cs.GetKernelThreadGroupSizes(kernelIndex, out uint groupX, out uint groupY, out _);
|
|
return new Vector2Int(
|
|
Mathf.CeilToInt(textureSize.x / (float)groupX),
|
|
Mathf.CeilToInt(textureSize.y / (float)groupY)
|
|
);
|
|
}
|
|
|
|
private static GTAOComputeParams CreateGTAOComputeParams(ScreenSpaceAmbientOcclusionSettings settings, UniversalCameraData cameraData, in TextureDesc cameraColorDesc, Texture2D blueNoiseTexture)
|
|
{
|
|
GTAOComputeParams computeParams = new GTAOComputeParams();
|
|
float radius = SSAOUtils.CalculateRadius(settings);
|
|
|
|
computeParams.orthographicCamera = cameraData.camera.orthographic;
|
|
computeParams.ssaoParams = SSAOUtils.CalculateCommonParams(settings, radius);
|
|
CalculateGTAOViewParams(settings, cameraData, computeParams.orthographicCamera, radius, cameraColorDesc, out computeParams.ssaoParams2, out computeParams.depthToViewParams);
|
|
|
|
computeParams.sourceSize = PostProcessUtils.CalcShaderSourceSize(cameraColorDesc.width, cameraColorDesc.height, cameraColorDesc.useDynamicScale);
|
|
computeParams.projectionParams2 = SSAOUtils.CalculateProjectionParams2(cameraData);
|
|
|
|
if (settings.AOMethod == ScreenSpaceAmbientOcclusionSettings.AOMethodOptions.BlueNoise && blueNoiseTexture != null)
|
|
computeParams.blueNoiseParams = SSAOUtils.CalculateBlueNoiseParams(cameraData, blueNoiseTexture);
|
|
|
|
computeParams.historyLength = settings.GTAOHistoryLength;
|
|
computeParams.ghostingMitigation = settings.GTAOGhostingMitigation;
|
|
CalculateTemporalParams(settings, out computeParams.temporalRotation, out computeParams.temporalOffset);
|
|
return computeParams;
|
|
}
|
|
|
|
private static TemporalHistoryState GetTemporalHistoryState(RenderGraph renderGraph, ScreenSpaceAmbientOcclusionSettings settings, UniversalCameraData cameraData, bool useComputeShader)
|
|
{
|
|
var state = new TemporalHistoryState
|
|
{
|
|
historyReadTexture = TextureHandle.nullHandle,
|
|
historyWriteTexture = TextureHandle.nullHandle,
|
|
};
|
|
|
|
if (!settings.IsTemporalFilterActive || cameraData.historyManager == null)
|
|
return state;
|
|
|
|
cameraData.historyManager.RequestAccess<SSAOHistory>();
|
|
state.ssaoHistory = cameraData.historyManager.GetHistoryForWrite<SSAOHistory>();
|
|
if (state.ssaoHistory == null)
|
|
return state;
|
|
|
|
bool xrMultipassEnabled = false;
|
|
#if ENABLE_VR && ENABLE_XR_MODULE
|
|
xrMultipassEnabled = cameraData.xr.enabled && !cameraData.xr.singlePassEnabled;
|
|
#endif
|
|
bool wasReallocated = state.ssaoHistory.Update(cameraData, settings.Downsample, useComputeShader, xrMultipassEnabled);
|
|
|
|
int multipassId = 0;
|
|
#if ENABLE_VR && ENABLE_XR_MODULE
|
|
multipassId = cameraData.xr.multipassId;
|
|
#endif
|
|
int accumulationVersion = state.ssaoHistory.GetAccumulationVersion(multipassId);
|
|
bool isPreview = cameraData.camera.cameraType == CameraType.Preview;
|
|
bool isRenderRequest = cameraData.camera.isProcessingRenderRequest;
|
|
state.isNewFrame = !isPreview && !isRenderRequest && accumulationVersion != Time.frameCount;
|
|
RTHandle historyWrite = state.ssaoHistory.GetCurrentTexture(multipassId);
|
|
RTHandle historyRead = state.ssaoHistory.GetPreviousTexture(multipassId);
|
|
Debug.Assert(historyWrite != null && historyRead != null, "SSAO temporal history textures should be allocated here.");
|
|
|
|
state.historyWriteTexture = renderGraph.ImportTexture(historyWrite);
|
|
state.historyReadTexture = renderGraph.ImportTexture(historyRead);
|
|
state.historyReady = !wasReallocated && accumulationVersion >= 0;
|
|
|
|
return state;
|
|
}
|
|
|
|
private TextureHandle ImportBlueNoiseTexture(RenderGraph renderGraph, Texture2D blueNoiseTexture)
|
|
{
|
|
if (blueNoiseTexture == null)
|
|
return TextureHandle.nullHandle;
|
|
|
|
if (m_ComputePathState.blueNoiseRTHandle == null || m_ComputePathState.blueNoiseRTHandle.externalTexture != blueNoiseTexture)
|
|
{
|
|
m_ComputePathState.blueNoiseRTHandle?.Release();
|
|
m_ComputePathState.blueNoiseRTHandle = RTHandles.Alloc(blueNoiseTexture);
|
|
}
|
|
|
|
return renderGraph.ImportTexture(m_ComputePathState.blueNoiseRTHandle);
|
|
}
|
|
|
|
// ---- RecordRenderGraph ----
|
|
|
|
public override void RecordRenderGraph(RenderGraph renderGraph, ContextContainer frameData)
|
|
{
|
|
UniversalCameraData cameraData = frameData.Get<UniversalCameraData>();
|
|
UniversalResourceData resourceData = frameData.Get<UniversalResourceData>();
|
|
|
|
if (!resourceData.cameraDepthTexture.IsValid() || !resourceData.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);
|
|
|
|
bool useComputeShader = (m_CurrentSettings.NeedsComputeShader && m_SupportsComputeShader) && m_ComputePathState.shader != null && m_ComputePathState.gtaoKernel >= 0;
|
|
|
|
SSAOUtils.CreateRenderTextureHandles(renderGraph, resourceData, cameraColorDesc,
|
|
m_CurrentSettings, m_SupportsR8RenderTextureFormat, m_BlurType, enableRandomWrite: useComputeShader,
|
|
out TextureHandle aoTexture, out TextureHandle blurTexture, out TextureHandle temporalTexture, out TextureHandle finalTexture);
|
|
|
|
var temporalHistory = GetTemporalHistoryState(renderGraph, m_CurrentSettings, cameraData, useComputeShader);
|
|
|
|
SSAOUtils.SetupCameraViewMatrices(cameraData, ref m_CameraViewData);
|
|
m_BlueNoiseTextureIndex = SSAOUtils.AdvanceBlueNoiseIndex(m_CurrentSettings, m_BlueNoiseTextures, m_BlueNoiseTextureIndex);
|
|
|
|
if (useComputeShader)
|
|
{
|
|
RecordGTAOComputePass(renderGraph, aoTexture, blurTexture, temporalTexture, finalTexture, temporalHistory, cameraData, resourceData, cameraColorDesc);
|
|
}
|
|
else
|
|
{
|
|
// GTAO raster-fragment fallback - reuse shared raster recording
|
|
TextureHandle cameraDepthTexture = resourceData.cameraDepthTexture;
|
|
TextureHandle cameraNormalsTexture = resourceData.cameraNormalsTexture;
|
|
|
|
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);
|
|
}
|
|
}
|
|
|
|
// ---- Compute Pass Recording ----
|
|
|
|
private void RecordGTAOComputePass(RenderGraph renderGraph, TextureHandle aoTexture, TextureHandle blurTexture, TextureHandle temporalTexture, TextureHandle finalTexture,
|
|
in TemporalHistoryState temporalHistory, UniversalCameraData cameraData, UniversalResourceData resourceData, in TextureDesc cameraColorDesc)
|
|
{
|
|
TextureHandle cameraDepthTexture = resourceData.cameraDepthTexture;
|
|
TextureHandle cameraNormalsTexture = resourceData.cameraNormalsTexture;
|
|
TextureHandle motionVectorTexture = resourceData.motionVectorColor;
|
|
bool temporalEnabled = m_CurrentSettings.IsTemporalFilterActive;
|
|
bool isTemporalTextureValid = temporalTexture.IsValid();
|
|
bool isHistoryReadTextureValid = temporalHistory.historyReadTexture.IsValid();
|
|
bool isHistoryWriteTextureValid = temporalHistory.historyWriteTexture.IsValid();
|
|
bool hasTemporalResources = temporalEnabled && isTemporalTextureValid && isHistoryReadTextureValid && isHistoryWriteTextureValid;
|
|
bool shouldSeedHistory = hasTemporalResources && temporalHistory.isNewFrame && !temporalHistory.historyReady;
|
|
bool willRunTemporalFilter = hasTemporalResources && (temporalHistory.historyReady || shouldSeedHistory);
|
|
|
|
TextureDesc aoDesc = aoTexture.GetDescriptor(renderGraph);
|
|
Vector2Int aoSize = new Vector2Int(aoDesc.width, aoDesc.height);
|
|
Vector2Int aoDispatchSize = CalculateDispatchSize(aoSize, m_ComputePathState.shader, m_ComputePathState.gtaoKernel);
|
|
|
|
Texture2D blueNoiseTexture = SSAOUtils.GetBlueNoiseTexture(m_BlueNoiseTextures, m_BlueNoiseTextureIndex);
|
|
if (m_CurrentSettings.AOMethod == ScreenSpaceAmbientOcclusionSettings.AOMethodOptions.BlueNoise)
|
|
Debug.Assert(blueNoiseTexture != null, "Blue noise texture is null. Blue noise mode requires a valid blue noise texture.");
|
|
TextureHandle blueNoiseHandle = ImportBlueNoiseTexture(renderGraph, blueNoiseTexture ?? Texture2D.blackTexture);
|
|
|
|
var computeParams = CreateGTAOComputeParams(m_CurrentSettings, cameraData, cameraColorDesc, blueNoiseTexture);
|
|
|
|
// GTAO
|
|
RecordGTAOMainPass(renderGraph, cameraData, computeParams, blueNoiseHandle, cameraDepthTexture, cameraNormalsTexture, aoTexture, aoDispatchSize, willRunTemporalFilter);
|
|
|
|
// Spatial filter
|
|
TextureHandle spatialFilteredTexture = aoTexture;
|
|
Debug.Assert(blurTexture.IsValid(), "GTAO compute path requires an allocated blur texture.");
|
|
|
|
if (m_CurrentSettings.GTAOSpatialFilter == ScreenSpaceAmbientOcclusionSpatialFilter.Box)
|
|
{
|
|
RecordComputeDispatchPass(renderGraph, "GTAO Box Spatial Filter 1", m_ComputePathState.boxSpatialFilterKernel, aoDispatchSize, aoTexture, blurTexture, ShaderIDs._BlurOutput, cameraDepthTexture, 4.0f);
|
|
RecordComputeDispatchPass(renderGraph, "GTAO Box Spatial Filter 2", m_ComputePathState.boxSpatialFilterKernel, aoDispatchSize, blurTexture, aoTexture, ShaderIDs._BlurOutput, cameraDepthTexture, 2.0f);
|
|
RecordComputeDispatchPass(renderGraph, "GTAO Box Spatial Filter 3", m_ComputePathState.boxSpatialFilterKernel, aoDispatchSize, aoTexture, blurTexture, ShaderIDs._BlurOutput, cameraDepthTexture, 1.0f);
|
|
spatialFilteredTexture = blurTexture;
|
|
}
|
|
else
|
|
{
|
|
RecordComputeDispatchPass(renderGraph, "GTAO BlurH", m_ComputePathState.blurHKernel, aoDispatchSize, aoTexture, blurTexture, ShaderIDs._BlurOutput);
|
|
RecordComputeDispatchPass(renderGraph, "GTAO BlurV", m_ComputePathState.blurVKernel, aoDispatchSize, blurTexture, aoTexture, ShaderIDs._BlurOutput);
|
|
spatialFilteredTexture = aoTexture;
|
|
}
|
|
|
|
// Temporal filter and history update
|
|
if (willRunTemporalFilter)
|
|
{
|
|
if (shouldSeedHistory)
|
|
RecordCopyHistoryPass(renderGraph, "GTAO SeedHistory", aoDispatchSize, spatialFilteredTexture, cameraDepthTexture, temporalHistory.historyReadTexture);
|
|
|
|
// Scene View and editor redraws can render the same frame again after history has been advanced.
|
|
// Keep resolving against history, but stop reprojection motion for those redraws.
|
|
TextureHandle activeMotionVectorTexture = temporalHistory.isNewFrame ? motionVectorTexture : renderGraph.defaultResources.blackTexture;
|
|
RecordTemporalFilterPass(renderGraph, aoDispatchSize, spatialFilteredTexture, cameraDepthTexture, temporalHistory.historyReadTexture, temporalHistory.historyWriteTexture, activeMotionVectorTexture, temporalTexture);
|
|
}
|
|
|
|
// Determine the final source for downstream passes
|
|
TextureHandle resultTexture = willRunTemporalFilter ? temporalTexture : spatialFilteredTexture;
|
|
|
|
// Final / AfterOpaque blit
|
|
if (m_CurrentSettings.AfterOpaque)
|
|
{
|
|
bool useBlitAfterOpaquePass = m_CurrentSettings.GTAOSpatialFilter == ScreenSpaceAmbientOcclusionSpatialFilter.Box;
|
|
int afterOpaqueShaderPass = useBlitAfterOpaquePass
|
|
? (int)SSAOUtils.ShaderPasses.BoxAfterOpaque
|
|
: (int)SSAOUtils.ShaderPasses.BilateralAfterOpaque;
|
|
RecordAfterOpaqueBlitPass(renderGraph, computeParams, resultTexture, resourceData.activeColorTexture, afterOpaqueShaderPass);
|
|
}
|
|
else if (finalTexture.IsValid())
|
|
{
|
|
TextureDesc finalDesc = finalTexture.GetDescriptor(renderGraph);
|
|
Vector2Int finalSize = new Vector2Int(finalDesc.width, finalDesc.height);
|
|
Vector2Int finalDispatchSize = CalculateDispatchSize(finalSize, m_ComputePathState.shader, m_ComputePathState.finalBlitKernel);
|
|
RecordFinalBlitPass(renderGraph, resultTexture, finalTexture, m_CurrentSettings.DirectLightingStrength, finalDispatchSize);
|
|
}
|
|
|
|
if (willRunTemporalFilter && temporalHistory.isNewFrame && temporalHistory.ssaoHistory != null)
|
|
{
|
|
int multipassId = 0;
|
|
#if ENABLE_VR && ENABLE_XR_MODULE
|
|
multipassId = cameraData.xr.multipassId;
|
|
#endif
|
|
temporalHistory.ssaoHistory.SetAccumulationVersion(multipassId, Time.frameCount);
|
|
}
|
|
}
|
|
|
|
private void RecordGTAOMainPass(RenderGraph renderGraph, UniversalCameraData cameraData, GTAOComputeParams computeParams,
|
|
TextureHandle blueNoiseTexture, TextureHandle depthTexture, TextureHandle normalsTexture, TextureHandle aoTexture, Vector2Int dispatchSize, bool willRunTemporalFilter)
|
|
{
|
|
using (var builder = renderGraph.AddComputePass<GTAOComputePassData>("GTAO Compute", out var passData, m_ProfilingSampler))
|
|
{
|
|
passData.cs = m_ComputePathState.shader;
|
|
passData.kernel = m_ComputePathState.gtaoKernel;
|
|
passData.dispatchSize = dispatchSize;
|
|
passData.computeParams = computeParams;
|
|
passData.useBlueNoise = m_CurrentSettings.AOMethod == ScreenSpaceAmbientOcclusionSettings.AOMethodOptions.BlueNoise;
|
|
passData.localKeywords = m_ComputePathState.keywords;
|
|
passData.willRunTemporalFilter = willRunTemporalFilter;
|
|
passData.directionCount = m_CurrentSettings.GTAODirectionCount;
|
|
passData.stepCount = m_CurrentSettings.GTAOStepCount;
|
|
passData.spatialFilter = m_CurrentSettings.GTAOSpatialFilter;
|
|
|
|
#if ENABLE_VR && ENABLE_XR_MODULE
|
|
int eyeCount = cameraData.xr.enabled && cameraData.xr.singlePassEnabled ? 2 : 1;
|
|
#else
|
|
int eyeCount = 1;
|
|
#endif
|
|
Array.Copy(m_CameraViewData.viewProjections, passData.cameraViewProjections, eyeCount);
|
|
Array.Copy(m_CameraViewData.topLeftCorner, passData.cameraTopLeftCorner, eyeCount);
|
|
Array.Copy(m_CameraViewData.xExtent, passData.cameraXExtent, eyeCount);
|
|
Array.Copy(m_CameraViewData.yExtent, passData.cameraYExtent, eyeCount);
|
|
Array.Copy(m_CameraViewData.zExtent, passData.cameraZExtent, eyeCount);
|
|
|
|
passData.aoTexture = aoTexture;
|
|
builder.UseTexture(aoTexture, AccessFlags.Write);
|
|
|
|
passData.depthTexture = depthTexture;
|
|
builder.UseTexture(depthTexture, AccessFlags.Read);
|
|
|
|
passData.normalsTexture = normalsTexture;
|
|
builder.UseTexture(normalsTexture, AccessFlags.Read);
|
|
|
|
passData.blueNoiseTexture = blueNoiseTexture;
|
|
builder.UseTexture(blueNoiseTexture, AccessFlags.Read);
|
|
|
|
builder.AllowGlobalStateModification(true);
|
|
builder.SetRenderFunc(static (GTAOComputePassData data, ComputeGraphContext ctx) =>
|
|
{
|
|
var cmd = ctx.cmd;
|
|
var cs = data.cs;
|
|
ref var computeParams = ref data.computeParams;
|
|
|
|
cmd.SetKeyword(cs, data.localKeywords.blueNoise, data.useBlueNoise);
|
|
cmd.SetKeyword(cs, data.localKeywords.interleavedGradient, !data.useBlueNoise);
|
|
cmd.SetKeyword(cs, data.localKeywords.temporalFiltering, data.willRunTemporalFilter);
|
|
cmd.SetKeyword(cs, data.localKeywords.orthographic, computeParams.orthographicCamera);
|
|
|
|
cmd.SetComputeVectorParam(cs, SSAOUtils.ShaderConstants._SSAOParams, computeParams.ssaoParams);
|
|
cmd.SetComputeVectorParam(cs, SSAOUtils.ShaderConstants._SSAOParams2, computeParams.ssaoParams2);
|
|
cmd.SetComputeVectorParam(cs, SSAOUtils.ShaderConstants._AODepthToViewParams, computeParams.depthToViewParams);
|
|
cmd.SetComputeVectorParam(cs, SSAOUtils.ShaderConstants._SourceSize, computeParams.sourceSize);
|
|
cmd.SetComputeVectorParam(cs, SSAOUtils.ShaderConstants._ProjectionParams2, computeParams.projectionParams2);
|
|
cmd.SetComputeMatrixArrayParam(cs, SSAOUtils.ShaderConstants._CameraViewProjections, data.cameraViewProjections);
|
|
cmd.SetComputeVectorArrayParam(cs, SSAOUtils.ShaderConstants._CameraViewTopLeftCorner, data.cameraTopLeftCorner);
|
|
cmd.SetComputeVectorArrayParam(cs, SSAOUtils.ShaderConstants._CameraViewXExtent, data.cameraXExtent);
|
|
cmd.SetComputeVectorArrayParam(cs, SSAOUtils.ShaderConstants._CameraViewYExtent, data.cameraYExtent);
|
|
cmd.SetComputeVectorArrayParam(cs, SSAOUtils.ShaderConstants._CameraViewZExtent, data.cameraZExtent);
|
|
cmd.SetComputeIntParam(cs, ShaderIDs._GTAODirectionCount, data.directionCount);
|
|
cmd.SetComputeIntParam(cs, ShaderIDs._GTAOStepCount, data.stepCount);
|
|
cmd.SetComputeIntParam(cs, ShaderIDs._GTAOSpatialFilter, (int)data.spatialFilter);
|
|
|
|
cmd.SetComputeVectorParam(cs, SSAOUtils.ShaderConstants._SSAOBlueNoiseParams, computeParams.blueNoiseParams);
|
|
cmd.SetComputeTextureParam(cs, data.kernel, SSAOUtils.ShaderConstants._BlueNoiseTexture, data.blueNoiseTexture);
|
|
|
|
if (data.willRunTemporalFilter)
|
|
{
|
|
cmd.SetComputeFloatParam(cs, ShaderIDs._SSAOHistoryLength, computeParams.historyLength);
|
|
cmd.SetComputeFloatParam(cs, ShaderIDs._SSAOGhostingMitigation, computeParams.ghostingMitigation);
|
|
cmd.SetComputeFloatParam(cs, ShaderIDs._SSAOTemporalRotation, computeParams.temporalRotation);
|
|
cmd.SetComputeIntParam(cs, ShaderIDs._SSAOTemporalOffset, computeParams.temporalOffset);
|
|
}
|
|
|
|
cmd.SetComputeTextureParam(cs, data.kernel, ShaderIDs._CameraDepthTexture, data.depthTexture);
|
|
cmd.SetComputeTextureParam(cs, data.kernel, SSAOUtils.ShaderConstants._CameraNormalsTexture, data.normalsTexture);
|
|
cmd.SetComputeTextureParam(cs, data.kernel, ShaderIDs._AOOutput, data.aoTexture);
|
|
cmd.DispatchCompute(cs, data.kernel, data.dispatchSize.x, data.dispatchSize.y, 1);
|
|
});
|
|
}
|
|
}
|
|
|
|
private void RecordComputeDispatchPass(RenderGraph renderGraph, string passName, int kernel, Vector2Int dispatchSize, TextureHandle srcTexture, TextureHandle dstTexture, int dstPropertyId, TextureHandle depthTexture = default, float boxFilterStep = 0.0f)
|
|
{
|
|
using (var builder = renderGraph.AddComputePass<GTAOSingleDispatchPassData>(passName, out var passData, m_ProfilingSampler))
|
|
{
|
|
passData.cs = m_ComputePathState.shader;
|
|
passData.kernel = kernel;
|
|
passData.dispatchSize = dispatchSize;
|
|
passData.srcTexture = srcTexture;
|
|
passData.depthTexture = depthTexture;
|
|
passData.dstTexture = dstTexture;
|
|
passData.dstPropertyId = dstPropertyId;
|
|
passData.boxFilterStep = boxFilterStep;
|
|
|
|
builder.UseTexture(srcTexture, AccessFlags.Read);
|
|
if (depthTexture.IsValid())
|
|
builder.UseTexture(depthTexture, AccessFlags.Read);
|
|
builder.UseTexture(dstTexture, AccessFlags.Write);
|
|
|
|
builder.SetRenderFunc(static (GTAOSingleDispatchPassData data, ComputeGraphContext ctx) =>
|
|
{
|
|
ctx.cmd.SetComputeTextureParam(data.cs, data.kernel, SSAOUtils.ShaderConstants._BlitTexture, data.srcTexture);
|
|
if (data.depthTexture.IsValid())
|
|
ctx.cmd.SetComputeTextureParam(data.cs, data.kernel, ShaderIDs._CameraDepthTexture, data.depthTexture);
|
|
ctx.cmd.SetComputeFloatParam(data.cs, ShaderIDs._GTAOBoxFilterStep, data.boxFilterStep);
|
|
ctx.cmd.SetComputeTextureParam(data.cs, data.kernel, data.dstPropertyId, data.dstTexture);
|
|
ctx.cmd.DispatchCompute(data.cs, data.kernel, data.dispatchSize.x, data.dispatchSize.y, 1);
|
|
});
|
|
}
|
|
}
|
|
|
|
private void RecordCopyHistoryPass(RenderGraph renderGraph, string passName, Vector2Int dispatchSize, TextureHandle srcTexture, TextureHandle depthTexture, TextureHandle historyTexture)
|
|
{
|
|
using (var builder = renderGraph.AddComputePass<GTAOCopyHistoryPassData>(passName, out var passData, m_ProfilingSampler))
|
|
{
|
|
passData.cs = m_ComputePathState.shader;
|
|
passData.kernel = m_ComputePathState.copyHistoryKernel;
|
|
passData.dispatchSize = dispatchSize;
|
|
passData.srcTexture = srcTexture;
|
|
passData.depthTexture = depthTexture;
|
|
passData.historyTexture = historyTexture;
|
|
|
|
builder.UseTexture(srcTexture, AccessFlags.Read);
|
|
builder.UseTexture(depthTexture, AccessFlags.Read);
|
|
builder.UseTexture(historyTexture, AccessFlags.Write);
|
|
|
|
builder.SetRenderFunc(static (GTAOCopyHistoryPassData data, ComputeGraphContext ctx) =>
|
|
{
|
|
var cmd = ctx.cmd;
|
|
cmd.SetComputeTextureParam(data.cs, data.kernel, SSAOUtils.ShaderConstants._BlitTexture, data.srcTexture);
|
|
cmd.SetComputeTextureParam(data.cs, data.kernel, ShaderIDs._CameraDepthTexture, data.depthTexture);
|
|
cmd.SetComputeTextureParam(data.cs, data.kernel, ShaderIDs._AOOutputHistory, data.historyTexture);
|
|
cmd.DispatchCompute(data.cs, data.kernel, data.dispatchSize.x, data.dispatchSize.y, 1);
|
|
});
|
|
}
|
|
}
|
|
|
|
private void RecordTemporalFilterPass(RenderGraph renderGraph, Vector2Int dispatchSize, TextureHandle aoTexture, TextureHandle depthTexture, TextureHandle historyReadTexture, TextureHandle historyWriteTexture, TextureHandle motionVectorTexture, TextureHandle temporalTexture)
|
|
{
|
|
using (var builder = renderGraph.AddComputePass<GTAOTemporalPassData>("GTAO Temporal", out var passData, m_ProfilingSampler))
|
|
{
|
|
passData.cs = m_ComputePathState.shader;
|
|
passData.kernel = m_ComputePathState.temporalKernel;
|
|
passData.dispatchSize = dispatchSize;
|
|
passData.aoTexture = aoTexture;
|
|
passData.depthTexture = depthTexture;
|
|
passData.historyReadTexture = historyReadTexture;
|
|
passData.historyWriteTexture = historyWriteTexture;
|
|
passData.temporalTexture = temporalTexture;
|
|
passData.spatialFilter = m_CurrentSettings.GTAOSpatialFilter;
|
|
|
|
builder.UseTexture(aoTexture, AccessFlags.Read);
|
|
builder.UseTexture(depthTexture, AccessFlags.Read);
|
|
builder.UseTexture(historyReadTexture, AccessFlags.Read);
|
|
builder.UseTexture(historyWriteTexture, AccessFlags.Write);
|
|
builder.UseTexture(temporalTexture, AccessFlags.Write);
|
|
|
|
Debug.Assert(motionVectorTexture.IsValid(), "Motion vector texture is invalid. GTAO temporal filter requires a motion vector texture.");
|
|
passData.motionVectorTexture = motionVectorTexture;
|
|
builder.UseTexture(motionVectorTexture, AccessFlags.Read);
|
|
|
|
builder.SetRenderFunc(static (GTAOTemporalPassData data, ComputeGraphContext ctx) =>
|
|
{
|
|
var cmd = ctx.cmd;
|
|
cmd.SetComputeTextureParam(data.cs, data.kernel, SSAOUtils.ShaderConstants._BlitTexture, data.aoTexture);
|
|
cmd.SetComputeTextureParam(data.cs, data.kernel, ShaderIDs._CameraDepthTexture, data.depthTexture);
|
|
cmd.SetComputeTextureParam(data.cs, data.kernel, ShaderIDs._AOPackedHistory, data.historyReadTexture);
|
|
cmd.SetComputeTextureParam(data.cs, data.kernel, ShaderIDs._AOOutputHistory, data.historyWriteTexture);
|
|
cmd.SetComputeTextureParam(data.cs, data.kernel, ShaderIDs._MotionVectorTexture, data.motionVectorTexture);
|
|
cmd.SetComputeTextureParam(data.cs, data.kernel, ShaderIDs._OcclusionTexture, data.temporalTexture);
|
|
cmd.SetComputeIntParam(data.cs, ShaderIDs._GTAOSpatialFilter, (int)data.spatialFilter);
|
|
cmd.DispatchCompute(data.cs, data.kernel, data.dispatchSize.x, data.dispatchSize.y, 1);
|
|
});
|
|
}
|
|
}
|
|
|
|
private void RecordFinalBlitPass(RenderGraph renderGraph, TextureHandle srcTexture, TextureHandle finalTexture, float directLightingStrength, Vector2Int finalDispatchSize)
|
|
{
|
|
using (var builder = renderGraph.AddComputePass<GTAOFinalBlitPassData>("GTAO FinalBlit", out var passData, m_ProfilingSampler))
|
|
{
|
|
passData.cs = m_ComputePathState.shader;
|
|
passData.kernel = m_ComputePathState.finalBlitKernel;
|
|
passData.dispatchSize = finalDispatchSize;
|
|
passData.directLightingStrength = directLightingStrength;
|
|
passData.srcTexture = srcTexture;
|
|
passData.finalTexture = finalTexture;
|
|
|
|
builder.UseTexture(srcTexture, AccessFlags.Read);
|
|
builder.UseTexture(finalTexture, AccessFlags.Write);
|
|
builder.SetGlobalTextureAfterPass(finalTexture, SSAOUtils.ShaderConstants._SSAOFinalTexture);
|
|
builder.AllowGlobalStateModification(true);
|
|
|
|
builder.SetRenderFunc(static (GTAOFinalBlitPassData data, ComputeGraphContext ctx) =>
|
|
{
|
|
ctx.cmd.SetComputeTextureParam(data.cs, data.kernel, SSAOUtils.ShaderConstants._BlitTexture, data.srcTexture);
|
|
ctx.cmd.SetComputeTextureParam(data.cs, data.kernel, ShaderIDs._FinalOutput, data.finalTexture);
|
|
ctx.cmd.DispatchCompute(data.cs, data.kernel, data.dispatchSize.x, data.dispatchSize.y, 1);
|
|
ctx.cmd.SetKeyword(ShaderGlobalKeywords.ScreenSpaceOcclusion, true);
|
|
ctx.cmd.SetGlobalVector(SSAOUtils.ShaderConstants._AmbientOcclusionParam, new Vector4(1f, 0f, 0f, data.directLightingStrength));
|
|
});
|
|
}
|
|
}
|
|
|
|
private void RecordAfterOpaqueBlitPass(RenderGraph renderGraph, GTAOComputeParams computeParams, TextureHandle sourceTexture, TextureHandle targetTexture, int shaderPass)
|
|
{
|
|
using (var builder = renderGraph.AddRasterRenderPass<GTAOAfterOpaqueBlitPassData>("GTAO AfterOpaque Blit", out var passData, m_ProfilingSampler))
|
|
{
|
|
passData.material = m_Material;
|
|
passData.sourceSize = computeParams.sourceSize;
|
|
passData.ssaoParams = computeParams.ssaoParams;
|
|
passData.shaderPass = shaderPass;
|
|
passData.sourceTexture = sourceTexture;
|
|
passData.targetTexture = targetTexture;
|
|
|
|
builder.UseTexture(passData.sourceTexture, AccessFlags.Read);
|
|
builder.SetRenderAttachment(passData.targetTexture, 0, AccessFlags.Write);
|
|
|
|
builder.SetRenderFunc(static (GTAOAfterOpaqueBlitPassData data, RasterGraphContext ctx) =>
|
|
{
|
|
Vector4 viewScaleBias = SSAOUtils.ComputeScaleBias(data.sourceTexture, SSAOUtils.IsYFlip(ctx, in data.sourceTexture, in data.targetTexture));
|
|
data.material.SetVector(SSAOUtils.ShaderConstants._SourceSize, data.sourceSize);
|
|
data.material.SetVector(SSAOUtils.ShaderConstants._SSAOParams, data.ssaoParams);
|
|
Blitter.BlitTexture(ctx.cmd, data.sourceTexture, viewScaleBias, data.material, data.shaderPass);
|
|
});
|
|
}
|
|
}
|
|
|
|
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_ComputePathState.Release();
|
|
CoreUtils.Destroy(m_Material);
|
|
m_Material = null;
|
|
m_SSAOParamsPrev = default;
|
|
}
|
|
}
|
|
}
|
|
#endif
|