LumixEngine/data/pipelines/taa.shd
2023-09-15 17:27:30 +02:00

119 lines
No EOL
3.5 KiB
Text

include "pipelines/common.glsl"
compute_shader [[
layout(std140, binding = 4) uniform Data {
vec2 u_size;
};
layout(local_size_x = 16, local_size_y = 16, local_size_z = 1) in;
layout (binding = 0) uniform sampler2D u_history;
layout (binding = 1) uniform sampler2D u_depthbuf;
layout (binding = 2) uniform sampler2D u_current;
layout (binding = 3) uniform sampler2D u_motion_vectors;
layout (rgba8, binding = 3) uniform image2D u_output;
// https://gist.github.com/TheRealMJP/c83b8c0f46b63f3a88a5986f4fa982b1
vec4 catmullRom(sampler2D tex, vec2 uv, vec2 texSize)
{
vec2 samplePos = uv * texSize;
vec2 texPos1 = floor(samplePos - 0.5) + 0.5;
vec2 f = samplePos - texPos1;
vec2 w0 = f * (-0.5 + f * (1.0f - 0.5 * f));
vec2 w1 = 1.0f + f * f * (-2.5 + 1.5 * f);
vec2 w2 = f * (0.5 + f * (2.0f - 1.5 * f));
vec2 w3 = f * f * (-0.5 + 0.5 * f);
vec2 w12 = w1 + w2;
vec2 offset12 = w2 / (w1 + w2);
vec2 texPos0 = texPos1 - 1;
vec2 texPos3 = texPos1 + 2;
vec2 texPos12 = texPos1 + offset12;
texPos0 /= texSize;
texPos3 /= texSize;
texPos12 /= texSize;
vec4 result = vec4(0.0);
result += textureLod(tex, vec2(texPos0.x, texPos0.y), 0.0f) * w0.x * w0.y;
result += textureLod(tex, vec2(texPos12.x, texPos0.y), 0.0f) * w12.x * w0.y;
result += textureLod(tex, vec2(texPos3.x, texPos0.y), 0.0f) * w3.x * w0.y;
result += textureLod(tex, vec2(texPos0.x, texPos12.y), 0.0f) * w0.x * w12.y;
result += textureLod(tex, vec2(texPos12.x, texPos12.y), 0.0f) * w12.x * w12.y;
result += textureLod(tex, vec2(texPos3.x, texPos12.y), 0.0f) * w3.x * w12.y;
result += textureLod(tex, vec2(texPos0.x, texPos3.y), 0.0f) * w0.x * w3.y;
result += textureLod(tex, vec2(texPos12.x, texPos3.y), 0.0f) * w12.x * w3.y;
result += textureLod(tex, vec2(texPos3.x, texPos3.y), 0.0f) * w3.x * w3.y;
return result;
}
// https://www.iquilezles.org/www/articles/texture/texture.htm
vec4 getTexel(sampler2D tex, vec2 p, vec2 res) {
#if 1
return catmullRom(tex, p, res);
#else
p = p * res + 0.5;
vec2 i = floor(p);
vec2 f = p - i;
f = f * f * f * (f * (f * 6.0 - 15.0) + 10.0);
p = i + f;
p = (p - 0.5) / res;
return textureLod(tex, p, 0);
#endif
}
// https://www.elopezr.com/temporal-aa-and-the-quest-for-the-holy-trail/
void main()
{
ivec2 ij = ivec2(gl_GlobalInvocationID.xy);
if (any(greaterThanEqual(ij, ivec2(u_size.xy)))) return;
vec2 uv = (vec2(ij) + 0.5) / u_size.xy;
float depth = textureLod(u_depthbuf, uv, 0).x;
vec2 motionvec = textureLod(u_motion_vectors, uv, 0).xy * 2 - 1;
vec2 uv_prev = uv + motionvec;
vec4 current = textureLod(u_current, uv /*- Global.pixel_jitter*/, 0);
if (all(lessThan(uv_prev, vec2(1))) && all(greaterThan(uv_prev, vec2(0))) ) {
vec4 prev = getTexel(u_history, uv_prev, u_size);
#if 1 // color clamping
vec4 minColor = vec4(9001.0), maxColor = vec4(-9001.0);
#define ITER(x, y) \
{ \
vec4 color = textureLodOffset(u_current, uv, 0, ivec2(x, y)); \
minColor = min(minColor, color); \
maxColor = max(maxColor, color); \
}
ITER(-1, -1)
ITER(-1, 0)
ITER(-1, 1)
ITER(0, -1)
ITER(0, 1)
ITER(1, -1)
ITER(1, 0)
ITER(1, 1)
prev = clamp(prev, minColor, maxColor);
#endif
float lum0 = luminance(current.rgb);
float lum1 = luminance(prev.rgb);
float d = 1 - abs(lum0 - lum1) / max(lum0, max(lum1, 0.1));
float k_feedback = mix(0.9, 0.99, d * d);
current = mix(current, prev, k_feedback);
}
imageStore(u_output, ij, current);
}
]]