168 lines
5.4 KiB
HLSL
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);
|
|
}
|