尚未偵測到更新。GitHub 發布版本後會顯示在這裡。
個人 GitHub 帳號下公開儲存庫的擁有者可以登入並驗證所有權,自行管理介紹,無需管理員核准。
登入並產生驗證檔案,在 30 分鐘內將其提交至此儲存庫的預設分支。其他分支或分叉儲存庫中的檔案無效。然後在下方檢查檔案,即可無需管理員核准直接管理專案。請保留檔案以維持管理權限。
如需登入,將前往登入頁面。登入後請回到此處,再次點擊所選的驗證按鈕。
在專案資料夾中執行 /nomorevibe verify,即可驗證所有權並自行管理介紹。
一分鐘完成驗證AT-LP120XUSB turntable rendered with vgpu (WebGPU) in Next.js
翻譯準備中
取自儲存庫 README
正在載入完整 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.檢視完整 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