92 lines
2.1 KiB
GLSL
92 lines
2.1 KiB
GLSL
#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 projection;
|
|
mat4 inv_view;
|
|
mat4 inv_projection;
|
|
vec4 time_padded;
|
|
vec4 cam_pos;
|
|
};
|
|
|
|
const int MAX_MARCH_STEPS = 64;
|
|
const float EPS_DIST = 1e-6;
|
|
|
|
|
|
float sdf(vec3 point){
|
|
float t = 1.0 + 5.0*abs(sin(time_padded.x));
|
|
vec3 s1_local = point; //mod(point, vec3(t)) - vec3(t/2.0);
|
|
float s1 = length(s1_local) - t;
|
|
return s1;
|
|
}
|
|
|
|
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);
|
|
point += h * ray;
|
|
if (h + totaldist > max_depth)
|
|
break;
|
|
if (h < EPS_DIST) {
|
|
return vec4(point, totaldist + h);
|
|
}
|
|
|
|
totaldist += h;
|
|
}
|
|
|
|
return vec4(-1.0);
|
|
}
|
|
|
|
vec3 camray() {
|
|
vec2 ndc = uv * 2.0 - 1.0;
|
|
ndc.y = -ndc.y;
|
|
vec4 view_pos = inv_projection * 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;
|
|
if (d >= 1.0) return 1000.0;
|
|
vec4 ndc = vec4((uv * 2.0 - 1.0), d * 2.0 - 1.0, 1.0);
|
|
vec4 view_pos = inv_projection * 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(getnormal(hit.xyz), 1.0);
|
|
} else {
|
|
out_color = texture(screen, uv);
|
|
}
|
|
}
|
|
|