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

114 lines
3.8 KiB
Plaintext

#include "Packages/com.unity.render-pipelines.high-definition/Runtime/Lighting/ScreenSpaceLighting/GTAOCommon.hlsl"
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/NormalBuffer.hlsl"
#pragma kernel TemporalDenoise
#pragma multi_compile HALF_RES FULL_RES
uint PackHistoryData(float AO, float depth, float mvLen)
{
uint packedVal = 0;
packedVal = BitFieldInsert(0x000000ff, UnpackInt(AO, 8), packedVal);
packedVal = BitFieldInsert(0x0000ff00, UnpackInt(mvLen, 8) << 8, packedVal);
packedVal = BitFieldInsert(0xffff0000, UnpackInt(depth, 16) << 16, packedVal);
return packedVal;
}
void UnpackHistoryData(uint historyData, out float AO, out float depth, out float mvLen)
{
AO = UnpackUIntToFloat(historyData, 0, 8);
mvLen = UnpackUIntToFloat(historyData, 8, 8);
depth = UnpackUIntToFloat(historyData, 16, 16);
}
RW_TEXTURE2D_X(uint, _AOOutputHistory);
TEXTURE2D_X(_AOPackedBlurred);
TEXTURE2D_X_UINT(_AOPackedHistory);
#if HALF_RES
RW_TEXTURE2D_X(float, _OcclusionTexture);
#else
RW_TEXTURE2D_X(float, _OcclusionTexture);
#endif
float3 FindMinMaxAvgAO(float2 centralPos)
{
float minAO = 2.0f;
float maxAO = -2.0f;
float avg = 0;
for (int i = -1; i <= 1; ++i)
{
for (int j = -1; j <= 1; ++j)
{
float data = LOAD_TEXTURE2D_X(_AOPackedBlurred, (uint2)centralPos + uint2(i, j)).x;
float currAO, ignored;
UnpackData(data, currAO, ignored);
avg += currAO;
minAO = min(minAO, currAO);
maxAO = max(maxAO, currAO);
}
}
return float3(minAO, maxAO, avg/9);
}
[numthreads(8, 8, 1)]
void TemporalDenoise(uint3 dispatchThreadId : SV_DispatchThreadID)
{
UNITY_XR_ASSIGN_VIEW_INDEX(dispatchThreadId.z);
float currFrameData = _AOPackedBlurred[COORD_TEXTURE2D_X(dispatchThreadId.xy)].x;
float currDepth, currAO;
UnpackData(currFrameData, currAO, currDepth);
PositionInputs posInputs = GetPositionInput(float2(dispatchThreadId.xy), _ScreenSize.zw, uint2(8, 8));
#if HALF_RES
float2 closest = posInputs.positionSS * 2;
#else
float2 closest = posInputs.positionSS;
#endif
float2 motionVector;
DecodeMotionVector(LOAD_TEXTURE2D_X(_CameraMotionVectorsTexture, closest), motionVector);
float motionVecLength = length(motionVector);
float2 uv = (dispatchThreadId.xy + 0.5) * _AOBufferSize.zw;
float2 prevFrameNDC = uv - motionVector;
uint prevData = asuint(_AOPackedHistory[COORD_TEXTURE2D_X((prevFrameNDC) * _AOHistorySize.xy)].x);
float prevMotionVecLen, prevAO, prevDepth;
UnpackHistoryData(prevData, prevAO, prevDepth, prevMotionVecLen);
float motionVecWeighting = saturate(motionVecLength * 100.0);
float velWeight = 1.0f - saturate((abs(prevMotionVecLen - motionVecWeighting)) * 3.0f);
float3 minMax = FindMinMaxAvgAO(float2(dispatchThreadId.xy));
float minAO = minMax.x;
float maxAO = minMax.y;
float avg = minMax.z;
float nudge = lerp(_AOTemporalUpperNudgeLimit, _AOTemporalLowerNudgeLimit, motionVecWeighting) * abs(avg - currAO);
minAO -= nudge;
maxAO += nudge;
float diff = abs(currAO - prevAO) / Max3(prevAO, currAO, 0.1f);
float weight = 1.0 - diff;
float feedback = lerp(0.85, 0.95, weight * weight);
prevAO = clamp(prevAO, minAO, maxAO);
float depth_similarity = saturate(pow(prevDepth / currDepth, 1) + 0.01);
float newAO = (lerp(currAO, prevAO, feedback * depth_similarity * velWeight));
_AOOutputHistory[COORD_TEXTURE2D_X(dispatchThreadId.xy)] = PackHistoryData(newAO, currDepth, motionVecWeighting);
#ifdef HALF_RES
// The conversion and the pow happens in upsample phase.
_OcclusionTexture[COORD_TEXTURE2D_X(dispatchThreadId.xy)] = PackAOOutput(newAO, currDepth);
#else
_OcclusionTexture[COORD_TEXTURE2D_X(dispatchThreadId.xy)] = OutputFinalAO(newAO);
#endif
}