#version 450 layout(location = 0) in vec2 uv; layout(location = 0) out vec4 out_color; layout(set = 2, binding = 0) uniform sampler2D screen; layout(std140, set = 3, binding = 0) uniform UniformBlock { mat4 model; mat4 view; mat4 proj; mat4 inv_view; mat4 inv_proj; vec4 cam_pos; float time; int post_mode; vec2 atlas_adjust; }; float t(float x, float y) { return length(texture(screen, vec2(x, y)).xyz); } mat3 neighborhood() { vec2 d = 1.0 / vec2(textureSize(screen, 0)); return mat3(t(uv.x - d.x, uv.y - d.y), t(uv.x + 0.0, uv.y - d.y), t(uv.x + d.x, uv.y - d.y), t(uv.x - d.x, uv.y - 0.0), t(uv.x + 0.0, uv.y + 0.0), t(uv.x + d.x, uv.y - 0.0), t(uv.x - d.x, uv.y + d.y), t(uv.x + 0.0, uv.y + d.y), t(uv.x + d.x, uv.y + d.y)); } float sum3(mat3 m) { float s = 0.0; for (int c = 0; c < 3; ++c) { vec3 col = m[c]; s += col.x + col.y + col.z; } return s; } float f(mat3 kernel) { return abs(sum3(matrixCompMult(kernel, neighborhood()))); } float brightness(vec3 color) { return dot(color, vec3(0.299, 0.587, 0.114)); } float dither() { if(length(texture(screen, uv).xyz) == 0.0) return 0.0; vec2 coord = uv * textureSize(screen, 0).xy; int x = int(mod(coord.x, 4.0)); int y = int(mod(coord.y, 4.0)); int index = x + y * 4; float threshold[16] = float[]( 0.0/16.0, 8.0/16.0, 2.0/16.0, 10.0/16.0, 12.0/16.0, 4.0/16.0, 14.0/16.0, 6.0/16.0, 3.0/16.0, 11.0/16.0, 1.0/16.0, 9.0/16.0, 15.0/16.0,7.0/16.0, 13.0/16.0, 5.0/16.0 ); vec3 color = texture(screen, uv).rgb; return brightness(color) < threshold[index] ? 0.0 : 1.0; } void main() { const mat3 sobelx = mat3(-1.0, -2.0, -1.0, 0.0, 0.0, 0.0, 1.0, 2.0, 1.0); const mat3 sobely = mat3(-1.0, 0.0, 1.0, -2.0, 0.0, 2.0, -1.0, 0.0, 1.0); switch(post_mode) { case 0: out_color = texture(screen, uv); break; case 1: out_color = vec4(brightness(texture(screen, uv).xyz) < 0.5? 0.0 : 1.0); break; case 2: out_color = vec4(dither()); break; } return; out_color = out_color * 0.9 + 0.1*((t(uv.x, uv.y) > 0.01)? vec4(abs(f(sobelx) + f(sobely))) : vec4(0.0)); }