Skip to content

Construir un mundo abierto en el navegador, parte 27: Una isla creada con ruido y un suelo que parece real

Por Oleg Sidorkin, CTO y cofundador de Cinevva

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

La parte 26 añadió agua al mundo. Esta parte construye la tierra que hay debajo en dos etapas que reflejan cómo llega a formarse un lugar real. El Spike 54 es el terreno en sí: no se esculpe a mano, sino que se genera a partir de ruido y luego se erosiona hasta adquirir el drenaje y la costa de un lugar por el que realmente ha corrido el agua. El Spike 55 es la piel de ese terreno: resuelve el problema que arruina casi todos los suelos procedurales, que una textura teselada parece teselada. Juntos responden a una pregunta: ¿puede un creador obtener una isla verosímil y un suelo que se perciba como tal sin que un artista intervenga en ninguno de los dos? La respuesta es sí, si se copian las recetas adecuadas.

Una costa que el ruido por sí solo no puede darte

Abrir el Spike 54 en una pestaña nueva ↗ · Ver el código fuente

El mapa de alturas sigue las recetas de Red Blob Games, que consisten en una pila de pequeñas transformaciones donde cada una corrige un defecto específico del ruido sin procesar. El movimiento browniano fraccionario suma varias octavas de ruido Perlin para que el terreno tenga tanto colinas amplias como detalles finos, pero el FBM básico parece suave y alineado con la cuadrícula, así que primero se aplica una deformación de dominio al punto de muestreo: cada coordenada se desplaza mediante otro campo de ruido, p=p+noise(p)s, lo que curva las crestas y les da un aspecto orgánico en lugar de dejarlas ancladas a los ejes. Después, la redistribución, que eleva la altura a una potencia ek, reduce los tonos medios para que el mundo tenga valles planos y picos escarpados, en vez de mantenerlo todo en la misma pendiente suave. Lo que lo convierte en una isla, en lugar de en colinas infinitas, es una atenuación radial: se calcula la distancia euclídea desde el centro, d=min(1,nx2+ny2), y se mezcla la elevación hacia 1d para que el terreno descienda hasta el océano en los bordes. Un segundo campo de ruido independiente se convierte en un mapa de humedad, que no afecta a la forma, pero alimenta posteriormente la etapa de asignación de biomas.

Eso produce una forma, pero sigue siendo una forma creada con ruido. No tiene ríos, valles excavados por el agua ni abanicos de sedimentos, porque nada ha fluido nunca sobre ella. La solución es la erosión hidráulica, adaptada de la implementación de Sebastian Lague con licencia MIT. Miles de gotas de agua aparecen en posiciones aleatorias y descienden por las pendientes. Cada una conserva inercia para no realizar giros bruscos en ángulo recto, recoge sedimentos cuando acelera y los deposita cuando frena o se estanca. Un pincel circular precalculado distribuye cada evento de erosión sobre un radio pequeño para que la excavación sea suave en lugar de un arañazo de un solo píxel, y la evaporación elimina la gota al final de su vida. Con suficientes gotas, el terreno desarrolla aquello que el ruido no puede imitar: redes de drenaje que convergen, valles que se ensanchan aguas abajo y zonas llanas donde se acumularon los sedimentos.

Erosión en la GPU y ríos que saben dónde están

La erosión en la CPU es correcta, pero lenta, así que el spike también la adapta a un shader de cómputo de WebGPU. Lo interesante es lo que las operaciones atómicas de la GPU obligan a hacer. Las alturas se almacenan como valores de punto fijo i32 con una escala de un millón, porque WGSL no permite sumas atómicas con números de coma flotante. La única forma de que miles de gotas depositen y retiren sedimentos de una misma celda en paralelo sin condiciones de carrera es utilizar atomicAdd y atomicSub con enteros. La conversión de ida y vuelta a punto fijo implica que, bajo una erosión concurrente intensa, una celda puede volverse ocasionalmente un poco negativa, algo inofensivo que se limita al recuperar los datos. La versión para CPU precalcula una tabla de pinceles por celda, pero con una cuadrícula de 10012 esa tabla ocupa alrededor de 100 MB. Por eso, la versión para GPU vuelve a calcular sobre la marcha el pincel de cada gota, intercambiando un poco de aritmética por un gran ahorro de memoria. Las posiciones iniciales de las gotas siguen procediendo de la CPU mediante un generador Mulberry32, por lo que las ejecuciones son deterministas.

