Visualizando 86K Estrellas de GitHub como Langostas Procedurales
Construí una visualización 3D en tiempo real que renderiza cada una de las 86.546 estrellas de GitHub de moltbot como una langosta generada proceduralmente. Así es como logré 80K+ instancias a 60 FPS en un solo día.
Quería celebrar que un proyecto alcanzara 86.000 estrellas en GitHub. Un contador me parecía aburrido. Un sistema de partículas, genérico. Así que rendericé cada estrella como una langosta 3D generada proceduralmente.
Todo el proyecto me llevó unas seis horas.

¿Por qué langostas?
El proyecto que estaba visualizando—moltbot—tiene una temática de muda/langosta integrada en su identidad. En lugar de ignorarlo, lo aproveché. Cada estrella de GitHub se convierte en una langosta en un enjambre creciente que los usuarios pueden orbitar, atravesar con zoom y recorrer en el tiempo.
Es memorable de una forma que “86.546 estrellas” como texto nunca podría ser.
El problema de las 80K instancias
Renderizar 86.000 nodos individuales en Godot destruiría el rendimiento. Incluso con un nodo por langosta, gastarías todo tu presupuesto de frame en la sobrecarga del árbol de escenas antes de dibujar nada.
La solución es GPU instancing mediante MultiMesh. En lugar de 86.000 nodos, tienes un nodo con una sola llamada de dibujo. La GPU se encarga de la replicación.
var multimesh = MultiMesh.new()
multimesh.mesh = lobster_mesh
multimesh.transform_format = MultiMesh.TRANSFORM_3D
multimesh.use_custom_data = true
multimesh.instance_count = 100000 # Pre-asignar una vez
Pre-asigno 100.000 instancias al inicio. Añadir una nueva langosta solo significa actualizar su transform y hacerla visible—sin asignación de memoria, sin creación de nodos, sin picos de rendimiento.
Malla de langosta procedural
La langosta se genera completamente mediante código. Sin software de modelado 3D. Aproximadamente 340 triángulos por instancia:
| Componente | Detalles |
|---|---|
| Cuerpo | Elipsoide alargado (8 segmentos × 5 anillos) |
| Cola | 5 placas segmentadas + abanico de 3 placas |
| Pinzas | Dos pinzas articuladas (tamaño asimétrico) |
| Patas | 6 pares de apéndices articulados |
| Antenas | Dos sensores curvados |
La generación procedural significa que podía iterar el diseño en código sin pasar por Blender. También mantiene la exportación web pequeña—sin archivos de malla externos que cargar.
Evitando el ejército de clones
80.000 langostas idénticas parecerían un salvapantallas de 1998. El shader añade variación mediante datos personalizados empaquetados en cada instancia:
- Canales RGB: Tintado de color (tono del cuerpo, acento de pinza, claridad del vientre)
- Canal Alpha: Desfase de fase de animación
Cada langosta se balancea en una onda sinusoidal, pero con un desfase de fase único. El resultado es movimiento orgánico—ninguna langosta se mueve sincronizada con otra.
float phase = INSTANCE_CUSTOM.a * TAU;
float bob = sin(TIME * 2.0 + phase) * 0.1;
VERTEX.y += bob;
Distribución en esfera de Fibonacci
¿Dónde colocas 86.000 puntos en una esfera para que no parezcan una cuadrícula ni estén amontonados?
La espiral del ángulo dorado. Es el mismo patrón que usan las semillas de girasol—matemáticamente probado para evitar patrones visibles a cualquier escala.
const GOLDEN_ANGLE = PI * (3.0 - sqrt(5.0)) # ≈ 2.39996
func get_position(index: int, total: int) -> Vector3:
var y = 1.0 - (float(index) / (total - 1)) * 2.0
var radius_at_y = sqrt(1.0 - y * y)
var theta = GOLDEN_ANGLE * index
return Vector3(
cos(theta) * radius_at_y,
y,
sin(theta) * radius_at_y
) * sphere_radius
Con 86K instancias, puedes hacer zoom en cualquier parte y la distribución sigue pareciendo natural.
Interfaz de viaje en el tiempo
La visualización no es estática. Una línea de tiempo te permite recorrer el historial de estrellas del proyecto—desde 13 estrellas el primer día hasta 86.546 en el presente.
El pipeline de datos obtiene las marcas de tiempo de las estrellas mediante la API GraphQL de GitHub (la API REST tiene un límite de 40K estrellas), las agrega en conteos diarios y exporta como JSON. Aproximadamente 270 puntos de datos cubriendo 62 días de crecimiento.
La búsqueda binaria encuentra el conteo correcto para cualquier fecha: O(log n) para 270 puntos es efectivamente instantáneo.
Decisiones pensadas para web
El objetivo eran los navegadores web, lo que condicionó varias decisiones:
Renderer GL Compatibility. El Forward+ de Godot se ve mejor pero requiere WebGPU, que carece de soporte en navegadores. GL Compatibility apunta a WebGL 2.0—funciona en todas partes.
Renderizado sin iluminación. Sin sombras, sin iluminación compleja. Rendimiento consistente en todos los dispositivos y un estilo visual más limpio.
Controles táctiles. Pellizcar para zoom y arrastrar para orbitar funcionan junto con la entrada del ratón.
Cámara con auto-zoom. A medida que el enjambre crece, la cámara se aleja automáticamente para mantener todo visible. Los usuarios pueden anularlo manualmente.
En qué se fue el tiempo
Seis horas suena rápido. Aquí está el desglose aproximado:
| Fase | Tiempo |
|---|---|
| Configuración de MultiMesh + controles de cámara | 1 hora |
| Generación procedural de malla de langosta | 2 horas |
| Shader para variación instanciada | 1 hora |
| Pipeline de datos + UI de línea de tiempo | 1.5 horas |
| Pulido (auto-zoom, colores, exportación web) | 0.5 horas |
La malla procedural fue la parte más laboriosa. Conseguir que una langosta parezca una langosta mediante código—no Blender—requirió iteración. El resto fue aplicar técnicas conocidas.
Lo que aprendí
GPU instancing es la respuesta. Cada vez que necesites miles de objetos similares, recurre a MultiMesh (o equivalente en otros motores). La diferencia de rendimiento no es incremental—es categórica.
La generación procedural paga interés compuesto. Construir la malla en código se sintió más lento inicialmente, pero eliminó el pipeline artístico por completo. Los cambios eran instantáneos. La exportación web se mantuvo pequeña.
Las espirales de Fibonacci son mágicas. Ya había usado distribución de ángulo dorado antes, pero ver cómo aguanta con 86K puntos fue igualmente satisfactorio. Las matemáticas simplemente funcionan.
Las restricciones web clarifican. Apuntar al navegador me obligó a mantener las cosas simples: sombreado sin iluminación, sin post-procesado, tamaños de archivo mínimos. El resultado fue un proyecto más limpio.
¿Lo haría de nuevo?
Ya estoy pensando en ello. La misma técnica podría visualizar cualquier dato de series temporales—commits, descargas, registros de usuarios—con objetos 3D temáticos en lugar de gráficos.
Las langostas hicieron este proyecto memorable. El instancing lo hizo posible.
Código fuente
El código fuente completo está disponible en GitHub, incluyendo el workflow de Claude que usé para construirlo.