2021-09-09 20:42:29 -04:00

168 lines
5.4 KiB
HLSL

#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl"
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/ShaderLibrary/ShaderVariables.hlsl"
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/Builtin/BuiltinData.hlsl"
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Packing.hlsl"
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/Lighting/ScreenSpaceLighting/ShaderVariablesAmbientOcclusion.cs.hlsl"
#define _AOBaseResMip (int)_AOParams0.x
#define _AOFOVCorrection _AOParams0.y
#define _AORadius _AOParams0.z
#define _AOStepCount (uint)_AOParams0.w
#define _AOIntensity _AOParams1.x
#define _AOInvRadiusSq _AOParams1.y
#define _AOTemporalOffsetIdx _AOParams1.z
#define _AOTemporalRotationIdx _AOParams1.w
#define _AOInvStepCountPlusOne _AOParams2.z
#define _AOMaxRadiusInPixels (int)_AOParams2.w
#define _AOHistorySize _AOParams2.xy
#define _AODirectionCount _AOParams4.x
#define _FirstDepthMipOffset _FirstTwoDepthMipOffsets.xy
#define _SecondDepthMipOffset _FirstTwoDepthMipOffsets.zw
// For denoising, whether temporal or not
#define _BlurTolerance _AOParams3.x
#define _UpsampleTolerance _AOParams3.y
#define _NoiseFilterStrength _AOParams3.z
#define _StepSize _AOParams3.w
#define _AOTemporalUpperNudgeLimit _AOParams4.y
#define _AOTemporalLowerNudgeLimit _AOParams4.z
#define _AOSpatialBilateralAggressiveness _AOParams4.w
// If this is set to 0 best quality is achieved when full res, but performance is significantly lower.
// If set to 1, when full res, it may lead to extra aliasing and loss of detail, but still significant higher quality than half res.
#define HALF_RES_DEPTH_WHEN_FULL_RES 1 // Make this an option.
#define HALF_RES_DEPTH_WHEN_FULL_RES_FOR_CENTRAL 0
// This increases the quality when running with half resolution buffer, however it adds a bit of cost. Note that it will not have artifact as we already don't allow samples to be at the edge of the depth buffer.
#define MIN_DEPTH_GATHERED_FOR_CENTRAL 0
#define CENTRAL_AND_SAMPLE_DEPTH_FETCH_SAME_METHOD 0
#define LOWER_RES_SAMPLE 1
float GetMinDepth(float2 localUVs)
{
localUVs = ClampAndScaleUVForBilinear(localUVs, _AOBufferSize.zw);
localUVs.x = localUVs.x * 0.5f;
localUVs.y = localUVs.y * (1.0f / 3.0f) + (2.0f / 3.0f);
float4 gatheredDepth = GATHER_TEXTURE2D_X(_CameraDepthTexture, s_point_clamp_sampler, localUVs);
return min(Min3(gatheredDepth.x, gatheredDepth.y, gatheredDepth.z), gatheredDepth.w);
}
float GetDepthForCentral(float2 positionSS)
{
#ifdef FULL_RES
#if HALF_RES_DEPTH_WHEN_FULL_RES_FOR_CENTRAL
#if MIN_DEPTH_GATHERED_FOR_CENTRAL
float2 localUVs = positionSS.xy * _AOBufferSize.zw;
return GetMinDepth(localUVs);
#else // MIN_DEPTH_GATHERED_FOR_CENTRAL
return LOAD_TEXTURE2D_X(_CameraDepthTexture, float2(0.0f, _AORTHandleSize.y) + positionSS / 2).r;
#endif
#else // HALF_RES_DEPTH_WHEN_FULL_RES
return LOAD_TEXTURE2D_X(_CameraDepthTexture, positionSS).r;
#endif
#else // FULL_RES
#if MIN_DEPTH_GATHERED_FOR_CENTRAL
float2 localUVs = positionSS.xy * _AOBufferSize.zw;
return GetMinDepth(localUVs);
#else
return LOAD_TEXTURE2D_X(_CameraDepthTexture, _FirstDepthMipOffset + (uint2)positionSS.xy).r;
#endif
#endif
}
float GetDepthSample(float2 positionSS, bool lowerRes)
{
#if CENTRAL_AND_SAMPLE_DEPTH_FETCH_SAME_METHOD
return GetDepthForCentral(positionSS);
#endif
#ifdef FULL_RES
#if HALF_RES_DEPTH_WHEN_FULL_RES
return LOAD_TEXTURE2D_X(_CameraDepthTexture, _FirstDepthMipOffset + positionSS / 2).r;
#endif
return LOAD_TEXTURE2D_X(_CameraDepthTexture, positionSS).r;
#else // FULL_RES
#if LOWER_RES_SAMPLE
if (lowerRes)
{
return LOAD_TEXTURE2D_X(_CameraDepthTexture, _SecondDepthMipOffset + (uint2)positionSS.xy / 2).r;
}
else
#endif
{
return LOAD_TEXTURE2D_X(_CameraDepthTexture, _FirstDepthMipOffset + (uint2)positionSS.xy).r;
}
#endif
}
float GTAOFastAcos(float x)
{
float outVal = -0.156583 * abs(x) + HALF_PI;
outVal *= sqrt(1.0 - abs(x));
return x >= 0 ? outVal : PI - outVal;
}
// --------------------------------------------
// Output functions
// --------------------------------------------
float PackAOOutput(float AO, float depth)
{
uint packedDepth = PackFloatToUInt(depth, 0, 23);
uint packedAO = PackFloatToUInt(AO, 24, 8);
uint packedVal = packedAO | packedDepth;
// If it is a NaN we have no guarantee the sampler will keep the bit pattern, hence we invalidate the depth, meaning that the various bilateral passes will skip the sample.
if ((packedVal & 0x7FFFFFFF) > 0x7F800000)
{
packedVal = packedAO;
}
// We need to output as float as gather4 on an integer texture is not always supported.
return asfloat(packedVal);
}
void UnpackData(float data, out float AO, out float depth)
{
depth = UnpackUIntToFloat(asuint(data), 0, 23);
AO = UnpackUIntToFloat(asuint(data), 24, 8);
}
void UnpackGatheredData(float4 data, out float4 AOs, out float4 depths)
{
UnpackData(data.x, AOs.x, depths.x);
UnpackData(data.y, AOs.y, depths.y);
UnpackData(data.z, AOs.z, depths.z);
UnpackData(data.w, AOs.w, depths.w);
}
void GatherAOData(TEXTURE2D_X_FLOAT(_AODataSource), float2 UV, out float4 AOs, out float4 depths)
{
float4 data = GATHER_TEXTURE2D_X(_AODataSource, s_point_clamp_sampler, UV);
UnpackGatheredData(data, AOs, depths);
}
float OutputFinalAO(float AO)
{
return 1.0f - PositivePow(AO, _AOIntensity);
}