pleascach/assets/shaders/manual.frag
2024-02-16 13:00:35 -05:00

126 lines
2.4 KiB
GLSL

#version 450 core
#define MAX_STEPS 100
#define MAX_DIST 1000.0
layout (set = 0, binding = 1) uniform sampler2D tex;
layout (set = 0, binding = 0) uniform Matrices {
vec3 cam_pos;
float time;
vec4 viewport;
vec3 cam_dir;
uint n_objects;
float rad;
};
layout (location = 0) in vec2 pos;
layout (location = 0) out vec4 fragColor;
vec2 eps = vec2(0.001, 0.0);
/* joins two parts of a scene */
float op_union(float v1, float v2) {
return min(v1, v2);
}
/* subtracts sdf from scene */
float op_subtract(float v1, float v2) {
return max(v1, -v2);
}
/* twists! in the xz */
vec3 op_twist(vec3 p, float k) {
float c = cos(k*p.y);
float s = sin(k*p.y);
mat2 m = mat2(c, -s, s, c);
return vec3(m*p.xz, p.y);
}
float box(vec3 p, vec3 r) {
vec3 q = abs(p) - r;
return length(max(q,0.0)) + min(max(q.x, max(q.y,q.z)), 0.0);
}
/* square, centered at the origin */
float box(vec2 p, vec2 r) {
vec2 d = abs(p)-r;
return length(max(d, 0.0)) + min(max(d.x,d.y), 0.0);
}
/* infinite cross, used for construction of serpinski cube */
float infcross(vec3 p, float r) {
vec2 unit = vec2(r);
float box1 = box(p.xy, unit);
float box2 = box(p.yz, unit);
float box3 = box(p.zx, unit);
return op_union(op_union(box1, box2), box3);
}
float sphere(vec3 p, float r) {
return length(p) - r;
}
float sdf(vec3 p) {
p = op_twist(p.xzy, cos(time)).xzy;
float d = box(p, vec3(1.0));
float s = 1.0;
for(int i = 0; i < 5; i++) {
/* using mod to repeat across domain, then shift to +- */
vec3 a = mod(p * s, 2.0) - 1.0;
s *= 3.0;
vec3 r = 1.0 - 3.0*abs(a);
float c = infcross(r, rad)/s;
d = max(d, c);
}
return d;
}
vec3 norm(vec3 pos) {
return normalize(
vec3(
sdf(pos+eps.xyy),
sdf(pos+eps.yxy),
sdf(pos+eps.yyx)
) - sdf(pos)
);
}
vec2 raycast(vec3 dir) {
float t = 0.0;
for(int i = 0; i < MAX_STEPS; i++) {
float dt = sdf(cam_pos + dir * t);
if(dt < 0.0001*t)
return vec2(t, float(i));
else if(dt > MAX_DIST)
return vec2(0.0, -1.0);
t += dt;
}
return vec2(0.0, 64.0);
}
vec3 raygen() {
vec3 forward = cam_dir;
vec3 right = normalize(cross(forward, vec3(0.0, 1.0, 0.0)));
vec3 up = normalize(cross(right, forward));
return normalize(pos.x * right + pos.y * up + forward * 2.0);
}
vec3 gamma(vec3 c) {
return pow(c, vec3(0.4545));
}
void main() {
vec3 dir = raygen();
vec2 d = raycast(dir);
if(d.y == -1.0) {
fragColor = vec4(0.0);
return;
}
fragColor = vec4(d.y/MAX_STEPS);
fragColor.xyz = gamma(fragColor.xyz);
}