xash3d-fwgs/ref_vk/shaders/denoiser.comp

124 lines
3.9 KiB
Plaintext

#version 460
#include "noise.glsl"
layout(local_size_x = 16, local_size_y = 8, local_size_z = 1) in;
layout(set = 0, binding = 0, rgba16f) uniform image2D dest;
layout(set = 0, binding = 1, rgba8) uniform image2D src_base_color;
layout(set = 0, binding = 2, rgba16f) uniform image2D src_diffuse_gi;
layout(set = 0, binding = 3, rgba16f) uniform image2D src_specular;
layout(set = 0, binding = 4, rgba16f) uniform image2D src_additive;
layout(set = 0, binding = 5, rgba16f) uniform image2D src_normals;
// Blatantly copypasted from https://www.shadertoy.com/view/XsGfWV
vec3 aces_tonemap(vec3 color){
mat3 m1 = mat3(
0.59719, 0.07600, 0.02840,
0.35458, 0.90834, 0.13383,
0.04823, 0.01566, 0.83777
);
mat3 m2 = mat3(
1.60475, -0.10208, -0.00327,
-0.53108, 1.10813, -0.07276,
-0.07367, -0.00605, 1.07602
);
vec3 v = m1 * color;
vec3 a = v * (v + 0.0245786) - 0.000090537;
vec3 b = v * (0.983729 * v + 0.4329510) + 0.238081;
return pow(clamp(m2 * (a / b), 0.0, 1.0), vec3(1.0 / 2.2));
}
float normpdf2(in float x2, in float sigma) { return 0.39894*exp(-0.5*x2/(sigma*sigma))/sigma; }
float normpdf(in float x, in float sigma) { return normpdf2(x*x, sigma); }
void readNormals(ivec2 uv, out vec3 geometry_normal, out vec3 shading_normal) {
const vec4 n = imageLoad(src_normals, uv);
geometry_normal = vec3(n.xy, sqrt(1. - n.x*n.x - n.y*n.y));
shading_normal = vec3(n.zw, sqrt(1. - n.z*n.z - n.w*n.w));
}
void main() {
ivec2 res = ivec2(imageSize(src_base_color));
ivec2 pix = ivec2(gl_GlobalInvocationID);
if (any(greaterThanEqual(pix, res))) {
return;
}
const vec4 base_color = imageLoad(src_base_color, pix);
const float material_index = imageLoad(src_diffuse_gi, pix).a;
//imageStore(dest, pix, vec4(aces_tonemap(base_color.rgb), 0.)); return;
//imageStore(dest, pix, vec4((base_color.rgb), 0.)); return;
//imageStore(dest, pix, vec4(aces_tonemap(imageLoad(src_diffuse_gi, pix).rgb), 0.)); return;
//imageStore(dest, pix, vec4(aces_tonemap(imageLoad(src_specular, pix).rgb), 0.)); return;
vec3 geometry_normal, shading_normal;
readNormals(pix, geometry_normal, shading_normal);
//imageStore(dest, pix, vec4(.5 + geometry_normal * .5, 0.)); return;
/* const uint mi = uint(material_index); */
/* imageStore(dest, pix, vec4(rand3_f01(uvec3(mi,mi+1,mi+2)), 0.)); */
/* return; */
const int KERNEL_SIZE = 8;
float total_scale = 0.;
float specular_total_scale = 0.;
vec3 colour = vec3(0.);
vec3 speculour = vec3(0.);
for (int x = -KERNEL_SIZE; x <= KERNEL_SIZE; ++x)
for (int y = -KERNEL_SIZE; y <= KERNEL_SIZE; ++y) {
const ivec2 p = pix + ivec2(x, y);
if (any(greaterThanEqual(p, res)) || any(lessThan(p, ivec2(0)))) {
continue;
}
const vec4 c = imageLoad(src_diffuse_gi, p);
if (c.a != material_index)
continue;
vec3 sample_geometry_normal, sample_shading_normal;
readNormals(p, sample_geometry_normal, sample_shading_normal);
if ( dot(sample_geometry_normal, geometry_normal) < .99 )
continue;
// TODO bilaterally filter shading normals
const float sigma = KERNEL_SIZE / 2.;
const float scale = normpdf(x, sigma) * normpdf(y, sigma);
colour += scale * imageLoad(src_diffuse_gi, p).rgb;
total_scale += scale;
const int SPECULAR_KERNEL_SIZE = 2;
if (all(lessThan(abs(ivec2(x, y)), ivec2(SPECULAR_KERNEL_SIZE)))) {
const float spigma = SPECULAR_KERNEL_SIZE / 2.;
const float specuale = normpdf(x, spigma) * normpdf(y, spigma);
speculour += specuale * imageLoad(src_specular, p).rgb;
specular_total_scale += specuale;
}
}
if (total_scale > 0.) {
colour /= total_scale;
colour *= base_color.rgb;
}
if (specular_total_scale > 0.) {
speculour /= specular_total_scale;
//speculour *= base_color.rgb;
colour += speculour;
}
//colour += imageLoad(src_specular, pix).rgb;
colour += imageLoad(src_additive, pix).rgb;
colour = aces_tonemap(colour);
imageStore(dest, pix, vec4(colour, 0.));
//imageStore(dest, pix, imageLoad(src_diffuse_gi, pix));
}