221 lines
5.5 KiB
GLSL
221 lines
5.5 KiB
GLSL
layout(std140) uniform param {
|
|
float type;
|
|
float prev_type;
|
|
float transition;
|
|
} p;
|
|
|
|
in vec2 v_uv;
|
|
|
|
out vec4 o_color;
|
|
|
|
const float EPSILON = 1e-4;
|
|
const float INF = 1e+2;
|
|
|
|
/* ---- UTILITY FUNCTIONS ---- */
|
|
vec3 get_ray_direction(in vec2 p, in vec2 s, float fov) {
|
|
return normalize(vec3(p*s/2., s.y/tan(radians(fov)/2.)));
|
|
}
|
|
mat2 rot(in float theta) {
|
|
float c = cos(theta);
|
|
float s = sin(theta);
|
|
return mat2(c, -s, s, c);
|
|
}
|
|
#define get_normal(sdf, d, p) \
|
|
normalize(d - vec3( \
|
|
sdf(p-vec3(EPSILON, 0., 0.)), \
|
|
sdf(p-vec3(0., EPSILON, 0.)), \
|
|
sdf(p-vec3(0., 0., EPSILON))))
|
|
|
|
/* ---- SIGNED DISTANCE FUNCTIONS ---- */
|
|
/* https://iquilezles.org/www/articles/distfunctions/distfunctions.htm */
|
|
float sd_box( vec3 p, vec3 b ) {
|
|
vec3 q = abs(p) - b;
|
|
return length(max(q,0.)) + min(max(q.x,max(q.y,q.z)),0.);
|
|
}
|
|
float sd_round_box( vec3 p, vec3 b, float r ) {
|
|
vec3 q = abs(p) - b;
|
|
return length(max(q,0.0)) + min(max(q.x,max(q.y,q.z)),0.0) - r;
|
|
}
|
|
|
|
/* ---- SCENE: infinite boxes ---- */
|
|
float infinite_boxes_sd_scene(in vec3 p) {
|
|
p = abs(p);
|
|
p = mod(p, 2.) - 1.;
|
|
return sd_box(p, vec3(.5));
|
|
}
|
|
vec3 infinite_boxes_raymarch(in vec2 uv, in vec3 eye) {
|
|
vec3 dir = get_ray_direction(uv, uni.resolution, 60.);
|
|
|
|
float h = 2., d, i;
|
|
for (i = 0.; i < 100.; ++i) {
|
|
d = infinite_boxes_sd_scene(eye + dir*h);
|
|
if (d < EPSILON || h > 100.) break;
|
|
h += d;
|
|
}
|
|
float a = 45./(i+1.)/h;
|
|
return mix(vec3(.3, .3, .4), vec3(.6, .8, .7), clamp(a, 0., 1.));
|
|
}
|
|
vec4 infinite_boxes(void) {
|
|
vec2 e2 = vec2(0., 1.) / uni.resolution;
|
|
|
|
vec3 eye = vec3(0., fract(uni.time/60.)*2., 0.);
|
|
|
|
eye.xy += fract(uni.pos.xy/2.)*2. + uni.pos.zw - vec2(.5, .5);
|
|
|
|
vec3 col = infinite_boxes_raymarch(v_uv, eye);
|
|
vec3 scol =
|
|
infinite_boxes_raymarch(v_uv + e2, eye) +
|
|
infinite_boxes_raymarch(v_uv - e2, eye);
|
|
scol /= 2.;
|
|
return vec4(mix(col, scol, .5), 1.);
|
|
}
|
|
|
|
/* ---- SCENE: HOLLOW MOUNTAINS ---- */
|
|
float hollow_mountains_sd_scene(in vec3 p, in vec3 v) {
|
|
float s = 8., r;
|
|
p = abs(mod(p, 2.) - 1.)*2.;
|
|
for (float i = 0.; i < 5.; ++i) {
|
|
p = 1. - abs(p-v);
|
|
r = 1.4/dot(p, p);
|
|
s *= r;
|
|
p *= r;
|
|
}
|
|
return length(p)/s;
|
|
}
|
|
vec4 hollow_mountains(in vec3 color) {
|
|
vec3 dir = get_ray_direction(v_uv, uni.resolution, 60.);
|
|
|
|
vec3 eye = vec3(0., 0., 0.);
|
|
eye.xy = fract(uni.pos.xy/2.)*2. + uni.pos.zw;
|
|
|
|
float t = abs(fract(uni.time/20.)*2.-1.);
|
|
t = t*t*(3.-2.*t);
|
|
vec3 v = vec3(.9, 1., .94+t*.1);
|
|
|
|
float h = 1.3, d, i;
|
|
for (i = 0.; i < 60.; ++i) {
|
|
d = hollow_mountains_sd_scene(eye + dir*h, v);
|
|
if (d < EPSILON || h > 100.) break;
|
|
h += d;
|
|
}
|
|
|
|
float a = 200./(i+1.)/h;
|
|
return vec4(mix(vec3(.2, .2, .2), color, a), 1.);
|
|
}
|
|
|
|
/* ---- SCENE: JAIL ---- */
|
|
float jail_sd_scene(in vec3 p) {
|
|
p = mod(p, 2.) - 1.;
|
|
|
|
float dist = INF;
|
|
for (float i = 0.; i < 7.; ++i) {
|
|
float t = PI/6.*i*2.;
|
|
|
|
vec3 p2 = p;
|
|
p2.x += cos(t)*.1;
|
|
p2.xz *= rot(t);
|
|
p2.y += .4*(i-3.);
|
|
|
|
dist = min(dist, sd_box(p2, vec3(.19)));
|
|
}
|
|
return dist;
|
|
}
|
|
vec3 jail_raymarch(in vec2 uv, in vec3 eye) {
|
|
vec3 dir = get_ray_direction(uv, uni.resolution.xy, 60.);
|
|
|
|
float h = 1.6, d, i;
|
|
for (i = 0.; i < 20.; ++i) {
|
|
d = jail_sd_scene(eye + dir*h);
|
|
if (d < EPSILON || h > INF) break;
|
|
h += d;
|
|
}
|
|
vec3 p = eye + dir*h;
|
|
vec3 norm = get_normal(jail_sd_scene, d, p);
|
|
|
|
float diffuse = clamp(dot(vec3(0., 0., 1.), norm), 0., 1.);
|
|
|
|
float a = 3. + diffuse*.7;
|
|
|
|
a /= pow(h*.3, 2.) * (i*.2+1.);
|
|
a = clamp(a, 0., 1.);
|
|
|
|
return mix(vec3(.2, .3, .3), vec3(.4, .4, .5), a) + vec3(.7, .4, .4)*a;
|
|
}
|
|
vec4 jail(void) {
|
|
vec2 e1 = vec2(1., 0.)/uni.resolution.xy;
|
|
vec2 e2 = vec2(0., 1.)/uni.resolution.xy;
|
|
|
|
vec3 eye = vec3(0., 0., -4.);
|
|
|
|
eye.xy += fract(uni.pos.xy/2.)*2. + uni.pos.zw + vec2(.5, .5);
|
|
|
|
vec3 col = jail_raymarch(v_uv, eye);
|
|
vec3 scol =
|
|
jail_raymarch(v_uv + e1 + e2, eye) +
|
|
jail_raymarch(v_uv + e1 - e2, eye) +
|
|
jail_raymarch(v_uv - e1 + e2, eye) +
|
|
jail_raymarch(v_uv - e1 - e2, eye);
|
|
scol /= 4.;
|
|
return vec4(mix(col, scol, .5), 1.);
|
|
}
|
|
|
|
/* ---- SCENE: fabric ---- */
|
|
float fabric_sd_rope(in vec3 p) {
|
|
p.yz *= rot(PI/8. + p.x*PI);
|
|
return sd_round_box(p, vec3(2.5, .2, .2), .03);
|
|
}
|
|
float fabric_sd_scene(in vec3 p) {
|
|
p = mod(p, 4.) - 2.;
|
|
|
|
vec3 p2 = p/sqrt(2.);
|
|
p2.xy *= rot(PI/4.);
|
|
p2.y = mod(p2.y, 2.) - 1.;
|
|
float dist = fabric_sd_rope(p2);
|
|
|
|
p2 = p/sqrt(2.);
|
|
p2.xy *= rot(-PI/4.);
|
|
p2.y = mod(p2.y, 2.) - 1.;
|
|
dist = min(dist, fabric_sd_rope(p2));
|
|
|
|
return dist;
|
|
}
|
|
vec4 fabric(void) {
|
|
vec3 dir = get_ray_direction(v_uv, uni.resolution.xy, 80.);
|
|
vec3 eye = vec3(0., 0., -4.);
|
|
|
|
eye.xy += uni.pos.zw*4.;
|
|
|
|
float h = 4.5, d, i;
|
|
for (i = 0.; i < 50.; ++i) {
|
|
d = fabric_sd_scene(eye + dir*h);
|
|
if (d < EPSILON || h > INF) break;
|
|
h += d;
|
|
}
|
|
|
|
vec3 norm = get_normal(fabric_sd_scene, h, eye + dir*h);
|
|
float diffuse = clamp(dot(vec3(0., 0., -1.), norm), .5, 1.);
|
|
|
|
float a = diffuse*.9 - .3;
|
|
a /= pow(h*.08, 2.) * (i*.3+.5);
|
|
a = clamp(a, 0., 1.);
|
|
|
|
vec3 col = mix(vec3(.25, .3, .2), vec3(.4, .6, .7), a) + vec3(1., .0, .0)*a;
|
|
return vec4(col, 1.);
|
|
}
|
|
|
|
vec4 scene(in float type) {
|
|
return
|
|
type == 1.? infinite_boxes():
|
|
type == 2.? hollow_mountains(vec3(.1, .4, .1)):
|
|
type == 3.? hollow_mountains(vec3(.4, .1, .1)):
|
|
type == 4.? jail():
|
|
type == 5.? fabric():
|
|
vec4(1.);
|
|
}
|
|
void main(void) {
|
|
vec4 prev = vec4(0.), next = vec4(0.);
|
|
if (p.transition > 0.) next = clamp(scene(p.type), 0., 1.);
|
|
if (p.transition < 1.) prev = clamp(scene(p.prev_type), 0., 1.);
|
|
o_color = mix(prev, next, p.transition);
|
|
}
|