Dos pasadas adicionales convierten el terreno erosionado en un mapa legible. El drenaje utiliza el método D8 de acumulación de flujo de Red Blob: se deposita una unidad de lluvia en cada celda, se ordenan todas las celdas por elevación descendente y se transfiere el agua acumulada de cada celda a su único vecino más bajo. Así, el agua se concentra a lo largo de los valles naturales y cualquier celda cuya acumulación supere un umbral se marca como río. El problema es que un mapa de alturas erosionado tiene depresiones, hundimientos locales sin salida cuesta abajo. El agua que entra en una depresión simplemente se detiene y rompe la acumulación. Por eso, antes de calcular el drenaje, el rellenado de depresiones Planchon-Darboux eleva cada una hasta situarla justo por encima de su vecino más bajo, minNeighbour+ϵ, iterando durante menos de veinte pasadas hasta que todas las celdas tienen algún lugar por el que drenar. Por último, los biomas se asignan al estilo de Red Blob mediante una consulta en dos ejes que cruza elevación y humedad, de modo que una celda alta y seca se convierte en roca, mientras que una baja y húmeda se convierte en ciénaga. Encima se aplican excepciones basadas en la pendiente: las caras empinadas se fuerzan a roca sin importar la humedad, la franja de la línea de agua se convierte en playa y las elevaciones más altas reciben nieve. El resultado es una isla que se entiende de un vistazo, generada de principio a fin a partir de dos semillas de ruido.

La tesela que no deja de repetirse

Abrir el Spike 55 en una pestaña nueva ↗ · Ver el código fuente

Un terreno necesita un material que cubra kilómetros a partir de una textura de apenas un par de metros, y en cuanto se escala una tesela para cubrir el suelo, el ojo detecta la repetición. El Spike 55 es una prueba comparativa A/B de cuatro modos de muestreo sobre la misma geometría e iluminación, por lo que la única variable es cómo se lee la textura. La referencia básica es plain: una sola muestra en las UV escaladas, que se repite de forma evidente cada pocos metros y solo existe como el rival al que hay que superar. Las capas PBR gratuitas proceden de Poly Haven a través de su CDN: textura difusa, mapa ARM empaquetado (oclusión ambiental, rugosidad y metalicidad) y un mapa normal GL, todo con licencia CC0, cargado con anisotropía 8 y mipmaps.

Los otros tres modos son distintos ataques contra la repetición. El modo hex-linear es la cuadrícula triangular de Heitz-Neyret: se coloca una retícula triangular sesgada sobre la superficie, y cada fragmento queda dentro de un triángulo cuyos tres vértices toman muestras desplazadas aleatoriamente. Estas se mezclan mediante pesos baricéntricos para que las regiones vecinas muestreen distintas partes de la textura y el teselado a gran escala desaparezca. Sin embargo, una mezcla lineal básica de tres muestras promedia sus colores en los bordes de los triángulos, lo que deja un patrón triangular visible, exactamente el artefacto que apareció en el spike 48. El modo hex-vp es la corrección publicada en el mismo artículo de 2018: tras la suma baricéntrica, resta el color medio de la textura, vuelve a escalar mediante la raíz cuadrada inversa de la suma de los pesos al cuadrado para mantener constante la varianza y, después, vuelve a añadir la media. Esto mantiene estable el contraste en toda la mezcla y hace que los triángulos desaparezcan. Por esa razón, el material realiza inicialmente una lectura de 1 por 1 de cada textura cargada para estimar su color medio. El cuarto modo, iq-untiled, es la técnica 3 de repetición de texturas de Inigo Quilez: dos muestras desplazadas que se mezclan mediante un patrón de variación de baja frecuencia; solo dos muestras en lugar de tres y ninguna estructura triangular desde el principio, la opción económica que mantiene una buena calidad.

