Skip to content

Instantly share code, notes, and snippets.

@N8python
Created July 12, 2026 00:38
Show Gist options
  • Select an option

  • Save N8python/1ec6be983c92f8f52b33c0db3635a319 to your computer and use it in GitHub Desktop.

Select an option

Save N8python/1ec6be983c92f8f52b33c0db3635a319 to your computer and use it in GitHub Desktop.
Full model used by N8AO's new neural denoiser.
// N8AO 2.0.0 generated neural Poisson-blur fragment shader
// Variant: Neural-High, 16 denoise taps, perspective camera, standard depth
// Network: 552 inline int8 coefficients, 517 nonzero terms after zero pruning
// This is the exact ShaderMaterial fragment source; Three.js prepends its GLSL3 program prefix.
#define NEURAL_DENOISE
layout(location = 0) out highp vec4 neuralFragColor;
#define gl_FragColor neuralFragColor
uniform sampler2D sceneDiffuse;
uniform highp sampler2D sceneDepth;
uniform sampler2D tDiffuse;
uniform sampler2D blueNoise;
uniform mat4 projectionMatrixInv;
uniform mat4 viewMatrixInv;
uniform vec2 resolution;
uniform float r;
uniform float radius;
uniform float worldRadius;
uniform float index;
uniform float near;
uniform float far;
uniform float distanceFalloff;
uniform bool screenSpaceRadius;
varying vec2 vUv;
highp float linearize_depth(highp float d, highp float zNear,highp float zFar)
{
highp float z_n = 2.0 * d - 1.0;
return 2.0 * zNear * zFar / (zFar + zNear - z_n * (zFar - zNear));
}
highp float linearize_depth_log(highp float d, highp float nearZ,highp float farZ) {
float depth = pow(2.0, d * log2(farZ + 1.0)) - 1.0;
float a = farZ / (farZ - nearZ);
float b = farZ * nearZ / (nearZ - farZ);
float linDepth = a + b / depth;
return linearize_depth(linDepth, nearZ, farZ);
}
highp float linearize_depth_ortho(highp float d, highp float nearZ, highp float farZ) {
return nearZ + (farZ - nearZ) * d;
}
float depthToClipZ(float depth) {
#ifdef REVERSEDEPTH
return depth;
#else
return depth * 2.0 - 1.0;
#endif
}
bool isBackgroundDepth(float depth) {
#ifdef REVERSEDEPTH
return depth == 0.0;
#else
return depth == 1.0;
#endif
}
vec3 getWorldPosLog(vec3 posS) {
vec2 uv = posS.xy;
float z = posS.z;
float nearZ =near;
float farZ = far;
float depth = pow(2.0, z * log2(farZ + 1.0)) - 1.0;
float a = farZ / (farZ - nearZ);
float b = farZ * nearZ / (nearZ - farZ);
float linDepth = a + b / depth;
vec4 clipVec = vec4(uv, linDepth, 1.0) * 2.0 - 1.0;
vec4 wpos = projectionMatrixInv * clipVec;
return wpos.xyz / wpos.w;
}
vec3 getWorldPos(float depth, vec2 coord) {
#ifdef LOGDEPTH
#ifndef ORTHO
return getWorldPosLog(vec3(coord, depth));
#endif
#endif
#ifdef ORTHO
float z = depthToClipZ(depth);
vec4 clipSpacePosition = vec4(coord * 2. - 1., z, 1.);
vec4 viewSpacePosition = projectionMatrixInv * clipSpacePosition;
viewSpacePosition.xyz /= viewSpacePosition.w;
return viewSpacePosition.xyz;
#else
vec2 ndc = coord * 2. - 1.;
float ndcZ = depthToClipZ(depth);
mat4 Q = projectionMatrixInv;
vec3 view = vec3(Q[0][0] * ndc.x + Q[3][0], Q[1][1] * ndc.y + Q[3][1], Q[3][2]);
float invW = 1.0 / (Q[2][3] * ndcZ + Q[3][3]);
return view * invW;
#endif
}
#ifdef NEURAL_DENOISE
struct NeuralToken {
highp vec4 lo;
highp vec4 hi;
};
NeuralToken neuralTapInput(NeuralToken raw) {
NeuralToken scaledInput = NeuralToken(
raw.lo * vec4(
2.283243417739868,
0.8810898065567017,
0.8210930228233337,
3.752316474914551
),
raw.hi * vec4(
3.6375720500946045,
2.670454978942871,
10.249449729919434,
0.12639354169368744
)
);
return NeuralToken(
max(vec4(
0.1096231754049479 * (scaledInput.lo.y + 7.0 * scaledInput.lo.z + (-scaledInput.hi.x) + (-7.0 * scaledInput.hi.y) + 31.0 * scaledInput.hi.w) + 1.4143863870620592,
0.1096231754049479 * ((-scaledInput.lo.x) + 14.0 * scaledInput.lo.y + (-126.0 * scaledInput.lo.z) + (-scaledInput.hi.y) + 2.0 * scaledInput.hi.z + 26.0 * scaledInput.hi.w) + -1.3870972504272245,
0.1096231754049479 * (66.0 * scaledInput.lo.y + (-73.0 * scaledInput.lo.z) + (-12.0 * scaledInput.hi.z) + 22.0 * scaledInput.hi.w) + 12.96982868512481,
0.1096231754049479 * ((-76.0 * scaledInput.lo.y) + (-90.0 * scaledInput.lo.z) + (-scaledInput.hi.x) + (-7.0 * scaledInput.hi.y) + (-3.0 * scaledInput.hi.z) + 58.0 * scaledInput.hi.w) + 5.017747360526078
), vec4(0.0)),
max(vec4(
0.1096231754049479 * (2.0 * scaledInput.lo.y + 6.0 * scaledInput.lo.z + 3.0 * scaledInput.hi.y + 4.0 * scaledInput.hi.z + (-40.0 * scaledInput.hi.w)) + -4.1297649139710675,
0.1096231754049479 * (3.0 * scaledInput.lo.y + (-13.0 * scaledInput.lo.z) + scaledInput.hi.y + (-7.0 * scaledInput.hi.z) + (-13.0 * scaledInput.hi.w)) + 7.631823377900882,
0.1096231754049479 * ((-7.0 * scaledInput.lo.y) + 10.0 * scaledInput.lo.z + (-2.0 * scaledInput.hi.x) + (-7.0 * scaledInput.hi.y) + (-39.0 * scaledInput.hi.w)) + 2.6245270598182344,
0.1096231754049479 * ((-13.0 * scaledInput.lo.y) + (-19.0 * scaledInput.lo.z) + (-2.0 * scaledInput.hi.x) + 20.0 * scaledInput.hi.y + (-scaledInput.hi.z) + 3.0 * scaledInput.hi.w) + -3.8866388148399498
), vec4(0.0))
);
}
NeuralToken neuralTapOutput(NeuralToken inputToken) {
return NeuralToken(
max(vec4(
0.017949438644286102 * (18.0 * inputToken.lo.x + (-4.0 * inputToken.lo.y) + 47.0 * inputToken.lo.z + 19.0 * inputToken.lo.w + 74.0 * inputToken.hi.x + (-94.0 * inputToken.hi.y) + (-21.0 * inputToken.hi.z) + (-9.0 * inputToken.hi.w)) + -0.3867710530757904,
0.017949438644286102 * (73.0 * inputToken.lo.x + (-59.0 * inputToken.lo.y) + 88.0 * inputToken.lo.z + (-10.0 * inputToken.lo.w) + (-3.0 * inputToken.hi.x) + 71.0 * inputToken.hi.y + (-7.0 * inputToken.hi.z) + 24.0 * inputToken.hi.w) + 0.1349504142999649,
0.017949438644286102 * (20.0 * inputToken.lo.x + 74.0 * inputToken.lo.y + 24.0 * inputToken.lo.z + (-31.0 * inputToken.lo.w) + (-12.0 * inputToken.hi.x) + (-10.0 * inputToken.hi.y) + (-15.0 * inputToken.hi.z) + (-45.0 * inputToken.hi.w)) + 0.35706064105033875,
0.017949438644286102 * ((-126.0 * inputToken.lo.x) + 2.0 * inputToken.lo.y + (-4.0 * inputToken.lo.z) + 27.0 * inputToken.lo.w + (-5.0 * inputToken.hi.x) + 24.0 * inputToken.hi.y + 35.0 * inputToken.hi.z + (-11.0 * inputToken.hi.w)) + -0.5938405394554138
), vec4(0.0)),
max(vec4(
0.017949438644286102 * ((-4.0 * inputToken.lo.x) + 9.0 * inputToken.lo.y + (-8.0 * inputToken.lo.z) + 26.0 * inputToken.lo.w + (-10.0 * inputToken.hi.x) + 27.0 * inputToken.hi.y + 26.0 * inputToken.hi.z + (-20.0 * inputToken.hi.w)) + -0.031154220923781395,
0.017949438644286102 * (17.0 * inputToken.lo.x + (-50.0 * inputToken.lo.y) + 5.0 * inputToken.lo.z + (-35.0 * inputToken.lo.w) + (-5.0 * inputToken.hi.y) + 12.0 * inputToken.hi.z + (-71.0 * inputToken.hi.w)) + 1.4079623222351074,
0.017949438644286102 * (89.0 * inputToken.lo.x + (-58.0 * inputToken.lo.y) + 22.0 * inputToken.lo.z + (-83.0 * inputToken.lo.w) + (-115.0 * inputToken.hi.x) + 7.0 * inputToken.hi.y + (-16.0 * inputToken.hi.z) + (-89.0 * inputToken.hi.w)) + -1.9221038818359375,
0.017949438644286102 * (89.0 * inputToken.lo.x + 22.0 * inputToken.lo.y + inputToken.lo.z + (-20.0 * inputToken.lo.w) + (-22.0 * inputToken.hi.x) + (-25.0 * inputToken.hi.y) + (-26.0 * inputToken.hi.z) + 44.0 * inputToken.hi.w) + 0.6029739379882812
), vec4(0.0))
);
}
NeuralToken neuralEncodeGlobal(vec4 raw) {
vec3 scaledInput = raw.xyz * vec3(
10.771836280822754, 1.9548665285110474, 1.612365484237671
);
return NeuralToken(
max(vec4(
0.021090541950849095 * (101.0 * scaledInput.x + (-4.0 * scaledInput.y) + 7.0 * scaledInput.z) + -21.524604707001238,
0.021090541950849095 * ((-127.0 * scaledInput.x) + 6.0 * scaledInput.y + (-11.0 * scaledInput.z)) + 27.111714715139033,
0.021090541950849095 * (3.0 * scaledInput.x + scaledInput.y) + -0.6588789590469037,
0.021090541950849095 * ((-16.0 * scaledInput.x) + (-7.0 * scaledInput.y) + 8.0 * scaledInput.z) + 4.497741949827374
), vec4(0.0)),
max(vec4(
0.021090541950849095 * ((-8.0 * scaledInput.x) + (-scaledInput.y) + 7.0 * scaledInput.z) + 1.690871031740089,
0.021090541950849095 * ((-4.0 * scaledInput.x)) + 1.080641590014308,
0.021090541950849095 * ((-12.0 * scaledInput.x) + (-3.0 * scaledInput.y) + (-13.0 * scaledInput.z)) + 2.470025460444304,
0.021090541950849095 * (scaledInput.x + 2.0 * scaledInput.z) + -0.38586191737528186
), vec4(0.0))
);
}
NeuralToken neuralKeyProject(NeuralToken inputToken) {
return NeuralToken(
vec4(
0.1733924937791441 * ((-inputToken.lo.y) + (-inputToken.lo.z) + inputToken.lo.w + inputToken.hi.x + inputToken.hi.y + inputToken.hi.z + inputToken.hi.w) + 0.0,
0.1733924937791441 * ((-64.0 * inputToken.lo.x) + 32.0 * inputToken.lo.y + 49.0 * inputToken.lo.z + 23.0 * inputToken.lo.w + (-25.0 * inputToken.hi.x) + 4.0 * inputToken.hi.y + 27.0 * inputToken.hi.z + (-22.0 * inputToken.hi.w)) + 0.0,
0.1733924937791441 * (inputToken.lo.y + (-inputToken.lo.z) + (-inputToken.lo.w) + (-inputToken.hi.x) + inputToken.hi.y + inputToken.hi.z) + 0.0,
0.1733924937791441 * ((-34.0 * inputToken.lo.x) + 38.0 * inputToken.lo.y + 64.0 * inputToken.lo.z + 88.0 * inputToken.lo.w + 13.0 * inputToken.hi.x + (-53.0 * inputToken.hi.y) + (-41.0 * inputToken.hi.z) + 58.0 * inputToken.hi.w) + 0.0
),
vec4(
0.1733924937791441 * ((-7.0 * inputToken.lo.x) + (-4.0 * inputToken.lo.y) + 79.0 * inputToken.lo.z + (-41.0 * inputToken.lo.w) + 27.0 * inputToken.hi.x + 26.0 * inputToken.hi.y + 14.0 * inputToken.hi.z + 2.0 * inputToken.hi.w) + 0.0,
0.1733924937791441 * ((-2.0 * inputToken.lo.x) + inputToken.lo.y + inputToken.lo.z + inputToken.lo.w + (-inputToken.hi.x) + (-inputToken.hi.y) + inputToken.hi.z + inputToken.hi.w) + 0.0,
0.1733924937791441 * (inputToken.lo.x + (-inputToken.lo.y) + (-inputToken.lo.z) + (-inputToken.lo.w) + (-inputToken.hi.x) + (-inputToken.hi.y) + inputToken.hi.z + inputToken.hi.w) + 0.0,
0.1733924937791441 * (4.0 * inputToken.lo.x + (-3.0 * inputToken.lo.y) + 126.0 * inputToken.lo.z + 42.0 * inputToken.lo.w + (-40.0 * inputToken.hi.x) + (-116.0 * inputToken.hi.y) + 35.0 * inputToken.hi.z + 20.0 * inputToken.hi.w) + 0.0
)
);
}
NeuralToken neuralValueProject(NeuralToken inputToken) {
return NeuralToken(
vec4(
0.013986751242596301 * ((-16.0 * inputToken.lo.x) + (-6.0 * inputToken.lo.y) + 40.0 * inputToken.lo.z + (-17.0 * inputToken.lo.w) + 84.0 * inputToken.hi.x + (-76.0 * inputToken.hi.y) + 59.0 * inputToken.hi.z + 51.0 * inputToken.hi.w) + 0.0,
0.013986751242596301 * ((-10.0 * inputToken.lo.x) + (-2.0 * inputToken.lo.y) + (-10.0 * inputToken.lo.z) + (-inputToken.lo.w) + (-23.0 * inputToken.hi.x) + 74.0 * inputToken.hi.y + (-70.0 * inputToken.hi.z) + 23.0 * inputToken.hi.w) + 0.0,
0.013986751242596301 * ((-5.0 * inputToken.lo.x) + 4.0 * inputToken.lo.y + 4.0 * inputToken.lo.z + (-7.0 * inputToken.lo.w) + (-77.0 * inputToken.hi.x) + 127.0 * inputToken.hi.y + 20.0 * inputToken.hi.z + (-48.0 * inputToken.hi.w)) + 0.0,
0.013986751242596301 * ((-36.0 * inputToken.lo.x) + 4.0 * inputToken.lo.y + (-17.0 * inputToken.lo.z) + (-12.0 * inputToken.lo.w) + (-4.0 * inputToken.hi.x) + 10.0 * inputToken.hi.y + 29.0 * inputToken.hi.z + (-27.0 * inputToken.hi.w)) + 0.0
),
vec4(
0.013986751242596301 * ((-2.0 * inputToken.lo.x) + 11.0 * inputToken.lo.y + (-47.0 * inputToken.lo.z) + (-50.0 * inputToken.lo.w) + (-54.0 * inputToken.hi.x) + (-3.0 * inputToken.hi.y) + 14.0 * inputToken.hi.z + 11.0 * inputToken.hi.w) + 0.0,
0.013986751242596301 * ((-23.0 * inputToken.lo.x) + (-inputToken.lo.y) + 109.0 * inputToken.lo.z + 31.0 * inputToken.lo.w + 4.0 * inputToken.hi.x + (-100.0 * inputToken.hi.y) + (-33.0 * inputToken.hi.z) + (-36.0 * inputToken.hi.w)) + 0.0,
0.013986751242596301 * ((-19.0 * inputToken.lo.x) + (-8.0 * inputToken.lo.z) + 20.0 * inputToken.lo.w + (-35.0 * inputToken.hi.x) + (-24.0 * inputToken.hi.y) + 79.0 * inputToken.hi.z + 2.0 * inputToken.hi.w) + 0.0,
0.013986751242596301 * (44.0 * inputToken.lo.x + 2.0 * inputToken.lo.y + 5.0 * inputToken.lo.z + 7.0 * inputToken.lo.w + 22.0 * inputToken.hi.x + (-70.0 * inputToken.hi.y) + (-67.0 * inputToken.hi.z) + (-35.0 * inputToken.hi.w)) + 0.0
)
);
}
vec4 neuralQueryScores(NeuralToken key) {
return vec4(
0.0038647791370749474 * key.lo.x + 0.09565000981092453 * key.lo.y + 0.002756686182692647 * key.lo.z + -0.08183622360229492 * key.lo.w + -0.15209506452083588 * key.hi.x + -0.0006105066277086735 * key.hi.y + 0.0010439646430313587 * key.hi.z + -0.03020688332617283 * key.hi.w,
0.005065929610282183 * key.lo.x + 0.14488759636878967 * key.lo.y + 0.003160916268825531 * key.lo.z + -0.0855727270245552 * key.lo.w + -0.3123375475406647 * key.hi.x + 0.00039022407145239413 * key.hi.y + 0.0037786494940519333 * key.hi.z + 0.1451321840286255 * key.hi.w,
-0.002009483054280281 * key.lo.x + 0.0597594790160656 * key.lo.y + 0.0045239729806780815 * key.lo.z + -0.08765853196382523 * key.lo.w + -0.13884992897510529 * key.hi.x + -0.0021647117100656033 * key.hi.y + 0.003985927440226078 * key.hi.z + 0.09727758169174194 * key.hi.w,
0.007170629221946001 * key.lo.x + 0.0786278173327446 * key.lo.y + 0.004103775601834059 * key.lo.z + -0.1198369711637497 * key.lo.w + -0.2925199568271637 * key.hi.x + -0.002055276418104768 * key.hi.y + 0.0030450925696641207 * key.hi.z + 0.14401987195014954 * key.hi.w
);
}
NeuralToken neuralHead(
vec4 runningSummaryLo[4],
vec4 runningSummaryHi[4]
) {
return NeuralToken(
max(vec4(
0.04935851140909355 * ((-45.0 * runningSummaryLo[0].x) + (-7.0 * runningSummaryLo[0].y) + (-45.0 * runningSummaryLo[0].z) + (-20.0 * runningSummaryLo[0].w) + 7.0 * runningSummaryHi[0].x + (-13.0 * runningSummaryHi[0].y) + 120.0 * runningSummaryHi[0].z + (-24.0 * runningSummaryHi[0].w) + (-15.0 * runningSummaryLo[1].x) + (-26.0 * runningSummaryLo[1].y) + (-19.0 * runningSummaryLo[1].z) + runningSummaryLo[1].w + 27.0 * runningSummaryHi[1].x + (-48.0 * runningSummaryHi[1].y) + (-4.0 * runningSummaryHi[1].z) + (-10.0 * runningSummaryHi[1].w) + runningSummaryLo[2].x + (-5.0 * runningSummaryLo[2].y) + (-24.0 * runningSummaryLo[2].z) + 64.0 * runningSummaryLo[2].w + 91.0 * runningSummaryHi[2].x + (-runningSummaryHi[2].y) + (-68.0 * runningSummaryHi[2].z) + 39.0 * runningSummaryHi[2].w + 54.0 * runningSummaryLo[3].x + 39.0 * runningSummaryLo[3].y + 101.0 * runningSummaryLo[3].z + (-40.0 * runningSummaryLo[3].w) + (-127.0 * runningSummaryHi[3].x) + 64.0 * runningSummaryHi[3].y + (-41.0 * runningSummaryHi[3].z) + (-17.0 * runningSummaryHi[3].w)) + -0.15895532071590424,
0.04935851140909355 * ((-23.0 * runningSummaryLo[0].x) + (-19.0 * runningSummaryLo[0].y) + 3.0 * runningSummaryLo[0].z + 35.0 * runningSummaryLo[0].w + (-2.0 * runningSummaryHi[0].x) + 33.0 * runningSummaryHi[0].y + 3.0 * runningSummaryHi[0].z + 9.0 * runningSummaryHi[0].w + (-64.0 * runningSummaryLo[1].x) + (-32.0 * runningSummaryLo[1].y) + 30.0 * runningSummaryLo[1].z + 42.0 * runningSummaryLo[1].w + (-112.0 * runningSummaryHi[1].x) + 12.0 * runningSummaryHi[1].y + 28.0 * runningSummaryHi[1].z + (-11.0 * runningSummaryHi[1].w) + 15.0 * runningSummaryLo[2].x + 2.0 * runningSummaryLo[2].y + (-4.0 * runningSummaryLo[2].z) + (-7.0 * runningSummaryLo[2].w) + 7.0 * runningSummaryHi[2].x + (-3.0 * runningSummaryHi[2].y) + (-5.0 * runningSummaryHi[2].z) + runningSummaryHi[2].w + 76.0 * runningSummaryLo[3].x + 48.0 * runningSummaryLo[3].y + (-34.0 * runningSummaryLo[3].z) + (-67.0 * runningSummaryLo[3].w) + 103.0 * runningSummaryHi[3].x + (-40.0 * runningSummaryHi[3].y) + (-26.0 * runningSummaryHi[3].z) + runningSummaryHi[3].w) + 0.007501596584916115,
0.04935851140909355 * (58.0 * runningSummaryLo[0].x + (-11.0 * runningSummaryLo[0].y) + 46.0 * runningSummaryLo[0].z + (-41.0 * runningSummaryLo[0].w) + 5.0 * runningSummaryHi[0].x + (-6.0 * runningSummaryHi[0].y) + (-17.0 * runningSummaryHi[0].z) + (-8.0 * runningSummaryHi[0].w) + 13.0 * runningSummaryLo[1].x + 17.0 * runningSummaryLo[1].y + (-35.0 * runningSummaryLo[1].z) + 45.0 * runningSummaryLo[1].w + 27.0 * runningSummaryHi[1].x + (-17.0 * runningSummaryHi[1].y) + (-28.0 * runningSummaryHi[1].z) + 7.0 * runningSummaryHi[1].w + (-53.0 * runningSummaryLo[2].x) + 12.0 * runningSummaryLo[2].y + (-51.0 * runningSummaryLo[2].z) + 6.0 * runningSummaryLo[2].w + (-32.0 * runningSummaryHi[2].x) + (-5.0 * runningSummaryHi[2].y) + 58.0 * runningSummaryHi[2].z + (-9.0 * runningSummaryHi[2].w) + (-28.0 * runningSummaryLo[3].x) + (-21.0 * runningSummaryLo[3].y) + 37.0 * runningSummaryLo[3].z + (-12.0 * runningSummaryLo[3].w) + runningSummaryHi[3].x + 20.0 * runningSummaryHi[3].y + 2.0 * runningSummaryHi[3].z + 2.0 * runningSummaryHi[3].w) + -0.47742825746536255,
0.04935851140909355 * (11.0 * runningSummaryLo[0].x + 7.0 * runningSummaryLo[0].y + (-4.0 * runningSummaryLo[0].z) + (-9.0 * runningSummaryLo[0].w) + 2.0 * runningSummaryHi[0].x + (-15.0 * runningSummaryHi[0].y) + (-runningSummaryHi[0].z) + (-8.0 * runningSummaryHi[0].w) + 16.0 * runningSummaryLo[1].x + 12.0 * runningSummaryLo[1].y + (-27.0 * runningSummaryLo[1].z) + (-runningSummaryLo[1].w) + 61.0 * runningSummaryHi[1].x + (-5.0 * runningSummaryHi[1].y) + (-runningSummaryHi[1].z) + 4.0 * runningSummaryHi[1].w + (-7.0 * runningSummaryLo[2].x) + (-2.0 * runningSummaryLo[2].y) + 7.0 * runningSummaryLo[2].z + 4.0 * runningSummaryLo[2].w + runningSummaryHi[2].x + 4.0 * runningSummaryHi[2].y + (-2.0 * runningSummaryHi[2].z) + 4.0 * runningSummaryHi[2].w + (-18.0 * runningSummaryLo[3].x) + (-16.0 * runningSummaryLo[3].y) + 28.0 * runningSummaryLo[3].z + 6.0 * runningSummaryLo[3].w + (-65.0 * runningSummaryHi[3].x) + 16.0 * runningSummaryHi[3].y + 3.0 * runningSummaryHi[3].z + (-3.0 * runningSummaryHi[3].w)) + 0.01632097363471985
), vec4(0.0)),
max(vec4(
0.04935851140909355 * ((-5.0 * runningSummaryLo[0].x) + (-2.0 * runningSummaryLo[0].y) + (-40.0 * runningSummaryLo[0].w) + (-21.0 * runningSummaryHi[0].x) + (-22.0 * runningSummaryHi[0].y) + 14.0 * runningSummaryHi[0].z + 30.0 * runningSummaryHi[0].w + (-21.0 * runningSummaryLo[1].x) + 49.0 * runningSummaryLo[1].y + 15.0 * runningSummaryLo[1].z + (-64.0 * runningSummaryLo[1].w) + 43.0 * runningSummaryHi[1].x + 19.0 * runningSummaryHi[1].y + 23.0 * runningSummaryHi[1].z + 18.0 * runningSummaryHi[1].w + 5.0 * runningSummaryLo[2].x + (-15.0 * runningSummaryLo[2].y) + 21.0 * runningSummaryLo[2].z + 21.0 * runningSummaryLo[2].w + 30.0 * runningSummaryHi[2].x + 17.0 * runningSummaryHi[2].y + (-11.0 * runningSummaryHi[2].z) + (-6.0 * runningSummaryHi[2].w) + 22.0 * runningSummaryLo[3].x + (-38.0 * runningSummaryLo[3].y) + (-20.0 * runningSummaryLo[3].z) + 97.0 * runningSummaryLo[3].w + (-46.0 * runningSummaryHi[3].x) + (-5.0 * runningSummaryHi[3].y) + (-13.0 * runningSummaryHi[3].z) + (-59.0 * runningSummaryHi[3].w)) + -0.48355796933174133,
0.04935851140909355 * (26.0 * runningSummaryLo[0].x + (-13.0 * runningSummaryLo[0].y) + 11.0 * runningSummaryLo[0].z + (-2.0 * runningSummaryLo[0].w) + (-10.0 * runningSummaryHi[0].x) + (-8.0 * runningSummaryHi[0].y) + 2.0 * runningSummaryHi[0].z + (-15.0 * runningSummaryHi[0].w) + (-17.0 * runningSummaryLo[1].x) + (-27.0 * runningSummaryLo[1].y) + (-9.0 * runningSummaryLo[1].z) + 26.0 * runningSummaryLo[1].w + 7.0 * runningSummaryHi[1].x + (-7.0 * runningSummaryHi[1].y) + 6.0 * runningSummaryHi[1].z + 9.0 * runningSummaryHi[1].w + (-32.0 * runningSummaryLo[2].x) + 5.0 * runningSummaryLo[2].y + (-9.0 * runningSummaryLo[2].z) + 12.0 * runningSummaryLo[2].w + 49.0 * runningSummaryHi[2].x + 17.0 * runningSummaryHi[2].y + (-runningSummaryHi[2].z) + 24.0 * runningSummaryHi[2].w + 20.0 * runningSummaryLo[3].x + 35.0 * runningSummaryLo[3].y + 14.0 * runningSummaryLo[3].z + (-33.0 * runningSummaryLo[3].w) + (-50.0 * runningSummaryHi[3].x) + (-runningSummaryHi[3].y) + (-4.0 * runningSummaryHi[3].z) + (-26.0 * runningSummaryHi[3].w)) + -0.1052703931927681,
0.04935851140909355 * (11.0 * runningSummaryLo[0].x + 11.0 * runningSummaryLo[0].y + 9.0 * runningSummaryLo[0].z + (-80.0 * runningSummaryLo[0].w) + 30.0 * runningSummaryHi[0].x + 9.0 * runningSummaryHi[0].y + 36.0 * runningSummaryHi[0].z + 6.0 * runningSummaryHi[0].w + (-12.0 * runningSummaryLo[1].x) + (-4.0 * runningSummaryLo[1].y) + (-7.0 * runningSummaryLo[1].z) + 39.0 * runningSummaryLo[1].w + (-10.0 * runningSummaryHi[1].x) + (-30.0 * runningSummaryHi[1].y) + (-49.0 * runningSummaryHi[1].z) + runningSummaryHi[1].w + (-43.0 * runningSummaryLo[2].x) + (-20.0 * runningSummaryLo[2].y) + (-34.0 * runningSummaryLo[2].z) + 76.0 * runningSummaryLo[2].w + (-36.0 * runningSummaryHi[2].x) + (-10.0 * runningSummaryHi[2].y) + 15.0 * runningSummaryHi[2].z + (-8.0 * runningSummaryHi[2].w) + 43.0 * runningSummaryLo[3].x + 31.0 * runningSummaryLo[3].y + 38.0 * runningSummaryLo[3].z + (-42.0 * runningSummaryLo[3].w) + 39.0 * runningSummaryHi[3].x + 37.0 * runningSummaryHi[3].y + (-7.0 * runningSummaryHi[3].z) + 7.0 * runningSummaryHi[3].w) + -0.8414919376373291,
0.04935851140909355 * (8.0 * runningSummaryLo[0].x + 16.0 * runningSummaryLo[0].y + 28.0 * runningSummaryLo[0].z + (-83.0 * runningSummaryLo[0].w) + 32.0 * runningSummaryHi[0].x + 9.0 * runningSummaryHi[0].y + 23.0 * runningSummaryHi[0].z + (-13.0 * runningSummaryHi[0].w) + 39.0 * runningSummaryLo[1].x + 119.0 * runningSummaryLo[1].y + 23.0 * runningSummaryLo[1].z + (-127.0 * runningSummaryLo[1].w) + (-24.0 * runningSummaryHi[1].x) + 8.0 * runningSummaryHi[1].y + (-48.0 * runningSummaryHi[1].z) + (-29.0 * runningSummaryHi[1].w) + (-7.0 * runningSummaryLo[2].x) + (-33.0 * runningSummaryLo[2].y) + (-12.0 * runningSummaryLo[2].z) + 58.0 * runningSummaryLo[2].w + (-24.0 * runningSummaryHi[2].x) + (-29.0 * runningSummaryHi[2].y) + (-19.0 * runningSummaryHi[2].z) + 12.0 * runningSummaryHi[2].w + (-55.0 * runningSummaryLo[3].x) + (-90.0 * runningSummaryLo[3].y) + 126.0 * runningSummaryLo[3].w + 26.0 * runningSummaryHi[3].x + 42.0 * runningSummaryHi[3].y + 54.0 * runningSummaryHi[3].z + 22.0 * runningSummaryHi[3].w) + -0.21046382188796997
), vec4(0.0))
);
}
float neuralOutput(NeuralToken head) {
return 0.0030087142047955295 * (11.0 * head.lo.x + 11.0 * head.lo.y + 14.0 * head.lo.z + (-27.0 * head.lo.w) + 9.0 * head.hi.x + (-22.0 * head.hi.y) + 127.0 * head.hi.z + 6.0 * head.hi.w) + -0.0005526235327124596;
}
vec3 neuralSafeNormalize(vec3 value, vec3 fallback) {
float lengthSquared = dot(value, value);
return lengthSquared > 1e-12 ? value * inversesqrt(lengthSquared) : fallback;
}
mat3 neuralLocalFrame(vec3 inputNormal) {
vec3 frameNormal = neuralSafeNormalize(inputNormal, vec3(0.0, 0.0, 1.0));
vec3 helper = abs(frameNormal.z) < 0.999
? vec3(0.0, 0.0, 1.0)
: vec3(0.0, 1.0, 0.0);
vec3 tangent = neuralSafeNormalize(
cross(helper, frameNormal),
vec3(1.0, 0.0, 0.0)
);
vec3 bitangent = cross(frameNormal, tangent);
return transpose(mat3(tangent, bitangent, frameNormal));
}
void neuralConsumeToken(
NeuralToken token,
inout vec4 runningMaximum,
inout vec4 runningDenominator,
inout vec4 runningSummaryLo[4],
inout vec4 runningSummaryHi[4]
) {
NeuralToken key = neuralKeyProject(token);
NeuralToken value = neuralValueProject(token);
vec4 score = neuralQueryScores(key) * 0.3535533905932738;
vec4 newMaximum = max(runningMaximum, score);
vec4 oldScale = exp(runningMaximum - newMaximum);
vec4 newScale = exp(score - newMaximum);
runningSummaryLo[0] = runningSummaryLo[0] * oldScale.x + value.lo * newScale.x;
runningSummaryHi[0] = runningSummaryHi[0] * oldScale.x + value.hi * newScale.x;
runningSummaryLo[1] = runningSummaryLo[1] * oldScale.y + value.lo * newScale.y;
runningSummaryHi[1] = runningSummaryHi[1] * oldScale.y + value.hi * newScale.y;
runningSummaryLo[2] = runningSummaryLo[2] * oldScale.z + value.lo * newScale.z;
runningSummaryHi[2] = runningSummaryHi[2] * oldScale.z + value.hi * newScale.z;
runningSummaryLo[3] = runningSummaryLo[3] * oldScale.w + value.lo * newScale.w;
runningSummaryHi[3] = runningSummaryHi[3] * oldScale.w + value.hi * newScale.w;
runningDenominator = runningDenominator * oldScale + newScale;
runningMaximum = newMaximum;
}
void neuralEncodeTap(
NeuralToken raw,
inout vec4 runningMaximum,
inout vec4 runningDenominator,
inout vec4 runningSummaryLo[4],
inout vec4 runningSummaryHi[4]
) {
NeuralToken first = neuralTapInput(raw);
NeuralToken token = neuralTapOutput(first);
neuralConsumeToken(
token,
runningMaximum,
runningDenominator,
runningSummaryLo,
runningSummaryHi
);
}
float neuralFinish(
float baselineAO,
inout vec4 runningMaximum,
inout vec4 runningDenominator,
inout vec4 runningSummaryLo[4],
inout vec4 runningSummaryHi[4]
) {
vec4 raw = vec4(
baselineAO,
log(max(worldRadius, 1e-6)),
log(max(distanceFalloff, 1e-6)),
0.0
);
NeuralToken token = neuralEncodeGlobal(raw);
neuralConsumeToken(
token,
runningMaximum,
runningDenominator,
runningSummaryLo,
runningSummaryHi
);
vec4 inverseDenominator = 1.0 / max(runningDenominator, vec4(1e-12));
runningSummaryLo[0] *= inverseDenominator.x;
runningSummaryHi[0] *= inverseDenominator.x;
runningSummaryLo[1] *= inverseDenominator.y;
runningSummaryHi[1] *= inverseDenominator.y;
runningSummaryLo[2] *= inverseDenominator.z;
runningSummaryHi[2] *= inverseDenominator.z;
runningSummaryLo[3] *= inverseDenominator.w;
runningSummaryHi[3] *= inverseDenominator.w;
NeuralToken head = neuralHead(runningSummaryLo, runningSummaryHi);
return neuralOutput(head);
}
#endif
#include <common>
#define NUM_SAMPLES 16
uniform vec2 poissonDisk[NUM_SAMPLES];
void main() {
const float pi = 3.14159;
vec2 texelSize = vec2(1.0 / resolution.x, 1.0 / resolution.y);
vec2 uv = vUv;
vec4 data = texture2D(tDiffuse, vUv);
float occlusion = data.r;
float baseOcc = data.r;
vec3 normal = data.gba * 2.0 - 1.0;
float count = 1.0;
float d = texture2D(sceneDepth, vUv).x;
if (isBackgroundDepth(d)) {
gl_FragColor = data;
return;
}
vec3 worldPos = getWorldPos(d, vUv);
float size = radius;
float angle;
#ifdef NEURAL_DENOISE
// The neural material is only bound for denoise iteration two.
angle = texture2D(blueNoise, gl_FragCoord.xy / 128.0).z * PI2;
#else
if (index == 0.0) {
angle = texture2D(blueNoise, gl_FragCoord.xy / 128.0).w * PI2;
} else if (index == 1.0) {
angle = texture2D(blueNoise, gl_FragCoord.xy / 128.0).z * PI2;
} else if (index == 2.0) {
angle = texture2D(blueNoise, gl_FragCoord.xy / 128.0).y * PI2;
} else {
angle = texture2D(blueNoise, gl_FragCoord.xy / 128.0).x * PI2;
}
#endif
mat2 rotationMatrix = mat2(cos(angle), -sin(angle), sin(angle), cos(angle));
float radiusToUse = screenSpaceRadius ? distance(
worldPos,
getWorldPos(d, vUv +
vec2(worldRadius, 0.0) / resolution)
) : worldRadius;
float distanceFalloffToUse =screenSpaceRadius ?
radiusToUse * distanceFalloff
: radiusToUse * distanceFalloff * 0.2;
float invDistance = (1.0 / distanceFalloffToUse);
#ifdef NEURAL_DENOISE
mat3 neuralWorldToLocal = neuralLocalFrame(normal);
float neuralInverseRadius = 1.0 / max(radiusToUse, 1e-6);
float neuralInverseDistance = 1.0 / max(distanceFalloffToUse, 1e-6);
vec4 neuralMaximum = vec4(-1e30);
vec4 neuralDenominator = vec4(0.0);
vec4 neuralSummaryLo[4];
vec4 neuralSummaryHi[4];
for (int query = 0; query < 4; query++) {
neuralSummaryLo[query] = vec4(0.0);
neuralSummaryHi[query] = vec4(0.0);
}
#endif
for(int i = 0; i < NUM_SAMPLES; i++) {
vec2 offset = (rotationMatrix * poissonDisk[i]) * texelSize * size;
vec4 dataSample = texture2D(tDiffuse, uv + offset);
float occSample = dataSample.r;
vec3 normalSample = dataSample.gba * 2.0 - 1.0;
float dSample = texture2D(sceneDepth, uv + offset).x;
vec3 worldPosSample = getWorldPos(dSample, uv + offset);
float tangentPlaneDist = abs(dot(worldPosSample - worldPos, normal));
float rangeCheck = float(!isBackgroundDepth(dSample)) * exp(-1.0 * tangentPlaneDist * invDistance ) * max(dot(normal, normalSample), 0.0);
occlusion += occSample * rangeCheck;
count += rangeCheck;
#ifdef NEURAL_DENOISE
if (!isBackgroundDepth(dSample)) {
vec3 localDelta = (neuralWorldToLocal * (worldPosSample - worldPos))
* neuralInverseRadius;
vec3 localNormal = neuralWorldToLocal
* neuralSafeNormalize(normalSample, vec3(0.0, 0.0, 1.0));
NeuralToken rawTap = NeuralToken(
vec4(localDelta, localNormal.x),
vec4(
localNormal.y,
localNormal.z,
occSample,
tangentPlaneDist * neuralInverseDistance
)
);
neuralEncodeTap(
rawTap,
neuralMaximum,
neuralDenominator,
neuralSummaryLo,
neuralSummaryHi
);
}
#endif
}
if (count > 0.0) {
occlusion /= count;
}
occlusion = clamp(occlusion, 0.0, 1.0);
if (occlusion == 0.0) {
occlusion = 1.0;
}
#ifdef NEURAL_DENOISE
occlusion = clamp(
occlusion + neuralFinish(
occlusion,
neuralMaximum,
neuralDenominator,
neuralSummaryLo,
neuralSummaryHi
),
0.0,
1.0
);
#endif
gl_FragColor = vec4(occlusion, 0.5 + 0.5 * normal);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment