Skip to content

Construir un mundo abierto en el navegador, parte 10: Caos en las costuras y el combate contra el jefe de las esquinas

Por Oleg Sidorkin, CTO y cofundador de Cinevva

¿Acabas de llegar? Consulta la guía de la serie. Explica qué es un spike y enlaza todas las partes.

Si las partes anteriores parecían metódicas, este capítulo se sintió como un combate.

Los spikes del 17 al 22 fueron nuestra era de los casos límite. Marching cubes con LOD dual, costuras en los límites entre mapas de alturas y MC, chunks de esquina con resoluciones mixtas donde confluyen tres o cuatro niveles de LOD, generación de costuras en la GPU y comportamiento del modo de respaldo. Cada spike abordó una situación de fallo específica que habíamos encontrado o previsto.

El spike 17 probó marching cubes duales con dos niveles de LOD activos simultáneamente. El reto era que los chunks vecinos de un mismo chunk podían tener resoluciones distintas en caras diferentes. La lógica de celdas de transición del spike 16 funcionaba para una cara cada vez, pero cuando un chunk necesitaba celdas de transición en varias caras, la gestión del búfer de vértices se complicaba. Había que generar y añadir las celdas de transición de cada cara sin sobrescribir las demás.

Abrir el spike 19 en una pestaña nueva ↗ · Ver código fuente

El primer villano recurrente fue el orden de orientación de los vértices. Varias veces creímos tener problemas de topología y después descubrimos que eran problemas de orientación. El descarte de caras posteriores se estaba comiendo triángulos válidos de las costuras porque su orientación estaba invertida respecto a la malla principal. La misma causa raíz producía síntomas visuales distintos según el ángulo de la cámara. La solución fue imponer una convención de orientación coherente en el código que emite las celdas de transición y verificarla con un control para activar materiales de doble cara.

El segundo villano fue la falsa confianza que producía una corrección parcial. Una costura podía parecer perfecta desde un ángulo de cámara y romperse cuando los chunks de mayor y menor resolución intercambiaban sus roles de LOD. La celda de transición es asimétrica. Muestrea de forma distinta el lado de alta resolución y el de baja resolución. Si la lógica que determina «qué lado es de alta resolución» está invertida en una configuración, solo se ve el error cuando la cámara se mueve a una posición concreta.

Después llegó una de nuestras recuperaciones favoritas. Estábamos persiguiendo un artefacto de corte en las costuras de las teselas del mapa de alturas y culpábamos a la lógica de transición. Perdimos dos días con ello. El verdadero culpable era el sobredibujado obsoleto. La geometría de mayor resolución de un fotograma anterior seguía en la cola del búfer después de que el chunk pasara a un LOD inferior. El rango de dibujado seguía configurado con el recuento de vértices anterior, que era mayor. En cuanto limitamos el rango de dibujado al recuento de vértices activos indicado por el contador atómico del shader de cómputo, el «misterioso problema de las costuras» desapareció.

Fue un excelente recordatorio de que los errores de renderizado suelen hacerse pasar por errores de generación de mallas. La geometría había sido correcta todo el tiempo. La llamada de dibujado simplemente estaba leyendo más allá del final de los datos válidos.

Para el spike 22 ya estábamos probando un respaldo híbrido en el que los chunks podían pasar de marching cubes al modo de mapa de alturas bajo determinadas condiciones, como cuando el chunk no contenía ediciones volumétricas y estaba lo bastante lejos de la cámara. Esto nos ofreció una vía más práctica que una política de todo o nada. Los chunks editados del campo cercano usan MC para conservar la libertad volumétrica. Los chunks no editados del campo lejano usan mapas de alturas para mejorar la eficiencia.

Abrir el spike 22 en una pestaña nueva ↗ · Ver código fuente

Este capítulo fue la caída pronunciada de la montaña rusa. Frustrante y productivo al mismo tiempo. Muchas de las correcciones individuales fueron pequeñas, a veces una sola línea que cambiaba un operador de comparación o un desplazamiento. Pero el conocimiento que aportaron sobre la interacción entre las transiciones de LOD, la gestión de búferes y los rangos de dibujado no fue pequeño en absoluto.

En la parte 11 abordamos la capa de estabilización que llegó después del caos: modos de chunk basados en políticas y la transición de corregir errores de forma reactiva a definir reglas explícitas para el sistema.

Tecnología mencionada en este capítulo

Marching cubes con LOD dual. Ejecución de marching cubes con dos niveles de resolución simultáneos, con celdas de transición que unen el límite. El reto es que los chunks vecinos de un mismo chunk pueden tener resoluciones distintas en caras diferentes, lo que requiere generar celdas de transición independientes para cada cara. Las celdas de transición de cada cara se añaden al búfer de vértices sin sobrescribir las demás. Los contadores atómicos registran el recuento total de vértices activos de todas las caras.

Orden de orientación de los vértices. El orden de los vértices dentro de cada triángulo determina qué lado es la cara «frontal». Se necesita una orientación coherente —normalmente en sentido antihorario al observarla desde fuera— para el descarte de caras posteriores. Cuando las celdas de transición emiten triángulos, su orientación debe coincidir con la convención de la malla principal. Invertirla hace que el descarte de caras posteriores elimine triángulos válidos de las costuras, lo que parece producir superficies ausentes desde determinados ángulos de cámara. Una técnica habitual de depuración consiste en activar side: THREE.DoubleSide en el material para confirmar si los artefactos se deben a problemas de orientación o a huecos topológicos reales.

Respaldo de mapa de alturas a MC. Un modo de chunk híbrido en el que los chunks lejanos o no editados usan terreno basado en mapas de alturas —barato, con una superficie sin volumen—, mientras que los chunks cercanos o editados usan marching cubes —volumétrico y compatible con cuevas—. La decisión de usar el respaldo depende de la distancia a la cámara y de si el chunk contiene ediciones SDF. La costura entre un chunk de mapa de alturas y uno de MC requiere su propia geometría de transición, similar a Transvoxel, pero conectando dos representaciones distintas en lugar de dos niveles de LOD. Consulta mapa de alturas híbrido + capas volumétricas.

Rango de dibujado y contadores atómicos. En la generación de mallas dirigida por la GPU, el shader de cómputo escribe vértices en un búfer e incrementa un contador atómico para registrar cuántos vértices se han emitido. La llamada de dibujado debe usar este contador como recuento de vértices, no la capacidad del búfer. Si el rango de dibujado no se limita al recuento activo, los vértices obsoletos de fotogramas anteriores —que aún permanecen en la cola del búfer— producen geometría fantasma: finas esquirlas y triángulos parpadeantes que parecen errores de topología, pero en realidad son artefactos de renderizado provocados por leer más allá de los datos válidos.


Parte 10 de 12.
Anterior: Parte 9 - Transvoxel comenzó con una estructura básica
Siguiente: Parte 11 - Modo basado en políticas, no un modo codificado de forma rígida
Guía de la serie: /es/blog/2026-02-25-open-world-browser-series-guide