|
|
@@ -3,11 +3,14 @@
|
|
|
// Code licensed under the BSD License.
|
|
|
// http://www.anki3d.org/LICENSE
|
|
|
|
|
|
-#pragma anki mutator BLUR_ORIENTATION 0 1
|
|
|
+#pragma anki mutator BLUR_ORIENTATION 0 1 // 0: in X asix, 1: in Y axis
|
|
|
|
|
|
#pragma anki start comp
|
|
|
|
|
|
#include <AnKi/Shaders/Include/IndirectDiffuseTypes.h>
|
|
|
+#include <AnKi/Shaders/PackFunctions.glsl>
|
|
|
+#include <AnKi/Shaders/Functions.glsl>
|
|
|
+#include <AnKi/Shaders/BilateralFilter.glsl>
|
|
|
|
|
|
const UVec2 WORKGROUP_SIZE = UVec2(8u, 8u);
|
|
|
layout(local_size_x = WORKGROUP_SIZE.x, local_size_y = WORKGROUP_SIZE.y) in;
|
|
|
@@ -17,15 +20,117 @@ layout(set = 0, binding = 1) uniform texture2D u_toDenoiseTex;
|
|
|
layout(set = 0, binding = 2) uniform texture2D u_depthTex;
|
|
|
layout(set = 0, binding = 3) uniform texture2D u_gbuffer2Tex;
|
|
|
layout(set = 0, binding = 4) uniform texture2D u_momentsAndHistoryLengthTex;
|
|
|
-layout(set = 0, binding = 5) writeonly uniform uimage2D u_outImg;
|
|
|
+layout(set = 0, binding = 5) writeonly uniform image2D u_outImg;
|
|
|
|
|
|
-layout(push_constant, std140, row_major) uniform b_pc
|
|
|
+layout(push_constant, std430, row_major) uniform b_pc
|
|
|
{
|
|
|
- IndirectDiffuseDenoiseUniforms m_unis;
|
|
|
+ IndirectDiffuseDenoiseUniforms u_unis;
|
|
|
};
|
|
|
|
|
|
+Vec3 unproject(Vec2 ndc, F32 depth)
|
|
|
+{
|
|
|
+ const Vec4 worldPos4 = u_unis.m_invertedViewProjectionJitterMat * Vec4(ndc, depth, 1.0);
|
|
|
+ const Vec3 worldPos = worldPos4.xyz / worldPos4.w;
|
|
|
+ return worldPos;
|
|
|
+}
|
|
|
+
|
|
|
+F32 computeSpatialVariance(Vec2 uv)
|
|
|
+{
|
|
|
+ const F32 kernel[2][2] = {{1.0 / 4.0, 1.0 / 8.0}, {1.0 / 8.0, 1.0 / 16.0}};
|
|
|
+ const I32 radius = 1;
|
|
|
+ const Vec2 texelSize = 1.0 / u_unis.m_viewportSizef;
|
|
|
+ Vec2 sumMoments = Vec2(0.0);
|
|
|
+
|
|
|
+ for(I32 yy = -radius; yy <= radius; yy++)
|
|
|
+ {
|
|
|
+ for(I32 xx = -radius; xx <= radius; xx++)
|
|
|
+ {
|
|
|
+ const Vec2 newUv = uv + Vec2(xx, yy) * texelSize;
|
|
|
+ const F32 k = kernel[abs(xx)][abs(yy)];
|
|
|
+ sumMoments += textureLod(u_momentsAndHistoryLengthTex, u_linearAnyClampSampler, newUv, 0.0).xy * k;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return abs(sumMoments.y - sumMoments.x * sumMoments.x);
|
|
|
+}
|
|
|
+
|
|
|
void main()
|
|
|
{
|
|
|
+ if(skipOutOfBoundsInvocations(WORKGROUP_SIZE, u_unis.m_viewportSize))
|
|
|
+ {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ const Vec2 uv = (Vec2(gl_GlobalInvocationID.xy) + 0.5) / u_unis.m_viewportSizef;
|
|
|
+
|
|
|
+ // Reference
|
|
|
+ const F32 depthCenter = textureLod(u_depthTex, u_linearAnyClampSampler, uv, 0.0).r;
|
|
|
+ if(depthCenter == 1.0)
|
|
|
+ {
|
|
|
+ imageStore(u_outImg, IVec2(gl_GlobalInvocationID.xy), Vec4(0.0));
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ const Vec3 positionCenter = unproject(UV_TO_NDC(uv), depthCenter);
|
|
|
+ const Vec3 normalCenter = readNormalFromGBuffer(u_gbuffer2Tex, u_linearAnyClampSampler, uv);
|
|
|
+
|
|
|
+ // Decide the amount of blurring
|
|
|
+ const F32 varianceCenter = computeSpatialVariance(uv);
|
|
|
+ const F32 historyLength = textureLod(u_momentsAndHistoryLengthTex, u_linearAnyClampSampler, uv, 0.0).z;
|
|
|
+
|
|
|
+ F32 sampleCount;
|
|
|
+ if(historyLength < 2.0)
|
|
|
+ {
|
|
|
+ // Worst case
|
|
|
+ sampleCount = u_unis.m_maxSampleCount;
|
|
|
+ }
|
|
|
+ else if(historyLength > 4.0 && varianceCenter < 0.0001)
|
|
|
+ {
|
|
|
+ // Best case
|
|
|
+ sampleCount = u_unis.m_minSampleCount;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ // Every other case
|
|
|
+
|
|
|
+ F32 blur = varianceCenter * 100.0;
|
|
|
+ blur = min(1.0, blur);
|
|
|
+
|
|
|
+ sampleCount = mix(u_unis.m_minSampleCount, u_unis.m_maxSampleCount, blur);
|
|
|
+ }
|
|
|
+
|
|
|
+ sampleCount = 32.0;
|
|
|
+ sampleCount = sampleCount / 2.0;
|
|
|
+ sampleCount = floor(sampleCount);
|
|
|
+
|
|
|
+ // Sample
|
|
|
+ F32 weight = EPSILON;
|
|
|
+ Vec3 color = Vec3(0.0);
|
|
|
+
|
|
|
+ for(F32 i = -sampleCount; i <= sampleCount; i += 1.0)
|
|
|
+ {
|
|
|
+ const Vec2 texelSize = 1.0 / u_unis.m_viewportSizef;
|
|
|
+#if BLUR_ORIENTATION == 0
|
|
|
+ const Vec2 sampleUv = Vec2(uv.x + i * texelSize.x, uv.y);
|
|
|
+#else
|
|
|
+ const Vec2 sampleUv = Vec2(uv.x, uv.y + i * texelSize.y);
|
|
|
+#endif
|
|
|
+
|
|
|
+ const F32 depthTap = textureLod(u_depthTex, u_linearAnyClampSampler, sampleUv, 0.0).r;
|
|
|
+ const Vec3 positionTap = unproject(UV_TO_NDC(sampleUv), depthTap);
|
|
|
+ const Vec3 normalTap =
|
|
|
+ unpackNormalFromGBuffer(textureLod(u_gbuffer2Tex, u_linearAnyClampSampler, sampleUv, 0.0));
|
|
|
+
|
|
|
+ F32 w = calculateBilateralWeightPlane(positionCenter, normalCenter, positionTap, normalTap, 1.0);
|
|
|
+ // w *= gaussianWeight(0.4, abs(F32(i)) / (sampleCount + 1.0));
|
|
|
+ weight += w;
|
|
|
+
|
|
|
+ color += textureLod(u_toDenoiseTex, u_linearAnyClampSampler, sampleUv, 0.0).xyz * w;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Normalize and store
|
|
|
+ color /= weight;
|
|
|
+ imageStore(u_outImg, IVec2(gl_GlobalInvocationID.xy), Vec4(color, 0.0));
|
|
|
}
|
|
|
|
|
|
#pragma anki end
|