Skip to content

Instantly share code, notes, and snippets.

@uta8a
Created December 27, 2022 14:42
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save uta8a/5fa4586019c38a9a82d12fb5a7feb0b7 to your computer and use it in GitHub Desktop.
Save uta8a/5fa4586019c38a9a82d12fb5a7feb0b7 to your computer and use it in GitHub Desktop.
video-glsl.mp4

URL

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);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment