16
0
mirror of https://github.com/MaSzyna-EU07/maszyna.git synced 2026-07-18 00:49:19 +02:00
Files
maszyna/shaders/postfx_ssao.frag

72 lines
2.2 KiB
GLSL

in vec2 f_coords;
layout(location = 0) out vec4 out_color;
#texture (depth_tex, 0, R)
uniform sampler2D depth_tex;
#texture (noise_tex, 1, RGB)
uniform sampler2D noise_tex;
#include <common>
vec3 view_pos_from_depth(vec2 uv, float depth) {
vec4 clip = vec4(uv * 2.0 - 1.0, depth * 2.0 - 1.0, 1.0);
vec4 view = inverse(projection) * clip;
return view.xyz / view.w;
}
// Deterministic hemisphere sample (z > 0), mimics the C++ kernel generator
vec3 kernel_sample(int i) {
float fi = float(i);
vec3 dir = normalize(vec3(
fract(sin(fi * 12.9898) * 43758.5453) * 2.0 - 1.0,
fract(sin(fi * 78.2330) * 43758.5453) * 2.0 - 1.0,
fract(sin(fi * 37.7190) * 43758.5453) // z >= 0 -> hemisphere
));
float len = fract(sin(fi * 94.6720) * 43758.5453);
float scale = fi / 32.0;
scale = mix(0.1, 1.0, scale * scale); // bias samples inward
return dir * len * scale;
}
void main() {
float d = texture(depth_tex, f_coords).r;
if (d >= 1.0) { out_color = vec4(1.0); return; } // skybox -> no occlusion
vec3 pos = view_pos_from_depth(f_coords, d);
vec3 ddx = dFdx(pos);
vec3 ddy = dFdy(pos);
vec3 n = normalize(cross(ddx, ddy));
// derive screen size from the depth texture instead of a UBO field
vec2 screen_size = vec2(textureSize(depth_tex, 0));
vec2 noise_uv = f_coords * (screen_size / 4.0);
vec3 rvec = texture(noise_tex, noise_uv).xyz;
vec3 t = normalize(rvec - n * dot(rvec, n));
vec3 b = cross(n, t);
mat3 TBN = mat3(t, b, n);
const int KERNEL = 32;
const float RADIUS = 0.5;
const float BIAS = 0.025;
float occ = 0.0;
for (int i = 0; i < KERNEL; ++i) {
vec3 sp = TBN * kernel_sample(i);
sp = pos + sp * RADIUS;
vec4 clip = projection * vec4(sp, 1.0);
vec3 ndc = clip.xyz / clip.w;
vec2 suv = ndc.xy * 0.5 + 0.5;
float sd = texture(depth_tex, suv).r;
float szv = view_pos_from_depth(suv, sd).z;
float range = smoothstep(0.0, 1.0, RADIUS / abs(pos.z - szv));
occ += (szv >= sp.z + BIAS ? 1.0 : 0.0) * range;
}
out_color = vec4(1.0 - occ / float(KERNEL));
}