Plinken SVG
A lucide “users” icon, pasted verbatim into a triple-quoted string and
turned into a 3D mesh by svg(src, depth:, size:) — strokes and all. It
turns on its Y axis as a translucent-blue glass mark (material opacity:)
while a spectral prism fan tilts toward the camera and sweeps a bright
crest across the spectrum. The fan’s brightness rides a vertical emissive
gradient(top:, bottom:), and opt-in bloom(...) makes only the brightest
crest glow. Everything loops seamlessly over 6s.
// Plinken SVG — an SVG icon turned into a turning 3D mark over a prism.
//
// Showcases runner 0.0.5 features: a verbatim SVG (the lucide "users"
// icon) pasted in a triple-quoted string and extruded by svg(src,
// depth:, size:); translucent material via opacity:; a vertical emissive
// gradient(top:, bottom:); and opt-in bloom(...). The mark sits in front
// of the beams in Z; a spectral fan tilts toward the camera and sweeps a
// bright crest once per loop. Loops seamlessly over 6s.
runner "0.0.5";
use std.shapes.*;
use std.mesh3d.*;
use std.text;
use std.lighting.*;
use std.scene3d.*;
use std.anim.*;
scene plinken_svg(duration: Duration = 6s) -> Frame {
let bg = rect(width: 1080px, height: 1080px, fill: oklch(0.08, 0.03, 280));
// The hero: one full turn every 6s, forever, with a slow wobble and a
// gentle breathing scale to keep the highlights alive.
let spin = animate { 0s => 0deg, 6s => 360deg } with { repeat: forever };
let wobble = wave(amplitude: 6deg, period: 6s);
let pulse = animate {
0s => 1.00,
1.5s => 1.035,
3s => 1.00,
6s => 1.00,
} with { easing: easing.out_cubic, repeat: forever };
// Emissive hue the mark picks up from the prism — a slow spectral drift
// so its self-glow shifts through the colours over the loop.
let pickup = animate { 0s => 250deg, 6s => 610deg } with { repeat: forever };
// Hero: the lucide "users" (plural) SVG, pasted verbatim via a triple-
// quoted string and turned into a 3D mesh by the svg(...) primitive
// (runner 0.0.5). Its stroked outlines (head rings + shoulder arcs)
// become extruded ribbons with `depth`; `size` sets its height in frame
// px. Big, in front, translucent blue, turning on Y. One material + spin
// wraps the whole figure.
let person = svg("""<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2"/><path d="M16 3.128a4 4 0 0 1 0 7.744"/><path d="M22 21v-2a4 4 0 0 0-3-3.87"/><circle cx="9" cy="7" r="4"/></svg>""", depth: 80px, size: 820px)
.material(fill: oklch(0.56, 0.15, 258),
metalness: 0.35,
roughness: 0.16,
opacity: 0.88,
emissive: oklch(0.50, 0.13, pickup),
emissive_intensity: 0.30)
.rotate(x: wobble, y: spin)
.scale(pulse)
.translate(y: 40px, z: 200px);
// ---- Prism fan -----------------------------------------------------
// Seven spectral wedges share one apex at (0, -80) — the point just under
// the mark — and fan down to the base at y = -600, tiling a wide span
// (x: -760..760) so that, after the forward tilt below, the beams reach
// the bottom frame edge and corners. Each wedge is an extruded triangle,
// self-lit, its emissive crest staggered so a bright "switch-on" sweeps
// the fan once per loop (wedge k peaks at k*(6/7)s).
let i0 = animate { 0s => 2.2, 0.6s => 0.7, 5.4s => 0.7, 6s => 2.2 } with { repeat: forever };
let i1 = animate { 0s => 0.7, 0.26s => 0.7, 0.86s => 2.2, 1.46s => 0.7, 6s => 0.7 } with { repeat: forever };
let i2 = animate { 0s => 0.7, 1.11s => 0.7, 1.71s => 2.2, 2.31s => 0.7, 6s => 0.7 } with { repeat: forever };
let i3 = animate { 0s => 0.7, 1.97s => 0.7, 2.57s => 2.2, 3.17s => 0.7, 6s => 0.7 } with { repeat: forever };
let i4 = animate { 0s => 0.7, 2.83s => 0.7, 3.43s => 2.2, 4.03s => 0.7, 6s => 0.7 } with { repeat: forever };
let i5 = animate { 0s => 0.7, 3.69s => 0.7, 4.29s => 2.2, 4.89s => 0.7, 6s => 0.7 } with { repeat: forever };
let i6 = animate { 0s => 0.7, 4.54s => 0.7, 5.14s => 2.2, 5.74s => 0.7, 6s => 0.7 } with { repeat: forever };
// The deployed viewer recentres every extruded path on its own bounding
// box (geom.center()), so each wedge is translated back by its bbox
// centre to restore the shared apex at (0,-80) and the tiled base at
// y=-600. bbox-centre y is (-80 + -600)/2 = -340 for all; x varies.
let w0 = extrude(path(points: [vec2(0, -80), vec2(-760, -600), vec2(-543, -600)]), depth: 8px).material(fill: oklch(0.66, 0.24, 25), emissive: oklch(0.66, 0.24, 25), emissive_intensity: gradient(top: 0.3, bottom: i0)).translate(x: -380.0px, y: -340.0px);
let w1 = extrude(path(points: [vec2(0, -80), vec2(-543, -600), vec2(-326, -600)]), depth: 8px).material(fill: oklch(0.74, 0.2, 60), emissive: oklch(0.74, 0.2, 60), emissive_intensity: gradient(top: 0.3, bottom: i1)).translate(x: -271.4px, y: -340.0px);
let w2 = extrude(path(points: [vec2(0, -80), vec2(-326, -600), vec2(-109, -600)]), depth: 8px).material(fill: oklch(0.88, 0.18, 98), emissive: oklch(0.88, 0.18, 98), emissive_intensity: gradient(top: 0.3, bottom: i2)).translate(x: -162.9px, y: -340.0px);
let w3 = extrude(path(points: [vec2(0, -80), vec2(-109, -600), vec2(109, -600)]), depth: 8px).material(fill: oklch(0.74, 0.21, 150), emissive: oklch(0.74, 0.21, 150), emissive_intensity: gradient(top: 0.3, bottom: i3)).translate(x: 0.0px, y: -340.0px);
let w4 = extrude(path(points: [vec2(0, -80), vec2(109, -600), vec2(326, -600)]), depth: 8px).material(fill: oklch(0.72, 0.16, 210), emissive: oklch(0.72, 0.16, 210), emissive_intensity: gradient(top: 0.3, bottom: i4)).translate(x: 162.9px, y: -340.0px);
let w5 = extrude(path(points: [vec2(0, -80), vec2(326, -600), vec2(543, -600)]), depth: 8px).material(fill: oklch(0.62, 0.2, 265), emissive: oklch(0.62, 0.2, 265), emissive_intensity: gradient(top: 0.3, bottom: i5)).translate(x: 271.4px, y: -340.0px);
let w6 = extrude(path(points: [vec2(0, -80), vec2(543, -600), vec2(760, -600)]), depth: 8px).material(fill: oklch(0.58, 0.23, 320), emissive: oklch(0.58, 0.23, 320), emissive_intensity: gradient(top: 0.3, bottom: i6)).translate(x: 380.0px, y: -340.0px);
// ---- Lighting ------------------------------------------------------
// A soft neutral key/fill for the mark's form, plus three coloured point
// lights between the fan and the mark (toward the camera, z ≈ +300..340)
// whose hues drift around the wheel out of phase — the prism colours
// washing up onto the mark.
let hueA = animate { 0s => 0deg, 6s => 360deg } with { repeat: forever };
let hueB = animate { 0s => 120deg, 6s => 480deg } with { repeat: forever };
let hueC = animate { 0s => 240deg, 6s => 600deg } with { repeat: forever };
let lights = [
ambient(0.30),
directional(from: vec3(2, 4, 6), intensity: 1.1),
point(at: vec3(-260px, -150px, 300px), intensity: 0.9, range: 1100px, color: oklch(0.72, 0.18, hueA)),
point(at: vec3( 0px, -120px, 340px), intensity: 0.8, range: 1100px, color: oklch(0.72, 0.18, hueB)),
point(at: vec3( 260px, -150px, 300px), intensity: 0.9, range: 1100px, color: oklch(0.72, 0.18, hueC)),
// Opt-in glow: a high threshold so only the brightest prism crest
// blooms — keeps the haze off the matte background and the P, which
// stays the crisp hero on top of a softly glowing beam.
bloom(strength: 0.55, radius: 0.4, threshold: 0.72),
];
// Tilt the whole fan toward the camera so the beam reads as coming at the
// viewer. The group pivots about the world origin, which sits just above
// the fan's apex, so the apex stays put and the base swings forward.
let fan = compose [w0, w1, w2, w3, w4, w5, w6];
compose [
bg,
render3d(
compose [fan.rotate(x: -12deg), person],
lights: lights,
camera: camera(distance: 2166),
),
]
}