Sobre cualquiera de estos modos puede aplicarse una proyección triplanar opcional, que permite que el mismo material envuelva un acantilado sin estirarse. En vez de utilizar una sola UV, el shader muestrea tres proyecciones sobre los ejes del mundo: las superficies orientadas hacia X leen el plano YZ, las orientadas hacia Y leen ZX y las orientadas hacia Z leen XY. Después las mezcla mediante abs(normalWorld) elevado a una potencia de realce entre cuatro y ocho, para que una pendiente de 45 grados no convierta las tres proyecciones superpuestas en una masa borrosa. La comparativa deja clara la contrapartida: la mezcla hexagonal que conserva la varianza ofrece la mejor calidad, mientras que el método de dos muestras de Quilez es la opción orientada al rendimiento. Ambos superan al modo básico por un margen lo bastante amplio como para que ningún creador deba publicar jamás una tesela sin tratar.

Tecnología mencionada en este capítulo

Generación de mapas de alturas mediante recetas apiladas. Las recetas de Red Blob Games combinan ruido sin procesar para convertirlo en terreno: FBM con deformación de dominio (p=p+noise(p)s) para crear crestas orgánicas, redistribución ek para obtener valles planos y picos escarpados, y una atenuación radial euclídea mezclada hacia 1d para hundir los bordes en el océano y formar una isla. Un segundo campo de ruido sirve como mapa de humedad para asignar los biomas. Consulta generación de paisajes.

Erosión hidráulica en CPU y GPU. El modelo de gotas de Sebastian Lague (inercia, capacidad de transporte, pincel circular precalculado para depositar sedimentos y evaporación) excava redes de drenaje reales que el ruido no puede imitar. La adaptación de cómputo para WebGPU almacena las alturas como valores de punto fijo i32 con una escala de un millón, de modo que las gotas puedan aplicar atomicAdd/atomicSub en paralelo sobre la misma celda. También recalcula sobre la marcha el pincel de cada gota para evitar una tabla de unos 100 MB con una resolución de 10012, y genera las posiciones iniciales mediante un generador Mulberry32 determinista.

Drenaje D8 con rellenado de depresiones. La acumulación de flujo D8 de Red Blob deposita una unidad de lluvia por celda, ordena las celdas por elevación descendente y transfiere el agua al vecino más bajo de cada celda, marcando como ríos las que superan un umbral. El rellenado de depresiones Planchon-Darboux eleva primero cada hundimiento local hasta minNeighbour+ϵ (en menos de veinte pasadas), de modo que el agua nunca quede atrapada y la acumulación permanezca conectada. Una consulta en dos ejes que cruza elevación y humedad asigna los biomas, con excepciones según la pendiente que fuerzan roca en los acantilados, playa en la línea de agua y nieve en los picos.

Cuatro formas de romper la repetición de texturas. Sobre geometría e iluminación idénticas: plain (una muestra, con un teselado evidente), hex-linear (cuadrícula triangular de Heitz-Neyret, cuya mezcla lineal deja un patrón triangular), hex-vp (la corrección de EGSR 2018 §3.3 que conserva la varianza restando la media, reescalando mediante la raíz cuadrada inversa de los pesos al cuadrado y volviendo a sumar la media, lo que requiere una lectura media de 1×1 por textura) e iq-untiled (la técnica 3 de dos muestras de Inigo Quilez). La proyección triplanar muestrea tres planos de los ejes del mundo y los mezcla mediante abs(normalWorld) elevado a una potencia de 4-8 para evitar que los acantilados se estiren. La conservación de la varianza gana en calidad; las dos muestras, en coste. Consulta materiales de terreno.


Parte 27 de 29. Anterior: Parte 26 - Tres formas de crear agua Siguiente: Parte 28 - Hierba hasta el horizonte y un suelo que se oculta a sí mismo Guía de la serie: /es/blog/2026-02-25-open-world-browser-series-guide