mirror of
https://github.com/hanzo-apps/hanzo.ai.git
synced 2026-10-30 14:58:08 +00:00
Nine concepts to the owner's mockup, grey on true black, the subject right
of centre and the left 40% kept dark for a card's words: Enso a brushed
ensÅ shedding particles over water and mist, Kai three panes of glass
threaded by falling light, Zen a sphere in raked sand, Iro mountains and
cloud spilling out of a frame, Koma film frames running into depth, Oto a
mirrored waveform, Koe twisting ribbons, Uta a fan rising over strings,
Mori a wireframe peak.
Each is one fragment shader over film/models/gl.js, a pure function of the
loop's phase, so the frame after the last is the first. film.mjs steps it
on the GPU, refuses a seam, and cuts public/models/<name>.{webp,webm,mp4}:
1200x1500 for every model and a 1500x1500 Enso, 30 fps, each loop under
700 KB. Frames stay in film/models/frames (ignored).
55 lines
2.0 KiB
HTML
55 lines
2.0 KiB
HTML
<!doctype html>
|
|
<html data-seconds="6">
|
|
<meta charset="utf-8" />
|
|
<title>Koe</title>
|
|
<style>html,body{margin:0;background:#000}canvas{display:block}</style>
|
|
<body>
|
|
<canvas></canvas>
|
|
<!--
|
|
Koe: a voice drawn as ribbons. Forty fine sine lines, each a blend of two
|
|
waves, so together they twist like one ribbon turning in the light, rising
|
|
out of the dark on the left and swelling to the right. In the loop both
|
|
waves travel, one twice as fast as the other, and the ribbon turns over.
|
|
-->
|
|
<script type="x-shader/x-fragment">
|
|
const int N = 34;
|
|
|
|
// One ribbon: N lines, each a blend of two waves, so together they twist.
|
|
float ribbon(vec2 f, float x, float A, float dA, float grow, float k1, float k2, float m2, float off, float gain){
|
|
float H = R.y;
|
|
float L = 0.;
|
|
for (int i = 0; i < N; i++) {
|
|
float t = float(i) / float(N - 1);
|
|
float p1 = k1 * x - TAU * P + off;
|
|
float p2 = k2 * x - TAU * P * m2 + off * 1.7 + 1.9 + t * 1.4;
|
|
float w = mix(sin(p1), .8 * sin(p2), t);
|
|
float dw = mix(k1 * cos(p1), .8 * k2 * cos(p2), t);
|
|
float yi = .5 * H + A * w;
|
|
float slope = (A * dw + dA * w) / H;
|
|
float d = abs(f.y - yi) / sqrt(1. + slope * slope);
|
|
float edge = abs(t - .5) * 2.;
|
|
float bright = (.3 + .5 * (1. - edge * edge)) * grow * gain;
|
|
L += bright * (1. - smoothstep(.25, 1.05, d)) + exp(-d / 6.) * .025 * grow * gain;
|
|
}
|
|
return L;
|
|
}
|
|
|
|
float scene(vec2 f){
|
|
float H = R.y;
|
|
float x = f.x / H;
|
|
float x0 = .3 * R.x / H;
|
|
// The ribbons swell out of nothing on the left and hold to the right.
|
|
float grow = smoothstep(x0, x0 + .36, x);
|
|
float A = .23 * H * grow;
|
|
float dA = .23 * H * (smoothstep(x0, x0 + .36, x + .001) - grow) / .001;
|
|
float L = ribbon(f, x, A, dA, grow, 7.2, 4.6, 2., .3, 1.)
|
|
+ ribbon(f, x, A * .78, dA * .78, grow, 5.6, 8.4, 1., 2.6, .6);
|
|
// The left of the frame is the words': keep it dark.
|
|
L *= mix(.1, 1., smoothstep(.22, .45, f.x / R.x));
|
|
return pow(tone(L * 1.05), .9);
|
|
}
|
|
</script>
|
|
<script src="./gl.js"></script>
|
|
</body>
|
|
</html>
|