Doop
Doop is an open-source multiplayer design canvas and design MCP for Claude Code, Codex, and any AI agent. Design side by side with agents — free in beta.
Audio-Technica AT-LP120XUSB professional turntable rendered in real time with WebGPU via vgpu: PBR, studio lighting, soft shadows and bloom.
DesignTypeScript · WGSLGitHub @arvenz0210OnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
No updates detected yet. GitHub releases will appear here.
Owners of public repositories under a personal GitHub account can sign in to verify ownership and manage the introduction themselves. No administrator approval is needed.
Sign in, generate a verification file, and commit it to this repository’s default branch within 30 minutes. Files on other branches or forks do not count. Then check the file below to manage the project without administrator approval. Keep the file to retain your access.
If needed, you will go to sign-in. After signing in, return here and press your chosen verification button again.
Run /nomorevibe verify in your project folder to verify ownership and manage the introduction yourself.
Verify in one minuteAsk about other verification options
AT-LP120XUSB turntable rendered with vgpu (WebGPU) in Next.js
Translation pending
Taken from the repository README
Loading the full README. The saved excerpt is shown below.
Visor 3D en tiempo real de una bandeja giradisco profesional (Audio-Technica AT-LP120XUSB, acabado negro) construido con Next.js 16 y vgpu, la librería WebGPU de Vercel Labs. Todo el render corre en WebGPU a través de la API de vgpu (draw, effect, target, frameLoop, uniforms, módulos WGSL con import/export), sin three.js.Read the full README ↗
Visor 3D en tiempo real de una bandeja giradisco profesional (Audio-Technica
AT-LP120XUSB, acabado negro) construido con Next.js 16 y vgpu,
la librería WebGPU de Vercel Labs. Todo el render corre en WebGPU a través de la API
de vgpu (draw, effect, target, frameLoop, uniforms, módulos WGSL con
import/export), sin three.js.
lib/gltf/glb.ts, sin dependencias).orbitControls) con auto‑rotación, plato girando a 33⅓ rpm,
y un acabado "Negro" que recolorea el dorado del modelo original a negro satinado.pnpm install
pnpm dev
# http://localhost:3000 -> bandeja giradisco
# http://localhost:3000/?model=helmet -> Damaged Helmet (Khronos), prueba de pipeline
Requiere un navegador con WebGPU (Chrome/Edge 113+, Safari 26+).
Los .glb viven en public/models/ y están fuera de git por tamaño.
| id | archivo | fuente |
|---|---|---|
turntable | public/models/turntable.glb | Pioneer PLX‑1000 Turntable Ltd. (Remastered) · Mateusz Kołakowski · CC BY 4.0 |
helmet | public/models/DamagedHelmet.glb | Khronos glTF Sample Assets · CC BY‑NC 4.0 |
No existe un modelo libre del AT‑LP120XUSB; el PLX‑1000 comparte la misma
arquitectura (clon del Technics SL‑1200: brazo en S, plato con puntos de estrobo,
pitch fader) y el acabado "Negro" lo acerca al AT‑LP120X negro. Para usar otro GLB,
añade una entrada en lib/models.ts.
app/ layout + página (Server Component) que monta el visor
components/ TurntableViewer.tsx (client) + HUD
lib/gltf/glb.ts parser GLB -> buffers intercalados, materiales, instancias
lib/render/engine.ts ciclo de render vgpu: sombra -> PBR HDR -> bloom -> post
lib/render/environment.ts horneado IBL (entorno, prefiltro GGX, irradiancia, LUT)
lib/render/textures.ts subida de imágenes + mipmaps, blit, samplers glTF
lib/render/shaders/*.wgsl módulos WGSL (common, pbr, shadow, env, prefilter, ...)
Atajos: arrastrar orbita, rueda acerca, R reinicia la cámara, H oculta la UI.
lib/models.ts describe la escena además del GLB principal:
attachments: el disco (public/models/vinyl.glb) se recoloca sobre el plato
detectado geométricamente (mallas finas de huella casi cuadrada), se escala a su
diámetro real (fitDiameter: 0.3 m) y gira con él a 33⅓ rpm. Los GLB de Sketchfab
traen una inclinación de presentación en el nodo raíz; ignoreNodeTransforms usa el
espacio de malla en bruto y upAxis lo endereza.tonearm: lista de mallas que forman el brazo (tubo, headshell, cápsula, cables,
contrapeso). El visor lo gira sobre su eje hasta que la púa queda a playRadius
(146 mm, surco de entrada) y lo inclina hasta apoyarla en la superficie del disco.
La geometría de la púa es la original del modelo, sin simplificar.Los console.info [viewer] resumen tiempos de carga y el ángulo aplicado al brazo.
playbackRate del audio; el HUD muestra % y rpm.public/audio/track.m4a + public/audio/cover.jpg (carátula pintada en la
etiqueta del disco). Ambos están fuera de git y del deploy público: son material con
derechos, descargado para uso local con yt-dlp desde el enlace indicado en
lib/models.ts. Sin ellos el visor funciona igual (sin sonido y con la etiqueta original). El sonido se
activa con el botón "Activar sonido" (política de autoplay) y solo suena con la púa
apoyada; el espectro del HUD sale de un AnalyserNode.El picking usa las cajas envolventes de cada malla (rayo desde la cámara) con prioridad para las piezas interactivas; el arrastre del pitch captura el puntero y no orbita la cámara.
La página usa siempre la vista "mesa" (añade ?layout=studio para el set oscuro con
cámara orbital y panel de controles): fondo blanco, cámara fija
picada (~54°) ajustada al ancho, sombra suave (PCF ancho) compuesta en post sobre el blanco,
y debajo solo la carátula y el título. No hay botones: el primer toque activa el audio y los
gestos sobre la escena (brazo, START/STOP, pitch) siguen activos. La cámara se mueve con un
dedo sobre la mesa (fuera de la bandeja) o con dos dedos (pinza = zoom, giro = yaw).
El reposabrazos se oculta mientras el brazo está sobre el disco, y los LED azules solo se
encienden con el motor en marcha.
START/STOP, 33, 45 y QUARTZ son cajas en el espacio de la escena (controls.buttons en
lib/models.ts). Al tocarlas su LED parpadea un instante (feedback de pulsación, sin deformar
geometría) y luego sigue el estado: 33/45 seleccionan la velocidad
nominal del plato (el audio sube a 45 rpm como en un disco real), QUARTZ bloquea el pitch
a 0 % (LED encendido) hasta volver a pulsarlo. El brazo avanza hacia el centro al ritmo del
plato como en una cara real (~20 min de surco).
En teléfonos (puntero táctil) el visor carga turntable.mobile.glb y vinyl.mobile.glb:
piezas pequeñas decimadas (≤10k triángulos por malla, scripts/build-mobile-assets.mjs),
placas intactas, texturas a 1k (WebP en la bandeja, PNG en el disco) y vértices cuantizados
(KHR_mesh_quantization). Además baja el DPR a 1.25, usa shadow map 1024 con 8 taps, omite el
bloom y limita a 60 fps. Fuerza un modo con ?quality=mobile o ?quality=high.
node scripts/build-mobile-assets.mjs public/models/turntable.glb /tmp/t3.glb 10000
npx @gltf-transform/cli@4 resize /tmp/t3.glb /tmp/t4.glb --width 1024 --height 1024
npx @gltf-transform/cli@4 webp /tmp/t4.glb /tmp/t5.glb --quality 90
npx @gltf-transform/cli@4 quantize /tmp/t5.glb public/models/turntable.mobile.glb --quantize-position 14 --quantize-normal 8 --quantize-texcoord 12
El motor mide los fps reales y sube o baja por una escalera de calidad (escala de render del
target HDR 0.5→1.0 con reescalado en post, taps de sombra 4/8/16, bloom on/off). Baja un
escalón si cae de 30 fps y sube si supera 54 fps con margen; un nivel que falló no se
reintenta durante 20 s. El escritorio arranca arriba del todo; el móvil en el nivel medio y
sube hasta 2× de DPR si el teléfono lo aguanta. La consola registra cada cambio ([viewer] quality level).
La web pública no incluye el audio ni la carátula (material con derechos). Para uso personal
existe un segundo proyecto de Vercel, saturday-night-private, desplegado directamente desde
la carpeta local (incluye public/audio/, ver .vercelignore) y protegido con contraseña
mediante proxy.ts (HTTP Basic, variable SITE_PASSWORD). Para actualizarlo:
vercel link --yes --project saturday-night-private && vercel --prod && vercel link --yes --project saturday-night