video-glsl.mp4
twigl, mode: classic
code
precision highp float;
uniform vec2 resolution;
uniform vec2 mouse;
uniform float time;
const float PI = 3.14159265359;
const float fov = 50.0;
const float fovx = PI * fov / 360.0;
const float S = 0.01;
const vec3 deltax = vec3(S ,0., 0.);
const vec3 deltay = vec3(0. ,S, 0.);
const vec3 deltaz = vec3(0. ,0., S);
vec3 draw_background(vec2 canvas, float side) {
float B = 0.1; // border
float W = 0.03; //width
float S = 0.3;
vec3 background_color = vec3(0.0, 0.0, 0.05);
vec2 pad = (resolution - side) / 2.0;
vec2 regularized = (canvas - pad) / side; // 0 ~ 1
vec3 border_color = vec3(abs(sin(2.0 * regularized.x)), abs(cos(regularized.y)), 0.9);
vec2 bottom_left = pad;
vec2 top_right = resolution - pad;
vec2 inside = step(bottom_left, canvas) - step(top_right, canvas);
vec2 border_inside = step(B, regularized) - step(1.0 - B, regularized);
vec2 stage_inside = step(B+W, regularized) - step(1.0 - B - W, regularized);
vec3 stage = mix(border_color, background_color, stage_inside.x * stage_inside.y);
vec3 content = mix(background_color, stage, border_inside.x * border_inside.y);
vec3 res = mix(background_color, content, inside.x * inside.y);
return res;
}
// square?
float distanceToNearestSurface(vec3 p) {
vec3 q = abs(p) - vec3(1.);
float dist = max(max(q.x, q.y), q.z);
if (q.x > 0. && q.y > 0. && q.z > 0.) {
dist = length(q);
}
return dist;
}
vec3 computeSurfaceNormal(vec3 p) {
float d = distanceToNearestSurface(p);
return normalize(vec3(distanceToNearestSurface(p + deltax) - d, distanceToNearestSurface(p + deltay) - d, distanceToNearestSurface(p + deltaz) - d));
}
vec3 computeLambert(vec3 p, vec3 n, vec3 l) {
float side = min(resolution.x, resolution.y);
vec2 pad = (resolution - side) / 2.0;
vec2 regularized = (gl_FragCoord.xy - pad) / side; // 0 ~ 1
float b = dot(normalize(l-p), n);
vec3 color = vec3(b * 1.6 * abs(sin(3. * sin(time) * regularized.y)), 0.8 * abs(cos(12. * b * (regularized.x * regularized.y))), b * abs(2. * sin(regularized.x)));
vec3 color2 = color.yzx;
vec3 color3 = color.xyz;
return mix(color3, color2, abs(sin(time)));
}
vec3 intersectsWithWorld(vec3 p, vec3 dir) {
float dist = 0.;
float nearest = 0.;
for (int i = 0; i < 30; i++) {
float nearest = distanceToNearestSurface(p + dir * dist);
if (nearest < 0.01) {
vec3 hit = p + dir * dist;
vec3 light = vec3(p);
return computeLambert(hit, computeSurfaceNormal(hit), light);
}
dist += nearest;
}
return draw_background(gl_FragCoord.xy, min(resolution.x, resolution.y));
}
void main(){
vec2 uv = gl_FragCoord.xy/resolution;
float cameraDistance = 7.;
float theta = 0.;
float phi =PI/2. * time;
vec3 cameraPosition = vec3(cameraDistance * cos(theta) * cos(phi), cameraDistance * sin(theta) * cos(phi), cameraDistance * sin(phi));
vec3 cameraDirection = vec3(-1. * cos(theta) * cos(phi), -1. * sin(theta) * cos(phi), -1. * sin(phi));
vec3 cameraUp = vec3(0., 1., 0.);
// generate ray
float fovy = fovx * resolution.y/resolution.x;
float ulen = tan(fovx);
float vlen = tan(fovy);
vec2 camUV = uv*2. - vec2(1., 1.);
vec3 nright = normalize(cross(cameraUp, cameraDirection));
vec3 pixel = cameraPosition + cameraDirection + nright * camUV.x * ulen + cameraUp * camUV.y * vlen;
vec3 rayDirection = normalize(pixel - cameraPosition);
vec3 pixelColor = intersectsWithWorld(cameraPosition, rayDirection);
gl_FragColor = vec4(pixelColor, 1.0);
}