Pruébalo en vivo Sobre este proyecto
Los seis paneles son geometría WebGL real dentro de la Scene —tienen grosor y curvatura, ocultan al personaje y este los oculta a ellos, y su orden de profundidad se mantiene correcto desde cualquier ángulo—. No son tarjetas DOM flotando sobre un Canvas.
Toda la interacción se apoya en un reparto claro de funciones: 3D sirve para explorar; 2D, para controlar. Los paneles se encargan de la navegación y la selección, derivan alrededor del personaje y giran con los gestos; el control de reproducción propiamente dicho pertenece a la interfaz estable en screen space de la parte inferior. Elegir una canción no es un cambio de estado, sino una transferencia continua —el propio panel desciende volando para convertirse en reproductor y, cuando se elige otra pista, el anterior regresa a su posición 3D original—.
Puntos clave
- Al arrastrar el espacio vacío, las tarjetas musicales giran alrededor del personaje y continúan por inercia; al arrastrar al personaje, solo este rota, sin alterar la cámara ni los paneles. Ambos derivan lentamente en direcciones opuestas —ese movimiento contrapuesto hace que el conjunto se perciba como un cuerpo en órbita y no como un fondo—.
- Al hacer clic en un panel, este se desprende del espacio 3D, pasa junto al personaje y se despliega como reproductor horizontal en la parte inferior; al elegir otro, dos paneles vuelan a la vez —el anterior se repliega hasta su posición original exacta mientras el nuevo avanza—.
- La rueda desplaza la cámara en profundidad entre 4.6 y 16 unidades de mundo: al acercarla, los paneles del primer plano desbordan el encuadre; al alejarla, todo el espacio se reúne en una constelación musical vista desde arriba.
- El marco de cuatro esquinas del cursor personalizado se acopla al quad proyectado real de cada panel —los corchetes se sitúan en las auténticas esquinas en perspectiva y giran con la inclinación del panel—.
Análisis técnico
Recursos 3D · La exportación de Tripo sin modificar
Artist.glb se entrega exactamente como sale de Tripo: 59 MB, 1.02M vértices y un mapa de color base de 8192² —sin reducción de polígonos, sin redimensionado y con todo el detalle original—. El coste está asumido (~350 MB VRAM tras generar el mipmap y un millón de vértices redibujados por frame), y dos decisiones lo mantienen bajo control: la malla pesada se excluye del raycasting —un millón de triángulos por cada movimiento del puntero bloquearían el hilo principal— y se sustituye por una cápsula invisible dimensionada a partir de los límites del propio modelo; además, como la exportación no contiene clips de animación, el personaje recibe una animación idle a nivel de grupo (un balanceo lento más un milímetro de respiración) en lugar de un esqueleto inventado.
Una pipeline de meshopt en scripts/ reduce el mismo archivo a 2.9 MB; el modelo se mide y normaliza durante la carga, por lo que cambiar de build no exige modificar el código.
Materiales · Simplificar el material de volumen de las exportaciones de Tripo
Las exportaciones de Tripo etiquetan la malla con KHR_materials_volume, que llega a three.js como un MeshPhysicalMaterial con una ruta transmission/thickness que esta Scene ni necesita ni puede permitirse. Durante la carga, cada material se sustituye por MeshStandardMaterial conservando el conjunto completo de mapas PBR —misma apariencia, sin ese coste—.
Los ShaderMaterials personalizados incluyen colorspace_fragment de forma explícita: sin él, escriben valores lineales directamente en un framebuffer sRGB y se renderizan casi negros.
Paneles musicales · Geometría real sobre una curva
Cada panel combina cuatro tipos de geometría —una cara, una banda perimetral extruida para aportar grosor real, una placa posterior translúcida y quads de interacción invisibles— que comparten un único conjunto de buffers en caché; solo cambia la transformación del grupo para cada tarjeta. Todo se crea en plano y se envuelve sobre un gran cilindro vertical: el surco de progreso y el reloj se integran en la misma curva, en lugar de anidarse bajo ella, y el relleno de progreso es un corte UV inyectado en un MeshBasicMaterial —escalar una malla levantaría su extremo más lejano fuera de la curva—.
El arte del panel se reparte entre tres Canvas según la frecuencia de actualización: la cara de 1320×680 se pinta una vez, la franja temporal se repinta cuando cambia el segundo mostrado y el icono solo cuando cambia la reproducción —nada costoso entra en el render loop—. Los seis paneles transparentes omiten las escrituras de profundidad y reciben en cada frame una renderOrder por bandas según su distancia a la cámara, para que la oclusión se mantenga correcta desde cualquier ángulo.
Transición de 3D a 2D · Una tarjeta aterriza como reproductor
Una malla WebGL no puede convertirse en un nodo DOM, así que la continuidad se construye a partir de tres elementos: un proyector mantiene actualizado en cada frame el cuadro en screen space de todas las tarjetas —incluidas las ocultas, porque el vuelo de regreso necesita un punto de llegada—; el primer frame del panel DOM es exactamente el bitmap del Canvas ya pintado para la textura WebGL de la tarjeta, no una recreación en HTML que nunca encajaría del todo; y la tarjeta se oculta en ese mismo frame —dos elementos en un mismo lugar, uno de ellos invisible—.
El ensanchamiento no comienza hasta que se ha completado ~35% del vuelo —estirar una tarjeta 2:1 hasta convertirla en una barra 11:1 en pleno trayecto desharía la imagen—, y la ruta sigue una curva de Bézier cuadrática arqueada hacia un lado, de modo que una tarjeta que llega desde la esquina superior izquierda rodea al personaje. El destino se vuelve a leer en cada frame: la constelación sigue derivando, y un rect capturado al despegar haría que el panel aterrizara junto a su tarjeta.


