-
Notifications
You must be signed in to change notification settings - Fork 869
Expand file tree
/
Copy pathScreenResolveUpsampling.compute
More file actions
103 lines (79 loc) · 4.39 KB
/
ScreenResolveUpsampling.compute
File metadata and controls
103 lines (79 loc) · 4.39 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
#pragma only_renderers d3d11 playstation xboxone xboxseries vulkan metal glcore ps5
#pragma kernel Upsample
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/GBufferCommon.hlsl"
#include "Packages/com.unity.render-pipelines.core/Runtime/Sampling/QuasiRandom.hlsl"
#include "Packages/com.unity.render-pipelines.core/Runtime/Lighting/SurfaceCache/VectorLogic.hlsl"
#include "Packages/com.unity.render-pipelines.core/Runtime/Lighting/SurfaceCache/IrradianceCompression.hlsl"
#include "Packages/com.unity.render-pipelines.core/Runtime/Lighting/SurfaceCache/PatchUtil.hlsl"
#include "Packages/com.unity.render-pipelines.core/Runtime/Lighting/SurfaceCache/Common.hlsl"
Texture2D<float> _FullResDepths;
Texture2D<float3> _FullResFlatNormals;
Texture2D<float3> _FullResShadedNormals;
Texture2D<float3> _LowResIrradiancesL0;
Texture2D<float3> _LowResIrradiancesL10;
Texture2D<float3> _LowResIrradiancesL11;
Texture2D<float3> _LowResIrradiancesL12;
RWTexture2D<float4> _FullResIrradiances;
float _FilterRadius;
uint _SampleCount;
float4x4 _ClipToWorldTransform;
[numthreads(16, 16, 1)]
void Upsample(uint2 targetPixelPos : SV_DispatchThreadID)
{
uint2 fullRes;
_FullResDepths.GetDimensions(fullRes.x, fullRes.y);
if (any(targetPixelPos >= fullRes))
return;
QrngKronecker rng;
rng.Init(targetPixelPos, 0);
const float ndcDepth = LoadNdcDepth(_FullResDepths, targetPixelPos);
if (ndcDepth == invalidNdcDepth)
return;
const float2 targetPixelUv = PixelPosToUvPos(targetPixelPos, rcp(float2(fullRes)));
const float3 targetWorldPos = ComputeWorldSpacePosition(targetPixelUv, ndcDepth, _ClipToWorldTransform);
const float3 targetWorldFlatNormal = _FullResFlatNormals[targetPixelPos];
const int2 targetPixelPosLowRes = int2(targetPixelPos / lowResScreenScaling);
const float reciprocalSampleCount = rcp(_SampleCount);
float weightSum = 0.0f;
SphericalHarmonics::RGBL1 irradianceSum = (SphericalHarmonics::RGBL1)0;
for (uint sampleIdx = 0; sampleIdx < _SampleCount; ++sampleIdx)
{
const float goldenAngle = 2.39996323f;
const float kernelExponent = 0.5f;
const float angle = rng.GetFloat(0) + goldenAngle * sampleIdx;
const float radius = pow(float(sampleIdx + 1) * reciprocalSampleCount, kernelExponent) * _FilterRadius;
float2 sinCos;
sincos(angle, sinCos.x, sinCos.y);
const int2 samplePixelPosLowRes = targetPixelPosLowRes + int2(sinCos * radius);
if(any(VECTOR_LOGIC_OR(samplePixelPosLowRes < 0, int2(fullRes) <= samplePixelPosLowRes)))
continue;
const uint2 samplePixelPosFullRes = samplePixelPosLowRes * lowResScreenScaling;
const float sampleDepth = _FullResDepths[samplePixelPosFullRes];
if (sampleDepth == 0.0f)
continue;
const float2 sampleUvPosFullRes = (float2(samplePixelPosFullRes) + 0.5f) / float2(fullRes);
const float3 sampleWorldPos = ComputeWorldSpacePosition(sampleUvPosFullRes, sampleDepth, _ClipToWorldTransform);
const float3 sampleWorldFlatNormal = _FullResFlatNormals[samplePixelPosFullRes].xyz;
const SphericalHarmonics::RGBL1 contribution = IrradianceCompression::LoadAndDecompress(_LowResIrradiancesL0, _LowResIrradiancesL10, _LowResIrradiancesL11, _LowResIrradiancesL12, samplePixelPosLowRes);
float weight = 1.0f;
weight *= max(0.0f, dot(targetWorldFlatNormal, sampleWorldFlatNormal));
const float planeDistance = abs(dot(targetWorldFlatNormal, sampleWorldPos - targetWorldPos));
const float maxWeight = 32.0f;
weight *= min(1.0f / planeDistance, maxWeight);
// This effectively acts as a fallback in cases where a pixel finds no good samples.
weight += 0.01f;
if (all(contribution.l0 == PatchUtil::invalidIrradiance))
continue;
weightSum += weight;
SphericalHarmonics::MulAddMut(irradianceSum, weight, contribution);
}
float3 output = 0.0f;
if (weightSum != 0.0f)
{
const SphericalHarmonics::RGBL1 irradiance = SphericalHarmonics::MulPure(irradianceSum, rcp(weightSum));
const float3 unpackedNormal = UnpackGBufferNormal(_FullResShadedNormals[targetPixelPos]);
output = max(0.0f, SphericalHarmonics::Eval(irradiance, unpackedNormal));
}
_FullResIrradiances[targetPixelPos] = float4(output, 1);
}