#version 450 layout(location = 0) in vec2 uv; layout(location = 0) out vec4 out_color; layout(set = 2, binding = 0) uniform sampler2D screen; layout(set = 2, binding = 1) uniform sampler2D depth_tex; 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; }; const int MAX_MARCH_STEPS = 64; const float EPS_DIST = 1e-6; float sdf(vec3 point) { vec3 p = point - cam_pos.xyz; const float speed = 1.0 + exp(sin(time)); float t = speed * time; const int N = 5; float d = 1.0/EPS_DIST; float orbit_radius = 0.4; float radius = 0.03; for(int i = 0; i < N; i++) { float phase = ((3.14159 * 2.0) / float(N)) * float(i); d = min(d, length(p - orbit_radius*vec3(sin(t + phase), 0.0, cos(t + phase))) - radius); } return d; } vec3 getnormal(vec3 p) { float e = EPS_DIST; return normalize(vec3( sdf(p + vec3(e, 0.0, 0.0)) - sdf(p - vec3(e, 0.0, 0.0)), sdf(p + vec3(0.0, e, 0.0)) - sdf(p - vec3(0.0, e, 0.0)), sdf(p + vec3(0.0, 0.0, e)) - sdf(p - vec3(0.0, 0.0, e)) )); } vec4 march(vec3 point, vec3 ray, float max_depth) { float totaldist = 0.0; int i; for (i = 0; i < MAX_MARCH_STEPS && totaldist < max_depth; i += 1) { float h = sdf(point); if (h < EPS_DIST) { totaldist += h; return vec4(point, totaldist); } totaldist += h; if (totaldist > max_depth) break; point += h * ray; } return vec4(-1.0); } vec3 camray() { vec2 ndc = uv * 2.0 - 1.0; ndc.y = -ndc.y; vec4 view_pos = inv_proj * vec4(ndc, 1.0, 1.0); view_pos /= view_pos.w; return normalize((inv_view * vec4(normalize(view_pos.xyz), 0.0)).xyz); } vec4 kernel(float max_depth) { max_depth = (max_depth > 0.0)? max_depth : 1000.0; vec3 cam_ray = camray(); return march(cam_pos.xyz, cam_ray, max_depth); } float linearize_depth(vec2 uv) { float d = texture(depth_tex, uv).r; vec4 ndc = vec4(uv * 2.0 - 1.0, d * 2.0 - 1.0, 1.0); vec4 view_pos = inv_proj * ndc; view_pos /= view_pos.w; return -view_pos.z; // view space, positive distance } void main() { float max_depth = linearize_depth(uv); vec4 hit = kernel(max_depth); if (hit.w > 0.0) { out_color = vec4(1.0);//out_color = vec4(getnormal(hit.xyz), 1.0); } else { out_color = texture(screen, uv); } }