<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/">
    <channel>
        <title>Cinevva Blog</title>
        <link>https://app.cinevva.com</link>
        <description>Novedades del producto, notas de creadores y experimentos.</description>
        <lastBuildDate>Sat, 15 Aug 2026 21:31:21 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <copyright>Copyright 2024-present Cinevva</copyright>
        <item>
            <title><![CDATA[Nota de verificación: «Del boceto al vídeo y al 3D jugable»]]></title>
            <link>https://app.cinevva.com/es/blog/2026-03-04-sketch-to-animated-3d-character-factcheck-note</link>
            <guid>https://app.cinevva.com/es/blog/2026-03-04-sketch-to-animated-3d-character-factcheck-note</guid>
            <pubDate>Sat, 15 Aug 2026 21:16:53 GMT</pubDate>
            <content:encoded><![CDATA[<h1 id="nota-de-verificacion-«del-boceto-al-video-y-al-3d-jugable»" tabindex="-1">Nota de verificación: «Del boceto al vídeo y al 3D jugable» <a class="header-anchor" href="#nota-de-verificacion-«del-boceto-al-video-y-al-3d-jugable»" aria-label="Permalink to &quot;Nota de verificación: «Del boceto al vídeo y al 3D jugable»&quot;"></a></h1>
<p><strong>Para:</strong> Oleg Sidorkin<br>
<strong>Asunto:</strong> <a href="https://app.cinevva.com/blog/2026-03-04-sketch-to-animated-3d-character" target="_blank" rel="noreferrer">app.cinevva.com/blog/2026-03-04-sketch-to-animated-3d-character</a><br>
<strong>Verificado con:</strong> repositorio cinevva-site (sitio de marketing + worker)</p>
<hr>
<h2 id="verificado-✓" tabindex="-1">Verificado ✓ <a class="header-anchor" href="#verificado-✓" aria-label="Permalink to &quot;Verificado ✓&quot;"></a></h2>
<ul>
<li>Los <strong>nombres de las herramientas</strong> (Image Generator, Video Generator, 3D Model Generator) y el <strong>enlace</strong> <code>/es/tools/hunyuan3d</code> coinciden con el código.</li>
<li>El <strong>autor</strong> (Oleg Sidorkin, CTO) es correcto.</li>
<li><strong>Flujo de trabajo de vídeo:</strong> se admiten la interpolación entre el fotograma inicial y el final, el formato 9:16, una duración de 3 a 15 s y el modo storyboard.</li>
<li><strong>Proceso 3D:</strong> Hunyuan3D y «3D Model Generator» son correctos; el rigging automático (Tripo) y «subir GLB → modelo con rig + biblioteca de animaciones» coinciden con la implementación.</li>
<li><strong>Cinevva Engine</strong> y «Refleja el estado a principios de 2026» son precisos.</li>
</ul>
<hr>
<h2 id="correccion-necesaria" tabindex="-1">Corrección necesaria <a class="header-anchor" href="#correccion-necesaria" aria-label="Permalink to &quot;Corrección necesaria&quot;"></a></h2>
<p><strong>«Seedance 1.5 Pro»</strong> — En este repositorio, el vídeo se implementa con <strong>Kling 3.0 Pro</strong> (fal.ai), no con Seedance 1.5 Pro:</p>
<ul>
<li><code>worker/src/genai/fal-video.ts</code> usa <code>fal-ai/kling-video/v3/pro/...</code></li>
<li><code>worker/src/index.ts</code> registra el coste como <code>model: 'kling-3.0-pro'</code></li>
<li><code>tools/video.md</code> dice: «Genera vídeos cortos con IA a partir de texto o imágenes usando <strong>Kling 3.0 Pro</strong>»</li>
</ul>
<p>El nombre de la API o del producto es «seedance» (por ejemplo, <code>/genai/seedance/generate</code>), pero el modelo subyacente es Kling 3.0 Pro. Seedance 1.5 Pro es un modelo diferente (ByteDance). Las fuentes públicas suelen limitar Seedance 1.5 Pro a unos 10 s; aquí Kling admite 15 s.</p>
<p><strong>Recomendación:</strong> En el artículo, denomina al modelo de vídeo <strong>«Kling 3.0 Pro»</strong> (o, por ejemplo, «Video Generator (Kling 3.0 Pro)») para que coincida con el sitio de marketing y la documentación. Si el backend de la aplicación realmente usa Seedance 1.5 Pro, alinea los textos de la aplicación y <code>tools/video.md</code> para que describan el mismo modelo.</p>
<hr>
<h2 id="no-verificable-en-el-repositorio" tabindex="-1">No verificable en el repositorio <a class="header-anchor" href="#no-verificable-en-el-repositorio" aria-label="Permalink to &quot;No verificable en el repositorio&quot;"></a></h2>
<p>Cubcoats, Kali the Kitty, Mimi Chao y las afirmaciones comerciales relacionadas son externos; no se han verificado.</p>
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Visor del código fuente de prototipos]]></title>
            <link>https://app.cinevva.com/es/blog/spike-source</link>
            <guid>https://app.cinevva.com/es/blog/spike-source</guid>
            <pubDate>Sat, 15 Aug 2026 21:16:53 GMT</pubDate>
            <description><![CDATA[Consulta el código fuente de cualquier prototipo de la serie del navegador de mundo abierto.]]></description>
            <content:encoded><![CDATA[<h1 id="abriendo-en-el-creador" tabindex="-1">Abriendo en el creador… <a class="header-anchor" href="#abriendo-en-el-creador" aria-label="Permalink to &quot;Abriendo en el creador…&quot;"></a></h1>
<p v-if="spikeId">
  Te estamos llevando al <strong>prototipo {{ spikeId }}</strong> en el Creador de Juegos.
  Si no se te redirige, <a :href="`/es/create#spike-${spikeId}`">ábrelo aquí</a>.
</p>
<p v-else>
  <a href="/es/create">Abrir el Creador de Juegos</a>.
</p>
<p style="margin-top:1rem">
  <a href="/es/blog/2026-02-25-open-world-browser-series-guide">← Volver a la guía de la serie</a>
</p>
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Simular un entorno de ejecución que dice no: cómo aislamos el navegador para que se comporte como WeChat]]></title>
            <link>https://app.cinevva.com/es/blog/2026-07-19-sandboxing-wechat-strict-mode</link>
            <guid>https://app.cinevva.com/es/blog/2026-07-19-sandboxing-wechat-strict-mode</guid>
            <pubDate>Sun, 19 Jul 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Nuestro creador de juegos con IA ahora genera juegos portables a WeChat, pero una regla en un prompt no deja de ser una sugerencia. Por eso incorporamos un sandbox de modo estricto en la vista previa: un script que hace que el navegador lance errores allí donde WeChat lo haría y envía las infracciones directamente al ciclo de depuración de la propia IA. Este es el diseño, la lista de APIs bloqueadas y las cuatro excepciones que más nos enseñaron.]]></description>
            <content:encoded><![CDATA[<h1 id="simular-un-entorno-de-ejecucion-que-dice-no-como-aislamos-el-navegador-para-que-se-comporte-como-wechat" tabindex="-1">Simular un entorno de ejecución que dice no: cómo aislamos el navegador para que se comporte como WeChat <a class="header-anchor" href="#simular-un-entorno-de-ejecucion-que-dice-no-como-aislamos-el-navegador-para-que-se-comporte-como-wechat" aria-label="Permalink to &quot;Simular un entorno de ejecución que dice no: cómo aislamos el navegador para que se comporte como WeChat&quot;"></a></h1>
<p><em>Por <a href="/es/about.html">Oleg Sidorkin</a>, CTO y cofundador de Cinevva</em></p>
<img src="https://cdn.cinevva.com/blog/wechat-strict-sandbox-hero.jpg" alt="Una pequeña escena de juego 3D dentro de una cúpula de cristal transparente, con iconos de herramientas tachados flotando fuera del cristal" style="width:100%;border-radius:8px;margin:1.5rem 0" />
<p>Hace poco lanzamos un <a href="/es/news/2026-07-19-wechat-mini-game-mode.html">modo de minijuegos de WeChat</a> en nuestro Creador de Juegos: un perfil de compilación que mantiene los juegos generados por IA dentro del subconjunto de la plataforma web capaz de sobrevivir a una adaptación al entorno de ejecución de WeChat. El perfil es un conjunto de reglas de generación. Nada de interfaces DOM, Pointer Lock, audio que no sea MP3 ni código dinámico. El modelo las sigue como los modelos suelen seguir las reglas; es decir, casi siempre.</p>
<p>«Casi siempre» no basta cuando todas las infracciones son invisibles en el navegador y fatales tras exportar. Un juego con una barra de salud en HTML funciona perfectamente en nuestra vista previa y muestra una pantalla en blanco en WeChat, porque los minijuegos de WeChat no tienen DOM. Así que construimos lo que convierte esas reglas de sugerencias en leyes físicas: un sandbox de modo estricto que hace que el propio navegador se niegue a hacer lo que WeChat no puede hacer. Este artículo explica cómo funciona.</p>
<h2 id="la-decision-fundamental-simular-la-ausencia-no-la-presencia" tabindex="-1">La decisión fundamental: simular la ausencia, no la presencia <a class="header-anchor" href="#la-decision-fundamental-simular-la-ausencia-no-la-presencia" aria-label="Permalink to &quot;La decisión fundamental: simular la ausencia, no la presencia&quot;"></a></h2>
<p>El enfoque obvio sería emular WeChat: implementar <code>wx.createCanvas</code>, <code>wx.onTouchStart</code>, <code>wx.setStorageSync</code> y ejecutar los juegos contra la superficie emulada de <code>wx.*</code>. Nosotros tomamos el camino contrario, y la razón está en la estructura de nuestro proceso de exportación.</p>
<p>Los juegos del modo WeChat siguen escribiéndose contra las API del navegador. Durante el empaquetado, un adaptador —siguiendo el enfoque estándar de la comunidad de weapp-adapter— asigna esas API del navegador a <code>wx.*</code>. Eso significa que nuestros juegos nunca llaman directamente a <code>wx.*</code>, por lo que un emulador de <code>wx</code> probaría rutas de código que no existen. Lo que realmente rompe una adaptación no es la ausencia de <code>wx.*</code> en el navegador. Es la <em>presencia</em> de API del navegador sin equivalente en WeChat, utilizadas inadvertidamente durante la generación. <code>document.createElement('div')</code>. <code>requestPointerLock()</code>. IndexedDB. Un archivo <code>.ogg</code> que Chrome decodifica sin problemas y que nunca funcionará en WeChat para iOS.</p>
<p>Por eso el sandbox simula la ausencia. Todo lo que WeChat no tiene se elimina, se bloquea o se señala en la vista previa, y el juego se desarrolla desde su primer fotograma dentro de la intersección entre ambas plataformas.</p>
<h2 id="donde-reside-en-un-service-worker-que-ya-existia" tabindex="-1">Dónde reside: en un service worker que ya existía <a class="header-anchor" href="#donde-reside-en-un-service-worker-que-ya-existia" aria-label="Permalink to &quot;Dónde reside: en un service worker que ya existía&quot;"></a></h2>
<p>La vista previa de nuestro editor sigue una ruta de servicio poco habitual que hizo que esto resultara casi gratuito. Los juegos del editor no se sirven desde la red. Un service worker intercepta las solicitudes a <code>/game/*</code> y sirve los archivos desde IndexedDB; así, el iframe de vista previa se recarga al instante sin un viaje de ida y vuelta al servidor. Ese worker ya inyectaba dos archivos virtuales en cada página del juego: un script de captura de errores que reenvía al editor la salida de la consola y los fallos, y un inspector de escenas en vivo.</p>
<p>El sandbox es el tercer archivo virtual, <code>_wechat-strict.js</code>, que se inyecta en el <code>&lt;head&gt;</code> de la página inmediatamente después del script de captura y antes de ejecutar cualquier código del juego. El orden es crítico por partida doble. Debe ejecutarse después de la captura para que sus llamadas a <code>console.error</code> ya estén interceptadas y lleguen al editor, y antes de los módulos del juego para que los bloqueos estén preparados cuando se ejecute la primera línea de código.</p>
<p>La activación usa un truco de una sola línea. El interruptor de WeChat del creador se conserva en <code>localStorage</code>, y el iframe de vista previa comparte origen con el editor, así que el entorno de pruebas se limita a leer directamente la opción:</p>
<div class="language-js vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">try</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">  if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (localStorage.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">getItem</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'cinevva-gc-profile'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">!==</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> 'wechat-minigame'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">} </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">catch</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (e) { </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; }</span></span></code></pre>
</div><p>Para cualquier juego que no sea de WeChat, el script consiste en una única comparación de cadenas y un retorno anticipado. Sin indicador de compilación, sin viajes de ida y vuelta al servidor y sin estado que sincronizar con el service worker.</p>
<h2 id="la-lista-de-bloqueos-y-la-taxonomia-de-dos-niveles" tabindex="-1">La lista de bloqueos y la taxonomía de dos niveles <a class="header-anchor" href="#la-lista-de-bloqueos-y-la-taxonomia-de-dos-niveles" aria-label="Permalink to &quot;La lista de bloqueos y la taxonomía de dos niveles&quot;"></a></h2>
<p>No todas las infracciones merecen la misma respuesta, así que el entorno de pruebas distingue dos niveles. Las API que <em>no existen</em> en WeChat lanzan una excepción, porque eso es lo que sucede después de exportar y un fallo durante la generación es la representación más honesta de un fallo durante la revisión. Las cosas que <em>existen pero fallan más adelante</em> se señalan mediante errores claros en la consola sin modificar su comportamiento, porque bloquearlas ocultaría el estado real del juego a la persona que está iterando sobre él.</p>
<p>El nivel que lanza excepciones: la creación de cualquier elemento de interfaz HTML, tanto mediante <code>createElement</code> como mediante <code>createElementNS</code> —Three.js crea su canvas con la variante NS, así que ambas rutas necesitan el mismo control—, <code>eval</code>, <code>new Function</code>, <code>requestPointerLock</code> y el registro de service workers. Cada excepción incluye la solución en su mensaje:</p>
<div class="language-js vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">throw</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> violate</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"document.createElement('"</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> +</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> tag </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "') — Los minijuegos de WeChat no tienen DOM. "</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> +</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">  "Dibuja la interfaz en un canvas (canvas 2D fuera de pantalla -> THREE.CanvasTexture sobre un quad en espacio de pantalla) "</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> +</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">  "y realiza tú mismo la detección de toques."</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);</span></span></code></pre>
</div><p>El nivel de avisos: leer <code>indexedDB</code> —devuelve <code>undefined</code>, exactamente igual que WeChat, además de un error que señala a <code>localStorage</code>—, audio en cualquier formato que WeChat para iOS no pueda decodificar —comprobado en tres lugares: el constructor <code>Audio</code>, el setter <code>src</code> del prototipo del elemento multimedia y las URL obtenidas—, solicitudes de red a cualquier origen que no sea el del propio juego o nuestra CDN de recursos —en WeChat requieren un dominio incluido en la lista blanca y registrado mediante ICP— y la aparición de Tone.js en cualquier lugar.</p>
<p>También hay una auditoría posterior a la carga que se ejecuta un momento después de que la página se estabilice: recorre <code>&lt;body&gt;</code> e informa de cualquier elemento HTML introducido mediante el propio marcado del juego en lugar de crearse dinámicamente. Los HUD estáticos eluden fácilmente un control sobre <code>createElement</code>, así que ese control por sí solo no basta.</p>
<p>Todos los informes se deduplican por mensaje y se limitan a cincuenta por sesión. Un error de bucle invertido que crea un div por fotograma produce un solo error, no una avalancha que ahogue la señal.</p>
<h2 id="las-cuatro-excepciones-que-mas-nos-ensenaron" tabindex="-1">Las cuatro excepciones que más nos enseñaron <a class="header-anchor" href="#las-cuatro-excepciones-que-mas-nos-ensenaron" aria-label="Permalink to &quot;Las cuatro excepciones que más nos enseñaron&quot;"></a></h2>
<p>Construir un sandbox consiste principalmente en decidir qué <em>no</em> bloquear, y cada excepción surgió cuando nuestras propias herramientas dejaron de funcionar durante el desarrollo.</p>
<p><strong>Nuestro depurador funciona con eval.</strong> La herramienta <code>execute_js</code> del creador, que la IA utiliza para inspeccionar el juego en ejecución, evalúa código mediante el gestor de mensajes del script de captura, que llama a <code>eval</code>. Bloquear <code>eval</code> sin más habría cegado a la propia IA. La solución: antes de bloquearlo, el entorno guarda la función real en una propiedad no enumerable, y el gestor del script de captura recurre a ella:</p>
<div class="language-js vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">Object.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">defineProperty</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(window, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'__cinevvaRealEval'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, { value: window.eval, enumerable: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">false</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> });</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">window.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">eval</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> function</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> () { </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">throw</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> violate</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'eval() está prohibido en los minijuegos de WeChat.'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">); };</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// script de captura, al recibir el mensaje:</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">returnValue </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (window.__cinevvaRealEval </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">||</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> eval)(e.data.code);</span></span></code></pre>
</div><p>El código del juego que intente utilizar <code>eval</code> sigue fallando. El depurador no.</p>
<p><strong>El grabador también crea elementos.</strong> Nuestro grabador de vídeos cortos se inyecta en el iframe del juego como un <code>&lt;script&gt;</code> creado mediante el propio <code>document.createElement</code> del iframe, y descarga los vídeos terminados mediante un clic sintético en un elemento <code>&lt;a&gt;</code>. Bloquear esas etiquetas habría roto la grabación únicamente en el modo WeChat. Por eso <code>script</code> sigue estando permitido y <code>a</code> genera un aviso sin lanzar una excepción. Un juego que incluya un enlace real sigue siendo señalado, y las herramientas continúan funcionando.</p>
<p><strong>Los eventos de teclado se mantienen.</strong> La IA verifica los controles mediante una herramienta que simula pulsaciones de teclas y después comprueba cómo ha cambiado el estado del juego. Suprimir la entrada de teclado para simular un teléfono habría destruido el ciclo de verificación de controles que detecta errores de cámara invertida. La prioridad de los controles táctiles se aplica mediante las reglas de generación y el esquema de controles del perfil, no mediante el sandbox.</p>
<p><strong>WebGL2 se mantiene, y el motivo merece su propia sección más abajo.</strong> La lista inicial de bloqueos impedía usar <code>getContext('webgl2')</code> para forzar el renderizado «compatible con WebGL1» que exigía el perfil. El problema es que Three.js <a href="https://github.com/mrdoob/three.js/releases/tag/r163" target="_blank" rel="noreferrer">eliminó por completo la compatibilidad con WebGL1 en r163</a>, y nosotros fijamos la versión r181: bloquear WebGL2 habría dejado en blanco todos los juegos 3D del modo. La regla de renderizado del perfil era incoherente y se había escrito desde una concepción desactualizada de la plataforma. La auditoría del sandbox terminó auditando la propia especificación del sandbox, y seguir ese hilo nos llevó a un hallazgo importante.</p>
<h2 id="la-cuestion-de-webgl2-respondida-como-es-debido" tabindex="-1">La cuestión de WebGL2, respondida como es debido <a class="header-anchor" href="#la-cuestion-de-webgl2-respondida-como-es-debido" aria-label="Permalink to &quot;La cuestión de WebGL2, respondida como es debido&quot;"></a></h2>
<p>No interferir con la creación del contexto planteó la siguiente pregunta obvia: si nuestro motor requiere WebGL2, ¿dejan de funcionar los juegos en dispositivos WeChat que solo tienen WebGL1? Investigarla nos dio la imagen más clara que tenemos del mínimo de renderizado de la plataforma, así que aquí está, acompañada de fuentes.</p>
<p>En Android, el entorno de ejecución de minijuegos de WeChat ofrece WebGL2 con cualquier biblioteca base moderna, y el hardware GLES3 subyacente es prácticamente universal. iOS es donde está la verdadera historia. La documentación técnica de WeChat sobre la <a href="https://wechat-miniprogram.github.io/minigame-unity-webgl-transform/Design/WebGL2.html" target="_blank" rel="noreferrer">compatibilidad con WebGL2</a> y el <a href="https://developers.weixin.qq.com/minigame/dev/guide/performance/perf-high-performance-plus.html" target="_blank" rel="noreferrer">modo high-performance+</a> explica que, en iPhone, WebGL2 solo está disponible correctamente en el entorno high-performance+, que requiere un cliente reciente de WeChat —8.0.45 o posterior, y una versión superior en iOS 14— y, en la práctica, iOS 15.5 o posterior. Según la propia descripción de Tencent, el modo high-performance normal ejecuta WebGL2 «con más problemas», y el entorno normal de iOS no lo ofrece en absoluto.</p>
<p>La forma del fallo es lo realmente peligroso. En entornos incompatibles, <code>getContext('webgl2')</code> puede devolver un contexto válido en apariencia pero roto en lugar de null, un comportamiento que los desarrolladores <a href="https://developers.weixin.qq.com/community/develop/doc/000aee72868a381d6c261686651c00" target="_blank" rel="noreferrer">han pedido directamente a Tencent que corrija</a>. Un juego que confíe en el valor devuelto no falla de forma limpia. Muestra gráficos corruptos o una pantalla negra sin ningún aviso.</p>
<p>Así lo abordamos, en tres capas. El sandbox no modifica la creación de contextos WebGL2, porque bloquearla supondría luchar contra nuestro propio motor. Ahora, el perfil de generación exige una comprobación de arranque en todos los juegos: la creación del renderizador debe estar envuelta en try/catch y seguida de una prueba funcional (<code>typeof gl.createVertexArray === 'function'</code>, una capacidad exclusiva de WebGL2 que un contexto falso no tendrá), con un mensaje cordial dibujado en el canvas que diga «actualiza WeChat» si falla, en lugar de mostrar una pantalla en blanco. Es el mismo patrón que emplean los minijuegos convertidos desde Unity, razón por la cual normalmente se ven avisos de actualización y no pantallas negras. Y, cuando esté listo, el exportador fijará el modo high-performance+ en <code>game.json</code> para que la ruta compatible sea la predeterminada.</p>
<p>¿Cuál es el coste de exigir WebGL2 para la audiencia? Los usuarios con versiones anteriores a iOS 15.5 o clientes de WeChat anteriores a la 8.0.45: un porcentaje bajo de un solo dígito en 2026, pero concentrado en dispositivos antiguos, lo que importa más en algunos géneros que en otros. Si los datos reales de distribución llegan a indicar que merece la pena perseguir esa cola, tenemos reservada una vía de escape barata: fijar el perfil de WeChat en Three r162, la última versión compatible con WebGL1. Los juegos del perfil solo utilizan API básicas y estables, por lo que bajar de versión supone cambiar una sola línea del mapa de importaciones; una opción que mantendremos deliberadamente sin usar hasta que los datos la justifiquen.</p>
<h2 id="cerrar-el-ciclo-con-el-modelo" tabindex="-1">Cerrar el ciclo con el modelo <a class="header-anchor" href="#cerrar-el-ciclo-con-el-modelo" aria-label="Permalink to &quot;Cerrar el ciclo con el modelo&quot;"></a></h2>
<p>Esta es la parte que hace que todo esto merezca la pena para un producto centrado en la IA. Después de cada compilación, el agente del creador llama a una herramienta que lee la consola del juego y espera a que termine el arranque. El script de captura reenvía <code>console.error</code> a ese flujo. Por eso, una infracción <code>[wechat-strict]</code> no es un aviso que una persona pueda pasar por alto al desplazarse. Llega al canal exacto que el modelo ya comprueba antes de declarar terminada una compilación, en el mismo turno y con la solución explicada en el mensaje.</p>
<p>El perfil de generación cierra la última brecha con una instrucción: tratar cada mensaje <code>[wechat-strict]</code> como un error que impide completar la compilación, corregir la causa y no intentar nunca detectar ni eludir el entorno de pruebas. Un juego que solo funciona con el sandbox desactivado es un juego que fallará después de exportarlo, y eso es exactamente lo que se le dice al modelo.</p>
<p>En la práctica, el sandbox convierte un problema difuso de cumplimiento —«¿ha seguido el modelo las catorce reglas?»— en el ciclo de depuración que el sistema ya sabe resolver bien —«la consola muestra un error; corrígelo»—.</p>
<h2 id="lo-que-un-navegador-no-puede-simular" tabindex="-1">Lo que un navegador no puede simular <a class="header-anchor" href="#lo-que-un-navegador-no-puede-simular" aria-label="Permalink to &quot;Lo que un navegador no puede simular&quot;"></a></h2>
<p>La sección de honestidad. Este sandbox detecta infracciones relacionadas con la superficie de las API, que, según nuestras estimaciones, representan la gran mayoría de los problemas capaces de arruinar una adaptación. No puede detectar el rendimiento en un teléfono real, la ejecución de JavaScript sin JIT en iOS, las peculiaridades de la implementación WebGL de WeChat ni las diferencias de comportamiento de los códecs más allá de las extensiones de archivo. Para eso hace falta el entorno real.</p>
<p>Por eso el sandbox es el primero de tres niveles. El segundo, una vez que nuestro exportador genere proyectos para las herramientas de desarrollo de WeChat, será el simulador oficial controlado sin interfaz mediante la CLI de DevTools y miniprogram-automator: arrancar el paquete exportado, comprobar que se renderiza el primer fotograma y automatizar un toque. El tercero es la ruta oficial en dispositivos: códigos QR de vista previa y depuración remota en teléfonos físicos, donde residen las verdades que ningún otro entorno puede revelar. Cada nivel es más lento y más fiel que el anterior, y la función de cada uno es hacer que resulte poco frecuente tener que pasar al siguiente.</p>
<p>Si quieres probar el modo, activa el interruptor «Modo de minijuegos de WeChat» en el <a href="/es/create.html">Creador de Juegos</a>. Para conocer el contexto comercial y normativo, consulta <a href="/es/blog/2026-07-19-wechat-mini-games-guide-for-developers-outside-china.html">nuestra guía práctica para llegar a los quinientos millones de jugadores de WeChat</a>.</p>
<h2 id="referencias" tabindex="-1">Referencias <a class="header-anchor" href="#referencias" aria-label="Permalink to &quot;Referencias&quot;"></a></h2>
<ul>
<li><a href="https://developers.weixin.qq.com/minigame/dev/guide/runtime/js-support.html" target="_blank" rel="noreferrer">Documentación oficial de WeChat: compatibilidad con JavaScript en minijuegos</a></li>
<li><a href="https://developers.weixin.qq.com/minigame/en/dev/guide/best-practice/adapter.html" target="_blank" rel="noreferrer">Documentación oficial de WeChat: la capa de adaptación</a></li>
<li><a href="https://developers.weixin.qq.com/minigame/dev/guide/performance/perf-high-performance-plus.html" target="_blank" rel="noreferrer">Documentación oficial de WeChat: modo de alto rendimiento+</a></li>
<li><a href="https://wechat-miniprogram.github.io/minigame-unity-webgl-transform/Design/WebGL2.html" target="_blank" rel="noreferrer">Documentación de ingeniería de WeChat: compatibilidad con renderizado WebGL2 en minijuegos</a></li>
<li><a href="https://github.com/wechat-miniprogram/minigame-unity-webgl-transform/blob/main/Design/iOSOptimization.md" target="_blank" rel="noreferrer">Documentación de ingeniería de WeChat: modos de alto rendimiento y alto rendimiento+ en iOS</a></li>
<li><a href="https://developers.weixin.qq.com/community/develop/doc/000aee72868a381d6c261686651c00" target="_blank" rel="noreferrer">Comunidad de desarrolladores de WeChat: los contextos WebGL2 no funcionales deben devolver null</a></li>
<li><a href="https://developers.weixin.qq.com/miniprogram/en/dev/devtools/auto/" target="_blank" rel="noreferrer">Documentación oficial de WeChat: miniprogram-automator</a></li>
<li><a href="https://github.com/mrdoob/three.js/releases/tag/r163" target="_blank" rel="noreferrer">Notas de la versión r163 de Three.js (se eliminó la compatibilidad con WebGL1)</a></li>
</ul>
]]></content:encoded>
            <enclosure url="https://cdn.cinevva.com/blog/wechat-strict-sandbox-hero.jpg" length="0" type="image/jpg"/>
        </item>
        <item>
            <title><![CDATA[Minijuegos de WeChat: el mayor mercado de juegos instantáneos en el que no basta con publicar]]></title>
            <link>https://app.cinevva.com/es/blog/2026-07-19-wechat-mini-games-guide-for-developers-outside-china</link>
            <guid>https://app.cinevva.com/es/blog/2026-07-19-wechat-mini-games-guide-for-developers-outside-china</guid>
            <pubDate>Sun, 19 Jul 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[500 millones de jugadores mensuales, un mercado de 5.600 millones de dólares que se duplicó en un año y una plataforma a la que tu juego web no puede llegar mediante una URL. Qué son realmente los minijuegos de WeChat, las regulaciones a las que te enfrentarás como desarrollador fuera de China, la única vía de monetización que no requiere una licencia y cómo encaja el nuevo modo de minijuegos de Cinevva.]]></description>
            <content:encoded><![CDATA[<h1 id="minijuegos-de-wechat-el-mayor-mercado-de-juegos-instantaneos-en-el-que-no-basta-con-publicar" tabindex="-1">Minijuegos de WeChat: el mayor mercado de juegos instantáneos en el que no basta con publicar <a class="header-anchor" href="#minijuegos-de-wechat-el-mayor-mercado-de-juegos-instantaneos-en-el-que-no-basta-con-publicar" aria-label="Permalink to &quot;Minijuegos de WeChat: el mayor mercado de juegos instantáneos en el que no basta con publicar&quot;"></a></h1>
<p><em>Por <a href="/es/about.html">Oleg Sidorkin</a>, CTO y cofundador de Cinevva</em></p>
<img src="https://cdn.cinevva.com/blog/wechat-mini-games-market-hero.jpg" alt="Un smartphone que muestra un minijuego frente a una puerta con un sello de aprobación, junto a un documento sellado y varias monedas" style="width:100%;border-radius:8px;margin:1.5rem 0" />
<p>Si creas juegos web, hay un mercado de 500 millones de jugadores mensuales al que tus juegos no pueden llegar, por muy buena que sea su compatibilidad con dispositivos móviles. Está dentro de WeChat, sus ingresos casi se duplicaron el año pasado y entrar en él exige tanto una adaptación técnica como un proceso regulatorio del que la mayoría de los desarrolladores occidentales nunca han oído hablar.</p>
<p>Acabamos de lanzar la primera parte de nuestra respuesta: un <a href="/es/news/2026-07-19-wechat-mini-game-mode.html">modo experimental para minijuegos de WeChat</a> en Cinevva Game Creator. Este artículo cuenta la historia completa: qué es realmente la plataforma, cuáles son sus reglas y cómo sería una vía realista para un desarrollador de fuera de China.</p>
<h2 id="el-mercado-en-cifras-faciles-de-subestimar" tabindex="-1">El mercado, en cifras fáciles de subestimar <a class="header-anchor" href="#el-mercado-en-cifras-faciles-de-subestimar" aria-label="Permalink to &quot;El mercado, en cifras fáciles de subestimar&quot;"></a></h2>
<p>WeChat es la aplicación de comunicación de referencia en China, con una base total de más de 1.400 millones de usuarios activos mensuales. Los minijuegos funcionan dentro de ella como experiencias de juego instantáneas: no requieren instalación ni tienda de aplicaciones y pueden iniciarse desde un mensaje de chat, una búsqueda o un contenido compartido. En 2025, Tencent anunció que la plataforma de minijuegos había superado los 500 millones de usuarios activos mensuales, con más de 1.000 millones de jugadores registrados y unos 500.000 desarrolladores.</p>
<p>El dinero también es real. El mercado chino de minijuegos generó 39.800 millones de yuanes en 2024, unos 5.600 millones de dólares, lo que supone un crecimiento interanual del 99 %. Aproximadamente el 69 % procedió de compras dentro de la aplicación y el 31 %, de la publicidad. Conviene recordar ese reparto, porque la parte publicitaria resulta ser muy importante para los desarrolladores extranjeros.</p>
<p>Para ponerlo en perspectiva: los ingresos de los minijuegos durante ese único año son comparables a los de todo el mercado mundial de juegos web sobre el que se asientan plataformas como Poki, CrazyGames e itch.io. No es un nicho. Es un universo paralelo con sus propias reglas.</p>
<h2 id="por-que-no-puedes-adaptar-tu-juego-web-sin-mas" tabindex="-1">Por qué no puedes adaptar tu juego web sin más <a class="header-anchor" href="#por-que-no-puedes-adaptar-tu-juego-web-sin-mas" aria-label="Permalink to &quot;Por qué no puedes adaptar tu juego web sin más&quot;"></a></h2>
<p>Un minijuego de WeChat parece un juego web y está escrito en JavaScript, así que es natural asumir que adaptarlo solo requiere un fin de semana de trabajo. No es así, y los motivos son estructurales.</p>
<p>Los minijuegos no se ejecutan en un navegador. Se ejecutan en el entorno de ejecución propio de WeChat, que proporciona un lienzo, WebGL y un conjunto de API <code>wx.*</code>. No hay DOM ni CSS. Todos los botones, barras de salud, menús y cuadros de diálogo de tu juego deben dibujarse en el lienzo, y tu propio código debe detectar las interacciones con ellos. Si la interfaz de tu juego está hecha con HTML, esa interfaz no existe en WeChat.</p>
<p>El modelo de entrada también es distinto. No hay Pointer Lock ni ratón, por lo que una cámara de FPS pensada para ordenadores debe convertirse en una cámara controlada arrastrando el dedo. Tampoco hay teclado en el dispositivo principal. Si tu juego no puede jugarse por completo usando únicamente controles táctiles, no puede jugarse.</p>
<p>Los paquetes están limitados a 4 MB para el paquete principal y a 20 MB en total mediante subpaquetes, y todo lo que ejecute el juego debe estar dentro de ese paquete revisado. Esto nos lleva a la regla que define toda la plataforma: WeChat prohíbe la ejecución dinámica de código. Nada de <code>eval</code>, <code>new Function</code> ni descarga de JavaScript en tiempo de ejecución; además, Tencent rechaza activamente las aplicaciones que incorporan intérpretes de JS para sortear esta restricción. Cada juego es un artefacto cerrado y revisado.</p>
<p>Esta última regla explica por qué nunca habrá una «aplicación portal» que transmita juegos web a WeChat, ni nuestra ni de nadie. Cada juego pasa por el proceso de revisión como un minijuego independiente. Cualquier herramienta que quiera ayudarte en este ámbito debe permitirte producir paquetes limpios, autónomos y basados exclusivamente en lienzo. Esa es la restricción de diseño en torno a la cual desarrollamos nuestro nuevo modo.</p>
<h2 id="la-realidad-regulatoria" tabindex="-1">La realidad regulatoria <a class="header-anchor" href="#la-realidad-regulatoria" aria-label="Permalink to &quot;La realidad regulatoria&quot;"></a></h2>
<p>Ahora viene la parte que no tiene nada que ver con el código. China regula los juegos como medios publicados y los requisitos se acumulan en varias capas. Ninguno de ellos es secreto, pero casi nadie fuera de China los explica con claridad, así que aquí los tienes.</p>
<p><strong>Registro ICP.</strong> Desde finales de 2023, todos los miniprogramas y minijuegos deben completar un registro ICP —un trámite ante las autoridades chinas realizado a través de la plataforma de WeChat—. Suele tardar entre una y tres semanas.</p>
<p><strong>Prueba de derechos de autor para cada título.</strong> Cada juego necesita un registro de derechos de autor de software o la certificación electrónica de derechos de autor, que es más rápida. El proceso electrónico tarda aproximadamente entre diez y quince días por juego. Es un coste por título, algo importante si tienes previsto publicar muchos juegos pequeños.</p>
<p><strong>El banhao, si cobras dinero.</strong> Todo juego con compras dentro de la aplicación necesita una licencia de publicación de juegos de la Administración Nacional de Prensa y Publicaciones, conocida universalmente como banhao. Hay dos hechos que determinan lo que esto implica para ti como desarrollador extranjero. Primero, solo una empresa china puede solicitarla. Segundo, los títulos importados pasan por un proceso de aprobación independiente y más lento, que históricamente tarda entre seis y ocho meses cuando avanza. En la práctica, un desarrollador de fuera de China solo puede publicar un juego monetizado a través de una editora nacional con licencia que presente el juego, sea titular de la licencia y se encargue de su explotación.</p>
<p><strong>La excepción para juegos gratuitos con publicidad.</strong> Un juego gratuito sin pagos de ningún tipo no necesita un banhao. Aun así, puede generar ingresos mediante los componentes publicitarios propios de WeChat y, recuerda, la publicidad representó el 31 % de los ingresos de los minijuegos en 2024: más de 1.700 millones de dólares. Esta es la única vía que un pequeño desarrollador puede recorrer sin un socio empresarial chino, y así es como opera buena parte de la larga cola del mercado.</p>
<p>El resumen honesto: publicar un minijuego gratuito financiado con publicidad implica trámites que se miden en semanas. Publicar uno monetizado es un proyecto de desarrollo empresarial que se mide en meses y requiere un socio que deberás elegir con cuidado.</p>
<h2 id="que-hace-al-respecto-el-modo-de-minijuegos-de-cinevva" tabindex="-1">Qué hace al respecto el modo de minijuegos de Cinevva <a class="header-anchor" href="#que-hace-al-respecto-el-modo-de-minijuegos-de-cinevva" aria-label="Permalink to &quot;Qué hace al respecto el modo de minijuegos de Cinevva&quot;"></a></h2>
<p>No podemos presentar los trámites por ti. Lo que sí podemos hacer es garantizar que el juego en sí nunca sea el obstáculo, desde el primer prompt.</p>
<p>Con el modo para minijuegos de WeChat activado, Game Creator crea dentro del subconjunto portable: una interfaz dibujada en lienzo en lugar de HTML; controles táctiles como prioridad, con control de cámara mediante arrastre en lugar de Pointer Lock; renderizado ajustado al rendimiento de un teléfono de gama media, con una pantalla alternativa elegante cuando no esté disponible WebGL2 real; un presupuesto estricto para recursos y audio exclusivamente en MP3; sin importaciones dinámicas ni carga de código en tiempo de ejecución; y partidas guardadas que se asignan a la API de almacenamiento de WeChat. El juego sigue ejecutándose en el navegador como cualquier juego de Cinevva, por lo que puedes crearlo, probarlo y compartirlo con normalidad. Simplemente se mantiene dentro del subconjunto que sobrevive a la adaptación.</p>
<p>El exportador que generará un proyecto de WeChat DevTools listo para abrir a partir de uno de estos juegos está en desarrollo. Elegimos este orden deliberadamente. Un exportador puede empaquetar tu código, pero no puede deshacer un HUD en HTML ni rediseñar controles que solo funcionan con ratón. La portabilidad depende de cómo se construye el juego, por eso el modo llegó primero.</p>
<p>Si has leído nuestra <a href="/es/guides/wechat-mini-game-engines.html">guía de motores para minijuegos</a> o el <a href="/es/guides/publish-wechat-douyin-mini-games.html">tutorial de publicación para WeChat y Douyin</a>, se trata de aplicar el mismo planteamiento a la generación: la adaptación más barata es la que nunca tienes que hacer.</p>
<h2 id="una-estrategia-realista-para-un-desarrollador-de-fuera-de-china" tabindex="-1">Una estrategia realista para un desarrollador de fuera de China <a class="header-anchor" href="#una-estrategia-realista-para-un-desarrollador-de-fuera-de-china" aria-label="Permalink to &quot;Una estrategia realista para un desarrollador de fuera de China&quot;"></a></h2>
<p>Esto es lo que haríamos realmente con un primer título. Crearíamos algo pequeño y pensado para sesiones cortas, porque eso es lo que premia la plataforma: los éxitos son juegos que invitan a intentar una partida más, no aventuras épicas. Diseñaríamos primero para orientación vertical y exclusivamente para controles táctiles. Lo publicaríamos gratis con publicidad, lo que permite mantenerse al margen del banhao mientras averiguas si los jugadores chinos quieren tu juego. Nos encargaríamos directamente del registro ICP y de la certificación electrónica de derechos de autor; son procesos tediosos, pero asumibles. Y solo cuando el juego haya demostrado una buena retención y exista un potencial real de compras dentro de la aplicación, iniciaríamos las conversaciones con una editora llevando las cifras en la mano, porque una negociación cambia por completo cuando el juego ya tiene público.</p>
<p>Esa es la estrategia para la que se diseñó el nuevo modo: conseguir que producir juegos candidatos sea prácticamente gratuito, para que puedas permitirte descubrir qué funciona antes de empezar a gastar en el proceso regulatorio.</p>
<p>Si estás pensando en entrar en este mercado, nos gustaría sinceramente conocer tu opinión mientras el modo sigue tomando forma. <a href="/es/contact.html">Ponte en contacto</a> o empieza a crear en <a href="/es/create.html">Game Creator</a>.</p>
<h2 id="referencias" tabindex="-1">Referencias <a class="header-anchor" href="#referencias" aria-label="Permalink to &quot;Referencias&quot;"></a></h2>
<ul>
<li><a href="https://www.pocketgamer.biz/wechat-mini-games-crosses-500m-monthly-active-users-as-tencent-shifts-focus-to-retention/" target="_blank" rel="noreferrer">PocketGamer.biz: los minijuegos de WeChat superan los 500 millones de usuarios activos mensuales</a></li>
<li><a href="https://www.ichongqing.info/2025/07/02/wechat-mini-games-hits-1b-users-becomes-global-magnet-for-game-developers/" target="_blank" rel="noreferrer">iChongqing: los minijuegos de WeChat alcanzan los 1.000 millones de usuarios</a></li>
<li><a href="https://www.oreateai.com/blog/2025-wechat-mini-game-ecosystem-development-report-indepth-analysis-of-market-trends-and-typical-cases/7f0b62beb192f52409ae047d0bbae184" target="_blank" rel="noreferrer">Oreate: informe de 2025 sobre el desarrollo del ecosistema de minijuegos de WeChat (datos del mercado de 2024)</a></li>
<li><a href="https://developers.weixin.qq.com/minigame/dev/guide/runtime/js-support.html" target="_blank" rel="noreferrer">Documentación oficial de WeChat: compatibilidad con JavaScript y prohibición del código dinámico</a></li>
<li><a href="https://developers.weixin.qq.com/minigame/en/dev/guide/best-practice/adapter.html" target="_blank" rel="noreferrer">Documentación oficial de WeChat: la capa de adaptación para código de estilo navegador</a></li>
<li><a href="https://nikopartners.com/game-regulations-in-china-everything-you-need-to-know/" target="_blank" rel="noreferrer">Niko Partners: regulación de los juegos en China</a></li>
<li><a href="https://clearlaunch.dev/regulations/china-game-approval" target="_blank" rel="noreferrer">ClearLaunch: requisitos y aplicación de la aprobación de juegos en China (banhao)</a></li>
<li><a href="https://appinchina.co/blog/the-complete-guide-to-wechat-mini-games/" target="_blank" rel="noreferrer">AppInChina: la guía completa de los minijuegos de WeChat</a></li>
</ul>
]]></content:encoded>
            <enclosure url="https://cdn.cinevva.com/blog/wechat-mini-games-market-hero.jpg" length="0" type="image/jpg"/>
        </item>
        <item>
            <title><![CDATA[Beneficios récord, despidos récord: cómo los desarrolladores de videojuegos están consiguiendo realmente que los vuelvan a contratar en 2026]]></title>
            <link>https://app.cinevva.com/es/blog/2026-07-02-game-industry-layoffs-getting-rehired</link>
            <guid>https://app.cinevva.com/es/blog/2026-07-02-game-industry-layoffs-getting-rehired</guid>
            <pubDate>Thu, 02 Jul 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[La industria de los videojuegos generó 195.600 millones de dólares el año pasado y, aun así, despidió a un tercio de su personal. Estos son los datos reales sobre los despidos, por qué el mercado laboral se volvió tan despiadado y qué está logrando realmente que vuelvan a contratar a la gente.]]></description>
            <content:encoded><![CDATA[<h1 id="beneficios-record-despidos-record-como-los-desarrolladores-de-videojuegos-estan-consiguiendo-realmente-que-los-vuelvan-a-contratar-en-2026" tabindex="-1">Beneficios récord, despidos récord: cómo los desarrolladores de videojuegos están consiguiendo realmente que los vuelvan a contratar en 2026 <a class="header-anchor" href="#beneficios-record-despidos-record-como-los-desarrolladores-de-videojuegos-estan-consiguiendo-realmente-que-los-vuelvan-a-contratar-en-2026" aria-label="Permalink to &quot;Beneficios récord, despidos récord: cómo los desarrolladores de videojuegos están consiguiendo realmente que los vuelvan a contratar en 2026&quot;"></a></h1>
<p><em>Por <a href="/es/about.html">Mariana Muntean</a>, CEO de Cinevva</em></p>
<p>La industria de los videojuegos generó unos <strong>195.600 millones de dólares</strong> en 2025. Su mejor año hasta la fecha. Durante ese mismo periodo, aproximadamente <strong>uno de cada tres desarrolladores perdió su empleo</strong>.</p>
<p>Lee de nuevo esas dos frases. No deberían poder coexistir y, sin embargo, aquí estamos. Si te despidieron en los últimos dos años, ya sabes que las cifras no transmiten la sensación de una recesión. Es más bien como si te dijeran que el barco está bien mientras eres tú quien cae por la borda.</p>
<p>He sido desarrolladora independiente. He visto a amigos publicar el banner de «Open to Work» tres veces en dieciocho meses. Así que esto no es una opinión provocadora desde la barrera. Veamos qué ocurrió realmente y, después, la parte más importante si ahora mismo estás buscando trabajo: qué está consiguiendo de verdad que vuelvan a contratar a la gente.</p>
<h2 id="las-cifras-son-peores-de-lo-que-parece" tabindex="-1">Las cifras son peores de lo que parece <a class="header-anchor" href="#las-cifras-son-peores-de-lo-que-parece" aria-label="Permalink to &quot;Las cifras son peores de lo que parece&quot;"></a></h2>
<p>La ola de despidos comenzó en 2022 y nunca se detuvo realmente. No se trata de un mal trimestre. Es un reajuste estructural de cuatro años.</p>
<table tabindex="0">
<thead>
<tr>
<th>Año</th>
<th>Empleos eliminados en videojuegos</th>
</tr>
</thead>
<tbody>
<tr>
<td>2022</td>
<td>~8.500</td>
</tr>
<tr>
<td>2023</td>
<td>~10.500</td>
</tr>
<tr>
<td>2024</td>
<td>~14.600 (el máximo)</td>
</tr>
<tr>
<td>2025</td>
<td>~9.200</td>
</tr>
<tr>
<td>2026</td>
<td>por encima de 2025, con una previsión de ~11.580</td>
</tr>
</tbody>
</table>
<p>Eso supone aproximadamente <strong>entre 44.000 y 55.000 puestos de trabajo desaparecidos</strong> durante este periodo, dependiendo del registro en el que confíes (<a href="https://en.wikipedia.org/wiki/2022%E2%80%932026_video_game_industry_layoffs" target="_blank" rel="noreferrer">Wikipedia</a>, <a href="https://gamesbeat.com/global-gamings-workforce-grew-0-6-in-4-years-but-north-americas-shrank-11-5-amir-satvat/" target="_blank" rel="noreferrer">GamesBeat</a>). El informe State of the Game Industry 2026 de la GDC, basado en una encuesta a más de 2.300 profesionales, reveló que <strong>el 28 % de los desarrolladores de todo el mundo perdió su empleo en los últimos dos años, y la cifra asciende al 33 % en Estados Unidos</strong> (<a href="https://www.gamesindustry.biz/gdc-survey-reveals-layoffs-up-6-36-of-industry-using-ai-and-overwhelming-support-for-unionisation-in-the-us" target="_blank" rel="noreferrer">GamesIndustry.biz</a>). La mitad afirmó que su empresa actual o más reciente había realizado despidos durante los últimos doce meses.</p>
<p>Norteamérica se llevó la peor parte. El seguimiento de la fuerza laboral realizado por Amir Satvat, lo más parecido que tiene esta industria a un censo continuo, muestra que el número de trabajadores de la región se redujo mientras que el total mundial apenas cambió. Cerca del <strong>19 % de los trabajadores de la industria norteamericana del videojuego se vio afectado</strong> (<a href="https://gamesbeat.com/global-gamings-workforce-grew-0-6-in-4-years-but-north-americas-shrank-11-5-amir-satvat/" target="_blank" rel="noreferrer">GamesBeat</a>).</p>
<p>Esta es la estadística que explica por qué buscar trabajo parece imposible incluso después de que la contratación se haya «recuperado». Satvat calcula que alrededor de <strong>288.000 personas buscaban empleo en videojuegos</strong> durante este periodo. Recién graduados, veteranos despedidos y personas que estaban cambiando de carrera, todos solicitando el mismo conjunto limitado de vacantes. Cuando ahora envías tu currículum a una oferta de empleo, no compites con una docena de personas. Compites con un estadio entero.</p>
<h2 id="por-que-un-ano-record-tambien-trajo-cartas-de-despido" tabindex="-1">Por qué un año récord también trajo cartas de despido <a class="header-anchor" href="#por-que-un-ano-record-tambien-trajo-cartas-de-despido" aria-label="Permalink to &quot;Por qué un año récord también trajo cartas de despido&quot;"></a></h2>
<p>Los ingresos no desaparecieron. Se concentraron. Un número cada vez menor de gigantes de los juegos como servicio acapara una proporción desmesurada, lo que implica menos proyectos nuevos, menos equipos nuevos y menos proyectos medianos de los que antes absorbían talento. La inversión privada en videojuegos se redujo en más de la mitad en 2025 (<a href="https://respawn.outlookindia.com/gaming/gaming-news/record-profits-record-layoffs-inside-gamings-2026-paradox" target="_blank" rel="noreferrer">Outlook Respawn</a>). Los estudios respondieron como suelen hacerlo: cancelando proyectos, recortando presupuestos y trasladando trabajo a contratistas.</p>
<p>Así que los beneficios son reales y el sufrimiento también, y ambos apuntan a la misma causa. Es un pobre consuelo cuando eres tú quien actualiza constantemente la bandeja de entrada, pero revela algo útil. Este no es un mercado que esté esperando volver de golpe a 2021. Quienes consiguen que los vuelvan a contratar tampoco esperan que eso suceda. Se están adaptando al modo en que funciona realmente la contratación hoy.</p>
<h2 id="el-mercado-laboral-tiene-un-problema-de-autenticidad" tabindex="-1">El mercado laboral tiene un problema de autenticidad <a class="header-anchor" href="#el-mercado-laboral-tiene-un-problema-de-autenticidad" aria-label="Permalink to &quot;El mercado laboral tiene un problema de autenticidad&quot;"></a></h2>
<p>Habla con cualquiera que evalúe candidatos hoy y escucharás la misma queja. Están desbordados. Las ofertas de empleo reciben cientos de solicitudes en cuestión de horas, y la mayoría parecen escritas por la misma persona porque, en cierto sentido, las ha escrito la misma herramienta.</p>
<p>Los responsables de selección dijeron a TechRound que lo difícil no es detectar el uso de IA, sino que la avalancha de «contenido bien optimizado y con poco contexto» hace casi imposible encontrar a la persona que realmente comprende el puesto (<a href="https://techround.co.uk/news/linkedin-ai-slop-content-recruitment-process/" target="_blank" rel="noreferrer">TechRound</a>). La propia LinkedIn afirma ahora que detecta contenido genérico escrito por IA aproximadamente el 94 % de las veces y limita discretamente su alcance (<a href="https://techround.co.uk/news/linkedin-ai-slop-content-recruitment-process/" target="_blank" rel="noreferrer">TechRound</a>).</p>
<p>Si le das la vuelta, se convierte en la mejor noticia de todo este artículo. Cuando todo suena igual, ser específico es un superpoder. En un flujo de contenido con un acabado idéntico, la persona que muestra trabajo y razonamiento reales no solo destaca. Es la única señal entre todo el ruido.</p>
<h2 id="las-pruebas-siempre-vencen-a-la-apariencia" tabindex="-1">Las pruebas siempre vencen a la apariencia <a class="header-anchor" href="#las-pruebas-siempre-vencen-a-la-apariencia" aria-label="Permalink to &quot;Las pruebas siempre vencen a la apariencia&quot;"></a></h2>
<p>En el caso concreto de los puestos relacionados con videojuegos, lo que marca la diferencia no es un PDF más bonito. Son pruebas que alguien puede experimentar. Un profesional de selección con doce años de experiencia lo expresó sin rodeos: una versión jugable o un reel de demostración te ayuda más que casi cualquier otra cosa de tu candidatura.</p>
<p>Ese es el cambio. Un currículum le dice a un responsable de selección que entiendes de diseño. Una muestra jugable le permite sentirlo en entre 30 y 90 segundos. No puedes fingir una mecánica funcional como puedes fingir un punto en una lista. No puedes fingir un nivel explorable, un shader en funcionamiento, un rig que se mueva de verdad ni una señal de audio interactiva vinculada a una escena real. La interactividad es una prueba que resiste el escrutinio, porque detrás de ella hay una persona capaz de defender cada decisión.</p>
<p>Y esto último es lo que realmente ponen a prueba los responsables de selección. El método que utilizan para detectar portafolios inflados con IA es sencillo: preguntar por el proceso, no por el resultado. Alguien que haya generado un caso de estudio puede describir lo que dice, pero no las decisiones que hay detrás. Por eso, los portafolios más sólidos de 2026 incluyen los mismos cuatro elementos:</p>
<table tabindex="0">
<thead>
<tr>
<th>Capa</th>
<th>A qué responde</th>
</tr>
</thead>
<tbody>
<tr>
<td>Contexto</td>
<td>El encargo, la plataforma y las restricciones reales (presupuesto, plazo y limitaciones técnicas)</td>
</tr>
<tr>
<td>Contribución</td>
<td>De qué te encargaste personalmente frente a lo que hizo el equipo</td>
</tr>
<tr>
<td>Decisiones</td>
<td>Las concesiones que hiciste y qué conservaste, cambiaste y rechazaste</td>
</tr>
<tr>
<td>Resultado</td>
<td>Resultados medibles y verificables que cualquier persona pueda comprobar</td>
</tr>
</tbody>
</table>
<p>Esa parte de «conservaste, cambiaste y rechazaste» es la que la mayoría omite, y es la que demuestra criterio. El criterio es lo más difícil de fingir y es exactamente lo que compra un estudio: alguien capaz de elegir la idea correcta entre diez opciones plausibles. Evita la conclusión del tipo «aprendí muchísimo». Muestra la decisión que tomaste y por qué beneficiaba al jugador.</p>
<h2 id="unas-palabras-sobre-la-ia-porque-esta-industria-se-ha-ganado-el-derecho-a-estar-enfadada" tabindex="-1">Unas palabras sobre la IA, porque esta industria se ha ganado el derecho a estar enfadada <a class="header-anchor" href="#unas-palabras-sobre-la-ia-porque-esta-industria-se-ha-ganado-el-derecho-a-estar-enfadada" aria-label="Permalink to &quot;Unas palabras sobre la IA, porque esta industria se ha ganado el derecho a estar enfadada&quot;"></a></h2>
<p>Dirijo una plataforma que utiliza herramientas de IA y no voy a fingir que esa tensión no existe. La misma encuesta de la GDC reveló que <strong>el 52 % de los desarrolladores cree ahora que la IA generativa está teniendo un impacto negativo en la industria, frente al 18 % de hace dos años</strong>, y que la oposición más fuerte proviene de artistas, guionistas y programadores (<a href="https://www.gamesindustry.biz/gdc-survey-reveals-layoffs-up-6-36-of-industry-using-ai-and-overwhelming-support-for-unionisation-in-the-us" target="_blank" rel="noreferrer">GamesIndustry.biz</a>). Cuando acaban de despedirte y te dicen que un modelo podría hacer una parte de tu antiguo trabajo, «usa IA para tu portafolio» es una bofetada, no un consejo.</p>
<p>Así que lo diré con claridad. Nadie consigue que lo contraten entregando a un responsable de selección algo generado por una máquina que no puede explicar. El trabajo tiene que ser tuyo. Tus decisiones, tu oficio, tu responsabilidad. Si utilizaste una herramienta en alguna parte de un proyecto, dilo y demuestra tu criterio por encima de ella: qué conservaste, qué descartaste y por qué tu decisión era mejor para el jugador. Los responsables de contratación confían en quien trata una herramienta como a un becario que necesita orientación, no en quien se esconde detrás de ella. Ser sincero sobre tu proceso transmite profesionalidad, y la profesionalidad a menudo se reduce a «pensé en las consecuencias antes de publicar».</p>
<h2 id="donde-colocar-las-pruebas" tabindex="-1">Dónde colocar las pruebas <a class="header-anchor" href="#donde-colocar-las-pruebas" aria-label="Permalink to &quot;Dónde colocar las pruebas&quot;"></a></h2>
<p>Un consejo práctico, ya que muchas de estas conversaciones comienzan en LinkedIn. El feed penaliza mucho los enlaces externos, pero la sección Destacado de tu perfil no lo hace. Es el único lugar que convierte un enlace en una tarjeta de vista previa limpia sin penalización, y aparece en la parte superior del perfil, donde miran primero los responsables de selección. Fija entre tres y cinco elementos, colocando primero tu mejor trabajo, y recuerda que la mayoría lo verá desde un teléfono. Empieza por aquello que alguien pueda abrir y experimentar en cuestión de segundos.</p>
<p>Haz que sea rápido y honesto. Una demo que carga en menos de dos segundos y muestra una idea clara supera a un proyecto ambicioso que se entrecorta o devuelve un error 404. Los responsables de selección que revisan treinta portafolios en una tarde no esperan, y un enlace roto se interpreta como un mal hábito.</p>
<h2 id="por-que-nos-importa" tabindex="-1">Por qué nos importa <a class="header-anchor" href="#por-que-nos-importa" aria-label="Permalink to &quot;Por qué nos importa&quot;"></a></h2>
<p>En Cinevva creamos juegos para navegador que pueden jugarse al instante, lo que significa que gran parte de nuestro trabajo resulta ser exactamente lo que necesita un portafolio moderno: trabajo real que un responsable de selección puede abrir y jugar desde un único enlace, sin descargas ni instalaciones. Estamos prestando mucha atención a este problema porque quienes lo sufren son los nuestros. Si te despidieron, tus habilidades no se evaporaron. El mercado se volvió más ruidoso y cambió la forma de demostrar lo que sabes hacer.</p>
<p>La pregunta anterior era «¿dónde has trabajado?». La nueva es «enséñame algo que pueda jugar y dime por qué lo creaste así». Esa segunda pregunta es más difícil de manipular y mejor para quienes realmente saben hacer el trabajo. Si eres una de esas personas, este mercado es brutal, pero no está cerrado. Está esperando pruebas en las que pueda confiar.</p>
<hr>
<h2 id="fuentes" tabindex="-1">Fuentes <a class="header-anchor" href="#fuentes" aria-label="Permalink to &quot;Fuentes&quot;"></a></h2>
<ul>
<li><a href="https://www.gamesindustry.biz/gdc-survey-reveals-layoffs-up-6-36-of-industry-using-ai-and-overwhelming-support-for-unionisation-in-the-us" target="_blank" rel="noreferrer">State of the Game Industry 2026 de la GDC: despidos, IA y sindicalización</a></li>
<li><a href="https://gamesbeat.com/global-gamings-workforce-grew-0-6-in-4-years-but-north-americas-shrank-11-5-amir-satvat/" target="_blank" rel="noreferrer">GamesBeat: la fuerza laboral mundial de los videojuegos creció un 0,6 % en cuatro años, mientras que la de Norteamérica se redujo</a></li>
<li><a href="https://en.wikipedia.org/wiki/2022%E2%80%932026_video_game_industry_layoffs" target="_blank" rel="noreferrer">Wikipedia: despidos en la industria de los videojuegos entre 2022 y 2026</a></li>
<li><a href="https://respawn.outlookindia.com/gaming/gaming-news/record-profits-record-layoffs-inside-gamings-2026-paradox" target="_blank" rel="noreferrer">Outlook Respawn: beneficios récord, despidos récord</a></li>
<li><a href="https://www.gamedeveloper.com/business/industry-layoffs-are-seemingly-slowing-but-the-damage-has-already-been-done" target="_blank" rel="noreferrer">Game Developer: los despidos se están ralentizando, pero el daño ya está hecho</a></li>
<li><a href="https://techround.co.uk/news/linkedin-ai-slop-content-recruitment-process/" target="_blank" rel="noreferrer">TechRound: LinkedIn afronta una oleada de contenido basura generado con IA</a></li>
</ul>
<hr>
<p><strong>Relacionado:</strong></p>
<ul>
<li><a href="/es/blog/2026-01-18-skills-over-degrees.html">El mercado laboral se está transformando: de las credenciales a las habilidades</a></li>
<li><a href="/es/blog/2026-01-18-ai-controversy-and-post-ai-economy.html">La polémica de la IA, la confianza y la economía pos-IA de los videojuegos</a></li>
<li><a href="/es/blog/2026-02-10-the-intuitive-mind.html">La mente intuitiva en la era de la IA</a></li>
</ul>
]]></content:encoded>
            <enclosure url="https://app.cinevva.com/img/blog/skills-over-degrees.jpg" length="0" type="image/jpg"/>
        </item>
        <item>
            <title><![CDATA[Los mejores juegos gratis de navegador para jugar ahora (sin descargar)]]></title>
            <link>https://app.cinevva.com/es/blog/2026-06-30-best-free-browser-games-no-download</link>
            <guid>https://app.cinevva.com/es/blog/2026-06-30-best-free-browser-games-no-download</guid>
            <pubDate>Tue, 30 Jun 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Una selección de los mejores juegos de navegador a los que puedes jugar al instante, sin descargas ni instalaciones. Juegos indie muy valorados de puzles, roguelike, narrativa y ritmo.]]></description>
            <content:encoded><![CDATA[<h1 id="los-mejores-juegos-gratis-de-navegador-para-jugar-ahora-sin-descargar" tabindex="-1">Los mejores juegos gratis de navegador para jugar ahora (sin descargar) <a class="header-anchor" href="#los-mejores-juegos-gratis-de-navegador-para-jugar-ahora-sin-descargar" aria-label="Permalink to &quot;Los mejores juegos gratis de navegador para jugar ahora (sin descargar)&quot;"></a></h1>
<p><em>Por <a href="/es/about.html">Mariana Muntean</a>, CEO de Cinevva</em></p>
<p>Bueno, desde luego no teníamos pensado pasarnos una semana entera en itch.io. Lo que empezó como una búsqueda rápida se convirtió en... en fin, dejamos de contar más o menos al llegar a las doce horas. La idea era encontrar juegos a los que puedas jugar de inmediato: sin descargas ni instaladores trabajando en segundo plano. Haces clic y ya estás dentro. Así de fácil.</p>
<p>Estos son los que pasaron el corte.</p>
<h2 id="experiencias-interactivas-mejor-valoradas" tabindex="-1">Experiencias interactivas mejor valoradas <a class="header-anchor" href="#experiencias-interactivas-mejor-valoradas" aria-label="Permalink to &quot;Experiencias interactivas mejor valoradas&quot;"></a></h2>
<div class="showcase-card">
<img src="/img/showcases/anxiety.png" alt="Captura de pantalla de Adventures With Anxiety" loading="lazy">
<p><strong>Adventures With Anxiety!</strong> — Historia interactiva
Más de 6500 valoraciones con una media de 4,9. Es increíble que algo que te obliga a enfrentarte de lleno a la ansiedad tenga tantos seguidores, ¿verdad? Resulta incómodo de la mejor manera posible: de esa que se queda contigo. <a href="https://ncase.itch.io/anxiety" target="_blank" rel="noreferrer">Juega aquí</a></p>
</div>
<div class="showcase-card">
<img src="/img/showcases/wbwwb.png" alt="Captura de pantalla de We Become What We Behold" loading="lazy">
<p><strong>We Become What We Behold</strong> — Crítica social
7600 valoraciones y una puntuación de 4,8/5. Diez minutos para terminarlo. Días para dejar de pensar en él. <a href="https://ncase.itch.io/wbwwb" target="_blank" rel="noreferrer">Juega aquí</a></p>
</div>
<div class="showcase-card">
<img src="/img/showcases/six-cats-under.png" alt="Captura de pantalla de Six Cats Under" loading="lazy">
<p><strong>Six Cats Under</strong> — Aventura de puzles
Acogedor e ingenioso. El apartado visual hace gran parte del trabajo, y eso juega a su favor. Un 4,8/5 según más de 6400 personas. <a href="https://teambeanloop.itch.io/six-cats-under" target="_blank" rel="noreferrer">Juega aquí</a></p>
</div>
<div class="showcase-card">
<img src="/img/showcases/friday-night-funkin.gif" alt="Captura de pantalla de Friday Night Funkin" loading="lazy">
<p><strong>Friday Night Funkin'</strong> — Juego de ritmo
A estas alturas está por todas partes. Más de 11 700 valoraciones y un 4,7/5. <a href="https://ninja-muffin24.itch.io/funkin" target="_blank" rel="noreferrer">Juega aquí</a></p>
</div>
<div class="showcase-card">
<img src="/img/showcases/sort-the-court.png" alt="Captura de pantalla de Sort the Court" loading="lazy">
<p><strong>Sort the Court!</strong> — Simulador de reino
Tu única tarea: decir sí o no. No parece gran cosa. Y entonces desaparecen dos horas mientras sigues gobernando un pequeño reino. <a href="https://graebor.itch.io/sort-the-court" target="_blank" rel="noreferrer">Juega aquí</a></p>
</div>
<div class="showcase-card">
<img src="/img/showcases/dragonsweeper.png" alt="Captura de pantalla de Dragonsweeper" loading="lazy">
<p><strong>Dragonsweeper</strong> — Roguelike de puzles
Toma el Buscaminas y mézclalo con sistemas de RPG. Un 4,9/5: puede que sea el mejor juego de toda la lista. <a href="https://danielben.itch.io/dragonsweeper" target="_blank" rel="noreferrer">Juega aquí</a></p>
</div>
<h2 id="roguelike-y-estrategia-jugables-en-el-navegador" tabindex="-1">Roguelike y estrategia (jugables en el navegador) <a class="header-anchor" href="#roguelike-y-estrategia-jugables-en-el-navegador" aria-label="Permalink to &quot;Roguelike y estrategia (jugables en el navegador)&quot;"></a></h2>
<div class="showcase-card">
<img src="/img/showcases/backpack-hero.png" alt="Captura de pantalla de Backpack Hero" loading="lazy">
<p><strong>Backpack Hero</strong> — Roguelike de gestión de inventario
La versión para navegador es completamente gratis. La versión de pago añade más contenido, pero la versión web gratuita se sostiene por sí sola. <a href="https://thejaspel.itch.io/backpack-hero" target="_blank" rel="noreferrer">Juega aquí</a></p>
</div>
<div class="showcase-card">
<img src="/img/showcases/vampire-survivors.png" alt="Captura de pantalla de Vampire Survivors" loading="lazy">
<p><strong>Vampire Survivors</strong> — Bullet heaven
Solo es una demo: un escenario y siete personajes. Aun así, basta para entender por qué este juego devoró el tiempo libre de todo el mundo. <a href="https://poncle.itch.io/vampire-survivors" target="_blank" rel="noreferrer">Juega aquí</a></p>
</div>
<div class="showcase-card">
<img src="/img/showcases/dome-romantik.gif" alt="Captura de pantalla de Dome Romantik" loading="lazy">
<p><strong>Dome Romantik</strong> — Defensa y minería
Empezó como un proyecto para una game jam. Se convirtió en Dome Keeper. Y acabó siendo todo un éxito. El prototipo original sigue siendo muy bueno. <a href="https://bippinbits.itch.io/dome-romantik" target="_blank" rel="noreferrer">Juega aquí</a></p>
</div>
<h2 id="¿por-que-estos-en-concreto" tabindex="-1">¿Por qué estos en concreto? <a class="header-anchor" href="#¿por-que-estos-en-concreto" aria-label="Permalink to &quot;¿Por qué estos en concreto?&quot;"></a></h2>
<p>Probamos todos y cada uno de los enlaces. No fue un vistazo rápido: nos sentamos a jugar de verdad. Cargan sin complicaciones. Sin rarezas del navegador. Miles de valoraciones proceden de personas que nunca tocaron un botón de descarga; hicieron clic y empezaron a jugar directamente. ¿Ese camino sin fricciones entre «vaya, qué interesante» y jugar de verdad? La mayoría subestima hasta qué punto lo cambia todo.</p>
<h2 id="descubre-mas-juegos-web" tabindex="-1">Descubre más juegos web <a class="header-anchor" href="#descubre-mas-juegos-web" aria-label="Permalink to &quot;Descubre más juegos web&quot;"></a></h2>
<p>¿Todavía quieres más?</p>
<ul>
<li><a href="https://itch.io/games/top-rated/html5" target="_blank" rel="noreferrer">Juegos HTML5 mejor valorados en itch.io</a></li>
<li><a href="https://itch.io/games/top-rated/genre-platformer/html5" target="_blank" rel="noreferrer">Mejores juegos de plataformas HTML5</a></li>
<li><a href="https://itch.io/games/top-rated/html5/year-2024" target="_blank" rel="noreferrer">Juegos de 2024-2025</a></li>
</ul>
<h2 id="juegos-indie-destacados-requieren-descarga" tabindex="-1">Juegos indie destacados (requieren descarga) <a class="header-anchor" href="#juegos-indie-destacados-requieren-descarga" aria-label="Permalink to &quot;Juegos indie destacados (requieren descarga)&quot;"></a></h2>
<p>Hay juegos excelentes que no funcionan en el navegador. Estos merecen el paso adicional:</p>
<div class="showcase-card">
<img src="/img/showcases/slice-dice.png" alt="Captura de pantalla de Slice & Dice" loading="lazy">
<p><strong>Slice &amp; Dice</strong> — Roguelike de dados
Funciona en Windows, Mac y Android. <a href="https://tann.itch.io/slice-dice" target="_blank" rel="noreferrer">Consíguelo en itch.io</a></p>
</div>
<div class="showcase-card">
<img src="/img/showcases/stacklands.png" alt="Captura de pantalla de Stacklands" loading="lazy">
<p><strong>Stacklands</strong> — Construcción de aldeas con cartas
Para Windows y Mac. <a href="https://sokpop.itch.io/stacklands" target="_blank" rel="noreferrer">Consíguelo en itch.io</a></p>
</div>
<div class="showcase-card">
<img src="/img/showcases/luck-be-a-landlord.png" alt="Captura de pantalla de Luck be a Landlord" loading="lazy">
<p><strong>Luck be a Landlord</strong> — Roguelike de máquina tragaperras
Parece una ocurrencia pasajera. No lo es. Hay estrategia de verdad bajo esa apariencia de máquina tragaperras. <a href="https://trampolinetales.itch.io/luck-be-a-landlord" target="_blank" rel="noreferrer">itch.io</a></p>
</div>
<div class="showcase-card">
<img src="/img/showcases/patricks-parabox.png" alt="Captura de pantalla de Patrick's Parabox" loading="lazy">
<p><strong>Patrick's Parabox</strong> — Puzles recursivos
Prepárate para que te duela la cabeza. Y para disfrutarlo de todos modos. <a href="https://patricktraynor.itch.io/patricks-parabox" target="_blank" rel="noreferrer">itch.io</a></p>
</div>
<div class="showcase-card">
<img src="/img/showcases/dome-keeper.jpg" alt="Captura de pantalla de Dome Keeper" loading="lazy">
<p><strong>Dome Keeper</strong> — Defensa y minería
La versión completa de aquel prototipo de game jam que mencionamos. <a href="https://store.steampowered.com/app/1637320/Dome_Keeper/" target="_blank" rel="noreferrer">Encuéntralo en Steam</a></p>
</div>
<div class="showcase-card">
<img src="/img/showcases/brotato.jpg" alt="Captura de pantalla de Brotato" loading="lazy">
<p><strong>Brotato</strong> — Supervivencia en arena
<a href="https://store.steampowered.com/app/1942280/Brotato/" target="_blank" rel="noreferrer">Disponible en Steam</a></p>
</div>
<hr>
<p>Si creas juegos, hay algo sobre lo que vale la pena reflexionar: <strong>las versiones para navegador no interponen nada entre los jugadores y tu obra</strong>. No hay una descarga esperando en una cola que acabarán olvidando. No hay pantallas de instalación que superar. Con un clic ya están formándose una opinión sobre lo que has creado. No se habla lo suficiente de esa inmediatez, pero lo cambia todo.</p>
<p>¿Quieres lo mismo para tu propio juego? Puedes crear uno directamente en el navegador con el <a href="/es/create.html">creador de juegos de Cinevva</a>, y los que destacamos aparecen en nuestro <a href="/es/arcade.html">Arcade de la comunidad</a>.</p>
<ul>
<li><a href="/es/creators.html">Para creadores de juegos</a></li>
<li><a href="/es/tutorials/ship-web-game-fast.html">Crea un juego web que cargue rápido</a></li>
</ul>
]]></content:encoded>
            <enclosure url="https://app.cinevva.com/img/showcases/anxiety.png" length="0" type="image/png"/>
        </item>
        <item>
            <title><![CDATA[Motores de juegos web en 2026: PlayCanvas vs Three.js vs Babylon.js vs Unity WebGL]]></title>
            <link>https://app.cinevva.com/es/blog/2026-06-09-web-game-engines-2026-comparison</link>
            <guid>https://app.cinevva.com/es/blog/2026-06-09-web-game-engines-2026-comparison</guid>
            <pubDate>Tue, 09 Jun 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Una comparación actual y honesta de las principales formas de crear un juego 3D en el navegador en 2026: PlayCanvas (v2.20), Three.js, Babylon.js y Unity WebGL. Qué es cada uno, para quién está pensado, compatibilidad con WebGL2 y WebGPU, licencias y cómo elegir.]]></description>
            <content:encoded><![CDATA[<h1 id="motores-de-juegos-web-en-2026-playcanvas-vs-three-js-vs-babylon-js-vs-unity-webgl" tabindex="-1">Motores de juegos web en 2026: PlayCanvas vs Three.js vs Babylon.js vs Unity WebGL <a class="header-anchor" href="#motores-de-juegos-web-en-2026-playcanvas-vs-three-js-vs-babylon-js-vs-unity-webgl" aria-label="Permalink to &quot;Motores de juegos web en 2026: PlayCanvas vs Three.js vs Babylon.js vs Unity WebGL&quot;"></a></h1>
<p><em>Por <a href="/es/about.html">Oleg Sidorkin</a>, CTO y cofundador de Cinevva</em></p>
<img src="https://cdn.cinevva.com/blog/web-engines-2026-hero.jpg" alt="Una ventana de navegador que muestra una escena 3D pasando de una malla de alambre blanca a la izquierda a un colorido paisaje low-poly renderizado a la derecha" style="width:100%;border-radius:8px;margin:1.5rem 0" />
<p>Si quieres publicar un juego 3D que funcione en un navegador en 2026, tienes cuatro opciones consolidadas y algunas más recientes. Suelen agruparse bajo la etiqueta de «motores de juegos web», pero en realidad son herramientas muy distintas que resuelven problemas diferentes. Elegir la equivocada puede costarte meses. Esta es una comparación actual y verificada, escrita por personas que se dedican a desarrollar un motor 3D para la web y que evaluaron todas estas opciones antes de crear el suyo propio.</p>
<p>Repasaremos cada opción, qué es realmente, para quién está pensada y dónde se queda corta, y al final te ofreceremos una breve guía de decisión. Cuando mencionamos números de versión, son correctos a julio de 2026.</p>
<blockquote>
<p>¿Buscas una visión completa del mercado? Este artículo se centra en las cuatro principales opciones 3D. Para ver los 11 motores web clasificados y comparados —incluidas opciones 2D como Phaser, Defold y Construct—, consulta nuestra guía de los <a href="/es/guides/web-game-engines-comparison.html">mejores motores de juegos web para 2026</a>.</p>
</blockquote>
<h2 id="comparacion-rapida" tabindex="-1">Comparación rápida <a class="header-anchor" href="#comparacion-rapida" aria-label="Permalink to &quot;Comparación rápida&quot;"></a></h2>
<table tabindex="0">
<thead>
<tr>
<th></th>
<th>PlayCanvas</th>
<th>Three.js</th>
<th>Babylon.js</th>
<th>Unity WebGL</th>
<th>Cinevva</th>
</tr>
</thead>
<tbody>
<tr>
<td>Qué es</td>
<td>Motor completo + editor alojado</td>
<td>Biblioteca de renderizado</td>
<td>Motor completo + editor</td>
<td>Motor de escritorio con exportación web</td>
<td>Plataforma de mundos nativa de IA</td>
</tr>
<tr>
<td>Arquitectura</td>
<td>Entidad-componente (ECS)</td>
<td>Grafo de escena</td>
<td>Grafo de escena + componentes</td>
<td>GameObject/componente</td>
<td>Grafo de escena + constructor con IA</td>
</tr>
<tr>
<td>Programación</td>
<td>TypeScript / JavaScript</td>
<td>JavaScript (tú construyes el resto)</td>
<td>TypeScript / JavaScript</td>
<td>C# (compilado a Wasm)</td>
<td>Lenguaje natural + código</td>
</tr>
<tr>
<td>Renderizador</td>
<td>WebGL2, WebGPU en proceso de maduración</td>
<td>WebGL2, WebGPU en crecimiento</td>
<td>WebGL2, WebGPU avanzando</td>
<td>WebGL2 (exportación)</td>
<td>Solo WebGPU</td>
</tr>
<tr>
<td>Editor</td>
<td>Alojado, comercial</td>
<td>Ninguno</td>
<td>Basado en web, gratuito</td>
<td>De escritorio, comercial</td>
<td>Dentro del mundo, inmersivo</td>
</tr>
<tr>
<td>Física</td>
<td>Ammo / integraciones</td>
<td>Aportas la tuya</td>
<td>Havok integrado</td>
<td>Integrada (PhysX)</td>
<td>Solucionador de personajes personalizado</td>
</tr>
<tr>
<td>Licencia</td>
<td>Motor MIT, editor propietario</td>
<td>MIT</td>
<td>Apache 2.0</td>
<td>Propietaria</td>
<td>Propietaria</td>
</tr>
<tr>
<td>Ideal para</td>
<td>Juegos de navegador con flujo de estudio</td>
<td>3D personalizado, control total</td>
<td>Juegos con todo incluido</td>
<td>Adaptar juegos existentes de Unity</td>
<td>Creación de juegos con IA dentro del mundo</td>
</tr>
</tbody>
</table>
<p>El resto de este artículo explica la tabla.</p>
<h2 id="playcanvas" tabindex="-1">PlayCanvas <a class="header-anchor" href="#playcanvas" aria-label="Permalink to &quot;PlayCanvas&quot;"></a></h2>
<p>PlayCanvas es lo más parecido que existe en la web a un flujo de trabajo al estilo Unity. El motor es de código abierto bajo la licencia MIT y se encuentra en la versión 2.20.6 a julio de 2026. Utiliza un sistema de entidad-componente, permite escribir la lógica del juego en TypeScript o JavaScript y procesa los recursos mediante una canalización del lado del servidor que genera archivos GLB. Hay juegos comerciales reales que funcionan con él y grandes empresas lo utilizan en producción; Snap es un ejemplo público.</p>
<p>Conviene aclarar dos aspectos de PlayCanvas que suelen malinterpretarse. En primer lugar, aunque el motor tiene licencia MIT, el editor visual alojado que realmente utilizan la mayoría de los equipos es un producto comercial, no de código abierto. Puedes usar el motor gratuitamente sin él, pero el flujo de trabajo de editor más nube es la parte de pago. En segundo lugar, PlayCanvas se centra ante todo en WebGL2. Tiene una ruta WebGPU, pero todavía está madurando y aún no es el renderizador predeterminado, así que no elijas PlayCanvas hoy esperando usar shaders de cómputo WebGPU en producción.</p>
<p>Donde PlayCanvas destaca de verdad es en el Gaussian splatting 3D. Su editor y visor SuperSplat, cuyo código abrió el equipo, se encuentran entre las mejores herramientas disponibles para capturar y publicar escenas de splats en la web, con streaming basado en WebGPU para capturas de gran tamaño. Si lo tuyo son los entornos escaneados fotorrealistas, esa es una razón de peso para empezar aquí.</p>
<p><strong>Elige PlayCanvas si</strong> quieres un editor similar a Unity y una canalización de recursos gestionada para el navegador, y estás publicando el tipo de juego que desarrollaría un estudio. <strong>Busca otra opción si</strong> necesitas cómputo WebGPU hoy o quieres evitar un editor comercial alojado.</p>
<h2 id="three-js" tabindex="-1">Three.js <a class="header-anchor" href="#three-js" aria-label="Permalink to &quot;Three.js&quot;"></a></h2>
<p>Three.js no es un motor de juegos. Es una biblioteca de renderizado y, con mucha diferencia, la más utilizada de este ámbito. Te proporciona un grafo de escena, cámaras, luces, materiales, geometría, cargadores y un renderizador, y ahí se detiene. No incluye editor, física, sistema de entidades ni una forma impuesta de estructurar un juego. Todo eso debes añadirlo tú o tomarlo del ecosistema.</p>
<p>Ese intercambio lo define todo. Obtienes el máximo control y la comunidad más grande del 3D web, a cambio de tener que crear o integrar todo lo que se sitúa por encima del renderizador. Su renderizador WebGPU ha crecido de forma constante y ya puede utilizarse, aunque, como ocurre con los demás, la ruta WebGL2 sigue siendo la opción predeterminada más madura. Three.js tiene licencia MIT.</p>
<p><strong>Elige Three.js si</strong> quieres control total, una base mínima y cuentas con la capacidad técnica necesaria para construir encima los sistemas de tu juego. <strong>Busca otra opción si</strong> quieres que te proporcionen un editor y sistemas de juego ya preparados.</p>
<h2 id="babylon-js" tabindex="-1">Babylon.js <a class="header-anchor" href="#babylon-js" aria-label="Permalink to &quot;Babylon.js&quot;"></a></h2>
<p>Babylon.js es un motor completo con licencia Apache 2.0 y respaldado por un equipo de Microsoft. A diferencia de Three.js, incluye las piezas que de otro modo tendrías que integrar: un modelo de componentes, el motor de física Havok integrado, un editor web gratuito y una canalización de recursos. Su trabajo con WebGPU ha avanzado rápidamente y se encuentra entre los más desarrollados de los motores de propósito general, aunque sigue manteniendo WebGL2 como ruta de amplia compatibilidad. Babylon.js 9.0 (marzo de 2026) amplió aún más esa ventaja con iluminación agrupada en ambos backends, iluminación volumétrica basada en shaders de cómputo WebGPU y compatibilidad con sombras para splats gaussianos 3D.</p>
<p>Si tu planteamiento es «quiero un motor completo, con física incluida, y me parece bien trabajar según sus convenciones», Babylon es una opción predeterminada sólida y posiblemente la alternativa gratuita con más funciones de este ámbito.</p>
<p><strong>Elige Babylon.js si</strong> quieres todo incluido, física integrada y un editor gratuito. <strong>Busca otra opción si</strong> quieres una dependencia mínima o buscas específicamente un flujo de trabajo alojado al estilo Unity.</p>
<h2 id="unity-webgl" tabindex="-1">Unity WebGL <a class="header-anchor" href="#unity-webgl" aria-label="Permalink to &quot;Unity WebGL&quot;"></a></h2>
<p>Unity WebGL no es un motor web, sino un destino de exportación. Desarrollas en el editor de escritorio de Unity, con C#, y compilas un paquete WebGL que funciona en el navegador mediante WebAssembly. Esto lo convierte en la respuesta evidente para un caso concreto: ya tienes un juego de Unity y quieres una versión para navegador.</p>
<p>Para un proyecto concebido primero para la web, conlleva costes importantes. El entorno de ejecución y el peso de la descarga son considerables, el inicio es más lento que con un motor web nativo y el rendimiento en navegadores móviles es un problema conocido. Unity es propietario y su salida WebGL está orientada a WebGL2. Unity 6 incluye un backend WebGPU experimental, pero está desactivado de forma predeterminada y aún no está listo para producción.</p>
<p><strong>Elige Unity WebGL si</strong> tienes un proyecto de Unity existente que quieres llevar al navegador o tu equipo ya trabaja por completo con Unity. <strong>Busca otra opción si</strong> la carga instantánea en teléfonos de gama media es un requisito indispensable o si empiezas desde cero con un enfoque web-first.</p>
<h2 id="donde-encajan-la-ia-nativa-y-la-creacion-dentro-del-mundo" tabindex="-1">Dónde encajan la IA nativa y la creación dentro del mundo <a class="header-anchor" href="#donde-encajan-la-ia-nativa-y-la-creacion-dentro-del-mundo" aria-label="Permalink to &quot;Dónde encajan la IA nativa y la creación dentro del mundo&quot;"></a></h2>
<p>Todas las opciones anteriores comparten una premisa: un desarrollador crea el juego sentado ante un escritorio, dentro de un editor, y publica un entorno de ejecución. Esa premisa es correcta para la mayoría de los proyectos y, si describe el tuyo, elige una de las cuatro opciones anteriores.</p>
<p>Conviene saber que esa premisa ya no es la única opción, porque está surgiendo una categoría diferente. Nosotros desarrollamos Cinevva, una plataforma de mundos exclusiva para WebGPU en la que los juegos se crean desde dentro del propio mundo. En lugar de abrir un editor, eres un avatar situado en el espacio, describes lo que quieres y un constructor con IA lo convierte en terreno, objetos y comportamientos mientras permaneces allí. La creación y el juego forman parte de la misma sesión. A nivel interno, esto implicó apostar exclusivamente por WebGPU con terreno generado mediante shaders de cómputo, escribir un solucionador de personajes personalizado en lugar de usar un motor de física general y construir un sistema de animación y retargeting. Hablamos de ello en <a href="/es/blog/2026-06-08-why-we-built-our-own-webgpu-engine.html">por qué creamos nuestro propio motor WebGPU</a>.</p>
<p>Esto no sustituye a PlayCanvas ni a Babylon. Si eres un desarrollador que crea un juego específico, esas son las herramientas adecuadas. Cinevva persigue un objetivo distinto: permitir que personas que no desarrollan motores creen y compartan espacios jugables simplemente describiéndolos. Lo mencionamos aquí porque la pregunta «¿qué motor de juegos web debería utilizar?» tiene cada vez más una quinta respuesta que ni siquiera es un motor.</p>
<h2 id="matriz-completa-de-caracteristicas" tabindex="-1">Matriz completa de características <a class="header-anchor" href="#matriz-completa-de-caracteristicas" aria-label="Permalink to &quot;Matriz completa de características&quot;"></a></h2>
<p>La tabla rápida del principio contiene los puntos principales. Esta es la versión detallada, agrupada por subsistema. Antes, algunas observaciones sinceras sobre cómo interpretarla. «BYO» significa que debes aportar tu propia solución; es decir, el motor no la incluye, pero puedes añadirla mediante el ecosistema o tu propio código. Esto resulta especialmente importante en Three.js, que es una biblioteca de renderizado por diseño, por lo que «BYO» representa una característica de su filosofía, no una carencia. «Solo mediante exportación» en Unity significa que la capacidad existe en el editor de escritorio y se incorpora a la compilación WebGL, en lugar de ser nativa de la web. Las celdas de los competidores reflejan las funciones disponibles de serie y el comportamiento bien documentado a mediados de 2026. Las celdas de Cinevva reflejan lo que funciona en nuestra versión publicada; «previsto» indica aquello que está diseñado, pero aún no se ha desarrollado.</p>
<h3 id="renderizado" tabindex="-1">Renderizado <a class="header-anchor" href="#renderizado" aria-label="Permalink to &quot;Renderizado&quot;"></a></h3>
<table tabindex="0">
<thead>
<tr>
<th>Característica</th>
<th>Cinevva</th>
<th>PlayCanvas</th>
<th>Three.js</th>
<th>Babylon.js</th>
<th>Unity WebGL</th>
</tr>
</thead>
<tbody>
<tr>
<td>Renderizador principal</td>
<td>Solo WebGPU</td>
<td>WebGL2 (WebGPU beta)</td>
<td>WebGL2 (WebGPU en crecimiento)</td>
<td>WebGL2 (WebGPU avanzado)</td>
<td>WebGL2 (exportación)</td>
</tr>
<tr>
<td>Shaders de cómputo en producción</td>
<td>Sí (dependencia central)</td>
<td>Beta</td>
<td>Mediante WebGPU</td>
<td>Sí (WebGPU)</td>
<td>Solo mediante exportación, limitado</td>
</tr>
<tr>
<td>Creación de shaders</td>
<td>Nodos TSL + cómputo</td>
<td>Fragmentos de shader / GLSL</td>
<td>GLSL + nodos (TSL)</td>
<td>Material de nodos / GLSL / WGSL</td>
<td>ShaderLab / HLSL</td>
</tr>
<tr>
<td>Iluminación agrupada / forward+</td>
<td>Sí (froxel)</td>
<td>Sí</td>
<td>BYO</td>
<td>Sí</td>
<td>Sí</td>
</tr>
<tr>
<td>Nubes volumétricas y clima</td>
<td>Sí</td>
<td>BYO</td>
<td>BYO</td>
<td>Parcial</td>
<td>BYO</td>
</tr>
<tr>
<td>Herramientas de Gaussian splatting 3D</td>
<td>Previstas</td>
<td>Sí (SuperSplat, líder)</td>
<td>Comunidad</td>
<td>Sí</td>
<td>Plugins</td>
</tr>
</tbody>
</table>
<h3 id="mundo-y-terreno" tabindex="-1">Mundo y terreno <a class="header-anchor" href="#mundo-y-terreno" aria-label="Permalink to &quot;Mundo y terreno&quot;"></a></h3>
<table tabindex="0">
<thead>
<tr>
<th>Característica</th>
<th>Cinevva</th>
<th>PlayCanvas</th>
<th>Three.js</th>
<th>Babylon.js</th>
<th>Unity WebGL</th>
</tr>
</thead>
<tbody>
<tr>
<td>Streaming integrado para mundos grandes</td>
<td>Sí (fragmentos de 64 m)</td>
<td>BYO</td>
<td>BYO</td>
<td>BYO</td>
<td>Solo mediante exportación</td>
</tr>
<tr>
<td>Sistema de terreno</td>
<td>Mapa de alturas híbrido + marching cubes/SDF</td>
<td>BYO</td>
<td>BYO</td>
<td>Extensión</td>
<td>Integrado (escritorio)</td>
</tr>
<tr>
<td>Esculpido de terreno en tiempo de ejecución</td>
<td>Sí (GPU)</td>
<td>BYO</td>
<td>BYO</td>
<td>BYO</td>
<td>No (durante la edición)</td>
</tr>
<tr>
<td>Cuevas y salientes (topología 3D real)</td>
<td>Sí (marching cubes)</td>
<td>BYO</td>
<td>BYO</td>
<td>BYO</td>
<td>BYO</td>
</tr>
<tr>
<td>Vegetación y hierba instanciadas por GPU</td>
<td>Sí</td>
<td>Sí</td>
<td>BYO</td>
<td>Sí</td>
<td>Sí</td>
</tr>
</tbody>
</table>
<h3 id="fisica-y-personajes" tabindex="-1">Física y personajes <a class="header-anchor" href="#fisica-y-personajes" aria-label="Permalink to &quot;Física y personajes&quot;"></a></h3>
<table tabindex="0">
<thead>
<tr>
<th>Característica</th>
<th>Cinevva</th>
<th>PlayCanvas</th>
<th>Three.js</th>
<th>Babylon.js</th>
<th>Unity WebGL</th>
</tr>
</thead>
<tbody>
<tr>
<td>Motor de física</td>
<td>Solucionador cinemático personalizado</td>
<td>Integración con Ammo</td>
<td>BYO (Rapier/Cannon/Ammo)</td>
<td>Havok integrado</td>
<td>PhysX integrado</td>
</tr>
<tr>
<td>Dinámica de cuerpos rígidos</td>
<td>No (por diseño)</td>
<td>Sí</td>
<td>BYO</td>
<td>Sí</td>
<td>Sí</td>
</tr>
<tr>
<td>Controlador de personaje</td>
<td>Sí (FSM multimodo)</td>
<td>Plantillas / Ammo</td>
<td>BYO</td>
<td>Sí</td>
<td>Integrado</td>
</tr>
<tr>
<td>Colisión integrada con el terreno (SDF)</td>
<td>Sí</td>
<td>No</td>
<td>BYO</td>
<td>No</td>
<td>No</td>
</tr>
</tbody>
</table>
<h3 id="animacion" tabindex="-1">Animación <a class="header-anchor" href="#animacion" aria-label="Permalink to &quot;Animación&quot;"></a></h3>
<table tabindex="0">
<thead>
<tr>
<th>Característica</th>
<th>Cinevva</th>
<th>PlayCanvas</th>
<th>Three.js</th>
<th>Babylon.js</th>
<th>Unity WebGL</th>
</tr>
</thead>
<tbody>
<tr>
<td>Animación esquelética</td>
<td>Sí</td>
<td>Sí</td>
<td>Sí</td>
<td>Sí</td>
<td>Sí</td>
</tr>
<tr>
<td>Mezcla / máquina de estados</td>
<td>Sí (FSM resolutora)</td>
<td>Sí (grafo de estados de animación)</td>
<td>Mezclador (mezcla BYO)</td>
<td>Sí</td>
<td>Sí (Mecanim)</td>
</tr>
<tr>
<td>Retargeting de esqueletos</td>
<td>Sí (canalización)</td>
<td>Limitado</td>
<td>Comunidad</td>
<td>Parcial</td>
<td>Sí (humanoide)</td>
</tr>
<tr>
<td>Cinemática inversa</td>
<td>Prevista</td>
<td>Limitada</td>
<td>Comunidad</td>
<td>Sí</td>
<td>Sí</td>
</tr>
</tbody>
</table>
<h3 id="multijugador-y-backend" tabindex="-1">Multijugador y backend <a class="header-anchor" href="#multijugador-y-backend" aria-label="Permalink to &quot;Multijugador y backend&quot;"></a></h3>
<table tabindex="0">
<thead>
<tr>
<th>Característica</th>
<th>Cinevva</th>
<th>PlayCanvas</th>
<th>Three.js</th>
<th>Babylon.js</th>
<th>Unity WebGL</th>
</tr>
</thead>
<tbody>
<tr>
<td>Multijugador integrado</td>
<td>Sí (autoritativo en el edge)</td>
<td>BYO (Photon/Colyseus)</td>
<td>BYO</td>
<td>BYO</td>
<td>BYO (Netcode, no nativo de la web)</td>
</tr>
<tr>
<td>Mundo compartido persistente</td>
<td>Sí (Durable Objects por fragmento)</td>
<td>BYO</td>
<td>BYO</td>
<td>BYO</td>
<td>BYO</td>
</tr>
<tr>
<td>Chat de voz espacial</td>
<td>Sí (WebRTC + HRTF)</td>
<td>BYO</td>
<td>BYO</td>
<td>BYO</td>
<td>BYO</td>
</tr>
</tbody>
</table>
<h3 id="creacion-y-herramientas-de-autoria" tabindex="-1">Creación y herramientas de autoría <a class="header-anchor" href="#creacion-y-herramientas-de-autoria" aria-label="Permalink to &quot;Creación y herramientas de autoría&quot;"></a></h3>
<table tabindex="0">
<thead>
<tr>
<th>Característica</th>
<th>Cinevva</th>
<th>PlayCanvas</th>
<th>Three.js</th>
<th>Babylon.js</th>
<th>Unity WebGL</th>
</tr>
</thead>
<tbody>
<tr>
<td>Editor</td>
<td>Dentro del mundo, inmersivo</td>
<td>Alojado, estilo escritorio (comercial)</td>
<td>Ninguno (mínimo)</td>
<td>Basado en web (gratuito)</td>
<td>De escritorio (comercial)</td>
</tr>
<tr>
<td>Creación encarnada dentro del mundo</td>
<td>Sí</td>
<td>No</td>
<td>No</td>
<td>No</td>
<td>No</td>
</tr>
<tr>
<td>Creación mediante lenguaje natural / IA</td>
<td>Sí (constructor con IA)</td>
<td>No</td>
<td>No</td>
<td>No</td>
<td>No</td>
</tr>
<tr>
<td>Programación</td>
<td>Lenguaje natural + JS</td>
<td>TypeScript / JS</td>
<td>JavaScript</td>
<td>TypeScript / JS</td>
<td>C#</td>
</tr>
</tbody>
</table>
<h3 id="recursos-y-distribucion" tabindex="-1">Recursos y distribución <a class="header-anchor" href="#recursos-y-distribucion" aria-label="Permalink to &quot;Recursos y distribución&quot;"></a></h3>
<table tabindex="0">
<thead>
<tr>
<th>Característica</th>
<th>Cinevva</th>
<th>PlayCanvas</th>
<th>Three.js</th>
<th>Babylon.js</th>
<th>Unity WebGL</th>
</tr>
</thead>
<tbody>
<tr>
<td>Canalización de recursos del lado del servidor</td>
<td>Sí (GLB + LOD + KTX2 + Draco)</td>
<td>Sí (GLB)</td>
<td>Solo cargadores</td>
<td>Herramientas de importación</td>
<td>Sí</td>
</tr>
<tr>
<td>Generación de recursos con IA integrada</td>
<td>Sí (3D, imágenes, audio, música)</td>
<td>No</td>
<td>No</td>
<td>No</td>
<td>No</td>
</tr>
<tr>
<td>Búsqueda federada de recursos</td>
<td>Sí (once proveedores)</td>
<td>Tienda de recursos</td>
<td>No</td>
<td>No</td>
<td>Tienda de recursos</td>
</tr>
<tr>
<td>Funciona en el navegador, sin instalación</td>
<td>Sí</td>
<td>Sí</td>
<td>Sí</td>
<td>Sí</td>
<td>Sí (pesado)</td>
</tr>
<tr>
<td>Licencia del motor</td>
<td>Plataforma propietaria</td>
<td>Motor MIT, editor propietario</td>
<td>MIT</td>
<td>Apache 2.0</td>
<td>Propietaria</td>
</tr>
</tbody>
</table>
<p>El patrón de la matriz es la verdadera historia. Los motores de propósito general distribuyen sus fortalezas horizontalmente: cada uno hace la mayoría de las cosas de forma competente y te deja a ti el mundo, el backend y el flujo de creación. Cinevva se concentra verticalmente: hace menos cosas, pero controla todo el recorrido, desde el renderizador hasta un mundo compartido que creas desde dentro. Ninguno de los dos enfoques es mejor en términos absolutos. Responden a preguntas diferentes.</p>
<h2 id="como-elegir" tabindex="-1">Cómo elegir <a class="header-anchor" href="#como-elegir" aria-label="Permalink to &quot;Cómo elegir&quot;"></a></h2>
<p>Adapta la herramienta a la situación en lugar de guiarte por una lista de características.
Si ya tienes un juego hecho con Unity, expórtalo con Unity WebGL y acepta su peso. Si sois un estudio que busca un flujo de trabajo basado en un editor para juegos de navegador, usad PlayCanvas. Si quieres un motor gratuito y completo con físicas incluidas, usa Babylon.js. Si quieres control total y cuentas con un equipo capaz de desarrollar sobre un renderizador básico, usa Three.js. Y si tu objetivo no es crear un solo juego, sino permitir que la gente cree y juegue dentro de un mundo compartido describiendo cosas, esa es la categoría en la que trabajamos, y puedes <a href="/es/">probar Cinevva</a>.</p>
<p>Elijas lo que elijas, evalúalo con prototipos reales antes de comprometerte. Cada una de estas opciones puede sustentar un juego de verdad, y el coste de cambiar a mitad del desarrollo se mide en los meses que no dedicaste a publicar.</p>
]]></content:encoded>
            <enclosure url="https://cdn.cinevva.com/blog/web-engines-2026-hero.jpg" length="0" type="image/jpg"/>
        </item>
        <item>
            <title><![CDATA[Por qué creamos nuestro propio motor WebGPU en vez de bifurcar PlayCanvas]]></title>
            <link>https://app.cinevva.com/es/blog/2026-06-08-why-we-built-our-own-webgpu-engine</link>
            <guid>https://app.cinevva.com/es/blog/2026-06-08-why-we-built-our-own-webgpu-engine</guid>
            <pubDate>Mon, 08 Jun 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Three.js, Babylon.js, PlayCanvas, Unity WebGL: los evaluamos todos antes de escribir nuestro propio renderizador. Esto es lo que hace bien cada uno, las cuatro decisiones que nos llevaron a crear una solución propia y los casos en los que definitivamente no deberías hacer lo mismo que nosotros.]]></description>
            <content:encoded><![CDATA[<h1 id="por-que-creamos-nuestro-propio-motor-webgpu-en-vez-de-bifurcar-playcanvas" tabindex="-1">Por qué creamos nuestro propio motor WebGPU en vez de bifurcar PlayCanvas <a class="header-anchor" href="#por-que-creamos-nuestro-propio-motor-webgpu-en-vez-de-bifurcar-playcanvas" aria-label="Permalink to &quot;Por qué creamos nuestro propio motor WebGPU en vez de bifurcar PlayCanvas&quot;"></a></h1>
<p><em>Por <a href="/es/about.html">Oleg Sidorkin</a>, CTO y cofundador de Cinevva</em></p>
<img src="https://cdn.cinevva.com/blog/why-webgpu-engine-hero.jpg" alt="Un mundo estilizado de bajo número de polígonos renderizado por el motor WebGPU de Cinevva: colinas onduladas, una cueva excavada en un acantilado, un río serpenteante y un avatar avanzando por un sendero durante la hora dorada" style="width:100%;border-radius:8px;margin:1.5rem 0" />
<p>Toda persona con perfil técnico que ve Cinevva World hace la misma pregunta en menos de cinco minutos. Sois un equipo pequeño. Ya existen motores 3D maduros para la web. ¿Por qué escribisteis vuestro propio renderizador, vuestro propio sistema de física de personajes y vuestro propio sistema de animación, en lugar de apoyaros en PlayCanvas o Babylon y lanzar el producto antes?</p>
<p>Es una pregunta razonable, y «no se inventó aquí» no es una respuesta válida. Hicimos los deberes. Probamos los motores existentes, leímos su código fuente y desarrollamos prototipos sobre dos de ellos antes de tomar una decisión. Esta publicación cuenta la versión sincera de esa decisión: en qué destacan realmente las opciones disponibles, los cuatro puntos en los que nuestras necesidades divergieron lo suficiente como para justificar una solución propia y las situaciones en las que deberías elegir una de esas opciones en vez de imitarnos. Documentamos el propio desarrollo en una extensa <a href="/es/blog/2026-02-25-open-world-browser-series-guide.html">serie de ingeniería sobre cómo crear un mundo abierto en el navegador</a>, así que, cuando alguna afirmación de este artículo tenga detrás un registro práctico, incluiré un enlace.</p>
<h2 id="las-opciones-que-evaluamos-de-verdad" tabindex="-1">Las opciones que evaluamos de verdad <a class="header-anchor" href="#las-opciones-que-evaluamos-de-verdad" aria-label="Permalink to &quot;Las opciones que evaluamos de verdad&quot;"></a></h2>
<p>Hay cuatro cosas a las que se suele llamar «motores de juegos web», pero no son el mismo tipo de herramienta.</p>
<p><strong>Three.js</strong> es una biblioteca de renderizado, no un motor de juegos. Te proporciona un grafo de escena, materiales, cargadores y un renderizador, y después se aparta de tu camino. No incluye editor, física ni sistema de entidades, y tampoco impone una estructura para tu juego. Eso es tanto su atractivo como su coste. Tienes que construir por tu cuenta todo lo que está por encima del renderizador, pero nada se interpone en tu camino. Tiene licencia MIT, cuenta con el ecosistema más grande del sector y, cuando te encuentras con un oscuro error de shaders a las dos de la mañana, suele haber una respuesta esperándote en algún foro.</p>
<p><strong>Babylon.js</strong> es un motor completo con un grafo de escena, una integración de física (Havok), un pipeline de recursos y un editor web. Tiene licencia MIT, cuenta con el respaldo de un equipo de Microsoft y su trabajo con WebGPU ha avanzado rápidamente. Si quieres una solución con todo incluido y te sientes cómodo trabajando dentro de la estructura del motor, es una excelente opción predeterminada.</p>
<p><strong>PlayCanvas</strong> es lo más parecido a un «Unity para la web». En el momento de escribir esto, el motor está en la versión 2.19.6, publicada el 5 de junio de 2026, y su código es abierto bajo licencia MIT. Sin embargo, lo que la mayoría utiliza realmente es el editor visual alojado, que es un producto comercial y no es de código abierto. PlayCanvas emplea un sistema de entidades y componentes; permite programar en TypeScript o JavaScript; procesa los recursos mediante un pipeline GLB del lado del servidor; y ya se han publicado con él juegos comerciales reales (Snap, por ejemplo, utiliza PlayCanvas en producción). Su renderizador funciona con WebGL2 y dispone de una ruta WebGPU que todavía está madurando, en lugar de ser la opción predeterminada. Este último detalle importa más de lo que parece, y volveré a él más adelante.</p>
<p><strong>Unity WebGL</strong> no es en absoluto un motor web. Es un destino de exportación. Creas el juego en el editor de escritorio de Unity y lo compilas como un paquete WebGL. Es la herramienta adecuada cuando ya tienes un juego hecho con Unity y quieres llevarlo al navegador, y la herramienta equivocada cuando «cargar al instante en una pestaña de un teléfono de gama media» es un requisito innegociable, porque el tiempo de ejecución y el peso de la descarga vienen incluidos.</p>
<p>Cualquiera de estas opciones es una base razonable para un juego web normal. Nosotros no teníamos un juego web normal.</p>
<h2 id="primera-decision-webgpu-es-nuestro-punto-de-partida-no-nuestra-meta" tabindex="-1">Primera decisión: WebGPU es nuestro punto de partida, no nuestra meta <a class="header-anchor" href="#primera-decision-webgpu-es-nuestro-punto-de-partida-no-nuestra-meta" aria-label="Permalink to &quot;Primera decisión: WebGPU es nuestro punto de partida, no nuestra meta&quot;"></a></h2>
<p>La diferencia que nos aleja de todas las soluciones disponibles es esta: para nosotros, WebGPU es un requisito, no una función que incorporaremos con el tiempo.</p>
<p>Nuestro terreno no es un mapa de alturas estático. Es un sistema híbrido formado por un campo de mapas de alturas transmitido por streaming y chunks de marching cubes respaldados por un campo de distancias con signo. Gracias a ello, el mundo puede tener cuevas y salientes reales, y los creadores pueden esculpirlo en directo. Los pinceles de esculpido, la dispersión de vegetación y la generación de la malla del terreno se ejecutan como shaders de cómputo. Si eliminas el cómputo, el mundo no pierde calidad: sencillamente deja de funcionar.</p>
<p>Eso es justo lo contrario de la situación actual de los motores de propósito general. Su compatibilidad con WebGPU está diseñada como una mejora progresiva sobre un renderizador centrado en WebGL2, con una ruta alternativa para los navegadores que no lo admiten. PlayCanvas, en particular, prioriza WebGL2 y todavía mantiene WebGPU en fase beta. Es la decisión correcta para ellos, porque su cometido es ejecutar la mayor variedad posible de juegos en la mayor variedad posible de dispositivos. Nuestro cometido es más limitado y profundo, así que tomamos la decisión contraria: en el prototipo 13 pasamos a utilizar exclusivamente WebGPU y nunca miramos atrás. Los navegadores sin WebGPU no reciben una versión reducida, sino que no son compatibles, y medimos ese hecho como una cifra de alcance en vez de fingir que una alternativa basada en WebGL2 está a un único ajuste de configuración de distancia. No es así. Exigiría reescribir parcialmente nuestras etapas de terreno y vegetación.</p>
<p>Desarrollar sobre un motor centrado en WebGL2 habría implicado luchar contra sus supuestos de compatibilidad alternativa en cada función de cómputo o mantener para siempre dos rutas de renderizado. Controlar nuestro propio renderizador nos permitió tratar el cómputo como la base del sistema.</p>
<h2 id="segunda-decision-un-solucionador-para-personajes-no-un-motor-de-fisica" tabindex="-1">Segunda decisión: un solucionador para personajes, no un motor de física <a class="header-anchor" href="#segunda-decision-un-solucionador-para-personajes-no-un-motor-de-fisica" aria-label="Permalink to &quot;Segunda decisión: un solucionador para personajes, no un motor de física&quot;"></a></h2>
<p>La solución de manual consiste en incorporar un motor de física. Lo intentamos. Uno de los primeros prototipos validó Rapier ejecutándose en un worker, y funcionaba bien.</p>
<p>Aun así, escribimos nuestro propio sistema, y no hay rastro de Rapier, Cannon ni Ammo en la versión publicada. El motivo es el alcance. No necesitamos cuerpos rígidos, articulaciones, ragdolls ni un solucionador de restricciones. Necesitamos que una cápsula se mueva correctamente sobre el terreno, y necesitamos que caminar, deslizarse, planear, escalar y nadar compartan una única respuesta a «¿estoy tocando el suelo, sobre qué superficie y con qué ángulo?». Un motor de física general dificulta esa tarea en vez de facilitarla, porque esos modos terminan enfrentándose a sus resortes y amortiguadores internos.</p>
<p>Por eso, nuestro controlador de personajes es una <a href="/es/blog/2026-05-15-open-world-browser-part-29-pluggable-character.html">máquina de estados multicanal conectable</a>. Cada modo es una pequeña unidad que indica si quiere tomar el control durante este fotograma y, si gana, establece la velocidad y la orientación. Compiten por prioridad en tres canales —recurso, postura y locomoción— y todos consultan el mismo terreno. Las colisiones se resuelven mediante una sonda con forma de cápsula contra el mapa de alturas o el campo de distancias con signo, según el chunk.</p>
<p>El detalle del que más orgulloso estoy es poco llamativo. La detección del suelo examina todas las superficies de la columna vertical situada bajo tus pies y elige la más alta que esté a la altura de la cápsula o por debajo de ella, en vez de confiar en el gradiente del SDF. En el borde de un saliente, la superficie lateral más cercana es la pared del acantilado, por lo que una normal basada en el gradiente oscila entre «suelo» y «pared» y provoca deslizamientos fantasma. La consulta de la columna hace que estar de pie sobre un saliente resulte aburrido, que es exactamente lo que necesitas. Un collider de campos de altura listo para usar no nos habría proporcionado eso sin esfuerzo, porque, para empezar, no puede interpretar nuestro terreno. El terreno reside en la GPU y utiliza nuestro propio formato. Ningún motor externo puede detectar colisiones contra él sin que copiemos todo el campo a su formato de collider después de cada modificación.</p>
<h2 id="tercera-decision-animaciones-que-pueden-trasladarse-entre-rigs" tabindex="-1">Tercera decisión: animaciones que pueden trasladarse entre rigs <a class="header-anchor" href="#tercera-decision-animaciones-que-pueden-trasladarse-entre-rigs" aria-label="Permalink to &quot;Tercera decisión: animaciones que pueden trasladarse entre rigs&quot;"></a></h2>
<p>Los avatares utilizan el rig Synty POLYGON, y nuestros clips de movimiento proceden de una amplia biblioteca abierta de animaciones. Como el rig y los clips comparten nombres de huesos, el caso habitual no necesita retargeting durante la ejecución: las pistas simplemente se vinculan por nombre. Explicamos el pipeline completo de personajes en <a href="/es/blog/2026-05-10-open-world-browser-part-25-universal-characters.html">personajes universales</a>.</p>
<p>El trabajo interesante aparece cuando no coinciden. Creamos una fase de retargeting que asigna un esqueleto a otro, y hacerla correctamente exigió resolver tres problemas concretos. Primero hay que alinear las poses de enlace, porque combinar una pose en A con una pose en T añade silenciosamente unos treinta grados por articulación. Hay que escalar el movimiento de la raíz y la zancada con dos proporciones distintas: de la cadera al suelo para el eje vertical y la proporción general para el horizontal. Y hay que probar los clips adaptados frente a sus originales con una frecuencia de muestreo fija, para que las regresiones aparezcan antes de que las vea un jugador. Ese pipeline es lo que nos permite añadir nuevas fuentes de animaciones y, con el tiempo, personajes aportados por los creadores, sin tener que corregir manualmente cada clip.</p>
<p>Por encima se encuentra una máquina de estados de animación que selecciona en cada fotograma la familia de clips adecuada a partir del estado de movimiento: la variante del salto según la velocidad, la intensidad del aterrizaje según el impacto, la dirección de la pendiente a partir del producto escalar entre la velocidad y el gradiente del terreno, las paradas ajustadas a la fase de los pies para evitar que el personaje parezca caminar sobre la luna al detenerse y un debounce de cien milisegundos para que un choque contra una pared no te haga alternar de forma intermitente entre caminar y caer. Nada de esto es exótico, pero es el tipo de resultado que solo consigues cuando controlas toda la capa.</p>
<h2 id="cuarta-decision-la-parte-que-ningun-motor-incluye" tabindex="-1">Cuarta decisión: la parte que ningún motor incluye <a class="header-anchor" href="#cuarta-decision-la-parte-que-ningun-motor-incluye" aria-label="Permalink to &quot;Cuarta decisión: la parte que ningún motor incluye&quot;"></a></h2>
<p>Las otras tres decisiones tratan sobre cómo funciona el mundo. Esta trata sobre qué es el producto, y por eso compararlo con PlayCanvas es, en última instancia, un error de categoría.</p>
<p>PlayCanvas, Babylon, Unity y una aplicación de Three.js hecha a medida parten de la misma premisa: creas el juego sentado ante un escritorio, en un editor 2D, observando el mundo desde fuera; después pulsas el botón de reproducción y publicas un entorno de ejecución independiente. Incluso cuando permiten editar dentro del motor, sigues estando frente a una estación de trabajo, manipulando una escena que observas desde fuera.</p>
<p>Cinevva World invierte ese modelo. Creas desde dentro del mundo, como un avatar que ocupa el mismo espacio en el que estarán tus jugadores, describiendo lo que quieres y viendo cómo aparece. Crear y jugar forman una única sesión continua, no un paso de compilación conectado a un entorno de ejecución. Los referentes más cercanos son Roblox, Rec Room y Horizon Worlds, no los motores 3D web, e incluso aquellos conservan la mayor parte del proceso creativo en un escritorio. Lo que hace viable este enfoque sin un editor controlado con ratón es el constructor con IA, que convierte «coloca aquí un muelle iluminado con faroles» en geometría y posicionamiento.</p>
<p>No puedes añadir eso sin más a un motor de propósito general, porque no es una función de renderizado. Es la premisa de toda la arquitectura, desde la forma de editar el terreno durante la ejecución hasta el modo en que la red trata cada objeto como algo que una persona cercana acaba de crear.</p>
<h2 id="cuando-no-deberias-hacer-lo-mismo-que-nosotros" tabindex="-1">Cuándo no deberías hacer lo mismo que nosotros <a class="header-anchor" href="#cuando-no-deberias-hacer-lo-mismo-que-nosotros" aria-label="Permalink to &quot;Cuándo no deberías hacer lo mismo que nosotros&quot;"></a></h2>
<p>Esta es la parte que el género «creamos nuestro propio motor» suele omitir. Si quieres publicar un juego de navegador este trimestre, no nos imites. Usa PlayCanvas si quieres un editor al estilo Unity y un pipeline gestionado. Usa Babylon si quieres un motor completo con física incluida y te sientes cómodo dentro de su estructura. Usa Three.js si quieres el máximo control y el mínimo de decisiones impuestas, y cuentas con un equipo capaz de construir todo lo necesario sobre la biblioteca. Haz un port desde Unity si ya tienes un juego creado con Unity.</p>
<p>Escribir tu propio renderizador y tus propios sistemas de física y animación solo es la decisión correcta cuando la premisa de tu producto es incompatible con las soluciones disponibles, cuando lo que estás construyendo no es un juego ejecutado sobre un motor, sino un lugar que está hecho de uno. En nuestro caso era así. Probablemente no lo sea en el tuyo, y no pasa nada. El objetivo de evaluar las opciones con sinceridad es saber en qué caso te encuentras antes de escribir la primera línea.</p>
]]></content:encoded>
            <enclosure url="https://cdn.cinevva.com/blog/why-webgpu-engine-hero.jpg" length="0" type="image/jpg"/>
        </item>
        <item>
            <title><![CDATA[Un mundo vacío es un mundo triste: lo que todas las plataformas para creadores que sobrevivieron o murieron pueden enseñarnos]]></title>
            <link>https://app.cinevva.com/es/blog/2026-06-06-how-creator-worlds-live-or-die</link>
            <guid>https://app.cinevva.com/es/blog/2026-06-06-how-creator-worlds-live-or-die</guid>
            <pubDate>Sat, 06 Jun 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Creamos una IA que construye edificios enteros en un mundo 3D compartido a partir de una frase. Antes de abrirla a todo el mundo, estudiamos los lanzamientos de todas las plataformas comparables que pudimos encontrar. El cementerio es enorme, las supervivientes son pocas y la línea que las separa es más clara de lo que jamás admite el discurso publicitario. Estas son las historias, las cifras y lo que estamos haciendo de otra manera.]]></description>
            <content:encoded><![CDATA[<h1 id="un-mundo-vacio-es-un-mundo-triste-lo-que-todas-las-plataformas-para-creadores-que-sobrevivieron-o-murieron-pueden-ensenarnos" tabindex="-1">Un mundo vacío es un mundo triste: lo que todas las plataformas para creadores que sobrevivieron o murieron pueden enseñarnos <a class="header-anchor" href="#un-mundo-vacio-es-un-mundo-triste-lo-que-todas-las-plataformas-para-creadores-que-sobrevivieron-o-murieron-pueden-ensenarnos" aria-label="Permalink to &quot;Un mundo vacío es un mundo triste: lo que todas las plataformas para creadores que sobrevivieron o murieron pueden enseñarnos&quot;"></a></h1>
<p><em>Por <a href="/es/about.html">Oleg Sidorkin</a>, CTO y cofundador de Cinevva</em></p>
<figure style="margin:1.5rem 0">
<img src="/img/blog/ai-builder-hero.webp" alt="El Constructor con IA de Cinevva construyendo una casa de dos plantas a partir de una instrucción en el chat" style="width:100%;border-radius:10px">
<figcaption style="color:#9aa7b4;font-size:0.85rem;margin-top:0.5rem">Nuestro Constructor con IA. Alguien escribió «construye una segunda planta» y la IA colocó el forjado, levantó las paredes y, a continuación, ofreció añadir escaleras y un tejado, todo dentro de un mundo al que otras personas pueden entrar.</figcaption>
</figure>
<p>Ahora podemos generar mundos, y no me refiero a una demo. La imagen de arriba muestra nuestro editor. Alguien escribió «construye una segunda planta» en un cuadro de chat y vio cómo la IA colocaba el forjado, levantaba las paredes frontal, laterales y trasera, y ofrecía continuar con unas escaleras y un tejado. No son objetos decorativos ni texturas, sino estructuras completas colocadas en un mundo al que otras personas pueden entrar. Nuestro sistema también crea los componentes: modelos 3D, música, sonido y materiales.</p>
<p>Así que estamos cerca de abrir Cinevva World al público. Y antes de hacerlo, me puse a leer las necrológicas.</p>
<p>Porque esta es la incómoda verdad sobre lo que estamos construyendo. Durante quince años, equipos muy inteligentes y con una financiación extraordinaria han intentado hacer funcionar mundos creativos compartidos. Unos pocos se convirtieron en algunas de las creaciones más grandes que la humanidad haya construido jamás. La mayoría están muertos. La diferencia entre ambos resultados no es el talento ni el dinero, porque algunos de los proyectos muertos tenían más de ambos de lo que nosotros tendremos nunca. La diferencia reside en un pequeño número de decisiones que casi nadie acierta a la primera. Esto es lo que descubrí.</p>
<h2 id="el-cementerio" tabindex="-1">El cementerio <a class="header-anchor" href="#el-cementerio" aria-label="Permalink to &quot;El cementerio&quot;"></a></h2>
<p>Empecemos por los fracasos, porque son más sinceros que las historias de éxito. Los ganadores reescriben su historia para convertirla en un relato impecable. Los perdedores filtran memorandos.</p>
<h3 id="meta-horizon-worlds-la-habitacion-vacia-mas-cara-jamas-construida" tabindex="-1">Meta Horizon Worlds: la habitación vacía más cara jamás construida <a class="header-anchor" href="#meta-horizon-worlds-la-habitacion-vacia-mas-cara-jamas-construida" aria-label="Permalink to &quot;Meta Horizon Worlds: la habitación vacía más cara jamás construida&quot;"></a></h3>
<p>Meta gastó decenas de miles de millones en su apuesta por el metaverso. Reality Labs registró una <a href="https://www.cnbc.com/2026/03/18/meta-horizon-worlds-metaverse-vr.html" target="_blank" rel="noreferrer">pérdida operativa de 6.020 millones de dólares en un solo trimestre</a>, anunciada a principios de 2026, y llevaba años perdiendo varios miles de millones por trimestre. Su producto estrella era Horizon Worlds. Esto es lo que compró todo ese dinero.</p>
<figure style="margin:1.5rem 0">
<div style="position:relative;padding-bottom:56.25%;height:0;overflow:hidden;border-radius:10px">
<iframe src="https://www.youtube-nocookie.com/embed/mNbz7-ejnZw" title="Horizon Worlds: tráiler oficial" loading="lazy" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen style="position:absolute;top:0;left:0;width:100%;height:100%"></iframe>
</div>
<figcaption style="color:#9aa7b4;font-size:0.85rem;margin-top:0.5rem">Horizon Worlds de Meta, tráiler oficial. La plataforma en la que Meta gastó miles de millones abandona la realidad virtual en junio de 2026 para sobrevivir como aplicación móvil.</figcaption>
</figure>
<p>Un memorando interno filtrado, del que informaron <a href="https://fortune.com/2022/10/07/metas-horizon-world-quality-poor-not-even-employees-using-says-metaverse-vp-leaked-memo/amp/" target="_blank" rel="noreferrer">Fortune</a> y <a href="https://ryanschultz.com/2022/10/07/leaked-internal-memos-from-meta-detail-problems-with-horizon-worlds-and-horizon-workrooms/" target="_blank" rel="noreferrer">Ryan Schultz</a>, reveló que solo alrededor del 9 por ciento de los mundos creados llegaron a recibir 50 visitas o más. La inmensa mayoría no recibió ninguna visita aparte de la de su propio creador. Uno de los memorandos resumió el problema de la interacción en una frase que todo fundador de este sector debería llevar tatuada: <a href="https://kotaku.com/meta-facebook-horizon-worlds-vr-mark-zuckerberg-1849669048" target="_blank" rel="noreferrer">«un mundo vacío es un mundo triste»</a>. Los investigadores que querían encuestar a usuarios activos solo pudieron encontrar a 514, porque la base de jugadores era así de pequeña.</p>
<p>Las cifras de retención eran aún peores. Los datos filtrados mostraban que <a href="https://mixed-news.com/en/horizon-worlds-leak-only-1-in-10-users-return-web-launch-coming/" target="_blank" rel="noreferrer">solo alrededor de 1 de cada 10 usuarios regresaba</a> después de su primer mes. Meta redujo discretamente su propio objetivo para 2022 de 500.000 usuarios mensuales a 200.000, y aun así la plataforma tenía menos usuarios simultáneos que VRChat y menos que Second Life, un juego de 2003. Los paneles internos de uso del producto mostraban que ni siquiera los propios empleados de Meta lo utilizaban, lo que llevó a la dirección a empezar a responsabilizar a los mánagers de que sus equipos iniciaran sesión cada semana. Un vicepresidente puso al equipo en un «confinamiento de calidad» durante el resto del año y admitió por escrito que estaban trabajando en un producto que no había encontrado su encaje en el mercado.</p>
<p>En marzo de 2026, Meta <a href="https://www.cnbc.com/2026/03/18/meta-horizon-worlds-metaverse-vr.html" target="_blank" rel="noreferrer">anunció que eliminaría por completo la compatibilidad con la realidad virtual</a> y convertiría Horizon Worlds en una aplicación casi exclusivamente móvil, un punto de entrada para quienes no tuvieran visor que funcionaría, según su propio planteamiento, como Roblox. El metaverso más caro jamás construido terminó su vida intentando convertirse en lo que debería haber sido desde el primer día.</p>
<p>La lección no es que «la realidad virtual llegó demasiado pronto», aunque así fue. La lección es que ninguna cantidad de capital llena un mundo vacío. La densidad de contenido no es algo que pueda comprarse con un presupuesto de marketing. Si los mundos están vacíos, la gente se marcha, y cuando la gente se marcha, los mundos siguen vacíos. Ese círculo vicioso devoró a Meta.</p>
<h3 id="decentraland-y-the-sandbox-las-ciudades-fantasma-de-mil-millones-de-dolares" tabindex="-1">Decentraland y The Sandbox: las ciudades fantasma de mil millones de dólares <a class="header-anchor" href="#decentraland-y-the-sandbox-las-ciudades-fantasma-de-mil-millones-de-dolares" aria-label="Permalink to &quot;Decentraland y The Sandbox: las ciudades fantasma de mil millones de dólares&quot;"></a></h3>
<p>En octubre de 2022, un único dato incendió el mundo de las criptomonedas. <a href="https://www.coindesk.com/web3/2022/10/07/its-lonely-in-the-metaverse-decentralands-38-daily-active-users-in-a-13b-ecosystem" target="_blank" rel="noreferrer">DappRadar informó</a> de que Decentraland tenía 38 usuarios activos diarios. The Sandbox tenía 522. Cada uno de estos proyectos contaba entonces con una capitalización de mercado de alrededor de 1.300 millones de dólares.</p>
<figure style="margin:1.5rem 0">
<div style="position:relative;padding-bottom:56.25%;height:0;overflow:hidden;border-radius:10px">
<iframe src="https://www.youtube-nocookie.com/embed/Zg5vcdEeLOA" title="Teaser oficial de The Sandbox" loading="lazy" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen style="position:absolute;top:0;left:0;width:100%;height:100%"></iframe>
</div>
<figcaption style="color:#9aa7b4;font-size:0.85rem;margin-top:0.5rem">The Sandbox, teaser oficial. Tanto este proyecto como Decentraland alcanzaron valoraciones cercanas a los 1.300 millones de dólares mientras sus usuarios diarios se contaban por cientos o unos pocos miles.</figcaption>
</figure>
<p>Los proyectos rebatieron esas cifras, y el matiz importa más que la burla. La cifra de 38 solo contabilizaba las carteras únicas que realizaban transacciones en la cadena de bloques durante un día —lo que DappRadar denomina «pagadores»—, no a las personas que iniciaban sesión y recorrían el mundo sin interactuar con la cadena de bloques. Decentraland respondió que tenía <a href="https://blockworks.com/news/metaverse-platforms-set-the-record-straight-about-daily-active-users" target="_blank" rel="noreferrer">56.697 usuarios mensuales con sesión iniciada</a> y, según otras estimaciones, unos 8.000 al día. The Sandbox afirmó tener 39.000 usuarios diarios durante una temporada alfa, con una retención del 40 por ciento en el día 14.</p>
<p>Pero detengámonos un momento en esa diferencia, porque es la cifra más importante de todo este ensayo. Incluso tomando las cifras más favorables, tenemos valoraciones de miles de millones de dólares sustentadas, en el mejor de los casos, por unos pocos miles de usuarios diarios. A modo de comparación, la investigación reveló que Roblox, sin cadena de bloques, tenía <a href="https://blockworks.com/news/metaverse-platforms-set-the-record-straight-about-daily-active-users" target="_blank" rel="noreferrer">52 millones de usuarios activos diarios, pero solo 11,3 millones de usuarios de pago mensuales</a> durante el mismo periodo. La mayoría de las personas que habitan mundos virtuales gratuitos realizan transacciones rara vez o nunca. Esto funciona en ambos sentidos. Significa que la burla sobre los 38 usuarios activos diarios era injusta y que la valoración de mil millones de dólares era una fantasía. Ambas cosas medían la cifra equivocada. La valoración medía la especulación con los tokens. La burla medía las transacciones de las carteras. Ninguna medía si alguien se estaba divirtiendo.</p>
<p>Esa es la trampa de las métricas de vanidad en su forma más pura. Cuentas registradas, capitalización de mercado del token, mercado total disponible, repercusión en prensa: ninguna de ellas indica si tu mundo está vivo. Las únicas cifras que sí lo hacen son cuántas personas regresan y si quienes crean cosas siguen creándolas.</p>
<h3 id="dreams-la-herramienta-mas-hermosa-en-la-que-nadie-podia-quedarse" tabindex="-1">Dreams: la herramienta más hermosa en la que nadie podía quedarse <a class="header-anchor" href="#dreams-la-herramienta-mas-hermosa-en-la-que-nadie-podia-quedarse" aria-label="Permalink to &quot;Dreams: la herramienta más hermosa en la que nadie podía quedarse&quot;"></a></h3>
<p>Media Molecule, el estudio responsable de LittleBigPlanet, dedicó casi una década a crear Dreams, una herramienta de creación tan completa que la gente hizo en ella juegos jugables, cortometrajes de animación y álbumes de música. La crítica la adoraba. Y en <a href="https://www.pushsquare.com/news/2023/07/dreams-live-service-ending-as-media-molecule-couldnt-find-a-sustainable-path" target="_blank" rel="noreferrer">septiembre de 2023, el estudio puso fin al servicio en vivo</a>, afirmando sin rodeos que no había podido encontrar un modelo de negocio sostenible.</p>
<figure style="margin:1.5rem 0">
<div style="position:relative;padding-bottom:56.25%;height:0;overflow:hidden;border-radius:10px">
<iframe src="https://www.youtube-nocookie.com/embed/2ltgkcoQzow" title="Dreams | Tráiler de la fecha de lanzamiento | PS4" loading="lazy" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen style="position:absolute;top:0;left:0;width:100%;height:100%"></iframe>
</div>
<figcaption style="color:#9aa7b4;font-size:0.85rem;margin-top:0.5rem">Dreams, de Media Molecule. Una herramienta de creación que la gente adoraba, cuyo servicio en vivo terminó en 2023 sin que los creadores tuvieran forma alguna de ganar un céntimo.</figcaption>
</figure>
<p>El análisis posterior es una lista de errores autoinfligidos, y lo digo con enorme respeto, porque nosotros podríamos cometer cada uno de ellos. Dreams <a href="https://www.pushsquare.com/news/2023/07/dreams-live-service-ending-as-media-molecule-couldnt-find-a-sustainable-path" target="_blank" rel="noreferrer">nunca permitió a los creadores monetizar su trabajo</a>. La tienda interna prometida nunca llegó a publicarse. No había artículos cosméticos, ni pase de batalla, ni nada. Los creadores serios, los que convierten una herramienta en una plataforma, no tenían motivos para invertir años cuando no había ninguna recompensa posible. Se lanzó solo para PS4, sin versión para PC ni versión nativa para PS5 en el lanzamiento, lo que limitó drásticamente su audiencia potencial. Y el cofundador <a href="https://icon-era.com/threads/media-molecule-co-founders-biggest-regret-with-dreams-was-not-focusing-on-multiplayer-understands-new-ip-is-more-of-a-game-than-a-creative-tool.11724/" target="_blank" rel="noreferrer">Mark Healey dijo más tarde que lo que más lamentaba era no haberse centrado en el multijugador</a>, y que el equipo llegó a comprender que su creación funcionaba mejor como juego que como herramienta creativa.</p>
<p>Lee de nuevo esa última parte. El estudio de contenido generado por usuarios con más talento del mundo concluyó, a posteriori, que aquello debería haber sido primero un juego y después una herramienta. Esa es la frase más importante de todo este estudio, y volveremos a ella.</p>
<h3 id="el-resto-del-cementerio" tabindex="-1">El resto del cementerio <a class="header-anchor" href="#el-resto-del-cementerio" aria-label="Permalink to &quot;El resto del cementerio&quot;"></a></h3>
<p>El patrón se repite con una consistencia desoladora.</p>
<p><a href="https://www.gamedeveloper.com/business/crayta-to-shut-down-after-launch-platform-stadia-bites-the-dust" target="_blank" rel="noreferrer">Crayta</a>, una plataforma colaborativa para crear contenido generado por usuarios, cerró en marzo de 2023 y los usuarios perdieron todo lo que habían creado. Meta adquirió a su desarrollador en 2021 y, aun así, la plataforma acabó cerrando. La causa inmediata: se lanzó en Google Stadia y, cuando Stadia murió, Crayta murió con ella. Depender de una plataforma es como apuntarte a la cabeza con un arma cargada.</p>
<figure style="margin:1.5rem 0">
<img src="https://cdn.cinevva.com/blog/lived-or-died-crayta.webp" alt="Crayta, la plataforma colaborativa de creación de juegos" loading="lazy" style="width:100%;border-radius:10px">
<figcaption style="color:#9aa7b4;font-size:0.85rem;margin-top:0.5rem">Crayta se lanzó en Google Stadia. Cuando Stadia cerró en 2023, Crayta desapareció con ella y los creadores perdieron todo lo que habían hecho. Fotograma del tráiler.</figcaption>
</figure>
<p>Project Spark, el creador de juegos con contenido generado por usuarios de Microsoft, cerró años antes siguiendo la misma trayectoria: una herramienta potente, pero sin suficientes personas que se quedaran. Sansar, el sucesor en realidad virtual de Second Life creado por Linden Lab, fue vendido tras no conseguir atraer a una audiencia. High Fidelity, la segunda empresa de metaversos de Philip Rosedale, el propio fundador de Second Life, abandonó por completo los mundos virtuales para dedicarse a otra cosa.</p>
<figure style="margin:1.5rem 0">
<img src="https://cdn.cinevva.com/blog/lived-or-died-secondlife.webp" alt="Second Life, el mundo virtual creado por usuarios de Linden Lab" loading="lazy" style="width:100%;border-radius:10px">
<figcaption style="color:#9aa7b4;font-size:0.85rem;margin-top:0.5rem">Second Life, el mundo de Linden Lab lanzado en 2003, sigue en funcionamiento después de más de dos décadas. Sus propios sucesores en realidad virtual, Sansar y High Fidelity de Philip Rosedale, fracasaron. Fotograma del tráiler.</figcaption>
</figure>
<p>Y hay una señal que no puedes ignorar porque está ocurriendo ahora mismo: Rec Room <a href="https://www.uploadvr.com/vrchat-statement-after-rec-room-and-horizon-worlds-fold/" target="_blank" rel="noreferrer">anunció que cerrará con efecto a partir del 1 de junio de 2026</a>, afirmando que nunca logró una rentabilidad sostenida.</p>
<p>Los fundadores de empresas de metaversos, dedicados a construir metaversos, no podían permanecer en sus propios metaversos. Eso debería aterrorizar a cualquiera que crea que la parte difícil es el renderizado.</p>
<figure style="margin:1.5rem 0">
<img src="https://cdn.cinevva.com/blog/lived-or-died-recroom.webp" alt="Rec Room, el mundo social multiplataforma de contenido generado por usuarios" loading="lazy" style="width:100%;border-radius:10px">
<figcaption style="color:#9aa7b4;font-size:0.85rem;margin-top:0.5rem">Rec Room, uno de los mayores mundos sociales de creación, superó los 150 millones de jugadores acumulados y aun así cerró el 1 de junio de 2026, sin haber conseguido convertir ese alcance en un negocio sostenible. Fotograma del tráiler.</figcaption>
</figure>
<h2 id="los-supervivientes-y-lo-que-realmente-los-salvo" tabindex="-1">Los supervivientes y lo que realmente los salvó <a class="header-anchor" href="#los-supervivientes-y-lo-que-realmente-los-salvo" aria-label="Permalink to &quot;Los supervivientes y lo que realmente los salvó&quot;"></a></h2>
<p>Ahora, los que siguen vivos. Lo instructivo es que ninguno triunfó como cabría esperar, y varios lo hicieron pese a romper las reglas que siguieron los fracasados.</p>
<h3 id="roblox-el-exito-de-la-noche-a-la-manana-que-tardo-doce-anos" tabindex="-1">Roblox: el éxito de la noche a la mañana que tardó doce años <a class="header-anchor" href="#roblox-el-exito-de-la-noche-a-la-manana-que-tardo-doce-anos" aria-label="Permalink to &quot;Roblox: el éxito de la noche a la mañana que tardó doce años&quot;"></a></h3>
<p>Todo el mundo cita Roblox como modelo. Casi nadie copia lo que ocurrió de verdad, porque lo que ocurrió de verdad fueron doce años pareciendo un fracaso.</p>
<figure style="margin:1.5rem 0">
<div style="position:relative;padding-bottom:56.25%;height:0;overflow:hidden;border-radius:10px">
<iframe src="https://www.youtube-nocookie.com/embed/LTnMKjXEnMY" title="ROBLOX - Tráiler del juego" loading="lazy" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen style="position:absolute;top:0;left:0;width:100%;height:100%"></iframe>
</div>
<figcaption style="color:#9aa7b4;font-size:0.85rem;margin-top:0.5rem">Roblox. Atrajo a unas 100 personas en 2006 y tardó doce años en alcanzar un crecimiento exponencial, todo gracias a permitir que la comunidad creara los juegos.</figcaption>
</figure>
<p>La beta de Roblox de 2006 atrajo a <a href="https://www.howtheygrow.co/p/how-roblox-grows" target="_blank" rel="noreferrer">unos 100 entusiastas de la tecnología, con un pico de entre 30 y 40 usuarios simultáneos</a>. Después avanzó trabajosamente durante más de una década. Pasó de 9 millones de usuarios a principios de 2016 a 90 millones en 2019 y 214 millones en 2023. Su fundador, David Baszucki, se negó a abandonar la visión del contenido generado por usuarios incluso cuando Minecraft lo adelantó de forma espectacular en 2009. Lo consideraba una apuesta deliberada a fuego lento, y la decisión que marcó la diferencia fue permitir que la comunidad creara todos los juegos en lugar de desarrollarlos internamente. Eso eliminó el coste del contenido y convirtió a cada creador en un motor de crecimiento.</p>
<p>Pero aquí está la parte que se les escapa a quienes lo imitan superficialmente, y por eso mantengo abierta una segunda fuente. El <a href="https://www.matthewball.co/all/roblox2024" target="_blank" rel="noreferrer">análisis de 2024</a> de Matthew Ball muestra que Roblox opera con pérdidas brutales incluso a gran escala: un margen operativo aproximado del 38 % negativo, con solo un 6 % de los usuarios comprando su moneda en un mes determinado y unos ingresos por usuario muy inferiores a los de las plataformas de consola. Roblox es el juego más grande del mundo y aun así le cuesta ganar dinero. El círculo virtuoso es real y la economía es difícil. Quien te diga que una plataforma para creadores es una máquina de imprimir dinero intenta venderte algo.</p>
<p>Sin embargo, la lección más profunda está a plena vista en esas cifras de usuarios. La inmensa mayoría de los cientos de millones de usuarios de Roblox nunca crea nada. Entran para <em>jugar</em> a un catálogo de decenas de millones de juegos creados por otras personas. Ese catálogo tardó una década en crecer y necesitó una economía de pagos a desarrolladores. Roblox no es una herramienta de creación a la que la gente juega por casualidad. Es un lugar donde jugar en el que una pequeña fracción de los usuarios también crea. Ese orden lo es todo.</p>
<h3 id="minecraft-el-mundo-que-no-podia-estar-vacio" tabindex="-1">Minecraft: el mundo que no podía estar vacío <a class="header-anchor" href="#minecraft-el-mundo-que-no-podia-estar-vacio" aria-label="Permalink to &quot;Minecraft: el mundo que no podía estar vacío&quot;"></a></h3>
<p>Minecraft nunca tuvo el problema del mundo vacío, y entender por qué es la clave de todo.</p>
<figure style="margin:1.5rem 0">
<div style="position:relative;padding-bottom:56.25%;height:0;overflow:hidden;border-radius:10px">
<iframe src="https://www.youtube-nocookie.com/embed/MmB9b5njVbA" title="Tráiler oficial de Minecraft" loading="lazy" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen style="position:absolute;top:0;left:0;width:100%;height:100%"></iframe>
</div>
<figcaption style="color:#9aa7b4;font-size:0.85rem;margin-top:0.5rem">Minecraft, tráiler oficial. La supervivencia procedimental hacía que el mundo nunca estuviera vacío y que no necesitara contenido de usuarios para merecer la pena.</figcaption>
</figure>
<p>Minecraft se lanzó como un juego de supervivencia con generación procedimental. El mundo se construye solo, de forma infinita, y desde el primer minuto no estás mirando un lienzo en blanco sin saber qué hacer. Está anocheciendo y algo va a matarte, así que cavas. El juego es divertido para una sola persona, sin otros usuarios ni contenido generado por usuarios, para siempre, porque el generador procedimental es una máquina inagotable de contenido. Los mods, los servidores, los mapas personalizados, todo el ecosistema creativo: todo eso creció <em>sobre</em> un juego que ya se vendía por sí solo. El modo creativo llegó cuando millones de personas ya estaban enganchadas a la supervivencia. El boca a boca y YouTube hicieron el resto.</p>
<p>Minecraft resolvió el arranque en frío evitando tenerlo. Ese es el truco, y vamos a apropiárnoslo.</p>
<h3 id="juegos-de-navegador-la-distribucion-como-unica-ventaja-competitiva" tabindex="-1">Juegos de navegador: la distribución como única ventaja competitiva <a class="header-anchor" href="#juegos-de-navegador-la-distribucion-como-unica-ventaja-competitiva" aria-label="Permalink to &quot;Juegos de navegador: la distribución como única ventaja competitiva&quot;"></a></h3>
<p>Luego está el género más cercano a nuestro mecanismo real de distribución: el juego de navegador sin descargas.</p>
<figure style="margin:1.5rem 0">
<div style="position:relative;padding-bottom:56.25%;height:0;overflow:hidden;border-radius:10px">
<iframe src="https://www.youtube-nocookie.com/embed/oznO3GGzu2s" title="Tráiler de Krunker.io" loading="lazy" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen style="position:absolute;top:0;left:0;width:100%;height:100%"></iframe>
</div>
<figcaption style="color:#9aa7b4;font-size:0.85rem;margin-top:0.5rem">Krunker, un FPS de navegador en la tradición de los .io. Toda la ventaja competitiva del género es la distribución: un enlace que carga un juego completo sin descargas.</figcaption>
</figure>
<p><a href="https://news.viverse.com/post/what-are-io-games" target="_blank" rel="noreferrer">Agar.io alcanzó aproximadamente 5 millones de jugadores diarios en cuestión de semanas</a> tras su lanzamiento en 2015. Slither.io acumuló 68 millones de descargas móviles y 67 millones de partidas en el navegador. La investigación es tajante sobre el motivo: <a href="https://news.viverse.com/post/what-are-io-games" target="_blank" rel="noreferrer">«la ventaja competitiva del género .io es la propia distribución, no la mecánica de juego»</a>. Haces clic en un enlace y ya estás jugando. Sin instalación, sin cuenta, sin tienda de aplicaciones. <a href="https://medium.com/the-megacool-blog/9-growth-hacks-from-viral-hit-game-agar-io-7d8f71f70a0c" target="_blank" rel="noreferrer">La incorporación de Agar.io requería un solo clic</a>: escribe un nombre, pulsa jugar y ya estás dentro. Se propagó por las aplicaciones de chat como se propagan los vídeos en TikTok.</p>
<p>Pero este regalo esconde un filo que también nos afecta. Sin descarga no hay compromiso. La misma ausencia de fricción que facilita la entrada también facilita la salida, porque cerrar una pestaña no cuesta nada. La viralidad en el navegador es real, pero también es superficial por defecto. Los juegos .io sobrevivieron gracias a que eran divertidos de forma inmediata y evidente durante los primeros diez segundos. Los mundos de navegador que murieron eran fáciles de abrir, pero no te daban ningún motivo para quedarte una vez dentro.</p>
<h3 id="among-us-figma-townscaper-vrchat-cuatro-formas-mas-de-triunfar" tabindex="-1">Among Us, Figma, Townscaper, VRChat: cuatro formas más de triunfar <a class="header-anchor" href="#among-us-figma-townscaper-vrchat-cuatro-formas-mas-de-triunfar" aria-label="Permalink to &quot;Among Us, Figma, Townscaper, VRChat: cuatro formas más de triunfar&quot;"></a></h3>
<p>Cuatro ejemplos rápidos, porque cada uno aísla una palanca distinta.</p>
<p><a href="https://www.esports.net/news/how-among-us-blew-up-online-two-years-after-release/" target="_blank" rel="noreferrer">Among Us</a> salió en 2018 y durante dos años no tuvo ningún éxito comercial. Sus desarrolladores estuvieron a punto de abandonarlo. Entonces, en septiembre de 2020, lo descubrió una <a href="https://howtomarketagame.com/2020/09/14/among-us-the-4-lessons-of-their-viral-success/" target="_blank" rel="noreferrer">cadena de streamers cada vez más grandes</a>, que culminó en una retransmisión de varias horas de Sodapoppin, y se convirtió en un fenómeno mundial. El impulso inicial llegó de una aparición en la portada de itch.io y de un público coreano que llegó a representar la mitad de sus ventas. Lección: el gran salto puede llegar años después del lanzamiento, desde un canal que no habías previsto, si sobrevives el tiempo suficiente para que te descubran.</p>
<figure style="margin:1.5rem 0">
<div style="position:relative;padding-bottom:56.25%;height:0;overflow:hidden;border-radius:10px">
<iframe src="https://www.youtube-nocookie.com/embed/NSJ4cESNQfE" title="Tráiler del lanzamiento de Among Us en Steam" loading="lazy" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen style="position:absolute;top:0;left:0;width:100%;height:100%"></iframe>
</div>
<figcaption style="color:#9aa7b4;font-size:0.85rem;margin-top:0.5rem">Among Us. Pasó dos años casi inadvertido antes de que una cadena de streamers lo convirtiera en un fenómeno mundial en 2020.</figcaption>
</figure>
<p><a href="https://review.firstround.com/the-5-phases-of-figmas-community-led-growth-from-stealth-to-enterprise/" target="_blank" rel="noreferrer">Figma</a> permaneció en modo secreto durante unos tres años, se lanzó gratis y esperó otros dos años antes de empezar a cobrar. Su momento de activación era el modo multijugador: el instante en que un diseñador veía a otra persona editando el mismo archivo. Y esta es la parte importante. Al principio, el plan gratuito de Figma te limitaba a 2 colaboradores, lo que estrangulaba precisamente el momento mágico que vendía el producto, y lo solucionaron permitiendo colaboradores ilimitados para que la gente pudiera experimentar aquello de verdad. Sembraron la comunidad contactando directamente con referentes del diseño en Twitter. Lección: encuentra tu momento revelador y elimina todos los obstáculos entre un usuario nuevo y ese momento.</p>
<figure style="margin:1.5rem 0">
<div style="position:relative;padding-bottom:56.25%;height:0;overflow:hidden;border-radius:10px">
<iframe src="https://www.youtube-nocookie.com/embed/n5gJgkO2Dg0" title="Presentación del lanzamiento de Figma" loading="lazy" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen style="position:absolute;top:0;left:0;width:100%;height:100%"></iframe>
</div>
<figcaption style="color:#9aa7b4;font-size:0.85rem;margin-top:0.5rem">Figma. Su momento de activación era el modo multijugador, así que eliminó el límite de colaboradores del plan gratuito que bloqueaba la misma magia que vendía el producto.</figcaption>
</figure>
<p><a href="https://www.gamedeveloper.com/game-platforms/how-townscaper-works-a-story-four-games-in-the-making" target="_blank" rel="noreferrer">Townscaper</a> era un pequeño juguete creativo que se convirtió en un éxito gracias a sus capturas de pantalla. Su desarrollador vio cómo sus seguidores en Twitter pasaban de unos 20 000 a 90 000 con solo publicar clips durante el desarrollo, y lo interpretó como una señal temprana de que tendría éxito. Lección: si tu creación es hermosa y la gente la comparte por iniciativa propia antes incluso de que la hayas lanzado, esa es la validación más auténtica que existe.</p>
<figure style="margin:1.5rem 0">
<div style="position:relative;padding-bottom:56.25%;height:0;overflow:hidden;border-radius:10px">
<iframe src="https://www.youtube-nocookie.com/embed/hqq25n6cQqo" title="Tráiler de lanzamiento de Townscaper" loading="lazy" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen style="position:absolute;top:0;left:0;width:100%;height:100%"></iframe>
</div>
<figcaption style="color:#9aa7b4;font-size:0.85rem;margin-top:0.5rem">Townscaper, tráiler de lanzamiento. Un juguete creativo sin objetivos que se propagó gracias a las capturas de pantalla que la gente compartía por iniciativa propia.</figcaption>
</figure>
<p>Y <a href="https://www.uploadvr.com/vrchat-statement-after-rec-room-and-horizon-worlds-fold/" target="_blank" rel="noreferrer">VRChat</a>, durante los mismos meses en que se vinieron abajo tanto los miles de millones de Meta como Rec Room, alcanzó un récord de casi 160 000 usuarios simultáneos. Está impulsado por la comunidad y por los creadores, y ni de lejos cuenta con tanta financiación como los proyectos que murieron a su alrededor. VRChat atribuye su supervivencia a la lealtad y la creatividad de la comunidad por encima del capital. Lección, en palabras del propio superviviente: la pasión de unos creadores comprometidos dura más que el dinero.</p>
<h2 id="lo-que-realmente-separa-a-los-vivos-de-los-muertos" tabindex="-1">Lo que realmente separa a los vivos de los muertos <a class="header-anchor" href="#lo-que-realmente-separa-a-los-vivos-de-los-muertos" aria-label="Permalink to &quot;Lo que realmente separa a los vivos de los muertos&quot;"></a></h2>
<p>Pon las historias una al lado de otra y el patrón resulta evidente.</p>
<table tabindex="0">
<thead>
<tr>
<th>Plataforma</th>
<th>Por qué apostó</th>
<th>Cómo acabó</th>
<th>La lección</th>
</tr>
</thead>
<tbody>
<tr>
<td>Minecraft</td>
<td>Supervivencia procedimental, divertida para un jugador</td>
<td>El juego más vendido de la historia, más de 350 millones de copias</td>
<td>Nunca tengas un mundo vacío</td>
</tr>
<tr>
<td>Roblox</td>
<td>Juegos creados por la comunidad más pagos a creadores</td>
<td>Más de 80 millones de usuarios diarios tras doce años</td>
<td>Sé primero un lugar donde jugar y después una herramienta</td>
</tr>
<tr>
<td>Juegos .io</td>
<td>Juego de navegador con un clic y sin descargas</td>
<td>Millones de jugadores en cuestión de semanas</td>
<td>La distribución es la ventaja competitiva; el compromiso es superficial</td>
</tr>
<tr>
<td>Figma</td>
<td>Plan gratuito, multijugador en tiempo real</td>
<td>Una oferta de adquisición de unos 20 000 millones de dólares</td>
<td>Elimina todas las barreras al momento revelador</td>
</tr>
<tr>
<td>Among Us</td>
<td>Un juego social barato y paciencia</td>
<td>3,8 millones de usuarios simultáneos, con dos años de retraso</td>
<td>Sobrevive el tiempo suficiente para que te encuentren</td>
</tr>
<tr>
<td>Townscaper</td>
<td>Un juguete hermoso que merecía una captura de pantalla</td>
<td>Unas 380 000 ventas, difusión orgánica</td>
<td>Que te compartan por iniciativa propia es la señal más auténtica</td>
</tr>
<tr>
<td>VRChat</td>
<td>La energía de la comunidad y los creadores</td>
<td>Unos 160 000 usuarios simultáneos en 2026</td>
<td>La pasión dura más que el capital</td>
</tr>
<tr>
<td>Horizon Worlds</td>
<td>Miles de millones en capital, prioridad a la RV</td>
<td>La RV cerró en 2026; volvió aproximadamente 1 de cada 10 usuarios</td>
<td>El dinero no puede llenar un mundo vacío</td>
</tr>
<tr>
<td>Decentraland / Sandbox</td>
<td>Una economía de tókenes antes que un juego</td>
<td>Valoraciones de unos 1 300 millones de dólares, cientos de usuarios diarios</td>
<td>Una valoración no es un público</td>
</tr>
<tr>
<td>Dreams</td>
<td>Una herramienta profunda, sin economía ni multijugador</td>
<td>El servicio activo terminó en 2023</td>
<td>Paga a los creadores, lanza el multijugador y sé un juego</td>
</tr>
<tr>
<td>Crayta</td>
<td>Una plataforma de contenido generado por usuarios alojada en Stadia</td>
<td>Cerró con Stadia en 2023</td>
<td>Nunca construyas sobre una plataforma que pueda echarte</td>
</tr>
<tr>
<td>Project Spark / Sansar</td>
<td>Herramientas potentes, ningún motivo para volver</td>
<td>Cerraron o cambiaron de rumbo</td>
<td>Una herramienta sin juego no crea un hábito diario</td>
</tr>
</tbody>
</table>
<p>Lo que mata a los mundos creativos es la sala vacía. Horizon Worlds, Decentraland, Dreams, Crayta, Project Spark y Sansar murieron todos de la misma forma: no había suficiente gente, ni suficiente contenido, ni motivos suficientes para volver, dentro de un bucle que se retroalimenta. El problema del arranque en frío es el jefe final. Todo lo demás es un nivel de tutorial.</p>
<p>Lo que los salva es tener un motivo para existir antes de que llegue la multitud. Minecraft tenía la supervivencia procedimental. Roblox tenía una década de juegos cultivados con paciencia. Los juegos .io ofrecían diversión en diez segundos. Cada superviviente merecía tu tiempo incluso con un catálogo vacío. Cada víctima era un contenedor precioso que esperaba a que otras personas hicieran que mereciera la pena visitarlo. Esta es la confesión de Dreams convertida en principio general: crea primero un juego y después una plataforma. La plataforma es el segundo acto. Te la ganas siendo primero algo que la gente usa por su propio valor.
Las métricas que realmente predicen la supervivencia no son las que aparecen en el comunicado de prensa. La investigación es consistente al respecto. La señal definitiva del encaje entre producto y mercado es que tu <a href="https://newsletter.pmcurve.com/p/retention-masterclass" target="_blank" rel="noreferrer">curva de retención se estabiliza</a>: alguna cohorte de personas sigue regresando indefinidamente. Una curva que cae hasta cero significa que no hay encaje, por muy grande que sea la parte superior del embudo. Como referencias aproximadas del sector, se habla de una retención del <a href="https://solsten.io/blog/d1-d7-d30-retention-in-gaming" target="_blank" rel="noreferrer">40 por ciento el día 1, el 20 por ciento el día 7 y el 10 por ciento el día 30</a>, y el día 30 es el que predice la salud a largo plazo. Y en cualquier producto con una vertiente para creadores, es en el lado de la oferta donde mueres: <a href="https://forkoff.xyz/blog/founder-growth/two-sided-marketplace-cold-start-2026" target="_blank" rel="noreferrer">alrededor del 67 por ciento de los marketplaces fallidos se hunden por la oferta</a>, no por la demanda. La retención de creadores es la constante vital. Las cuentas registradas y las valoraciones son vanidad.</p>
<p>Hay algunas conclusiones más que se desprenden de estas historias. Monetiza a tus creadores o los perderás, porque Dreams demostró que la gente con talento no invertirá años sin nada que ganar. El multijugador suele ser el objetivo, no una funcionalidad, según el propio arrepentimiento de Media Molecule. Nunca construyas tu casa sobre una plataforma que pueda desahuciarte, como enseñó Crayta. Y no requerir descargas es un arma de doble filo: es el mejor canal de adquisición que existe y el mecanismo de compromiso más débil, así que toda la responsabilidad recae en que los primeros sesenta segundos sean buenos.</p>
<h2 id="la-trampa-que-subyace-a-todo-esto" tabindex="-1">La trampa que subyace a todo esto <a class="header-anchor" href="#la-trampa-que-subyace-a-todo-esto" aria-label="Permalink to &quot;La trampa que subyace a todo esto&quot;"></a></h2>
<p>Hay una capa más, específica de nuestro momento, porque tenemos una herramienta que los desaparecidos nunca tuvieron. Podemos generar mundos con IA. Y eso plantea una paradoja sobre la que llevo semanas cambiando de opinión.</p>
<p>Si es IA, ¿no debería ser cada mundo único, generado de cero para cada persona y adaptado a ella? Pero si el mundo de cada persona es único, ¿cómo va a encontrarse alguien con los demás, si un momento compartido requiere un lugar compartido? Y si, de todos modos, el mundo tiene que ser compartido, ¿para qué usar IA en vez de crear artesanalmente un lugar precioso como lo haría un estudio de verdad?</p>
<p>Cada uno de esos impulsos, llevado hasta sus últimas consecuencias, desemboca en algo que no funciona. Un mundo generado solo para ti es un mundo sin nadie dentro. Genie de Google puede crear un entorno jugable a partir de una frase, pero desaparece un minuto después: un solo jugador, sin memoria, sin vecinos. Ese es el callejón sin salida de la soledad. Pero crear artesanalmente un único mundo fijo también es un callejón sin salida: llenar a mano dos kilómetros cuadrados requiere cien personas y varios años y, cuando terminas, queda congelado, idéntico en tu centésima visita que en la primera e incapaz de crecer a medida que llega la gente.</p>
<p>La salida consiste en dejar de tratar «el mundo» como si fuera una sola cosa. Tiene tres capas, y lo único y lo compartido pueden habitar en capas distintas sin entrar en conflicto. El terreno sobre el que todos se encuentran es un único mundo compartido, seleccionado con un alto nivel de exigencia: el lugar de encuentro. Lo que llevas hasta él —tus recursos generados con IA, el edificio que creaste— es totalmente único, y lo depositas <em>dentro</em> del mundo compartido para que tu singularidad se convierta en el descubrimiento de los demás. Y tu recorrido por él —las misiones que recibes, aquello hacia lo que te orienta— se personaliza sin coste, porque una ruta no es un lugar. La falsa elección era entre «un mundo personalizado», que acaba con el multijugador, y «una ruta personalizada a través de un mundo compartido», que lo enriquece. Queremos lo segundo.</p>
<p>Así que el trabajo de la IA nunca fue entregar a cada persona un mundo privado. Su trabajo consiste en hacer que un único mundo compartido parezca infinito, vivo y personal al recorrerlo. Su singularidad nace de todo lo que se acumula en él con el tiempo, de la contribución irrepetible de cada creador. Cada servidor de Minecraft es único. Todos los usuarios de un servidor determinado lo comparten. Eso no es una contradicción. Ese es todo el truco, y la captura de pantalla que aparece al principio de esta publicación —la IA construyendo una casa que permanece en un mundo al que otras personas pueden entrar— es la materialización de ese truco.</p>
<h2 id="como-vamos-a-lanzar-cinevva-world" tabindex="-1">Cómo vamos a lanzar Cinevva World <a class="header-anchor" href="#como-vamos-a-lanzar-cinevva-world" aria-label="Permalink to &quot;Cómo vamos a lanzar Cinevva World&quot;"></a></h2>
<p>Así es como todo esto se traduce para nosotros. No es un plan de marketing. Son cinco apuestas, planteadas deliberadamente contra las cinco cosas que acabaron con todos los proyectos de la primera mitad de este artículo. Y evaluaré cada una según el respaldo real de las pruebas, porque un plan que no puedes evaluar no es más que un deseo con buena iluminación.</p>
<p><strong>Primera apuesta, aquella por la que me jugaría la empresa: lanzamos un juego, no una plataforma.</strong> Esto no es una preferencia, sino la conclusión más consistente de todo el estudio. Minecraft, Roblox y Fortnite empezaron ofreciendo algo divertido que <em>hacer</em> y desarrollaron encima la capa de creación. Media Molecule, el estudio de creación con más talento que existe, concluyó a posteriori que Dreams debería haber sido primero un juego. Por tanto, lo primero que hará una persona nueva en Cinevva World no será contemplar una parcela vacía. Será participar en un ciclo de juego con un objetivo, una razón para estar allí un martes cuando casi no haya nadie más conectado. La mayoría de quienes lleguen jugarán y nunca construirán, y eso forma parte del diseño, no es un fracaso. Es la forma real de Roblox: cientos de millones de personas que juegan, asentadas sobre una fina capa de personas que crean. El volante de crecimiento es el segundo acto, y tenemos que ganárnoslo. Estoy seguro de esta apuesta porque el cementerio ya realizó el experimento.</p>
<p><strong>Segunda apuesta, la que sinceramente sí es una jugada arriesgada: la IA nos permite producir la oferta que todos los demás murieron esperando.</strong> Quiero ser preciso sobre por qué esto es una apuesta y no una garantía, porque ninguna plataforma de este estudio arrancó jamás con IA generativa. Tengo un mecanismo, no una prueba. El mecanismo es este: aproximadamente dos tercios de las plataformas de dos caras mueren por el lado de la oferta, no por el de la demanda. La solución clásica consiste en simular la oferta hasta que sea real, como cuando DoorDash entregaba la comida por su cuenta, el equipo de Reddit publicaba con identidades falsas y los fundadores de Roblox crearon a mano los primeros juegos durante años. Nosotros podemos hacerlo mediante generación, con un coste y una velocidad que ninguno de ellos tuvo. Pero esta es la parte que me mantiene con los pies en la tierra, y es la lápida de Decentraland: Decentraland estaba lleno de contenido generado y atraía a unas treinta personas al día, porque bonito no significa que merezca tu tiempo. Así que no apuesto a que la IA haga divertido el mundo. No puede. Apuesto a que la IA elimine el cuello de botella de los recursos para que cada hora de nuestro escaso esfuerzo humano se dedique a lo único que realmente retiene a las personas: el ciclo de juego. La IA construye la colina a bajo coste. Nosotros construimos a mano la razón para subirla. Y limitaremos la oferta sintética inicial a <a href="https://forkoff.xyz/blog/founder-growth/two-sided-marketplace-cold-start-2026" target="_blank" rel="noreferrer">aproximadamente un 30 por ciento, convirtiéndola en contenido de creadores reales en unos 60 días</a>, porque una oferta falsa que nunca se vuelve real destruye la confianza en cuanto alguien se da cuenta.</p>
<p><strong>Tercera apuesta: publicamos nuestros propios criterios de cancelación.</strong> Esta es la diferencia entre un plan con los pies en la tierra y uno basado en la esperanza. La métrica que predijo la supervivencia en todos y cada uno de los casos fue si la <a href="https://newsletter.pmcurve.com/p/retention-masterclass" target="_blank" rel="noreferrer">curva de retención se estabiliza</a>, si alguna cohorte sigue regresando en lugar de decaer hasta cero. Así que esa es la prueba a la que nos someteremos, públicamente. Si la retención del día 7 de la alfa no se estabiliza, si los jugadores que nunca construyen no regresan, si la gente pasa de largo ante el contenido inicial generado por IA y lo ignora, la tesis es errónea, y la cambiaremos o nos detendremos. Seguiremos a jugadores y creadores como dos embudos separados, con dos momentos de revelación distintos, porque los datos dejan claro que no son la misma persona. Y no fingiremos que el dinero hace el trabajo inicial. Con cincuenta usuarios, o incluso con mil, las propinas y los ingresos del marketplace se redondean a cero, así que todavía no retienen a nadie. La retención inicial procede del ciclo de juego o no se produce en absoluto. Dreams es la prueba de lo que ocurre al plantearlo al revés.</p>
<p><strong>Cuarta apuesta: empezamos deliberadamente con un enfoque limitado.</strong> La investigación sobre productos conectados es unánime. No lanzas para un mercado, sino para una <a href="https://www.lennysnewsletter.com/p/atomic-network" target="_blank" rel="noreferrer">«red atómica»</a>, el grupo más pequeño con densidad suficiente para tener vida propia. Facebook comenzó en una sola universidad. La nuestra ya existe: los creadores de Cinevva que han generado recursos 3D, música y sonido, y que ya tienen un inventario que colocar. Cincuenta de ellos en un mismo mundo, a la misma hora, con un objetivo y una frontera, crean algo más denso y vivo de lo que jamás serán cincuenta mil registros dispersos. Las pruebas respaldan firmemente esta apuesta.</p>
<p><strong>Quinta apuesta, la menos sólida, y lo admito: decimos la verdad sobre el vacío en lugar de ocultarlo.</strong> Un mundo pulido y silencioso parece muerto, y todos los proyectos fallidos intentaron disimularlo con efectos ambientales. Nosotros probaremos lo contrario. Esta es la decisión menos demostrada de las cinco, más cercana a una corazonada que a una conclusión. Las primeras personas que entren no estarán visitando un producto inacabado. Serán los ciudadanos fundadores de un lugar que está vacío <em>porque han llegado pronto</em>, y lo que construyan seguirá en pie cuando lleguen los siguientes mil.</p>
<p>Ese es el plan, evaluado con honestidad. Cuatro apuestas que el cementerio respalda con firmeza y una apuesta realmente arriesgada por una herramienta que ninguno de los desaparecidos tuvo, acotada por la disciplina exacta de la que carecieron. Podemos generar la colina. No podemos generar la sensación de ser los primeros en subirla, ni al desconocido que saluda desde la cima. Nuestro trabajo consiste en hacer posible ese saludo, demostrarlo en la curva de retención y dejar de engañarnos en cuanto la curva diga que no.</p>
]]></content:encoded>
            <enclosure url="https://app.cinevva.com/img/blog/ai-builder-hero.webp" length="0" type="image/webp"/>
        </item>
        <item>
            <title><![CDATA[Construir un mundo abierto en el navegador, parte 30: Una cámara que respeta las paredes]]></title>
            <link>https://app.cinevva.com/es/blog/2026-06-04-open-world-browser-part-30-collision-aware-camera</link>
            <guid>https://app.cinevva.com/es/blog/2026-06-04-open-world-browser-part-30-collision-aware-camera</guid>
            <pubDate>Thu, 04 Jun 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Veintinueve partes construyeron un mundo por el que puedes caminar, nadar y construir, todo ello observado por una cámara que atravesaba sin más las colinas y las paredes de las casas. La parte 30 lo corrige con un brazo de cámara que detecta colisiones: un brazo con resorte que solo controla su propia longitud, un contrato de colisionadores intercambiables para que el terreno, los objetos y los edificios detengan la cámara mediante la misma interfaz, y una sonda de distancia con signo que respeta aquello que un mapa de alturas nunca podría representar: los salientes y las cuevas. Se integra como un posprocesado sobre OrbitControls sin reescribir ni una línea de los controles orbitales en los que ya confiábamos.]]></description>
            <content:encoded><![CDATA[<h1 id="construir-un-mundo-abierto-en-el-navegador-parte-30-una-camara-que-respeta-las-paredes" tabindex="-1">Construir un mundo abierto en el navegador, parte 30: Una cámara que respeta las paredes <a class="header-anchor" href="#construir-un-mundo-abierto-en-el-navegador-parte-30-una-camara-que-respeta-las-paredes" aria-label="Permalink to &quot;Construir un mundo abierto en el navegador, parte 30: Una cámara que respeta las paredes&quot;"></a></h1>
<p><em>Por <a href="/es/about.html">Oleg Sidorkin</a>, CTO y cofundador de Cinevva</em></p>
<p>¿Acabas de llegar? Consulta la <a href="/es/blog/2026-02-25-open-world-browser-series-guide.html">guía de la serie</a>. Explica qué es un prototipo exploratorio y enlaza todas las partes.</p>
<p>La <a href="/es/blog/2026-05-15-open-world-browser-part-29-pluggable-character.html">parte 29</a> nos dio un único controlador capaz de manejar cualquier cuerpo. Ahora el cuerpo se mueve correctamente. Camina, se desliza, nada, planea, trepa por cuevas y se agacha bajo salientes. El problema es lo que lo observa. Durante veintinueve partes, la cámara fue un sistema orbital estándar que seguía al jugador y hacía exactamente una cosa ingeniosa para evitar situaciones embarazosas: se negaba a inclinarse por debajo del horizonte para no deslizarse bajo un suelo plano. Esa limitación lo delata todo. Existe porque la cámara no tenía ni idea de dónde estaba realmente la geometría del mundo, así que la única defensa contra el atravesamiento era prohibir los ángulos en los que resultaba más probable. Al acercarte a una colina, la cámara se metía dentro de ella. Al entrar en una de las cuevas de marching cubes de la <a href="/es/blog/2026-02-25-open-world-browser-part-07-marching-cubes.html">parte 7</a>, acababas mirando el interior de una roca. Si construías una casa con las herramientas de creación de la <a href="/es/blog/2026-04-28-open-world-browser-part-16-structure-and-authoring.html">parte 16</a> y te quedabas de pie en una habitación, la cámara flotaba fuera de la pared mirando el revestimiento exterior. Esta parte consigue que la cámara respete la geometría tanto como ya lo hace el cuerpo.</p>
<h2 id="la-forma-del-problema-y-la-forma-de-la-solucion" tabindex="-1">La forma del problema y la forma de la solución <a class="header-anchor" href="#la-forma-del-problema-y-la-forma-de-la-solucion" aria-label="Permalink to &quot;La forma del problema y la forma de la solución&quot;"></a></h2>
<p>Una cámara en tercera persona tiene una tarea difícil y una docena de tareas fáciles. Las fáciles son seguir al personaje, suavizar el movimiento y gestionar los controles orbitales, y eso ya lo teníamos. La difícil es lo que la literatura académica denomina una restricción de visibilidad, y el estudio que todo el mundo cita, <em>Camera Control in Computer Graphics</em>, de Christie y Olivier, plantea todo el campo en torno a ella: mantener al sujeto encuadrado y sin oclusiones mientras se respeta el mundo. En tiempo de ejecución, esto se reduce a una pregunta engañosamente sencilla que se plantea en cada fotograma. El jugador es el pivote. El usuario ha rotado y ajustado el zoom hasta una posición deseada de la cámara, situada a cierta distancia detrás de él. ¿Hasta dónde puede colocarse realmente la cámara a lo largo de esa línea antes de introducirse en algo sólido? Si respondes con precisión, la cámara se recoge delante de la colina, se desliza por el brazo al retroceder hacia una esquina y se detiene ante el techo de la cueva en lugar de atravesarlo.</p>
<p>El patrón que resuelve esto es antiguo y está más que probado. Unreal lo llama spring arm, Godot incluye un nodo <code>SpringArm3D</code> y Cinemachine de Unity lo divide entre un sistema de seguimiento en tercera persona y una extensión para evitar oclusiones. La idea siempre es la misma. La cámara cuelga del extremo de un brazo anclado al pivote. Se mantiene a la longitud deseada cuando el trayecto está despejado, se retrae hacia el pivote cuando hay algo en medio y vuelve a extenderse con un efecto de resorte cuando el camino queda libre. <em>Real-Time Cameras</em>, de Mark Haigh-Hutchinson, responsable de cámaras de Metroid Prime, dedica capítulos enteros a los modos de fallo que convierten una implementación ingenua en algo capaz de marear a los jugadores. Tomamos ese patrón y construimos el nuestro, lo bastante pequeño como para leerlo de una sentada, en <code>public/world/src/camera-rig.mjs</code>.</p>
<figure style="margin:1.5rem 0;border:1px solid rgba(255,255,255,0.12);border-radius:8px;overflow:hidden;background:#0d1117">
<svg viewBox="0 0 680 290" width="100%" role="img" aria-label="Un brazo con resorte que se retrae a lo largo de su propia línea para que la esfera de sondeo descanse contra una pared en vez de atravesarla" style="display:block">
  <rect x="382" y="40" width="46" height="222" fill="#39424f" stroke="#5b6675"/>
  <text x="405" y="280" fill="#9aa7b4" font-size="13" text-anchor="middle" font-family="sans-serif">pared</text>
  <line x1="110" y1="212" x2="600" y2="70" stroke="#9aa7b4" stroke-width="2" stroke-dasharray="6 6"/>
  <line x1="110" y1="212" x2="360" y2="140" stroke="#6ea8fe" stroke-width="3"/>
  <circle cx="110" cy="212" r="6" fill="#e6edf3"/>
  <text x="110" y="234" fill="#e6edf3" font-size="13" text-anchor="middle" font-family="sans-serif">pivote (cabeza del jugador)</text>
  <circle cx="600" cy="70" r="9" fill="none" stroke="#9aa7b4" stroke-width="2"/>
  <text x="600" y="52" fill="#9aa7b4" font-size="13" text-anchor="middle" font-family="sans-serif">deseado (zoom del usuario)</text>
  <circle cx="360" cy="140" r="22" fill="rgba(110,168,254,0.18)" stroke="#6ea8fe" stroke-width="2"/>
  <circle cx="360" cy="140" r="5" fill="#6ea8fe"/>
  <text x="300" y="104" fill="#6ea8fe" font-size="13" text-anchor="middle" font-family="sans-serif">cámara + radio de sondeo r</text>
  <text x="222" y="192" fill="#6ea8fe" font-size="13" font-family="sans-serif" transform="rotate(-16 222 192)">ℓ (limitada)</text>
</svg>
<figcaption style="padding:0.6rem 1rem;color:#9aa7b4;font-size:0.85rem;border-top:1px solid rgba(255,255,255,0.12);font-family:sans-serif">El brazo mantiene la cámara en el nivel de zoom deseado por el usuario hasta que aparece un obstáculo; entonces se retrae a lo largo de la misma línea para que la esfera de sondeo descanse contra la superficie, en vez de que el plano cercano la atraviese.</figcaption>
</figure>
<h2 id="un-brazo-que-solo-controla-su-longitud" tabindex="-1">Un brazo que solo controla su longitud <a class="header-anchor" href="#un-brazo-que-solo-controla-su-longitud" aria-label="Permalink to &quot;Un brazo que solo controla su longitud&quot;"></a></h2>
<p>La regla de diseño que mantuvo pequeño el sistema procede del trabajo sobre el controlador de la parte 29: controlar una sola cosa por completo y rechazar todo lo demás. El sistema controla la longitud del brazo y nada más. El ángulo horizontal, la inclinación, el amortiguamiento de la órbita y los gestos táctiles y con la rueda del ratón permanecen en OrbitControls, que ya los resuelve bien y que no tenemos ningún interés en reescribir. Por tanto, este sistema no es un controlador de cámara. Es un posprocesado que se ejecuta después de los cálculos orbitales y corrige exactamente un número: la distancia entre el pivote y la cámara.</p>
<p>Esa decisión parece impecable, pero estuvo a punto de fallar de inmediato debido a cómo piensa OrbitControls. Al principio de cada actualización, lee la posición actual de la cámara y deriva de ella el radio de la órbita. Normalmente eso resulta invisible. Pero en cuanto nuestro sistema acorta la distancia de la cámara para esquivar una pared, en el siguiente fotograma OrbitControls lee esa posición acortada, concluye que el usuario debe haber acercado el zoom e incorpora ese acortamiento al zoom deseado por el usuario. Después de unos cuantos fotogramas, la cámara se ha desplomado sobre la cabeza del jugador y ya no vuelve a alejarse. La solución consiste en dos llamadas que enmarcan la actualización de los controles orbitales y constituyen toda la integración. Antes de que se ejecute OrbitControls, <code>beforeControls()</code> restaura la cámara a la distancia completa y sin acortar del fotograma anterior, para que los cálculos orbitales siempre lean el zoom real del usuario. Después de que se ejecute OrbitControls, <code>afterControls(dt)</code> lee esa posición deseada recién orbitada, resuelve la colisión, amortigua la longitud y coloca la cámara donde realmente debe renderizarse. La intención del usuario y la corrección de colisiones nunca interfieren entre sí, y el desplazamiento del zoom conserva exactamente la misma capacidad de respuesta que tenía antes de que existiera el sistema. La prueba sin interfaz gráfica que escribimos para el sistema verifica precisamente esto: empuja el brazo contra una pared durante sesenta fotogramas, despeja la pared y comprueba que la longitud vuelve con efecto de resorte al zoom completo de diez metros del usuario, en lugar de quedarse atascada en la distancia de colisión.</p>
<h2 id="un-contrato-cualquier-colisionador" tabindex="-1">Un contrato, cualquier colisionador <a class="header-anchor" href="#un-contrato-cualquier-colisionador" aria-label="Permalink to &quot;Un contrato, cualquier colisionador&quot;"></a></h2>
<p>El sistema nunca pregunta de qué está hecho el mundo. Un colisionador es simplemente un objeto con un método <code>probe</code>: el sistema le entrega un rayo, una distancia máxima y el radio de sondeo de la cámara, y recibe un número, la distancia máxima que puede recorrer la cámara antes de que ese colisionador la bloquee. El sistema consulta todos los colisionadores registrados y se queda con el impacto más cercano. Ese es todo el contrato, y es el mismo enfoque que utilizó el controlador del personaje al convertir la locomoción en comportamientos intercambiables. El terreno se conecta, los objetos se conectan y las estructuras de los edificios se conectan, cada uno detrás del mismo <code>probe</code>, mientras que el sistema permanece ajeno a todos ellos. Añadir un nuevo tipo de obstáculo significa añadir un colisionador a una lista, no editar la cámara.</p>
<p>Hay un detalle del contrato que demuestra su valor: el radio de sondeo. No lanzamos un rayo fino desde el pivote hasta la cámara, sino una esfera lo bastante grande como para contener el plano cercano de la cámara. Un único rayo detiene el centro de la cámara en la pared, pero el plano cercano tiene anchura, por lo que sus esquinas ya estarían hundidas en la pared antes de que el rayo central informara de un impacto. Barrer una esfera pequeña en lugar de un rayo es lo que hacen todas las implementaciones publicadas; Unreal lo expone como el tamaño de la sonda, y eso marca la diferencia entre una cámara que descansa limpiamente contra una superficie y otra que permite ver a través de ella en los bordes de la pantalla.</p>
<p>No estimamos ese radio, sino que lo derivamos. El punto del plano cercano más alejado de la cámara es una de sus esquinas, y la distancia hasta él se obtiene directamente de la proyección. Con un plano cercano <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.025ex;" xmlns="http://www.w3.org/2000/svg" width="1.357ex" height="1.025ex" role="img" focusable="false" viewBox="0 -442 600 453" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mi"><path data-c="1D45B" d="M21 287Q22 293 24 303T36 341T56 388T89 425T135 442Q171 442 195 424T225 390T231 369Q231 367 232 367L243 378Q304 442 382 442Q436 442 469 415T503 336T465 179T427 52Q427 26 444 26Q450 26 453 27Q482 32 505 65T540 145Q542 153 560 153Q580 153 580 145Q580 144 576 130Q568 101 554 73T508 17T439 -10Q392 -10 371 17T350 73Q350 92 386 193T423 345Q423 404 379 404H374Q288 404 229 303L222 291L189 157Q156 26 151 16Q138 -11 108 -11Q95 -11 87 -5T76 7T74 17Q74 30 112 180T152 343Q153 348 153 366Q153 405 129 405Q91 405 66 305Q60 285 60 284Q58 278 41 278H27Q21 284 21 287Z" style="stroke-width: 3;"/></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mi>n</mi></math></mjx-assistive-mml></mjx-container> y un campo de visión vertical <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.023ex;" xmlns="http://www.w3.org/2000/svg" width="1.061ex" height="1.618ex" role="img" focusable="false" viewBox="0 -705 469 715" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mi"><path data-c="1D703" d="M35 200Q35 302 74 415T180 610T319 704Q320 704 327 704T339 705Q393 701 423 656Q462 596 462 495Q462 380 417 261T302 66T168 -10H161Q125 -10 99 10T60 63T41 130T35 200ZM383 566Q383 668 330 668Q294 668 260 623T204 521T170 421T157 371Q206 370 254 370L351 371Q352 372 359 404T375 484T383 566ZM113 132Q113 26 166 26Q181 26 198 36T239 74T287 161T335 307L340 324H145Q145 321 136 286T120 208T113 132Z" style="stroke-width: 3;"/></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mi>θ</mi></math></mjx-assistive-mml></mjx-container>, la semialtura es <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.566ex;" xmlns="http://www.w3.org/2000/svg" width="14.408ex" height="2.262ex" role="img" focusable="false" viewBox="0 -750 6368.2 1000" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mi"><path data-c="210E" d="M137 683Q138 683 209 688T282 694Q294 694 294 685Q294 674 258 534Q220 386 220 383Q220 381 227 388Q288 442 357 442Q411 442 444 415T478 336Q478 285 440 178T402 50Q403 36 407 31T422 26Q450 26 474 56T513 138Q516 149 519 151T535 153Q555 153 555 145Q555 144 551 130Q535 71 500 33Q466 -10 419 -10H414Q367 -10 346 17T325 74Q325 90 361 192T398 345Q398 404 354 404H349Q266 404 205 306L198 293L164 158Q132 28 127 16Q114 -11 83 -11Q69 -11 59 -2T48 16Q48 30 121 320L195 616Q195 629 188 632T149 637H128Q122 643 122 645T124 664Q129 683 137 683Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(853.8,0)"><path data-c="3D" d="M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(1909.6,0)"><path data-c="1D45B" d="M21 287Q22 293 24 303T36 341T56 388T89 425T135 442Q171 442 195 424T225 390T231 369Q231 367 232 367L243 378Q304 442 382 442Q436 442 469 415T503 336T465 179T427 52Q427 26 444 26Q450 26 453 27Q482 32 505 65T540 145Q542 153 560 153Q580 153 580 145Q580 144 576 130Q568 101 554 73T508 17T439 -10Q392 -10 371 17T350 73Q350 92 386 193T423 345Q423 404 379 404H374Q288 404 229 303L222 291L189 157Q156 26 151 16Q138 -11 108 -11Q95 -11 87 -5T76 7T74 17Q74 30 112 180T152 343Q153 348 153 366Q153 405 129 405Q91 405 66 305Q60 285 60 284Q58 278 41 278H27Q21 284 21 287Z" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(2676.2,0)"><path data-c="74" d="M27 422Q80 426 109 478T141 600V615H181V431H316V385H181V241Q182 116 182 100T189 68Q203 29 238 29Q282 29 292 100Q293 108 293 146V181H333V146V134Q333 57 291 17Q264 -10 221 -10Q187 -10 162 2T124 33T105 68T98 100Q97 107 97 248V385H18V422H27Z" style="stroke-width: 3;"/><path data-c="61" d="M137 305T115 305T78 320T63 359Q63 394 97 421T218 448Q291 448 336 416T396 340Q401 326 401 309T402 194V124Q402 76 407 58T428 40Q443 40 448 56T453 109V145H493V106Q492 66 490 59Q481 29 455 12T400 -6T353 12T329 54V58L327 55Q325 52 322 49T314 40T302 29T287 17T269 6T247 -2T221 -8T190 -11Q130 -11 82 20T34 107Q34 128 41 147T68 188T116 225T194 253T304 268H318V290Q318 324 312 340Q290 411 215 411Q197 411 181 410T156 406T148 403Q170 388 170 359Q170 334 154 320ZM126 106Q126 75 150 51T209 26Q247 26 276 49T315 109Q317 116 318 175Q318 233 317 233Q309 233 296 232T251 223T193 203T147 166T126 106Z" transform="translate(389,0)" style="stroke-width: 3;"/><path data-c="6E" d="M41 46H55Q94 46 102 60V68Q102 77 102 91T102 122T103 161T103 203Q103 234 103 269T102 328V351Q99 370 88 376T43 385H25V408Q25 431 27 431L37 432Q47 433 65 434T102 436Q119 437 138 438T167 441T178 442H181V402Q181 364 182 364T187 369T199 384T218 402T247 421T285 437Q305 442 336 442Q450 438 463 329Q464 322 464 190V104Q464 66 466 59T477 49Q498 46 526 46H542V0H534L510 1Q487 2 460 2T422 3Q319 3 310 0H302V46H318Q379 46 379 62Q380 64 380 200Q379 335 378 343Q372 371 358 385T334 402T308 404Q263 404 229 370Q202 343 195 315T187 232V168V108Q187 78 188 68T191 55T200 49Q221 46 249 46H265V0H257L234 1Q210 2 183 2T145 3Q42 3 33 0H25V46H41Z" transform="translate(889,0)" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(4121.2,0)"><path data-c="2061" d="" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(4121.2,0)"><path data-c="28" d="M94 250Q94 319 104 381T127 488T164 576T202 643T244 695T277 729T302 750H315H319Q333 750 333 741Q333 738 316 720T275 667T226 581T184 443T167 250T184 58T225 -81T274 -167T316 -220T333 -241Q333 -250 318 -250H315H302L274 -226Q180 -141 137 -14T94 250Z" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(4510.2,0)"><path data-c="1D703" d="M35 200Q35 302 74 415T180 610T319 704Q320 704 327 704T339 705Q393 701 423 656Q462 596 462 495Q462 380 417 261T302 66T168 -10H161Q125 -10 99 10T60 63T41 130T35 200ZM383 566Q383 668 330 668Q294 668 260 623T204 521T170 421T157 371Q206 370 254 370L351 371Q352 372 359 404T375 484T383 566ZM113 132Q113 26 166 26Q181 26 198 36T239 74T287 161T335 307L340 324H145Q145 321 136 286T120 208T113 132Z" style="stroke-width: 3;"/></g><g data-mml-node="TeXAtom" data-mjx-texclass="ORD" transform="translate(4979.2,0)"><g data-mml-node="mo"><path data-c="2F" d="M423 750Q432 750 438 744T444 730Q444 725 271 248T92 -240Q85 -250 75 -250Q68 -250 62 -245T56 -231Q56 -221 230 257T407 740Q411 750 423 750Z" style="stroke-width: 3;"/></g></g><g data-mml-node="mn" transform="translate(5479.2,0)"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(5979.2,0)"><path data-c="29" d="M60 749L64 750Q69 750 74 750H86L114 726Q208 641 251 514T294 250Q294 182 284 119T261 12T224 -76T186 -143T145 -194T113 -227T90 -246Q87 -249 86 -250H74Q66 -250 63 -250T58 -247T55 -238Q56 -237 66 -225Q221 -64 221 250T66 725Q56 737 55 738Q55 746 60 749Z" style="stroke-width: 3;"/></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mi>h</mi><mo>=</mo><mi>n</mi><mi>tan</mi><mo data-mjx-texclass="NONE">⁡</mo><mo stretchy="false">(</mo><mi>θ</mi><mrow data-mjx-texclass="ORD"><mo>/</mo></mrow><mn>2</mn><mo stretchy="false">)</mo></math></mjx-assistive-mml></mjx-container>, la semianchura es <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.439ex;" xmlns="http://www.w3.org/2000/svg" width="13.744ex" height="2.009ex" role="img" focusable="false" viewBox="0 -694 6075 888" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mi"><path data-c="1D464" d="M580 385Q580 406 599 424T641 443Q659 443 674 425T690 368Q690 339 671 253Q656 197 644 161T609 80T554 12T482 -11Q438 -11 404 5T355 48Q354 47 352 44Q311 -11 252 -11Q226 -11 202 -5T155 14T118 53T104 116Q104 170 138 262T173 379Q173 380 173 381Q173 390 173 393T169 400T158 404H154Q131 404 112 385T82 344T65 302T57 280Q55 278 41 278H27Q21 284 21 287Q21 293 29 315T52 366T96 418T161 441Q204 441 227 416T250 358Q250 340 217 250T184 111Q184 65 205 46T258 26Q301 26 334 87L339 96V119Q339 122 339 128T340 136T341 143T342 152T345 165T348 182T354 206T362 238T373 281Q402 395 406 404Q419 431 449 431Q468 431 475 421T483 402Q483 389 454 274T422 142Q420 131 420 107V100Q420 85 423 71T442 42T487 26Q558 26 600 148Q609 171 620 213T632 273Q632 306 619 325T593 357T580 385Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(993.8,0)"><path data-c="3D" d="M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(2049.6,0)"><path data-c="210E" d="M137 683Q138 683 209 688T282 694Q294 694 294 685Q294 674 258 534Q220 386 220 383Q220 381 227 388Q288 442 357 442Q411 442 444 415T478 336Q478 285 440 178T402 50Q403 36 407 31T422 26Q450 26 474 56T513 138Q516 149 519 151T535 153Q555 153 555 145Q555 144 551 130Q535 71 500 33Q466 -10 419 -10H414Q367 -10 346 17T325 74Q325 90 361 192T398 345Q398 404 354 404H349Q266 404 205 306L198 293L164 158Q132 28 127 16Q114 -11 83 -11Q69 -11 59 -2T48 16Q48 30 121 320L195 616Q195 629 188 632T149 637H128Q122 643 122 645T124 664Q129 683 137 683Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(2847.8,0)"><path data-c="22C5" d="M78 250Q78 274 95 292T138 310Q162 310 180 294T199 251Q199 226 182 208T139 190T96 207T78 250Z" style="stroke-width: 3;"/></g><g data-mml-node="mtext" transform="translate(3348,0)"><path data-c="61" d="M137 305T115 305T78 320T63 359Q63 394 97 421T218 448Q291 448 336 416T396 340Q401 326 401 309T402 194V124Q402 76 407 58T428 40Q443 40 448 56T453 109V145H493V106Q492 66 490 59Q481 29 455 12T400 -6T353 12T329 54V58L327 55Q325 52 322 49T314 40T302 29T287 17T269 6T247 -2T221 -8T190 -11Q130 -11 82 20T34 107Q34 128 41 147T68 188T116 225T194 253T304 268H318V290Q318 324 312 340Q290 411 215 411Q197 411 181 410T156 406T148 403Q170 388 170 359Q170 334 154 320ZM126 106Q126 75 150 51T209 26Q247 26 276 49T315 109Q317 116 318 175Q318 233 317 233Q309 233 296 232T251 223T193 203T147 166T126 106Z" style="stroke-width: 3;"/><path data-c="73" d="M295 316Q295 356 268 385T190 414Q154 414 128 401Q98 382 98 349Q97 344 98 336T114 312T157 287Q175 282 201 278T245 269T277 256Q294 248 310 236T342 195T359 133Q359 71 321 31T198 -10H190Q138 -10 94 26L86 19L77 10Q71 4 65 -1L54 -11H46H42Q39 -11 33 -5V74V132Q33 153 35 157T45 162H54Q66 162 70 158T75 146T82 119T101 77Q136 26 198 26Q295 26 295 104Q295 133 277 151Q257 175 194 187T111 210Q75 227 54 256T33 318Q33 357 50 384T93 424T143 442T187 447H198Q238 447 268 432L283 424L292 431Q302 440 314 448H322H326Q329 448 335 442V310L329 304H301Q295 310 295 316Z" transform="translate(500,0)" style="stroke-width: 3;"/><path data-c="70" d="M36 -148H50Q89 -148 97 -134V-126Q97 -119 97 -107T97 -77T98 -38T98 6T98 55T98 106Q98 140 98 177T98 243T98 296T97 335T97 351Q94 370 83 376T38 385H20V408Q20 431 22 431L32 432Q42 433 61 434T98 436Q115 437 135 438T165 441T176 442H179V416L180 390L188 397Q247 441 326 441Q407 441 464 377T522 216Q522 115 457 52T310 -11Q242 -11 190 33L182 40V-45V-101Q182 -128 184 -134T195 -145Q216 -148 244 -148H260V-194H252L228 -193Q205 -192 178 -192T140 -191Q37 -191 28 -194H20V-148H36ZM424 218Q424 292 390 347T305 402Q234 402 182 337V98Q222 26 294 26Q345 26 384 80T424 218Z" transform="translate(894,0)" style="stroke-width: 3;"/><path data-c="65" d="M28 218Q28 273 48 318T98 391T163 433T229 448Q282 448 320 430T378 380T406 316T415 245Q415 238 408 231H126V216Q126 68 226 36Q246 30 270 30Q312 30 342 62Q359 79 369 104L379 128Q382 131 395 131H398Q415 131 415 121Q415 117 412 108Q393 53 349 21T250 -11Q155 -11 92 58T28 218ZM333 275Q322 403 238 411H236Q228 411 220 410T195 402T166 381T143 340T127 274V267H333V275Z" transform="translate(1450,0)" style="stroke-width: 3;"/><path data-c="63" d="M370 305T349 305T313 320T297 358Q297 381 312 396Q317 401 317 402T307 404Q281 408 258 408Q209 408 178 376Q131 329 131 219Q131 137 162 90Q203 29 272 29Q313 29 338 55T374 117Q376 125 379 127T395 129H409Q415 123 415 120Q415 116 411 104T395 71T366 33T318 2T249 -11Q163 -11 99 53T34 214Q34 318 99 383T250 448T370 421T404 357Q404 334 387 320Z" transform="translate(1894,0)" style="stroke-width: 3;"/><path data-c="74" d="M27 422Q80 426 109 478T141 600V615H181V431H316V385H181V241Q182 116 182 100T189 68Q203 29 238 29Q282 29 292 100Q293 108 293 146V181H333V146V134Q333 57 291 17Q264 -10 221 -10Q187 -10 162 2T124 33T105 68T98 100Q97 107 97 248V385H18V422H27Z" transform="translate(2338,0)" style="stroke-width: 3;"/></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mi>w</mi><mo>=</mo><mi>h</mi><mo>⋅</mo><mtext>aspect</mtext></math></mjx-assistive-mml></mjx-container>, y la esquina se encuentra a</p>
<mjx-container tabindex="0" class="MathJax" jax="SVG" display="true" style="direction: ltr; display: block; text-align: center; margin: 1em 0; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.357ex;" xmlns="http://www.w3.org/2000/svg" width="22.335ex" height="2.878ex" role="img" focusable="false" viewBox="0 -1114.2 9872 1272" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="msub"><g data-mml-node="mi"><path data-c="1D45F" d="M21 287Q22 290 23 295T28 317T38 348T53 381T73 411T99 433T132 442Q161 442 183 430T214 408T225 388Q227 382 228 382T236 389Q284 441 347 441H350Q398 441 422 400Q430 381 430 363Q430 333 417 315T391 292T366 288Q346 288 334 299T322 328Q322 376 378 392Q356 405 342 405Q286 405 239 331Q229 315 224 298T190 165Q156 25 151 16Q138 -11 108 -11Q95 -11 87 -5T76 7T74 17Q74 30 114 189T154 366Q154 405 128 405Q107 405 92 377T68 316T57 280Q55 278 41 278H27Q21 284 21 287Z" style="stroke-width: 3;"/></g><g data-mml-node="TeXAtom" transform="translate(484,-150) scale(0.707)" data-mjx-texclass="ORD"><g data-mml-node="mtext"><path data-c="6E" d="M41 46H55Q94 46 102 60V68Q102 77 102 91T102 122T103 161T103 203Q103 234 103 269T102 328V351Q99 370 88 376T43 385H25V408Q25 431 27 431L37 432Q47 433 65 434T102 436Q119 437 138 438T167 441T178 442H181V402Q181 364 182 364T187 369T199 384T218 402T247 421T285 437Q305 442 336 442Q450 438 463 329Q464 322 464 190V104Q464 66 466 59T477 49Q498 46 526 46H542V0H534L510 1Q487 2 460 2T422 3Q319 3 310 0H302V46H318Q379 46 379 62Q380 64 380 200Q379 335 378 343Q372 371 358 385T334 402T308 404Q263 404 229 370Q202 343 195 315T187 232V168V108Q187 78 188 68T191 55T200 49Q221 46 249 46H265V0H257L234 1Q210 2 183 2T145 3Q42 3 33 0H25V46H41Z" style="stroke-width: 3;"/><path data-c="65" d="M28 218Q28 273 48 318T98 391T163 433T229 448Q282 448 320 430T378 380T406 316T415 245Q415 238 408 231H126V216Q126 68 226 36Q246 30 270 30Q312 30 342 62Q359 79 369 104L379 128Q382 131 395 131H398Q415 131 415 121Q415 117 412 108Q393 53 349 21T250 -11Q155 -11 92 58T28 218ZM333 275Q322 403 238 411H236Q228 411 220 410T195 402T166 381T143 340T127 274V267H333V275Z" transform="translate(556,0)" style="stroke-width: 3;"/><path data-c="61" d="M137 305T115 305T78 320T63 359Q63 394 97 421T218 448Q291 448 336 416T396 340Q401 326 401 309T402 194V124Q402 76 407 58T428 40Q443 40 448 56T453 109V145H493V106Q492 66 490 59Q481 29 455 12T400 -6T353 12T329 54V58L327 55Q325 52 322 49T314 40T302 29T287 17T269 6T247 -2T221 -8T190 -11Q130 -11 82 20T34 107Q34 128 41 147T68 188T116 225T194 253T304 268H318V290Q318 324 312 340Q290 411 215 411Q197 411 181 410T156 406T148 403Q170 388 170 359Q170 334 154 320ZM126 106Q126 75 150 51T209 26Q247 26 276 49T315 109Q317 116 318 175Q318 233 317 233Q309 233 296 232T251 223T193 203T147 166T126 106Z" transform="translate(1000,0)" style="stroke-width: 3;"/><path data-c="72" d="M36 46H50Q89 46 97 60V68Q97 77 97 91T98 122T98 161T98 203Q98 234 98 269T98 328L97 351Q94 370 83 376T38 385H20V408Q20 431 22 431L32 432Q42 433 60 434T96 436Q112 437 131 438T160 441T171 442H174V373Q213 441 271 441H277Q322 441 343 419T364 373Q364 352 351 337T313 322Q288 322 276 338T263 372Q263 381 265 388T270 400T273 405Q271 407 250 401Q234 393 226 386Q179 341 179 207V154Q179 141 179 127T179 101T180 81T180 66V61Q181 59 183 57T188 54T193 51T200 49T207 48T216 47T225 47T235 46T245 46H276V0H267Q249 3 140 3Q37 3 28 0H20V46H36Z" transform="translate(1500,0)" style="stroke-width: 3;"/></g></g></g><g data-mml-node="mo" transform="translate(2149.6,0)"><path data-c="3D" d="M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z" style="stroke-width: 3;"/></g><g data-mml-node="msqrt" transform="translate(3205.4,0)"><g transform="translate(1020,0)"><g data-mml-node="msup"><g data-mml-node="mi"><path data-c="1D45B" d="M21 287Q22 293 24 303T36 341T56 388T89 425T135 442Q171 442 195 424T225 390T231 369Q231 367 232 367L243 378Q304 442 382 442Q436 442 469 415T503 336T465 179T427 52Q427 26 444 26Q450 26 453 27Q482 32 505 65T540 145Q542 153 560 153Q580 153 580 145Q580 144 576 130Q568 101 554 73T508 17T439 -10Q392 -10 371 17T350 73Q350 92 386 193T423 345Q423 404 379 404H374Q288 404 229 303L222 291L189 157Q156 26 151 16Q138 -11 108 -11Q95 -11 87 -5T76 7T74 17Q74 30 112 180T152 343Q153 348 153 366Q153 405 129 405Q91 405 66 305Q60 285 60 284Q58 278 41 278H27Q21 284 21 287Z" style="stroke-width: 3;"/></g><g data-mml-node="mn" transform="translate(633,289) scale(0.707)"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"/></g></g><g data-mml-node="mo" transform="translate(1258.8,0)"><path data-c="2B" d="M56 237T56 250T70 270H369V420L370 570Q380 583 389 583Q402 583 409 568V270H707Q722 262 722 250T707 230H409V-68Q401 -82 391 -82H389H387Q375 -82 369 -68V230H70Q56 237 56 250Z" style="stroke-width: 3;"/></g><g data-mml-node="msup" transform="translate(2259,0)"><g data-mml-node="mi"><path data-c="1D464" d="M580 385Q580 406 599 424T641 443Q659 443 674 425T690 368Q690 339 671 253Q656 197 644 161T609 80T554 12T482 -11Q438 -11 404 5T355 48Q354 47 352 44Q311 -11 252 -11Q226 -11 202 -5T155 14T118 53T104 116Q104 170 138 262T173 379Q173 380 173 381Q173 390 173 393T169 400T158 404H154Q131 404 112 385T82 344T65 302T57 280Q55 278 41 278H27Q21 284 21 287Q21 293 29 315T52 366T96 418T161 441Q204 441 227 416T250 358Q250 340 217 250T184 111Q184 65 205 46T258 26Q301 26 334 87L339 96V119Q339 122 339 128T340 136T341 143T342 152T345 165T348 182T354 206T362 238T373 281Q402 395 406 404Q419 431 449 431Q468 431 475 421T483 402Q483 389 454 274T422 142Q420 131 420 107V100Q420 85 423 71T442 42T487 26Q558 26 600 148Q609 171 620 213T632 273Q632 306 619 325T593 357T580 385Z" style="stroke-width: 3;"/></g><g data-mml-node="mn" transform="translate(749,289) scale(0.707)"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"/></g></g><g data-mml-node="mo" transform="translate(3633.8,0)"><path data-c="2B" d="M56 237T56 250T70 270H369V420L370 570Q380 583 389 583Q402 583 409 568V270H707Q722 262 722 250T707 230H409V-68Q401 -82 391 -82H389H387Q375 -82 369 -68V230H70Q56 237 56 250Z" style="stroke-width: 3;"/></g><g data-mml-node="msup" transform="translate(4634,0)"><g data-mml-node="mi"><path data-c="210E" d="M137 683Q138 683 209 688T282 694Q294 694 294 685Q294 674 258 534Q220 386 220 383Q220 381 227 388Q288 442 357 442Q411 442 444 415T478 336Q478 285 440 178T402 50Q403 36 407 31T422 26Q450 26 474 56T513 138Q516 149 519 151T535 153Q555 153 555 145Q555 144 551 130Q535 71 500 33Q466 -10 419 -10H414Q367 -10 346 17T325 74Q325 90 361 192T398 345Q398 404 354 404H349Q266 404 205 306L198 293L164 158Q132 28 127 16Q114 -11 83 -11Q69 -11 59 -2T48 16Q48 30 121 320L195 616Q195 629 188 632T149 637H128Q122 643 122 645T124 664Q129 683 137 683Z" style="stroke-width: 3;"/></g><g data-mml-node="mn" transform="translate(609,289) scale(0.707)"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"/></g></g></g><g data-mml-node="mo" transform="translate(0,204.2)"><path data-c="221A" d="M263 249Q264 249 315 130T417 -108T470 -228L725 302Q981 837 982 839Q989 850 1001 850Q1008 850 1013 844T1020 832V826L741 243Q645 43 540 -176Q479 -303 469 -324T453 -348Q449 -350 436 -350L424 -349L315 -96Q206 156 205 156L171 130Q138 104 137 104L111 130L263 249Z" style="stroke-width: 3;"/></g><rect width="5646.5" height="60" x="1020" y="994.2"/></g></g></g></svg><mjx-assistive-mml unselectable="on" display="block" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; overflow: hidden; width: 100%;"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><msub><mi>r</mi><mrow data-mjx-texclass="ORD"><mtext>near</mtext></mrow></msub><mo>=</mo><msqrt><msup><mi>n</mi><mn>2</mn></msup><mo>+</mo><msup><mi>w</mi><mn>2</mn></msup><mo>+</mo><msup><mi>h</mi><mn>2</mn></msup></msqrt></math></mjx-assistive-mml></mjx-container><p>El radio de sondeo es esa distancia a la esquina multiplicada por un pequeño margen de seguridad, con un mínimo fijo para que nunca caiga por debajo de un valor razonable en un frustum muy estrecho. Cada vez que cambian el campo de visión, la relación de aspecto o el plano cercano, el radio se vuelve a calcular, de modo que un cambio de tamaño de la ventana o un zoom que afecte a la proyección no pueda dejar discretamente la sonda demasiado pequeña para cubrir las esquinas que debe proteger.</p>
<h2 id="el-colisionador-que-sabe-de-cuevas" tabindex="-1">El colisionador que sabe de cuevas <a class="header-anchor" href="#el-colisionador-que-sabe-de-cuevas" aria-label="Permalink to &quot;El colisionador que sabe de cuevas&quot;"></a></h2>
<p>Aquí es donde el colisionador del terreno se vuelve interesante, porque el terreno de nuestro motor no es un mapa de alturas. Desde la parte 7 es un campo de distancia con signo, una función que indica a qué distancia está cualquier punto del espacio de la superficie sólida más cercana y si se encuentra dentro o fuera de la roca. Un valor positivo es aire; uno negativo, roca. Ese único hecho es la razón por la que nuestra cámara puede hacer algo que una cámara basada en mapas de alturas no puede hacer por su propia estructura. Un mapa de alturas conoce la altura del suelo en unas coordenadas x y z. No tiene concepto de techo, porque solo puede haber una superficie sobre cada punto. Por eso, una cámara basada en mapas de alturas puede impedir que entres en una colina, pero no tiene ni idea de que el borde de un saliente o el techo de una cueva cuelgan sobre el pivote, y atraviesa ambos sin más. Un campo de distancia conoce todas las superficies en tres dimensiones, así que la misma sonda que detiene la cámara contra una ladera también la detiene contra el techo de una cueva sin un solo caso especial.</p>
<figure style="margin:1.5rem 0;border:1px solid rgba(255,255,255,0.12);border-radius:8px;overflow:hidden;background:#0d1117">
<svg viewBox="0 0 680 320" width="100%" role="img" aria-label="Bajo un saliente, un mapa de alturas permite que el brazo atraviese la roca del techo, mientras que un campo de distancia con signo lo detiene en la cara inferior del techo" style="display:block">
  <path d="M680,320 L680,40 L250,40 L250,150 L430,150 L430,250 L250,250 L250,320 Z" fill="#39424f" stroke="#5b6675" stroke-width="1.5"/>
  <text x="340" y="205" fill="#9aa7b4" font-size="13" text-anchor="middle" font-family="sans-serif">cueva</text>
  <text x="540" y="100" fill="#5b6675" font-size="13" text-anchor="middle" font-family="sans-serif">roca sólida</text>
  <line x1="330" y1="212" x2="230" y2="60" stroke="#9aa7b4" stroke-width="2" stroke-dasharray="6 6"/>
  <line x1="290" y1="150" x2="250" y2="90" stroke="#f85149" stroke-width="4"/>
  <circle cx="330" cy="212" r="6" fill="#e6edf3"/>
  <text x="330" y="234" fill="#e6edf3" font-size="13" text-anchor="middle" font-family="sans-serif">jugador</text>
  <circle cx="230" cy="60" r="10" fill="none" stroke="#f85149" stroke-width="2"/>
  <text x="230" y="42" fill="#f85149" font-size="13" text-anchor="middle" font-family="sans-serif">mapa de alturas: atraviesa ✗</text>
  <circle cx="305" cy="170" r="9" fill="rgba(86,211,100,0.2)" stroke="#56d364" stroke-width="2"/>
  <text x="420" y="172" fill="#56d364" font-size="13" text-anchor="middle" font-family="sans-serif">SDF: se detiene en el techo ✓</text>
</svg>
<figcaption style="padding:0.6rem 1rem;color:#9aa7b4;font-size:0.85rem;border-top:1px solid rgba(255,255,255,0.12);font-family:sans-serif">Un mapa de alturas almacena una superficie por columna, por lo que nunca ve la placa de roca situada sobre el jugador y permite que el brazo atraviese el techo hacia arriba. El campo de distancia es negativo dentro de esa placa, así que la sonda entra en contacto con ella y la cámara se mantiene justo debajo del techo de la cueva.</figcaption>
</figure>
<p>Desplazar la sonda por el campo es una técnica con nombre propio y un artículo científico que la respalda. <em>Sphere Tracing</em>, de John Hart, publicado en 1996, es el método estándar para hacer avanzar un rayo por un campo de distancia. El truco consiste en que el campo no solo indica si has golpeado algo, sino también una distancia segura que puedes avanzar sin chocar con nada. Así que, en lugar de avanzar poco a poco con pasos fijos diminutos, se muestrea el campo, se avanza según el margen que indica y se repite el proceso, dando grandes pasos por el aire libre y pasos cortos y cuidadosos al acercarse a una superficie.
Sin embargo, hay una salvedad que nos impone el terreno. Un campo de distancias verdadero indica la distancia euclídea real hasta la superficie más cercana, y avanzar de una vez todo ese margen siempre es seguro. Pero donde el terreno sigue siendo un mapa de alturas en lugar de vóxeles esculpidos, el campo que podemos muestrear de forma económica no representa una distancia real, sino la separación vertical, el hueco en línea recta hacia abajo hasta el suelo. En una pendiente, ese valor exagera cuánto puede moverse realmente la cámara, porque la roca más cercana está a un lado, no justo debajo. La distancia real es menor por un factor que crece con el gradiente, <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.628ex;" xmlns="http://www.w3.org/2000/svg" width="12.643ex" height="2.851ex" role="img" focusable="false" viewBox="0 -982.5 5588 1260" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="msqrt"><g transform="translate(1020,0)"><g data-mml-node="mn"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(722.2,0)"><path data-c="2B" d="M56 237T56 250T70 270H369V420L370 570Q380 583 389 583Q402 583 409 568V270H707Q722 262 722 250T707 230H409V-68Q401 -82 391 -82H389H387Q375 -82 369 -68V230H70Q56 237 56 250Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(1722.4,0)"><path data-c="2016" d="M133 736Q138 750 153 750Q164 750 170 739Q172 735 172 250T170 -239Q164 -250 152 -250Q144 -250 138 -244L137 -243Q133 -241 133 -179T132 250Q132 731 133 736ZM329 739Q334 750 346 750Q353 750 361 744L362 743Q366 741 366 679T367 250T367 -178T362 -243L361 -244Q355 -250 347 -250Q335 -250 329 -239Q327 -235 327 250T329 739Z" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(2222.4,0)"><path data-c="2207" d="M46 676Q46 679 51 683H781Q786 679 786 676Q786 674 617 326T444 -26Q439 -33 416 -33T388 -26Q385 -22 216 326T46 676ZM697 596Q697 597 445 597T193 596Q195 591 319 336T445 80L697 596Z" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(3055.4,0)"><path data-c="210E" d="M137 683Q138 683 209 688T282 694Q294 694 294 685Q294 674 258 534Q220 386 220 383Q220 381 227 388Q288 442 357 442Q411 442 444 415T478 336Q478 285 440 178T402 50Q403 36 407 31T422 26Q450 26 474 56T513 138Q516 149 519 151T535 153Q555 153 555 145Q555 144 551 130Q535 71 500 33Q466 -10 419 -10H414Q367 -10 346 17T325 74Q325 90 361 192T398 345Q398 404 354 404H349Q266 404 205 306L198 293L164 158Q132 28 127 16Q114 -11 83 -11Q69 -11 59 -2T48 16Q48 30 121 320L195 616Q195 629 188 632T149 637H128Q122 643 122 645T124 664Q129 683 137 683Z" style="stroke-width: 3;"/></g><g data-mml-node="msup" transform="translate(3631.4,0)"><g data-mml-node="mo"><path data-c="2016" d="M133 736Q138 750 153 750Q164 750 170 739Q172 735 172 250T170 -239Q164 -250 152 -250Q144 -250 138 -244L137 -243Q133 -241 133 -179T132 250Q132 731 133 736ZM329 739Q334 750 346 750Q353 750 361 744L362 743Q366 741 366 679T367 250T367 -178T362 -243L361 -244Q355 -250 347 -250Q335 -250 329 -239Q327 -235 327 250T329 739Z" style="stroke-width: 3;"/></g><g data-mml-node="mn" transform="translate(533,289) scale(0.707)"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"/></g></g></g><g data-mml-node="mo" transform="translate(0,72.5)"><path data-c="221A" d="M263 249Q264 249 315 130T417 -108T470 -228L725 302Q981 837 982 839Q989 850 1001 850Q1008 850 1013 844T1020 832V826L741 243Q645 43 540 -176Q479 -303 469 -324T453 -348Q449 -350 436 -350L424 -349L315 -96Q206 156 205 156L171 130Q138 104 137 104L111 130L263 249Z" style="stroke-width: 3;"/></g><rect width="4568" height="60" x="1020" y="862.5"/></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><msqrt><mn>1</mn><mo>+</mo><mo data-mjx-texclass="OPEN" fence="false" stretchy="false">‖</mo><mi mathvariant="normal">∇</mi><mi>h</mi><msup><mo data-mjx-texclass="CLOSE" fence="false" stretchy="false">‖</mo><mn>2</mn></msup></msqrt></math></mjx-assistive-mml></mjx-container>, así que un paso dimensionado según el margen indicado se pasa de largo y puede saltar limpiamente por encima de una cresta. La solución es la subrelajación: avanzar solo una fracción del margen indicado en lugar de recorrerlo por completo. Esto sigue siendo seguro hasta pendientes de unos sesenta grados y, en las regiones de vóxeles con distancia verdadera, no cuesta nada salvo unas pocas muestras adicionales. Lo combinamos con un límite inferior para el paso, de modo que nunca se salte por completo una pared de cueva de una o dos celdas de grosor, y con un límite superior más estricto que mantiene barata la marcha. Cuando la esfera finalmente toca la superficie, una breve bisección afina el punto de contacto, y la cámara retrocede una distancia igual a su propio radio y se queda allí.</p>
<p>Expresado formalmente, el brazo es un rayo <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.566ex;" xmlns="http://www.w3.org/2000/svg" width="13.518ex" height="2.262ex" role="img" focusable="false" viewBox="0 -750 5975 1000" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="TeXAtom" data-mjx-texclass="ORD"><g data-mml-node="mi"><path data-c="1D42B" d="M405 293T374 293T324 312T305 361Q305 378 312 394Q315 397 315 399Q305 399 294 394T266 375T238 329T222 249Q221 241 221 149V62H308V0H298Q280 3 161 3Q47 3 38 0H29V62H98V210V303Q98 353 96 363T83 376Q69 380 42 380H29V442H32L118 446Q204 450 205 450H210V414L211 378Q247 449 315 449H321Q384 449 413 422T442 360Q442 332 424 313Z" style="stroke-width: 3;"/></g></g><g data-mml-node="mo" transform="translate(474,0)"><path data-c="28" d="M94 250Q94 319 104 381T127 488T164 576T202 643T244 695T277 729T302 750H315H319Q333 750 333 741Q333 738 316 720T275 667T226 581T184 443T167 250T184 58T225 -81T274 -167T316 -220T333 -241Q333 -250 318 -250H315H302L274 -226Q180 -141 137 -14T94 250Z" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(863,0)"><path data-c="1D461" d="M26 385Q19 392 19 395Q19 399 22 411T27 425Q29 430 36 430T87 431H140L159 511Q162 522 166 540T173 566T179 586T187 603T197 615T211 624T229 626Q247 625 254 615T261 596Q261 589 252 549T232 470L222 433Q222 431 272 431H323Q330 424 330 420Q330 398 317 385H210L174 240Q135 80 135 68Q135 26 162 26Q197 26 230 60T283 144Q285 150 288 151T303 153H307Q322 153 322 145Q322 142 319 133Q314 117 301 95T267 48T216 6T155 -11Q125 -11 98 4T59 56Q57 64 57 83V101L92 241Q127 382 128 383Q128 385 77 385H26Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(1224,0)"><path data-c="29" d="M60 749L64 750Q69 750 74 750H86L114 726Q208 641 251 514T294 250Q294 182 284 119T261 12T224 -76T186 -143T145 -194T113 -227T90 -246Q87 -249 86 -250H74Q66 -250 63 -250T58 -247T55 -238Q56 -237 66 -225Q221 -64 221 250T66 725Q56 737 55 738Q55 746 60 749Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(1890.8,0)"><path data-c="3D" d="M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z" style="stroke-width: 3;"/></g><g data-mml-node="TeXAtom" data-mjx-texclass="ORD" transform="translate(2946.6,0)"><g data-mml-node="mi"><path data-c="1D429" d="M32 442L123 446Q214 450 215 450H221V409Q222 409 229 413T251 423T284 436T328 446T382 450Q480 450 540 388T600 223Q600 128 539 61T361 -6H354Q292 -6 236 28L227 34V-132H296V-194H287Q269 -191 163 -191Q56 -191 38 -194H29V-132H98V113V284Q98 330 97 348T93 370T83 376Q69 380 42 380H29V442H32ZM457 224Q457 303 427 349T350 395Q282 395 235 352L227 345V104L233 97Q274 45 337 45Q383 45 420 86T457 224Z" style="stroke-width: 3;"/></g></g><g data-mml-node="mo" transform="translate(3807.8,0)"><path data-c="2B" d="M56 237T56 250T70 270H369V420L370 570Q380 583 389 583Q402 583 409 568V270H707Q722 262 722 250T707 230H409V-68Q401 -82 391 -82H389H387Q375 -82 369 -68V230H70Q56 237 56 250Z" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(4808,0)"><path data-c="1D461" d="M26 385Q19 392 19 395Q19 399 22 411T27 425Q29 430 36 430T87 431H140L159 511Q162 522 166 540T173 566T179 586T187 603T197 615T211 624T229 626Q247 625 254 615T261 596Q261 589 252 549T232 470L222 433Q222 431 272 431H323Q330 424 330 420Q330 398 317 385H210L174 240Q135 80 135 68Q135 26 162 26Q197 26 230 60T283 144Q285 150 288 151T303 153H307Q322 153 322 145Q322 142 319 133Q314 117 301 95T267 48T216 6T155 -11Q125 -11 98 4T59 56Q57 64 57 83V101L92 241Q127 382 128 383Q128 385 77 385H26Z" style="stroke-width: 3;"/></g><g data-mml-node="mstyle" transform="translate(5169,0)"><g data-mml-node="mspace"/></g><g data-mml-node="TeXAtom" data-mjx-texclass="ORD" transform="translate(5336,0)"><g data-mml-node="mi"><path data-c="1D41D" d="M351 686L442 690Q533 694 534 694H540V389Q540 327 540 253T539 163Q539 97 541 83T555 66Q569 62 596 62H609V31Q609 0 608 0Q588 0 510 -3T412 -6Q411 -6 411 16V38L401 31Q337 -6 265 -6Q159 -6 99 58T38 224Q38 265 51 303T92 375T165 429T272 449Q359 449 417 412V507V555Q417 597 415 607T402 620Q388 624 361 624H348V686H351ZM411 350Q362 399 291 399Q278 399 256 392T218 371Q195 351 189 320T182 238V221Q182 179 183 159T191 115T212 74Q241 46 288 46Q358 46 404 100L411 109V350Z" style="stroke-width: 3;"/></g></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mrow data-mjx-texclass="ORD"><mi mathvariant="bold">r</mi></mrow><mo stretchy="false">(</mo><mi>t</mi><mo stretchy="false">)</mo><mo>=</mo><mrow data-mjx-texclass="ORD"><mi mathvariant="bold">p</mi></mrow><mo>+</mo><mi>t</mi><mstyle scriptlevel="0"><mspace width="0.167em"/></mstyle><mrow data-mjx-texclass="ORD"><mi mathvariant="bold">d</mi></mrow></math></mjx-assistive-mml></mjx-container> que parte del pivote <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.439ex;" xmlns="http://www.w3.org/2000/svg" width="1.446ex" height="1.457ex" role="img" focusable="false" viewBox="0 -450 639 644" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="TeXAtom" data-mjx-texclass="ORD"><g data-mml-node="mi"><path data-c="1D429" d="M32 442L123 446Q214 450 215 450H221V409Q222 409 229 413T251 423T284 436T328 446T382 450Q480 450 540 388T600 223Q600 128 539 61T361 -6H354Q292 -6 236 28L227 34V-132H296V-194H287Q269 -191 163 -191Q56 -191 38 -194H29V-132H98V113V284Q98 330 97 348T93 370T83 376Q69 380 42 380H29V442H32ZM457 224Q457 303 427 349T350 395Q282 395 235 352L227 345V104L233 97Q274 45 337 45Q383 45 420 86T457 224Z" style="stroke-width: 3;"/></g></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mrow data-mjx-texclass="ORD"><mi mathvariant="bold">p</mi></mrow></math></mjx-assistive-mml></mjx-container> en la dirección unitaria <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.014ex;" xmlns="http://www.w3.org/2000/svg" width="1.446ex" height="1.584ex" role="img" focusable="false" viewBox="0 -694 639 700" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="TeXAtom" data-mjx-texclass="ORD"><g data-mml-node="mi"><path data-c="1D41D" d="M351 686L442 690Q533 694 534 694H540V389Q540 327 540 253T539 163Q539 97 541 83T555 66Q569 62 596 62H609V31Q609 0 608 0Q588 0 510 -3T412 -6Q411 -6 411 16V38L401 31Q337 -6 265 -6Q159 -6 99 58T38 224Q38 265 51 303T92 375T165 429T272 449Q359 449 417 412V507V555Q417 597 415 607T402 620Q388 624 361 624H348V686H351ZM411 350Q362 399 291 399Q278 399 256 392T218 371Q195 351 189 320T182 238V221Q182 179 183 159T191 115T212 74Q241 46 288 46Q358 46 404 100L411 109V350Z" style="stroke-width: 3;"/></g></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mrow data-mjx-texclass="ORD"><mi mathvariant="bold">d</mi></mrow></math></mjx-assistive-mml></mjx-container>, y la marcha avanza una fracción subrelajada del margen hasta el contacto que indica el campo, limitada por ambos extremos:</p>
<mjx-container tabindex="0" class="MathJax" jax="SVG" display="true" style="direction: ltr; display: block; text-align: center; margin: 1em 0; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.791ex;" xmlns="http://www.w3.org/2000/svg" width="46.581ex" height="2.713ex" role="img" focusable="false" viewBox="0 -849.5 20588.6 1199" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="msub"><g data-mml-node="mi"><path data-c="1D461" d="M26 385Q19 392 19 395Q19 399 22 411T27 425Q29 430 36 430T87 431H140L159 511Q162 522 166 540T173 566T179 586T187 603T197 615T211 624T229 626Q247 625 254 615T261 596Q261 589 252 549T232 470L222 433Q222 431 272 431H323Q330 424 330 420Q330 398 317 385H210L174 240Q135 80 135 68Q135 26 162 26Q197 26 230 60T283 144Q285 150 288 151T303 153H307Q322 153 322 145Q322 142 319 133Q314 117 301 95T267 48T216 6T155 -11Q125 -11 98 4T59 56Q57 64 57 83V101L92 241Q127 382 128 383Q128 385 77 385H26Z" style="stroke-width: 3;"/></g><g data-mml-node="TeXAtom" transform="translate(394,-150) scale(0.707)" data-mjx-texclass="ORD"><g data-mml-node="mi"><path data-c="1D45B" d="M21 287Q22 293 24 303T36 341T56 388T89 425T135 442Q171 442 195 424T225 390T231 369Q231 367 232 367L243 378Q304 442 382 442Q436 442 469 415T503 336T465 179T427 52Q427 26 444 26Q450 26 453 27Q482 32 505 65T540 145Q542 153 560 153Q580 153 580 145Q580 144 576 130Q568 101 554 73T508 17T439 -10Q392 -10 371 17T350 73Q350 92 386 193T423 345Q423 404 379 404H374Q288 404 229 303L222 291L189 157Q156 26 151 16Q138 -11 108 -11Q95 -11 87 -5T76 7T74 17Q74 30 112 180T152 343Q153 348 153 366Q153 405 129 405Q91 405 66 305Q60 285 60 284Q58 278 41 278H27Q21 284 21 287Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(600,0)"><path data-c="2B" d="M56 237T56 250T70 270H369V420L370 570Q380 583 389 583Q402 583 409 568V270H707Q722 262 722 250T707 230H409V-68Q401 -82 391 -82H389H387Q375 -82 369 -68V230H70Q56 237 56 250Z" style="stroke-width: 3;"/></g><g data-mml-node="mn" transform="translate(1378,0)"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" style="stroke-width: 3;"/></g></g></g><g data-mml-node="mo" transform="translate(2049.7,0)"><path data-c="3D" d="M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z" style="stroke-width: 3;"/></g><g data-mml-node="msub" transform="translate(3105.5,0)"><g data-mml-node="mi"><path data-c="1D461" d="M26 385Q19 392 19 395Q19 399 22 411T27 425Q29 430 36 430T87 431H140L159 511Q162 522 166 540T173 566T179 586T187 603T197 615T211 624T229 626Q247 625 254 615T261 596Q261 589 252 549T232 470L222 433Q222 431 272 431H323Q330 424 330 420Q330 398 317 385H210L174 240Q135 80 135 68Q135 26 162 26Q197 26 230 60T283 144Q285 150 288 151T303 153H307Q322 153 322 145Q322 142 319 133Q314 117 301 95T267 48T216 6T155 -11Q125 -11 98 4T59 56Q57 64 57 83V101L92 241Q127 382 128 383Q128 385 77 385H26Z" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(394,-150) scale(0.707)"><path data-c="1D45B" d="M21 287Q22 293 24 303T36 341T56 388T89 425T135 442Q171 442 195 424T225 390T231 369Q231 367 232 367L243 378Q304 442 382 442Q436 442 469 415T503 336T465 179T427 52Q427 26 444 26Q450 26 453 27Q482 32 505 65T540 145Q542 153 560 153Q580 153 580 145Q580 144 576 130Q568 101 554 73T508 17T439 -10Q392 -10 371 17T350 73Q350 92 386 193T423 345Q423 404 379 404H374Q288 404 229 303L222 291L189 157Q156 26 151 16Q138 -11 108 -11Q95 -11 87 -5T76 7T74 17Q74 30 112 180T152 343Q153 348 153 366Q153 405 129 405Q91 405 66 305Q60 285 60 284Q58 278 41 278H27Q21 284 21 287Z" style="stroke-width: 3;"/></g></g><g data-mml-node="mo" transform="translate(4196,0)"><path data-c="2B" d="M56 237T56 250T70 270H369V420L370 570Q380 583 389 583Q402 583 409 568V270H707Q722 262 722 250T707 230H409V-68Q401 -82 391 -82H389H387Q375 -82 369 -68V230H70Q56 237 56 250Z" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(5196.2,0)"><path data-c="63" d="M370 305T349 305T313 320T297 358Q297 381 312 396Q317 401 317 402T307 404Q281 408 258 408Q209 408 178 376Q131 329 131 219Q131 137 162 90Q203 29 272 29Q313 29 338 55T374 117Q376 125 379 127T395 129H409Q415 123 415 120Q415 116 411 104T395 71T366 33T318 2T249 -11Q163 -11 99 53T34 214Q34 318 99 383T250 448T370 421T404 357Q404 334 387 320Z" style="stroke-width: 3;"/><path data-c="6C" d="M42 46H56Q95 46 103 60V68Q103 77 103 91T103 124T104 167T104 217T104 272T104 329Q104 366 104 407T104 482T104 542T103 586T103 603Q100 622 89 628T44 637H26V660Q26 683 28 683L38 684Q48 685 67 686T104 688Q121 689 141 690T171 693T182 694H185V379Q185 62 186 60Q190 52 198 49Q219 46 247 46H263V0H255L232 1Q209 2 183 2T145 3T107 3T57 1L34 0H26V46H42Z" transform="translate(444,0)" style="stroke-width: 3;"/><path data-c="61" d="M137 305T115 305T78 320T63 359Q63 394 97 421T218 448Q291 448 336 416T396 340Q401 326 401 309T402 194V124Q402 76 407 58T428 40Q443 40 448 56T453 109V145H493V106Q492 66 490 59Q481 29 455 12T400 -6T353 12T329 54V58L327 55Q325 52 322 49T314 40T302 29T287 17T269 6T247 -2T221 -8T190 -11Q130 -11 82 20T34 107Q34 128 41 147T68 188T116 225T194 253T304 268H318V290Q318 324 312 340Q290 411 215 411Q197 411 181 410T156 406T148 403Q170 388 170 359Q170 334 154 320ZM126 106Q126 75 150 51T209 26Q247 26 276 49T315 109Q317 116 318 175Q318 233 317 233Q309 233 296 232T251 223T193 203T147 166T126 106Z" transform="translate(722,0)" style="stroke-width: 3;"/><path data-c="6D" d="M41 46H55Q94 46 102 60V68Q102 77 102 91T102 122T103 161T103 203Q103 234 103 269T102 328V351Q99 370 88 376T43 385H25V408Q25 431 27 431L37 432Q47 433 65 434T102 436Q119 437 138 438T167 441T178 442H181V402Q181 364 182 364T187 369T199 384T218 402T247 421T285 437Q305 442 336 442Q351 442 364 440T387 434T406 426T421 417T432 406T441 395T448 384T452 374T455 366L457 361L460 365Q463 369 466 373T475 384T488 397T503 410T523 422T546 432T572 439T603 442Q729 442 740 329Q741 322 741 190V104Q741 66 743 59T754 49Q775 46 803 46H819V0H811L788 1Q764 2 737 2T699 3Q596 3 587 0H579V46H595Q656 46 656 62Q657 64 657 200Q656 335 655 343Q649 371 635 385T611 402T585 404Q540 404 506 370Q479 343 472 315T464 232V168V108Q464 78 465 68T468 55T477 49Q498 46 526 46H542V0H534L510 1Q487 2 460 2T422 3Q319 3 310 0H302V46H318Q379 46 379 62Q380 64 380 200Q379 335 378 343Q372 371 358 385T334 402T308 404Q263 404 229 370Q202 343 195 315T187 232V168V108Q187 78 188 68T191 55T200 49Q221 46 249 46H265V0H257L234 1Q210 2 183 2T145 3Q42 3 33 0H25V46H41Z" transform="translate(1222,0)" style="stroke-width: 3;"/><path data-c="70" d="M36 -148H50Q89 -148 97 -134V-126Q97 -119 97 -107T97 -77T98 -38T98 6T98 55T98 106Q98 140 98 177T98 243T98 296T97 335T97 351Q94 370 83 376T38 385H20V408Q20 431 22 431L32 432Q42 433 61 434T98 436Q115 437 135 438T165 441T176 442H179V416L180 390L188 397Q247 441 326 441Q407 441 464 377T522 216Q522 115 457 52T310 -11Q242 -11 190 33L182 40V-45V-101Q182 -128 184 -134T195 -145Q216 -148 244 -148H260V-194H252L228 -193Q205 -192 178 -192T140 -191Q37 -191 28 -194H20V-148H36ZM424 218Q424 292 390 347T305 402Q234 402 182 337V98Q222 26 294 26Q345 26 384 80T424 218Z" transform="translate(2055,0)" style="stroke-width: 3;"/></g><g data-mml-node="mstyle" transform="translate(7807.2,0)"><g data-mml-node="mspace"/></g><g data-mml-node="TeXAtom" data-mjx-texclass="ORD" transform="translate(7806.9,0)"><g data-mml-node="mo" transform="translate(0 -0.5)"><path data-c="28" d="M152 251Q152 646 388 850H416Q422 844 422 841Q422 837 403 816T357 753T302 649T255 482T236 250Q236 124 255 19T301 -147T356 -251T403 -315T422 -340Q422 -343 416 -349H388Q359 -325 332 -296T271 -213T212 -97T170 56T152 251Z" style="stroke-width: 3;"/></g></g><g data-mml-node="mi" transform="translate(8264.9,0)"><path data-c="1D706" d="M166 673Q166 685 183 694H202Q292 691 316 644Q322 629 373 486T474 207T524 67Q531 47 537 34T546 15T551 6T555 2T556 -2T550 -11H482Q457 3 450 18T399 152L354 277L340 262Q327 246 293 207T236 141Q211 112 174 69Q123 9 111 -1T83 -12Q47 -12 47 20Q47 37 61 52T199 187Q229 216 266 252T321 306L338 322Q338 323 288 462T234 612Q214 657 183 657Q166 657 166 673Z" style="stroke-width: 3;"/></g><g data-mml-node="mstyle" transform="translate(8847.9,0)"><g data-mml-node="mspace"/></g><g data-mml-node="mo" transform="translate(9014.9,0)"><path data-c="28" d="M94 250Q94 319 104 381T127 488T164 576T202 643T244 695T277 729T302 750H315H319Q333 750 333 741Q333 738 316 720T275 667T226 581T184 443T167 250T184 58T225 -81T274 -167T316 -220T333 -241Q333 -250 318 -250H315H302L274 -226Q180 -141 137 -14T94 250Z" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(9403.9,0)"><path data-c="3A6" d="M312 622Q310 623 307 625T303 629T297 631T286 634T270 635T246 636T211 637H184V683H196Q220 680 361 680T526 683H538V637H511Q468 637 447 635T422 631T411 622V533L425 531Q525 519 595 466T665 342Q665 301 642 267T583 209T506 172T425 152L411 150V61Q417 55 421 53T447 48T511 46H538V0H526Q502 3 361 3T196 0H184V46H211Q231 46 245 46T270 47T286 48T297 51T303 54T307 57T312 61V150H310Q309 151 289 153T232 166T160 195Q149 201 136 210T103 238T69 284T56 342Q56 414 128 467T294 530Q309 532 310 533H312V622ZM170 342Q170 207 307 188H312V495H309Q301 495 282 491T231 469T186 423Q170 389 170 342ZM415 188Q487 199 519 236T551 342Q551 384 539 414T507 459T470 481T434 491T415 495H410V188H415Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(10125.9,0)"><path data-c="28" d="M94 250Q94 319 104 381T127 488T164 576T202 643T244 695T277 729T302 750H315H319Q333 750 333 741Q333 738 316 720T275 667T226 581T184 443T167 250T184 58T225 -81T274 -167T316 -220T333 -241Q333 -250 318 -250H315H302L274 -226Q180 -141 137 -14T94 250Z" style="stroke-width: 3;"/></g><g data-mml-node="TeXAtom" data-mjx-texclass="ORD" transform="translate(10514.9,0)"><g data-mml-node="mi"><path data-c="1D42B" d="M405 293T374 293T324 312T305 361Q305 378 312 394Q315 397 315 399Q305 399 294 394T266 375T238 329T222 249Q221 241 221 149V62H308V0H298Q280 3 161 3Q47 3 38 0H29V62H98V210V303Q98 353 96 363T83 376Q69 380 42 380H29V442H32L118 446Q204 450 205 450H210V414L211 378Q247 449 315 449H321Q384 449 413 422T442 360Q442 332 424 313Z" style="stroke-width: 3;"/></g></g><g data-mml-node="mo" transform="translate(10988.9,0)"><path data-c="28" d="M94 250Q94 319 104 381T127 488T164 576T202 643T244 695T277 729T302 750H315H319Q333 750 333 741Q333 738 316 720T275 667T226 581T184 443T167 250T184 58T225 -81T274 -167T316 -220T333 -241Q333 -250 318 -250H315H302L274 -226Q180 -141 137 -14T94 250Z" style="stroke-width: 3;"/></g><g data-mml-node="msub" transform="translate(11377.9,0)"><g data-mml-node="mi"><path data-c="1D461" d="M26 385Q19 392 19 395Q19 399 22 411T27 425Q29 430 36 430T87 431H140L159 511Q162 522 166 540T173 566T179 586T187 603T197 615T211 624T229 626Q247 625 254 615T261 596Q261 589 252 549T232 470L222 433Q222 431 272 431H323Q330 424 330 420Q330 398 317 385H210L174 240Q135 80 135 68Q135 26 162 26Q197 26 230 60T283 144Q285 150 288 151T303 153H307Q322 153 322 145Q322 142 319 133Q314 117 301 95T267 48T216 6T155 -11Q125 -11 98 4T59 56Q57 64 57 83V101L92 241Q127 382 128 383Q128 385 77 385H26Z" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(394,-150) scale(0.707)"><path data-c="1D45B" d="M21 287Q22 293 24 303T36 341T56 388T89 425T135 442Q171 442 195 424T225 390T231 369Q231 367 232 367L243 378Q304 442 382 442Q436 442 469 415T503 336T465 179T427 52Q427 26 444 26Q450 26 453 27Q482 32 505 65T540 145Q542 153 560 153Q580 153 580 145Q580 144 576 130Q568 101 554 73T508 17T439 -10Q392 -10 371 17T350 73Q350 92 386 193T423 345Q423 404 379 404H374Q288 404 229 303L222 291L189 157Q156 26 151 16Q138 -11 108 -11Q95 -11 87 -5T76 7T74 17Q74 30 112 180T152 343Q153 348 153 366Q153 405 129 405Q91 405 66 305Q60 285 60 284Q58 278 41 278H27Q21 284 21 287Z" style="stroke-width: 3;"/></g></g><g data-mml-node="mo" transform="translate(12246.1,0)"><path data-c="29" d="M60 749L64 750Q69 750 74 750H86L114 726Q208 641 251 514T294 250Q294 182 284 119T261 12T224 -76T186 -143T145 -194T113 -227T90 -246Q87 -249 86 -250H74Q66 -250 63 -250T58 -247T55 -238Q56 -237 66 -225Q221 -64 221 250T66 725Q56 737 55 738Q55 746 60 749Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(12635.1,0)"><path data-c="29" d="M60 749L64 750Q69 750 74 750H86L114 726Q208 641 251 514T294 250Q294 182 284 119T261 12T224 -76T186 -143T145 -194T113 -227T90 -246Q87 -249 86 -250H74Q66 -250 63 -250T58 -247T55 -238Q56 -237 66 -225Q221 -64 221 250T66 725Q56 737 55 738Q55 746 60 749Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(13246.4,0)"><path data-c="2212" d="M84 237T84 250T98 270H679Q694 262 694 250T679 230H98Q84 237 84 250Z" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(14246.6,0)"><path data-c="1D45F" d="M21 287Q22 290 23 295T28 317T38 348T53 381T73 411T99 433T132 442Q161 442 183 430T214 408T225 388Q227 382 228 382T236 389Q284 441 347 441H350Q398 441 422 400Q430 381 430 363Q430 333 417 315T391 292T366 288Q346 288 334 299T322 328Q322 376 378 392Q356 405 342 405Q286 405 239 331Q229 315 224 298T190 165Q156 25 151 16Q138 -11 108 -11Q95 -11 87 -5T76 7T74 17Q74 30 114 189T154 366Q154 405 128 405Q107 405 92 377T68 316T57 280Q55 278 41 278H27Q21 284 21 287Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(14697.6,0)"><path data-c="29" d="M60 749L64 750Q69 750 74 750H86L114 726Q208 641 251 514T294 250Q294 182 284 119T261 12T224 -76T186 -143T145 -194T113 -227T90 -246Q87 -249 86 -250H74Q66 -250 63 -250T58 -247T55 -238Q56 -237 66 -225Q221 -64 221 250T66 725Q56 737 55 738Q55 746 60 749Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(15086.6,0)"><path data-c="2C" d="M78 35T78 60T94 103T137 121Q165 121 187 96T210 8Q210 -27 201 -60T180 -117T154 -158T130 -185T117 -194Q113 -194 104 -185T95 -172Q95 -168 106 -156T131 -126T157 -76T173 -3V9L172 8Q170 7 167 6T161 3T152 1T140 0Q113 0 96 17Z" style="stroke-width: 3;"/></g><g data-mml-node="mstyle" transform="translate(15364.6,0)"><g data-mml-node="mspace"/></g><g data-mml-node="msub" transform="translate(15809.3,0)"><g data-mml-node="mi"><path data-c="1D460" d="M131 289Q131 321 147 354T203 415T300 442Q362 442 390 415T419 355Q419 323 402 308T364 292Q351 292 340 300T328 326Q328 342 337 354T354 372T367 378Q368 378 368 379Q368 382 361 388T336 399T297 405Q249 405 227 379T204 326Q204 301 223 291T278 274T330 259Q396 230 396 163Q396 135 385 107T352 51T289 7T195 -10Q118 -10 86 19T53 87Q53 126 74 143T118 160Q133 160 146 151T160 120Q160 94 142 76T111 58Q109 57 108 57T107 55Q108 52 115 47T146 34T201 27Q237 27 263 38T301 66T318 97T323 122Q323 150 302 164T254 181T195 196T148 231Q131 256 131 289Z" style="stroke-width: 3;"/></g><g data-mml-node="TeXAtom" transform="translate(502,-150) scale(0.707)" data-mjx-texclass="ORD"><g data-mml-node="mo"><path data-c="6D" d="M41 46H55Q94 46 102 60V68Q102 77 102 91T102 122T103 161T103 203Q103 234 103 269T102 328V351Q99 370 88 376T43 385H25V408Q25 431 27 431L37 432Q47 433 65 434T102 436Q119 437 138 438T167 441T178 442H181V402Q181 364 182 364T187 369T199 384T218 402T247 421T285 437Q305 442 336 442Q351 442 364 440T387 434T406 426T421 417T432 406T441 395T448 384T452 374T455 366L457 361L460 365Q463 369 466 373T475 384T488 397T503 410T523 422T546 432T572 439T603 442Q729 442 740 329Q741 322 741 190V104Q741 66 743 59T754 49Q775 46 803 46H819V0H811L788 1Q764 2 737 2T699 3Q596 3 587 0H579V46H595Q656 46 656 62Q657 64 657 200Q656 335 655 343Q649 371 635 385T611 402T585 404Q540 404 506 370Q479 343 472 315T464 232V168V108Q464 78 465 68T468 55T477 49Q498 46 526 46H542V0H534L510 1Q487 2 460 2T422 3Q319 3 310 0H302V46H318Q379 46 379 62Q380 64 380 200Q379 335 378 343Q372 371 358 385T334 402T308 404Q263 404 229 370Q202 343 195 315T187 232V168V108Q187 78 188 68T191 55T200 49Q221 46 249 46H265V0H257L234 1Q210 2 183 2T145 3Q42 3 33 0H25V46H41Z" style="stroke-width: 3;"/><path data-c="69" d="M69 609Q69 637 87 653T131 669Q154 667 171 652T188 609Q188 579 171 564T129 549Q104 549 87 564T69 609ZM247 0Q232 3 143 3Q132 3 106 3T56 1L34 0H26V46H42Q70 46 91 49Q100 53 102 60T104 102V205V293Q104 345 102 359T88 378Q74 385 41 385H30V408Q30 431 32 431L42 432Q52 433 70 434T106 436Q123 437 142 438T171 441T182 442H185V62Q190 52 197 50T232 46H255V0H247Z" transform="translate(833,0)" style="stroke-width: 3;"/><path data-c="6E" d="M41 46H55Q94 46 102 60V68Q102 77 102 91T102 122T103 161T103 203Q103 234 103 269T102 328V351Q99 370 88 376T43 385H25V408Q25 431 27 431L37 432Q47 433 65 434T102 436Q119 437 138 438T167 441T178 442H181V402Q181 364 182 364T187 369T199 384T218 402T247 421T285 437Q305 442 336 442Q450 438 463 329Q464 322 464 190V104Q464 66 466 59T477 49Q498 46 526 46H542V0H534L510 1Q487 2 460 2T422 3Q319 3 310 0H302V46H318Q379 46 379 62Q380 64 380 200Q379 335 378 343Q372 371 358 385T334 402T308 404Q263 404 229 370Q202 343 195 315T187 232V168V108Q187 78 188 68T191 55T200 49Q221 46 249 46H265V0H257L234 1Q210 2 183 2T145 3Q42 3 33 0H25V46H41Z" transform="translate(1111,0)" style="stroke-width: 3;"/></g></g></g><g data-mml-node="mo" transform="translate(17540,0)"><path data-c="2C" d="M78 35T78 60T94 103T137 121Q165 121 187 96T210 8Q210 -27 201 -60T180 -117T154 -158T130 -185T117 -194Q113 -194 104 -185T95 -172Q95 -168 106 -156T131 -126T157 -76T173 -3V9L172 8Q170 7 167 6T161 3T152 1T140 0Q113 0 96 17Z" style="stroke-width: 3;"/></g><g data-mml-node="mstyle" transform="translate(17818,0)"><g data-mml-node="mspace"/></g><g data-mml-node="msub" transform="translate(18262.7,0)"><g data-mml-node="mi"><path data-c="1D460" d="M131 289Q131 321 147 354T203 415T300 442Q362 442 390 415T419 355Q419 323 402 308T364 292Q351 292 340 300T328 326Q328 342 337 354T354 372T367 378Q368 378 368 379Q368 382 361 388T336 399T297 405Q249 405 227 379T204 326Q204 301 223 291T278 274T330 259Q396 230 396 163Q396 135 385 107T352 51T289 7T195 -10Q118 -10 86 19T53 87Q53 126 74 143T118 160Q133 160 146 151T160 120Q160 94 142 76T111 58Q109 57 108 57T107 55Q108 52 115 47T146 34T201 27Q237 27 263 38T301 66T318 97T323 122Q323 150 302 164T254 181T195 196T148 231Q131 256 131 289Z" style="stroke-width: 3;"/></g><g data-mml-node="TeXAtom" transform="translate(502,-150) scale(0.707)" data-mjx-texclass="ORD"><g data-mml-node="mo"><path data-c="6D" d="M41 46H55Q94 46 102 60V68Q102 77 102 91T102 122T103 161T103 203Q103 234 103 269T102 328V351Q99 370 88 376T43 385H25V408Q25 431 27 431L37 432Q47 433 65 434T102 436Q119 437 138 438T167 441T178 442H181V402Q181 364 182 364T187 369T199 384T218 402T247 421T285 437Q305 442 336 442Q351 442 364 440T387 434T406 426T421 417T432 406T441 395T448 384T452 374T455 366L457 361L460 365Q463 369 466 373T475 384T488 397T503 410T523 422T546 432T572 439T603 442Q729 442 740 329Q741 322 741 190V104Q741 66 743 59T754 49Q775 46 803 46H819V0H811L788 1Q764 2 737 2T699 3Q596 3 587 0H579V46H595Q656 46 656 62Q657 64 657 200Q656 335 655 343Q649 371 635 385T611 402T585 404Q540 404 506 370Q479 343 472 315T464 232V168V108Q464 78 465 68T468 55T477 49Q498 46 526 46H542V0H534L510 1Q487 2 460 2T422 3Q319 3 310 0H302V46H318Q379 46 379 62Q380 64 380 200Q379 335 378 343Q372 371 358 385T334 402T308 404Q263 404 229 370Q202 343 195 315T187 232V168V108Q187 78 188 68T191 55T200 49Q221 46 249 46H265V0H257L234 1Q210 2 183 2T145 3Q42 3 33 0H25V46H41Z" style="stroke-width: 3;"/><path data-c="61" d="M137 305T115 305T78 320T63 359Q63 394 97 421T218 448Q291 448 336 416T396 340Q401 326 401 309T402 194V124Q402 76 407 58T428 40Q443 40 448 56T453 109V145H493V106Q492 66 490 59Q481 29 455 12T400 -6T353 12T329 54V58L327 55Q325 52 322 49T314 40T302 29T287 17T269 6T247 -2T221 -8T190 -11Q130 -11 82 20T34 107Q34 128 41 147T68 188T116 225T194 253T304 268H318V290Q318 324 312 340Q290 411 215 411Q197 411 181 410T156 406T148 403Q170 388 170 359Q170 334 154 320ZM126 106Q126 75 150 51T209 26Q247 26 276 49T315 109Q317 116 318 175Q318 233 317 233Q309 233 296 232T251 223T193 203T147 166T126 106Z" transform="translate(833,0)" style="stroke-width: 3;"/><path data-c="78" d="M201 0Q189 3 102 3Q26 3 17 0H11V46H25Q48 47 67 52T96 61T121 78T139 96T160 122T180 150L226 210L168 288Q159 301 149 315T133 336T122 351T113 363T107 370T100 376T94 379T88 381T80 383Q74 383 44 385H16V431H23Q59 429 126 429Q219 429 229 431H237V385Q201 381 201 369Q201 367 211 353T239 315T268 274L272 270L297 304Q329 345 329 358Q329 364 327 369T322 376T317 380T310 384L307 385H302V431H309Q324 428 408 428Q487 428 493 431H499V385H492Q443 385 411 368Q394 360 377 341T312 257L296 236L358 151Q424 61 429 57T446 50Q464 46 499 46H516V0H510H502Q494 1 482 1T457 2T432 2T414 3Q403 3 377 3T327 1L304 0H295V46H298Q309 46 320 51T331 63Q331 65 291 120L250 175Q249 174 219 133T185 88Q181 83 181 74Q181 63 188 55T206 46Q208 46 208 23V0H201Z" transform="translate(1333,0)" style="stroke-width: 3;"/></g></g></g><g data-mml-node="TeXAtom" data-mjx-texclass="ORD" transform="translate(20130.6,0)"><g data-mml-node="mo" transform="translate(0 -0.5)"><path data-c="29" d="M305 251Q305 -145 69 -349H56Q43 -349 39 -347T35 -338Q37 -333 60 -307T108 -239T160 -136T204 27T221 250T204 473T160 636T108 740T60 807T35 839Q35 850 50 850H56H69Q197 743 256 566Q305 425 305 251Z" style="stroke-width: 3;"/></g></g></g></g></svg><mjx-assistive-mml unselectable="on" display="block" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; overflow: hidden; width: 100%;"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><msub><mi>t</mi><mrow data-mjx-texclass="ORD"><mi>n</mi><mo>+</mo><mn>1</mn></mrow></msub><mo>=</mo><msub><mi>t</mi><mi>n</mi></msub><mo>+</mo><mi>clamp</mi><mstyle scriptlevel="0"><mspace width="-0.167em"/></mstyle><mrow data-mjx-texclass="ORD"><mo minsize="1.2em" maxsize="1.2em">(</mo></mrow><mi>λ</mi><mstyle scriptlevel="0"><mspace width="0.167em"/></mstyle><mo stretchy="false">(</mo><mi mathvariant="normal">Φ</mi><mo stretchy="false">(</mo><mrow data-mjx-texclass="ORD"><mi mathvariant="bold">r</mi></mrow><mo stretchy="false">(</mo><msub><mi>t</mi><mi>n</mi></msub><mo stretchy="false">)</mo><mo stretchy="false">)</mo><mo>−</mo><mi>r</mi><mo stretchy="false">)</mo><mo>,</mo><mstyle scriptlevel="0"><mspace width="0.278em"/></mstyle><msub><mi>s</mi><mrow data-mjx-texclass="ORD"><mo data-mjx-texclass="OP" movablelimits="true">min</mo></mrow></msub><mo>,</mo><mstyle scriptlevel="0"><mspace width="0.278em"/></mstyle><msub><mi>s</mi><mrow data-mjx-texclass="ORD"><mo data-mjx-texclass="OP" movablelimits="true">max</mo></mrow></msub><mrow data-mjx-texclass="ORD"><mo minsize="1.2em" maxsize="1.2em">)</mo></mrow></math></mjx-assistive-mml></mjx-container><p>Aquí, <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: 0;" xmlns="http://www.w3.org/2000/svg" width="1.633ex" height="1.545ex" role="img" focusable="false" viewBox="0 -683 722 683" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mi"><path data-c="3A6" d="M312 622Q310 623 307 625T303 629T297 631T286 634T270 635T246 636T211 637H184V683H196Q220 680 361 680T526 683H538V637H511Q468 637 447 635T422 631T411 622V533L425 531Q525 519 595 466T665 342Q665 301 642 267T583 209T506 172T425 152L411 150V61Q417 55 421 53T447 48T511 46H538V0H526Q502 3 361 3T196 0H184V46H211Q231 46 245 46T270 47T286 48T297 51T303 54T307 57T312 61V150H310Q309 151 289 153T232 166T160 195Q149 201 136 210T103 238T69 284T56 342Q56 414 128 467T294 530Q309 532 310 533H312V622ZM170 342Q170 207 307 188H312V495H309Q301 495 282 491T231 469T186 423Q170 389 170 342ZM415 188Q487 199 519 236T551 342Q551 384 539 414T507 459T470 481T434 491T415 495H410V188H415Z" style="stroke-width: 3;"/></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mi mathvariant="normal">Φ</mi></math></mjx-assistive-mml></mjx-container> es la distancia con signo, positiva en el aire y negativa en la roca; <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.025ex;" xmlns="http://www.w3.org/2000/svg" width="1.02ex" height="1.025ex" role="img" focusable="false" viewBox="0 -442 451 453" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mi"><path data-c="1D45F" d="M21 287Q22 290 23 295T28 317T38 348T53 381T73 411T99 433T132 442Q161 442 183 430T214 408T225 388Q227 382 228 382T236 389Q284 441 347 441H350Q398 441 422 400Q430 381 430 363Q430 333 417 315T391 292T366 288Q346 288 334 299T322 328Q322 376 378 392Q356 405 342 405Q286 405 239 331Q229 315 224 298T190 165Q156 25 151 16Q138 -11 108 -11Q95 -11 87 -5T76 7T74 17Q74 30 114 189T154 366Q154 405 128 405Q107 405 92 377T68 316T57 280Q55 278 41 278H27Q21 284 21 287Z" style="stroke-width: 3;"/></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mi>r</mi></math></mjx-assistive-mml></mjx-container> es el radio de la sonda; <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.566ex;" xmlns="http://www.w3.org/2000/svg" width="8.862ex" height="2.262ex" role="img" focusable="false" viewBox="0 -750 3917.2 1000" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mi"><path data-c="1D706" d="M166 673Q166 685 183 694H202Q292 691 316 644Q322 629 373 486T474 207T524 67Q531 47 537 34T546 15T551 6T555 2T556 -2T550 -11H482Q457 3 450 18T399 152L354 277L340 262Q327 246 293 207T236 141Q211 112 174 69Q123 9 111 -1T83 -12Q47 -12 47 20Q47 37 61 52T199 187Q229 216 266 252T321 306L338 322Q338 323 288 462T234 612Q214 657 183 657Q166 657 166 673Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(860.8,0)"><path data-c="2208" d="M84 250Q84 372 166 450T360 539Q361 539 377 539T419 540T469 540H568Q583 532 583 520Q583 511 570 501L466 500Q355 499 329 494Q280 482 242 458T183 409T147 354T129 306T124 272V270H568Q583 262 583 250T568 230H124V228Q124 207 134 177T167 112T231 48T328 7Q355 1 466 0H570Q583 -10 583 -20Q583 -32 568 -40H471Q464 -40 446 -40T417 -41Q262 -41 172 45Q84 127 84 250Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(1805.6,0)"><path data-c="28" d="M94 250Q94 319 104 381T127 488T164 576T202 643T244 695T277 729T302 750H315H319Q333 750 333 741Q333 738 316 720T275 667T226 581T184 443T167 250T184 58T225 -81T274 -167T316 -220T333 -241Q333 -250 318 -250H315H302L274 -226Q180 -141 137 -14T94 250Z" style="stroke-width: 3;"/></g><g data-mml-node="mn" transform="translate(2194.6,0)"><path data-c="30" d="M96 585Q152 666 249 666Q297 666 345 640T423 548Q460 465 460 320Q460 165 417 83Q397 41 362 16T301 -15T250 -22Q224 -22 198 -16T137 16T82 83Q39 165 39 320Q39 494 96 585ZM321 597Q291 629 250 629Q208 629 178 597Q153 571 145 525T137 333Q137 175 145 125T181 46Q209 16 250 16Q290 16 318 46Q347 76 354 130T362 333Q362 478 354 524T321 597Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(2694.6,0)"><path data-c="2C" d="M78 35T78 60T94 103T137 121Q165 121 187 96T210 8Q210 -27 201 -60T180 -117T154 -158T130 -185T117 -194Q113 -194 104 -185T95 -172Q95 -168 106 -156T131 -126T157 -76T173 -3V9L172 8Q170 7 167 6T161 3T152 1T140 0Q113 0 96 17Z" style="stroke-width: 3;"/></g><g data-mml-node="mn" transform="translate(3139.2,0)"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(3639.2,0)"><path data-c="5D" d="M22 710V750H159V-250H22V-210H119V710H22Z" style="stroke-width: 3;"/></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mi>λ</mi><mo>∈</mo><mo stretchy="false">(</mo><mn>0</mn><mo>,</mo><mn>1</mn><mo stretchy="false">]</mo></math></mjx-assistive-mml></mjx-container> es el factor de subrelajación que evita que el campo del mapa de alturas, al exagerar la distancia, salte una pendiente; y <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.439ex;" xmlns="http://www.w3.org/2000/svg" width="9.148ex" height="1.439ex" role="img" focusable="false" viewBox="0 -442 4043.3 636" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="msub"><g data-mml-node="mi"><path data-c="1D460" d="M131 289Q131 321 147 354T203 415T300 442Q362 442 390 415T419 355Q419 323 402 308T364 292Q351 292 340 300T328 326Q328 342 337 354T354 372T367 378Q368 378 368 379Q368 382 361 388T336 399T297 405Q249 405 227 379T204 326Q204 301 223 291T278 274T330 259Q396 230 396 163Q396 135 385 107T352 51T289 7T195 -10Q118 -10 86 19T53 87Q53 126 74 143T118 160Q133 160 146 151T160 120Q160 94 142 76T111 58Q109 57 108 57T107 55Q108 52 115 47T146 34T201 27Q237 27 263 38T301 66T318 97T323 122Q323 150 302 164T254 181T195 196T148 231Q131 256 131 289Z" style="stroke-width: 3;"/></g><g data-mml-node="TeXAtom" transform="translate(502,-150) scale(0.707)" data-mjx-texclass="ORD"><g data-mml-node="mo"><path data-c="6D" d="M41 46H55Q94 46 102 60V68Q102 77 102 91T102 122T103 161T103 203Q103 234 103 269T102 328V351Q99 370 88 376T43 385H25V408Q25 431 27 431L37 432Q47 433 65 434T102 436Q119 437 138 438T167 441T178 442H181V402Q181 364 182 364T187 369T199 384T218 402T247 421T285 437Q305 442 336 442Q351 442 364 440T387 434T406 426T421 417T432 406T441 395T448 384T452 374T455 366L457 361L460 365Q463 369 466 373T475 384T488 397T503 410T523 422T546 432T572 439T603 442Q729 442 740 329Q741 322 741 190V104Q741 66 743 59T754 49Q775 46 803 46H819V0H811L788 1Q764 2 737 2T699 3Q596 3 587 0H579V46H595Q656 46 656 62Q657 64 657 200Q656 335 655 343Q649 371 635 385T611 402T585 404Q540 404 506 370Q479 343 472 315T464 232V168V108Q464 78 465 68T468 55T477 49Q498 46 526 46H542V0H534L510 1Q487 2 460 2T422 3Q319 3 310 0H302V46H318Q379 46 379 62Q380 64 380 200Q379 335 378 343Q372 371 358 385T334 402T308 404Q263 404 229 370Q202 343 195 315T187 232V168V108Q187 78 188 68T191 55T200 49Q221 46 249 46H265V0H257L234 1Q210 2 183 2T145 3Q42 3 33 0H25V46H41Z" style="stroke-width: 3;"/><path data-c="69" d="M69 609Q69 637 87 653T131 669Q154 667 171 652T188 609Q188 579 171 564T129 549Q104 549 87 564T69 609ZM247 0Q232 3 143 3Q132 3 106 3T56 1L34 0H26V46H42Q70 46 91 49Q100 53 102 60T104 102V205V293Q104 345 102 359T88 378Q74 385 41 385H30V408Q30 431 32 431L42 432Q52 433 70 434T106 436Q123 437 142 438T171 441T182 442H185V62Q190 52 197 50T232 46H255V0H247Z" transform="translate(833,0)" style="stroke-width: 3;"/><path data-c="6E" d="M41 46H55Q94 46 102 60V68Q102 77 102 91T102 122T103 161T103 203Q103 234 103 269T102 328V351Q99 370 88 376T43 385H25V408Q25 431 27 431L37 432Q47 433 65 434T102 436Q119 437 138 438T167 441T178 442H181V402Q181 364 182 364T187 369T199 384T218 402T247 421T285 437Q305 442 336 442Q450 438 463 329Q464 322 464 190V104Q464 66 466 59T477 49Q498 46 526 46H542V0H534L510 1Q487 2 460 2T422 3Q319 3 310 0H302V46H318Q379 46 379 62Q380 64 380 200Q379 335 378 343Q372 371 358 385T334 402T308 404Q263 404 229 370Q202 343 195 315T187 232V168V108Q187 78 188 68T191 55T200 49Q221 46 249 46H265V0H257L234 1Q210 2 183 2T145 3Q42 3 33 0H25V46H41Z" transform="translate(1111,0)" style="stroke-width: 3;"/></g></g></g><g data-mml-node="mo" transform="translate(1730.7,0)"><path data-c="2C" d="M78 35T78 60T94 103T137 121Q165 121 187 96T210 8Q210 -27 201 -60T180 -117T154 -158T130 -185T117 -194Q113 -194 104 -185T95 -172Q95 -168 106 -156T131 -126T157 -76T173 -3V9L172 8Q170 7 167 6T161 3T152 1T140 0Q113 0 96 17Z" style="stroke-width: 3;"/></g><g data-mml-node="msub" transform="translate(2175.4,0)"><g data-mml-node="mi"><path data-c="1D460" d="M131 289Q131 321 147 354T203 415T300 442Q362 442 390 415T419 355Q419 323 402 308T364 292Q351 292 340 300T328 326Q328 342 337 354T354 372T367 378Q368 378 368 379Q368 382 361 388T336 399T297 405Q249 405 227 379T204 326Q204 301 223 291T278 274T330 259Q396 230 396 163Q396 135 385 107T352 51T289 7T195 -10Q118 -10 86 19T53 87Q53 126 74 143T118 160Q133 160 146 151T160 120Q160 94 142 76T111 58Q109 57 108 57T107 55Q108 52 115 47T146 34T201 27Q237 27 263 38T301 66T318 97T323 122Q323 150 302 164T254 181T195 196T148 231Q131 256 131 289Z" style="stroke-width: 3;"/></g><g data-mml-node="TeXAtom" transform="translate(502,-150) scale(0.707)" data-mjx-texclass="ORD"><g data-mml-node="mo"><path data-c="6D" d="M41 46H55Q94 46 102 60V68Q102 77 102 91T102 122T103 161T103 203Q103 234 103 269T102 328V351Q99 370 88 376T43 385H25V408Q25 431 27 431L37 432Q47 433 65 434T102 436Q119 437 138 438T167 441T178 442H181V402Q181 364 182 364T187 369T199 384T218 402T247 421T285 437Q305 442 336 442Q351 442 364 440T387 434T406 426T421 417T432 406T441 395T448 384T452 374T455 366L457 361L460 365Q463 369 466 373T475 384T488 397T503 410T523 422T546 432T572 439T603 442Q729 442 740 329Q741 322 741 190V104Q741 66 743 59T754 49Q775 46 803 46H819V0H811L788 1Q764 2 737 2T699 3Q596 3 587 0H579V46H595Q656 46 656 62Q657 64 657 200Q656 335 655 343Q649 371 635 385T611 402T585 404Q540 404 506 370Q479 343 472 315T464 232V168V108Q464 78 465 68T468 55T477 49Q498 46 526 46H542V0H534L510 1Q487 2 460 2T422 3Q319 3 310 0H302V46H318Q379 46 379 62Q380 64 380 200Q379 335 378 343Q372 371 358 385T334 402T308 404Q263 404 229 370Q202 343 195 315T187 232V168V108Q187 78 188 68T191 55T200 49Q221 46 249 46H265V0H257L234 1Q210 2 183 2T145 3Q42 3 33 0H25V46H41Z" style="stroke-width: 3;"/><path data-c="61" d="M137 305T115 305T78 320T63 359Q63 394 97 421T218 448Q291 448 336 416T396 340Q401 326 401 309T402 194V124Q402 76 407 58T428 40Q443 40 448 56T453 109V145H493V106Q492 66 490 59Q481 29 455 12T400 -6T353 12T329 54V58L327 55Q325 52 322 49T314 40T302 29T287 17T269 6T247 -2T221 -8T190 -11Q130 -11 82 20T34 107Q34 128 41 147T68 188T116 225T194 253T304 268H318V290Q318 324 312 340Q290 411 215 411Q197 411 181 410T156 406T148 403Q170 388 170 359Q170 334 154 320ZM126 106Q126 75 150 51T209 26Q247 26 276 49T315 109Q317 116 318 175Q318 233 317 233Q309 233 296 232T251 223T193 203T147 166T126 106Z" transform="translate(833,0)" style="stroke-width: 3;"/><path data-c="78" d="M201 0Q189 3 102 3Q26 3 17 0H11V46H25Q48 47 67 52T96 61T121 78T139 96T160 122T180 150L226 210L168 288Q159 301 149 315T133 336T122 351T113 363T107 370T100 376T94 379T88 381T80 383Q74 383 44 385H16V431H23Q59 429 126 429Q219 429 229 431H237V385Q201 381 201 369Q201 367 211 353T239 315T268 274L272 270L297 304Q329 345 329 358Q329 364 327 369T322 376T317 380T310 384L307 385H302V431H309Q324 428 408 428Q487 428 493 431H499V385H492Q443 385 411 368Q394 360 377 341T312 257L296 236L358 151Q424 61 429 57T446 50Q464 46 499 46H516V0H510H502Q494 1 482 1T457 2T432 2T414 3Q403 3 377 3T327 1L304 0H295V46H298Q309 46 320 51T331 63Q331 65 291 120L250 175Q249 174 219 133T185 88Q181 83 181 74Q181 63 188 55T206 46Q208 46 208 23V0H201Z" transform="translate(1333,0)" style="stroke-width: 3;"/></g></g></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><msub><mi>s</mi><mrow data-mjx-texclass="ORD"><mo data-mjx-texclass="OP" movablelimits="true">min</mo></mrow></msub><mo>,</mo><msub><mi>s</mi><mrow data-mjx-texclass="ORD"><mo data-mjx-texclass="OP" movablelimits="true">max</mo></mrow></msub></math></mjx-assistive-mml></mjx-container> son los límites del paso que evitan tanto saltarse una pared delgada como alargar demasiado la marcha. El contacto es el primer <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.025ex;" xmlns="http://www.w3.org/2000/svg" width="0.817ex" height="1.441ex" role="img" focusable="false" viewBox="0 -626 361 637" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mi"><path data-c="1D461" d="M26 385Q19 392 19 395Q19 399 22 411T27 425Q29 430 36 430T87 431H140L159 511Q162 522 166 540T173 566T179 586T187 603T197 615T211 624T229 626Q247 625 254 615T261 596Q261 589 252 549T232 470L222 433Q222 431 272 431H323Q330 424 330 420Q330 398 317 385H210L174 240Q135 80 135 68Q135 26 162 26Q197 26 230 60T283 144Q285 150 288 151T303 153H307Q322 153 322 145Q322 142 319 133Q314 117 301 95T267 48T216 6T155 -11Q125 -11 98 4T59 56Q57 64 57 83V101L92 241Q127 382 128 383Q128 385 77 385H26Z" style="stroke-width: 3;"/></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mi>t</mi></math></mjx-assistive-mml></mjx-container> para el que <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.566ex;" xmlns="http://www.w3.org/2000/svg" width="11.08ex" height="2.262ex" role="img" focusable="false" viewBox="0 -750 4897.6 1000" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mi"><path data-c="3A6" d="M312 622Q310 623 307 625T303 629T297 631T286 634T270 635T246 636T211 637H184V683H196Q220 680 361 680T526 683H538V637H511Q468 637 447 635T422 631T411 622V533L425 531Q525 519 595 466T665 342Q665 301 642 267T583 209T506 172T425 152L411 150V61Q417 55 421 53T447 48T511 46H538V0H526Q502 3 361 3T196 0H184V46H211Q231 46 245 46T270 47T286 48T297 51T303 54T307 57T312 61V150H310Q309 151 289 153T232 166T160 195Q149 201 136 210T103 238T69 284T56 342Q56 414 128 467T294 530Q309 532 310 533H312V622ZM170 342Q170 207 307 188H312V495H309Q301 495 282 491T231 469T186 423Q170 389 170 342ZM415 188Q487 199 519 236T551 342Q551 384 539 414T507 459T470 481T434 491T415 495H410V188H415Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(722,0)"><path data-c="28" d="M94 250Q94 319 104 381T127 488T164 576T202 643T244 695T277 729T302 750H315H319Q333 750 333 741Q333 738 316 720T275 667T226 581T184 443T167 250T184 58T225 -81T274 -167T316 -220T333 -241Q333 -250 318 -250H315H302L274 -226Q180 -141 137 -14T94 250Z" style="stroke-width: 3;"/></g><g data-mml-node="TeXAtom" data-mjx-texclass="ORD" transform="translate(1111,0)"><g data-mml-node="mi"><path data-c="1D42B" d="M405 293T374 293T324 312T305 361Q305 378 312 394Q315 397 315 399Q305 399 294 394T266 375T238 329T222 249Q221 241 221 149V62H308V0H298Q280 3 161 3Q47 3 38 0H29V62H98V210V303Q98 353 96 363T83 376Q69 380 42 380H29V442H32L118 446Q204 450 205 450H210V414L211 378Q247 449 315 449H321Q384 449 413 422T442 360Q442 332 424 313Z" style="stroke-width: 3;"/></g></g><g data-mml-node="mo" transform="translate(1585,0)"><path data-c="28" d="M94 250Q94 319 104 381T127 488T164 576T202 643T244 695T277 729T302 750H315H319Q333 750 333 741Q333 738 316 720T275 667T226 581T184 443T167 250T184 58T225 -81T274 -167T316 -220T333 -241Q333 -250 318 -250H315H302L274 -226Q180 -141 137 -14T94 250Z" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(1974,0)"><path data-c="1D461" d="M26 385Q19 392 19 395Q19 399 22 411T27 425Q29 430 36 430T87 431H140L159 511Q162 522 166 540T173 566T179 586T187 603T197 615T211 624T229 626Q247 625 254 615T261 596Q261 589 252 549T232 470L222 433Q222 431 272 431H323Q330 424 330 420Q330 398 317 385H210L174 240Q135 80 135 68Q135 26 162 26Q197 26 230 60T283 144Q285 150 288 151T303 153H307Q322 153 322 145Q322 142 319 133Q314 117 301 95T267 48T216 6T155 -11Q125 -11 98 4T59 56Q57 64 57 83V101L92 241Q127 382 128 383Q128 385 77 385H26Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(2335,0)"><path data-c="29" d="M60 749L64 750Q69 750 74 750H86L114 726Q208 641 251 514T294 250Q294 182 284 119T261 12T224 -76T186 -143T145 -194T113 -227T90 -246Q87 -249 86 -250H74Q66 -250 63 -250T58 -247T55 -238Q56 -237 66 -225Q221 -64 221 250T66 725Q56 737 55 738Q55 746 60 749Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(2724,0)"><path data-c="29" d="M60 749L64 750Q69 750 74 750H86L114 726Q208 641 251 514T294 250Q294 182 284 119T261 12T224 -76T186 -143T145 -194T113 -227T90 -246Q87 -249 86 -250H74Q66 -250 63 -250T58 -247T55 -238Q56 -237 66 -225Q221 -64 221 250T66 725Q56 737 55 738Q55 746 60 749Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(3390.8,0)"><path data-c="2264" d="M674 636Q682 636 688 630T694 615T687 601Q686 600 417 472L151 346L399 228Q687 92 691 87Q694 81 694 76Q694 58 676 56H670L382 192Q92 329 90 331Q83 336 83 348Q84 359 96 365Q104 369 382 500T665 634Q669 636 674 636ZM84 -118Q84 -108 99 -98H678Q694 -104 694 -118Q694 -130 679 -138H98Q84 -131 84 -118Z" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(4446.6,0)"><path data-c="1D45F" d="M21 287Q22 290 23 295T28 317T38 348T53 381T73 411T99 433T132 442Q161 442 183 430T214 408T225 388Q227 382 228 382T236 389Q284 441 347 441H350Q398 441 422 400Q430 381 430 363Q430 333 417 315T391 292T366 288Q346 288 334 299T322 328Q322 376 378 392Q356 405 342 405Q286 405 239 331Q229 315 224 298T190 165Q156 25 151 16Q138 -11 108 -11Q95 -11 87 -5T76 7T74 17Q74 30 114 189T154 366Q154 405 128 405Q107 405 92 377T68 316T57 280Q55 278 41 278H27Q21 284 21 287Z" style="stroke-width: 3;"/></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mi mathvariant="normal">Φ</mi><mo stretchy="false">(</mo><mrow data-mjx-texclass="ORD"><mi mathvariant="bold">r</mi></mrow><mo stretchy="false">(</mo><mi>t</mi><mo stretchy="false">)</mo><mo stretchy="false">)</mo><mo>≤</mo><mi>r</mi></math></mjx-assistive-mml></mjx-container>, lo que significa que la superficie de la esfera ha alcanzado la roca, y la cámara se mantiene a esa longitud de arco menos su radio.</p>
<p>El colisionador incorpora un método adicional como red de seguridad: la despenetración. En principio, la colisión debería impedir que la cámara entre en un sólido, pero algunas situaciones se le escapan: un pivote que atraviesa una pared tan fina que el brazo comienza dentro de ella, una cueva recién esculpida con las herramientas de terreno mientras la cámara estaba en la roca que acaba de desaparecer, o una pieza de construcción colocada alrededor de la cámara. En esos casos, el colisionador comprueba si la cámara terminó el fotograma dentro de un sólido, donde <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.566ex;" xmlns="http://www.w3.org/2000/svg" width="8.587ex" height="2.262ex" role="img" focusable="false" viewBox="0 -750 3795.6 1000" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mi"><path data-c="3A6" d="M312 622Q310 623 307 625T303 629T297 631T286 634T270 635T246 636T211 637H184V683H196Q220 680 361 680T526 683H538V637H511Q468 637 447 635T422 631T411 622V533L425 531Q525 519 595 466T665 342Q665 301 642 267T583 209T506 172T425 152L411 150V61Q417 55 421 53T447 48T511 46H538V0H526Q502 3 361 3T196 0H184V46H211Q231 46 245 46T270 47T286 48T297 51T303 54T307 57T312 61V150H310Q309 151 289 153T232 166T160 195Q149 201 136 210T103 238T69 284T56 342Q56 414 128 467T294 530Q309 532 310 533H312V622ZM170 342Q170 207 307 188H312V495H309Q301 495 282 491T231 469T186 423Q170 389 170 342ZM415 188Q487 199 519 236T551 342Q551 384 539 414T507 459T470 481T434 491T415 495H410V188H415Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(722,0)"><path data-c="28" d="M94 250Q94 319 104 381T127 488T164 576T202 643T244 695T277 729T302 750H315H319Q333 750 333 741Q333 738 316 720T275 667T226 581T184 443T167 250T184 58T225 -81T274 -167T316 -220T333 -241Q333 -250 318 -250H315H302L274 -226Q180 -141 137 -14T94 250Z" style="stroke-width: 3;"/></g><g data-mml-node="TeXAtom" data-mjx-texclass="ORD" transform="translate(1111,0)"><g data-mml-node="mi"><path data-c="1D41C" d="M447 131H458Q478 131 478 117Q478 112 471 95T439 51T377 9Q330 -6 286 -6Q196 -6 135 35Q39 96 39 222Q39 324 101 384Q169 453 286 453Q359 453 411 431T464 353Q464 319 445 302T395 284Q360 284 343 305T325 353Q325 380 338 396H333Q317 398 295 398H292Q280 398 271 397T245 390T218 373T197 338T183 283Q182 275 182 231Q182 199 184 180T193 132T220 85T270 57Q289 50 317 50H326Q385 50 414 115Q419 127 423 129T447 131Z" style="stroke-width: 3;"/></g></g><g data-mml-node="mo" transform="translate(1622,0)"><path data-c="29" d="M60 749L64 750Q69 750 74 750H86L114 726Q208 641 251 514T294 250Q294 182 284 119T261 12T224 -76T186 -143T145 -194T113 -227T90 -246Q87 -249 86 -250H74Q66 -250 63 -250T58 -247T55 -238Q56 -237 66 -225Q221 -64 221 250T66 725Q56 737 55 738Q55 746 60 749Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(2288.8,0)"><path data-c="3C" d="M694 -11T694 -19T688 -33T678 -40Q671 -40 524 29T234 166L90 235Q83 240 83 250Q83 261 91 266Q664 540 678 540Q681 540 687 534T694 519T687 505Q686 504 417 376L151 250L417 124Q686 -4 687 -5Q694 -11 694 -19Z" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(3344.6,0)"><path data-c="1D45F" d="M21 287Q22 290 23 295T28 317T38 348T53 381T73 411T99 433T132 442Q161 442 183 430T214 408T225 388Q227 382 228 382T236 389Q284 441 347 441H350Q398 441 422 400Q430 381 430 363Q430 333 417 315T391 292T366 288Q346 288 334 299T322 328Q322 376 378 392Q356 405 342 405Q286 405 239 331Q229 315 224 298T190 165Q156 25 151 16Q138 -11 108 -11Q95 -11 87 -5T76 7T74 17Q74 30 114 189T154 366Q154 405 128 405Q107 405 92 377T68 316T57 280Q55 278 41 278H27Q21 284 21 287Z" style="stroke-width: 3;"/></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mi mathvariant="normal">Φ</mi><mo stretchy="false">(</mo><mrow data-mjx-texclass="ORD"><mi mathvariant="bold">c</mi></mrow><mo stretchy="false">)</mo><mo>&lt;</mo><mi>r</mi></math></mjx-assistive-mml></mjx-container>; si es así, lee el gradiente del campo, que apunta directamente hacia el aire libre porque <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: 0;" xmlns="http://www.w3.org/2000/svg" width="1.633ex" height="1.545ex" role="img" focusable="false" viewBox="0 -683 722 683" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mi"><path data-c="3A6" d="M312 622Q310 623 307 625T303 629T297 631T286 634T270 635T246 636T211 637H184V683H196Q220 680 361 680T526 683H538V637H511Q468 637 447 635T422 631T411 622V533L425 531Q525 519 595 466T665 342Q665 301 642 267T583 209T506 172T425 152L411 150V61Q417 55 421 53T447 48T511 46H538V0H526Q502 3 361 3T196 0H184V46H211Q231 46 245 46T270 47T286 48T297 51T303 54T307 57T312 61V150H310Q309 151 289 153T232 166T160 195Q149 201 136 210T103 238T69 284T56 342Q56 414 128 467T294 530Q309 532 310 533H312V622ZM170 342Q170 207 307 188H312V495H309Q301 495 282 491T231 469T186 423Q170 389 170 342ZM415 188Q487 199 519 236T551 342Q551 384 539 414T507 459T470 481T434 491T415 495H410V188H415Z" style="stroke-width: 3;"/></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mi mathvariant="normal">Φ</mi></math></mjx-assistive-mml></mjx-container> aumenta al salir de la roca, y desplaza la cámara hacia fuera siguiendo esa dirección:</p>
<mjx-container tabindex="0" class="MathJax" jax="SVG" display="true" style="direction: ltr; display: block; text-align: center; margin: 1em 0; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -2.172ex;" xmlns="http://www.w3.org/2000/svg" width="29.076ex" height="5.475ex" role="img" focusable="false" viewBox="0 -1460 12851.4 2420" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="TeXAtom" data-mjx-texclass="ORD"><g data-mml-node="mi"><path data-c="1D41C" d="M447 131H458Q478 131 478 117Q478 112 471 95T439 51T377 9Q330 -6 286 -6Q196 -6 135 35Q39 96 39 222Q39 324 101 384Q169 453 286 453Q359 453 411 431T464 353Q464 319 445 302T395 284Q360 284 343 305T325 353Q325 380 338 396H333Q317 398 295 398H292Q280 398 271 397T245 390T218 373T197 338T183 283Q182 275 182 231Q182 199 184 180T193 132T220 85T270 57Q289 50 317 50H326Q385 50 414 115Q419 127 423 129T447 131Z" style="stroke-width: 3;"/></g></g><g data-mml-node="mo" transform="translate(788.8,0)"><path data-c="2190" d="M944 261T944 250T929 230H165Q167 228 182 216T211 189T244 152T277 96T303 25Q308 7 308 0Q308 -11 288 -11Q281 -11 278 -11T272 -7T267 2T263 21Q245 94 195 151T73 236Q58 242 55 247Q55 254 59 257T73 264Q121 283 158 314T215 375T247 434T264 480L267 497Q269 503 270 505T275 509T288 511Q308 511 308 500Q308 493 303 475Q293 438 278 406T246 352T215 315T185 287T165 270H929Q944 261 944 250Z" style="stroke-width: 3;"/></g><g data-mml-node="TeXAtom" data-mjx-texclass="ORD" transform="translate(2066.6,0)"><g data-mml-node="mi"><path data-c="1D41C" d="M447 131H458Q478 131 478 117Q478 112 471 95T439 51T377 9Q330 -6 286 -6Q196 -6 135 35Q39 96 39 222Q39 324 101 384Q169 453 286 453Q359 453 411 431T464 353Q464 319 445 302T395 284Q360 284 343 305T325 353Q325 380 338 396H333Q317 398 295 398H292Q280 398 271 397T245 390T218 373T197 338T183 283Q182 275 182 231Q182 199 184 180T193 132T220 85T270 57Q289 50 317 50H326Q385 50 414 115Q419 127 423 129T447 131Z" style="stroke-width: 3;"/></g></g><g data-mml-node="mo" transform="translate(2799.8,0)"><path data-c="2B" d="M56 237T56 250T70 270H369V420L370 570Q380 583 389 583Q402 583 409 568V270H707Q722 262 722 250T707 230H409V-68Q401 -82 391 -82H389H387Q375 -82 369 -68V230H70Q56 237 56 250Z" style="stroke-width: 3;"/></g><g data-mml-node="TeXAtom" data-mjx-texclass="ORD" transform="translate(3800,0)"><g data-mml-node="mo" transform="translate(0 -0.5)"><path data-c="28" d="M152 251Q152 646 388 850H416Q422 844 422 841Q422 837 403 816T357 753T302 649T255 482T236 250Q236 124 255 19T301 -147T356 -251T403 -315T422 -340Q422 -343 416 -349H388Q359 -325 332 -296T271 -213T212 -97T170 56T152 251Z" style="stroke-width: 3;"/></g></g><g data-mml-node="mi" transform="translate(4258,0)"><path data-c="1D45F" d="M21 287Q22 290 23 295T28 317T38 348T53 381T73 411T99 433T132 442Q161 442 183 430T214 408T225 388Q227 382 228 382T236 389Q284 441 347 441H350Q398 441 422 400Q430 381 430 363Q430 333 417 315T391 292T366 288Q346 288 334 299T322 328Q322 376 378 392Q356 405 342 405Q286 405 239 331Q229 315 224 298T190 165Q156 25 151 16Q138 -11 108 -11Q95 -11 87 -5T76 7T74 17Q74 30 114 189T154 366Q154 405 128 405Q107 405 92 377T68 316T57 280Q55 278 41 278H27Q21 284 21 287Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(4931.2,0)"><path data-c="2212" d="M84 237T84 250T98 270H679Q694 262 694 250T679 230H98Q84 237 84 250Z" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(5931.4,0)"><path data-c="3A6" d="M312 622Q310 623 307 625T303 629T297 631T286 634T270 635T246 636T211 637H184V683H196Q220 680 361 680T526 683H538V637H511Q468 637 447 635T422 631T411 622V533L425 531Q525 519 595 466T665 342Q665 301 642 267T583 209T506 172T425 152L411 150V61Q417 55 421 53T447 48T511 46H538V0H526Q502 3 361 3T196 0H184V46H211Q231 46 245 46T270 47T286 48T297 51T303 54T307 57T312 61V150H310Q309 151 289 153T232 166T160 195Q149 201 136 210T103 238T69 284T56 342Q56 414 128 467T294 530Q309 532 310 533H312V622ZM170 342Q170 207 307 188H312V495H309Q301 495 282 491T231 469T186 423Q170 389 170 342ZM415 188Q487 199 519 236T551 342Q551 384 539 414T507 459T470 481T434 491T415 495H410V188H415Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(6653.4,0)"><path data-c="28" d="M94 250Q94 319 104 381T127 488T164 576T202 643T244 695T277 729T302 750H315H319Q333 750 333 741Q333 738 316 720T275 667T226 581T184 443T167 250T184 58T225 -81T274 -167T316 -220T333 -241Q333 -250 318 -250H315H302L274 -226Q180 -141 137 -14T94 250Z" style="stroke-width: 3;"/></g><g data-mml-node="TeXAtom" data-mjx-texclass="ORD" transform="translate(7042.4,0)"><g data-mml-node="mi"><path data-c="1D41C" d="M447 131H458Q478 131 478 117Q478 112 471 95T439 51T377 9Q330 -6 286 -6Q196 -6 135 35Q39 96 39 222Q39 324 101 384Q169 453 286 453Q359 453 411 431T464 353Q464 319 445 302T395 284Q360 284 343 305T325 353Q325 380 338 396H333Q317 398 295 398H292Q280 398 271 397T245 390T218 373T197 338T183 283Q182 275 182 231Q182 199 184 180T193 132T220 85T270 57Q289 50 317 50H326Q385 50 414 115Q419 127 423 129T447 131Z" style="stroke-width: 3;"/></g></g><g data-mml-node="mo" transform="translate(7553.4,0)"><path data-c="29" d="M60 749L64 750Q69 750 74 750H86L114 726Q208 641 251 514T294 250Q294 182 284 119T261 12T224 -76T186 -143T145 -194T113 -227T90 -246Q87 -249 86 -250H74Q66 -250 63 -250T58 -247T55 -238Q56 -237 66 -225Q221 -64 221 250T66 725Q56 737 55 738Q55 746 60 749Z" style="stroke-width: 3;"/></g><g data-mml-node="TeXAtom" data-mjx-texclass="ORD" transform="translate(7942.4,0)"><g data-mml-node="mo" transform="translate(0 -0.5)"><path data-c="29" d="M305 251Q305 -145 69 -349H56Q43 -349 39 -347T35 -338Q37 -333 60 -307T108 -239T160 -136T204 27T221 250T204 473T160 636T108 740T60 807T35 839Q35 850 50 850H56H69Q197 743 256 566Q305 425 305 251Z" style="stroke-width: 3;"/></g></g><g data-mml-node="mstyle" transform="translate(8400.4,0)"><g data-mml-node="mspace"/></g><g data-mml-node="mfrac" transform="translate(8567.4,0)"><g data-mml-node="mrow" transform="translate(720,710)"><g data-mml-node="mi"><path data-c="2207" d="M46 676Q46 679 51 683H781Q786 679 786 676Q786 674 617 326T444 -26Q439 -33 416 -33T388 -26Q385 -22 216 326T46 676ZM697 596Q697 597 445 597T193 596Q195 591 319 336T445 80L697 596Z" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(833,0)"><path data-c="3A6" d="M312 622Q310 623 307 625T303 629T297 631T286 634T270 635T246 636T211 637H184V683H196Q220 680 361 680T526 683H538V637H511Q468 637 447 635T422 631T411 622V533L425 531Q525 519 595 466T665 342Q665 301 642 267T583 209T506 172T425 152L411 150V61Q417 55 421 53T447 48T511 46H538V0H526Q502 3 361 3T196 0H184V46H211Q231 46 245 46T270 47T286 48T297 51T303 54T307 57T312 61V150H310Q309 151 289 153T232 166T160 195Q149 201 136 210T103 238T69 284T56 342Q56 414 128 467T294 530Q309 532 310 533H312V622ZM170 342Q170 207 307 188H312V495H309Q301 495 282 491T231 469T186 423Q170 389 170 342ZM415 188Q487 199 519 236T551 342Q551 384 539 414T507 459T470 481T434 491T415 495H410V188H415Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(1555,0)"><path data-c="28" d="M94 250Q94 319 104 381T127 488T164 576T202 643T244 695T277 729T302 750H315H319Q333 750 333 741Q333 738 316 720T275 667T226 581T184 443T167 250T184 58T225 -81T274 -167T316 -220T333 -241Q333 -250 318 -250H315H302L274 -226Q180 -141 137 -14T94 250Z" style="stroke-width: 3;"/></g><g data-mml-node="TeXAtom" data-mjx-texclass="ORD" transform="translate(1944,0)"><g data-mml-node="mi"><path data-c="1D41C" d="M447 131H458Q478 131 478 117Q478 112 471 95T439 51T377 9Q330 -6 286 -6Q196 -6 135 35Q39 96 39 222Q39 324 101 384Q169 453 286 453Q359 453 411 431T464 353Q464 319 445 302T395 284Q360 284 343 305T325 353Q325 380 338 396H333Q317 398 295 398H292Q280 398 271 397T245 390T218 373T197 338T183 283Q182 275 182 231Q182 199 184 180T193 132T220 85T270 57Q289 50 317 50H326Q385 50 414 115Q419 127 423 129T447 131Z" style="stroke-width: 3;"/></g></g><g data-mml-node="mo" transform="translate(2455,0)"><path data-c="29" d="M60 749L64 750Q69 750 74 750H86L114 726Q208 641 251 514T294 250Q294 182 284 119T261 12T224 -76T186 -143T145 -194T113 -227T90 -246Q87 -249 86 -250H74Q66 -250 63 -250T58 -247T55 -238Q56 -237 66 -225Q221 -64 221 250T66 725Q56 737 55 738Q55 746 60 749Z" style="stroke-width: 3;"/></g></g><g data-mml-node="mrow" transform="translate(220,-710)"><g data-mml-node="mo"><path data-c="2016" d="M133 736Q138 750 153 750Q164 750 170 739Q172 735 172 250T170 -239Q164 -250 152 -250Q144 -250 138 -244L137 -243Q133 -241 133 -179T132 250Q132 731 133 736ZM329 739Q334 750 346 750Q353 750 361 744L362 743Q366 741 366 679T367 250T367 -178T362 -243L361 -244Q355 -250 347 -250Q335 -250 329 -239Q327 -235 327 250T329 739Z" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(500,0)"><path data-c="2207" d="M46 676Q46 679 51 683H781Q786 679 786 676Q786 674 617 326T444 -26Q439 -33 416 -33T388 -26Q385 -22 216 326T46 676ZM697 596Q697 597 445 597T193 596Q195 591 319 336T445 80L697 596Z" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(1333,0)"><path data-c="3A6" d="M312 622Q310 623 307 625T303 629T297 631T286 634T270 635T246 636T211 637H184V683H196Q220 680 361 680T526 683H538V637H511Q468 637 447 635T422 631T411 622V533L425 531Q525 519 595 466T665 342Q665 301 642 267T583 209T506 172T425 152L411 150V61Q417 55 421 53T447 48T511 46H538V0H526Q502 3 361 3T196 0H184V46H211Q231 46 245 46T270 47T286 48T297 51T303 54T307 57T312 61V150H310Q309 151 289 153T232 166T160 195Q149 201 136 210T103 238T69 284T56 342Q56 414 128 467T294 530Q309 532 310 533H312V622ZM170 342Q170 207 307 188H312V495H309Q301 495 282 491T231 469T186 423Q170 389 170 342ZM415 188Q487 199 519 236T551 342Q551 384 539 414T507 459T470 481T434 491T415 495H410V188H415Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(2055,0)"><path data-c="28" d="M94 250Q94 319 104 381T127 488T164 576T202 643T244 695T277 729T302 750H315H319Q333 750 333 741Q333 738 316 720T275 667T226 581T184 443T167 250T184 58T225 -81T274 -167T316 -220T333 -241Q333 -250 318 -250H315H302L274 -226Q180 -141 137 -14T94 250Z" style="stroke-width: 3;"/></g><g data-mml-node="TeXAtom" data-mjx-texclass="ORD" transform="translate(2444,0)"><g data-mml-node="mi"><path data-c="1D41C" d="M447 131H458Q478 131 478 117Q478 112 471 95T439 51T377 9Q330 -6 286 -6Q196 -6 135 35Q39 96 39 222Q39 324 101 384Q169 453 286 453Q359 453 411 431T464 353Q464 319 445 302T395 284Q360 284 343 305T325 353Q325 380 338 396H333Q317 398 295 398H292Q280 398 271 397T245 390T218 373T197 338T183 283Q182 275 182 231Q182 199 184 180T193 132T220 85T270 57Q289 50 317 50H326Q385 50 414 115Q419 127 423 129T447 131Z" style="stroke-width: 3;"/></g></g><g data-mml-node="mo" transform="translate(2955,0)"><path data-c="29" d="M60 749L64 750Q69 750 74 750H86L114 726Q208 641 251 514T294 250Q294 182 284 119T261 12T224 -76T186 -143T145 -194T113 -227T90 -246Q87 -249 86 -250H74Q66 -250 63 -250T58 -247T55 -238Q56 -237 66 -225Q221 -64 221 250T66 725Q56 737 55 738Q55 746 60 749Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(3344,0)"><path data-c="2016" d="M133 736Q138 750 153 750Q164 750 170 739Q172 735 172 250T170 -239Q164 -250 152 -250Q144 -250 138 -244L137 -243Q133 -241 133 -179T132 250Q132 731 133 736ZM329 739Q334 750 346 750Q353 750 361 744L362 743Q366 741 366 679T367 250T367 -178T362 -243L361 -244Q355 -250 347 -250Q335 -250 329 -239Q327 -235 327 250T329 739Z" style="stroke-width: 3;"/></g></g><rect width="4044" height="60" x="120" y="220"/></g></g></g></svg><mjx-assistive-mml unselectable="on" display="block" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; overflow: hidden; width: 100%;"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><mrow data-mjx-texclass="ORD"><mi mathvariant="bold">c</mi></mrow><mo stretchy="false">←</mo><mrow data-mjx-texclass="ORD"><mi mathvariant="bold">c</mi></mrow><mo>+</mo><mrow data-mjx-texclass="ORD"><mo minsize="1.2em" maxsize="1.2em">(</mo></mrow><mi>r</mi><mo>−</mo><mi mathvariant="normal">Φ</mi><mo stretchy="false">(</mo><mrow data-mjx-texclass="ORD"><mi mathvariant="bold">c</mi></mrow><mo stretchy="false">)</mo><mrow data-mjx-texclass="ORD"><mo minsize="1.2em" maxsize="1.2em">)</mo></mrow><mstyle scriptlevel="0"><mspace width="0.167em"/></mstyle><mfrac><mrow><mi mathvariant="normal">∇</mi><mi mathvariant="normal">Φ</mi><mo stretchy="false">(</mo><mrow data-mjx-texclass="ORD"><mi mathvariant="bold">c</mi></mrow><mo stretchy="false">)</mo></mrow><mrow><mo data-mjx-texclass="OPEN" fence="false" stretchy="false">‖</mo><mi mathvariant="normal">∇</mi><mi mathvariant="normal">Φ</mi><mo stretchy="false">(</mo><mrow data-mjx-texclass="ORD"><mi mathvariant="bold">c</mi></mrow><mo stretchy="false">)</mo><mo data-mjx-texclass="CLOSE" fence="false" stretchy="false">‖</mo></mrow></mfrac></math></mjx-assistive-mml></mjx-container><p>Unas pocas iteraciones convergen en la isosuperficie de valor <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.025ex;" xmlns="http://www.w3.org/2000/svg" width="1.02ex" height="1.025ex" role="img" focusable="false" viewBox="0 -442 451 453" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mi"><path data-c="1D45F" d="M21 287Q22 290 23 295T28 317T38 348T53 381T73 411T99 433T132 442Q161 442 183 430T214 408T225 388Q227 382 228 382T236 389Q284 441 347 441H350Q398 441 422 400Q430 381 430 363Q430 333 417 315T391 292T366 288Q346 288 334 299T322 328Q322 376 378 392Q356 405 342 405Q286 405 239 331Q229 315 224 298T190 165Q156 25 151 16Q138 -11 108 -11Q95 -11 87 -5T76 7T74 17Q74 30 114 189T154 366Q154 405 128 405Q107 405 92 377T68 316T57 280Q55 278 41 278H27Q21 284 21 287Z" style="stroke-width: 3;"/></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mi>r</mi></math></mjx-assistive-mml></mjx-container>, y eso es lo que permite que una herramienta de esculpido excave el suelo bajo la cámara y que la vista se recupere en el siguiente fotograma en lugar de quedarse negra.</p>
<h2 id="entrar-de-golpe-salir-con-suavidad-y-no-sobresaltarse-ante-los-postes-de-una-valla" tabindex="-1">Entrar de golpe, salir con suavidad y no sobresaltarse ante los postes de una valla <a class="header-anchor" href="#entrar-de-golpe-salir-con-suavidad-y-no-sobresaltarse-ante-los-postes-de-una-valla" aria-label="Permalink to &quot;Entrar de golpe, salir con suavidad y no sobresaltarse ante los postes de una valla&quot;"></a></h2>
<p>Un brazo que simplemente salta cada fotograma a la distancia de colisión es peor que no tener brazo, porque el mundo está lleno de objetos delgados tras los que la cámara pasa durante un solo fotograma —un poste de valla, una farola, el tronco de un árbol—, y una cámara que se abalanza para esquivar cada uno y vuelve a abalanzarse en sentido contrario provoca mareo. Tanto el libro de Haigh-Hutchinson como la muy apreciada charla de Itay Keren sobre el movimiento de cámara llegan a la misma intuición: la cámara debe reaccionar ante las amenazas y el peligro más rápido de lo que se relaja cuando desaparecen. Por eso la amortiguación es deliberadamente asimétrica. Cuando aparece un oclusor y el brazo tiene que acortarse, entra casi al instante, porque un fotograma de intersección queda feo y el jugador tolera un repliegue rápido. Cuando el oclusor desaparece y el brazo quiere alargarse, sale lentamente, y solo después de que transcurra un breve temporizador de espera con espacio libre continuo. Esa espera es la histéresis que elimina los sobresaltos. Si giras la cámara rápidamente junto a un poste delgado, el poste nunca permanece despejado el tiempo suficiente como para activar la extensión lenta, así que la cámara se desliza junto a él como si no estuviera ahí, que es exactamente lo que espera la vista. Cinemachine presenta la misma idea mediante valores separados de amortiguación al entrar y al salir de una colisión, y esa asimetría es lo que hace que parezca un operador de cámara en lugar de un muelle.</p>
<p>En código, es una sola línea de suavizado exponencial cuya velocidad cambia según el signo de la variación. Si <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.045ex;" xmlns="http://www.w3.org/2000/svg" width="0.943ex" height="1.64ex" role="img" focusable="false" viewBox="0 -705 417 725" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mi"><path data-c="2113" d="M345 104T349 104T361 95T369 80T352 59Q268 -20 206 -20Q170 -20 146 3T113 53T99 104L94 129Q94 130 79 116T48 86T28 70Q22 70 15 79T7 94Q7 98 12 103T58 147L91 179V185Q91 186 91 191T92 200Q92 282 128 400T223 612T336 705Q397 705 397 636V627Q397 453 194 233Q185 223 180 218T174 211T171 208T165 201L163 186Q159 142 159 123Q159 17 208 17Q228 17 253 30T293 56T335 94Q345 104 349 104ZM360 634Q360 655 354 661T336 668Q328 668 322 666T302 645T272 592Q252 547 229 467T192 330L179 273Q179 272 186 280T204 300T221 322Q327 453 355 590Q360 612 360 634Z" style="stroke-width: 3;"/></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mi>ℓ</mi></math></mjx-assistive-mml></mjx-container> es la longitud actual del brazo, <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.023ex;" xmlns="http://www.w3.org/2000/svg" width="1.197ex" height="1.02ex" role="img" focusable="false" viewBox="0 -441 529 451" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mi"><path data-c="1D44E" d="M33 157Q33 258 109 349T280 441Q331 441 370 392Q386 422 416 422Q429 422 439 414T449 394Q449 381 412 234T374 68Q374 43 381 35T402 26Q411 27 422 35Q443 55 463 131Q469 151 473 152Q475 153 483 153H487Q506 153 506 144Q506 138 501 117T481 63T449 13Q436 0 417 -8Q409 -10 393 -10Q359 -10 336 5T306 36L300 51Q299 52 296 50Q294 48 292 46Q233 -10 172 -10Q117 -10 75 30T33 157ZM351 328Q351 334 346 350T323 385T277 405Q242 405 210 374T160 293Q131 214 119 129Q119 126 119 118T118 106Q118 61 136 44T179 26Q217 26 254 59T298 110Q300 114 325 217T351 328Z" style="stroke-width: 3;"/></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mi>a</mi></math></mjx-assistive-mml></mjx-container> la longitud que permite la colisión en este fotograma y <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.025ex;" xmlns="http://www.w3.org/2000/svg" width="2.701ex" height="1.645ex" role="img" focusable="false" viewBox="0 -716 1194 727" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mi"><path data-c="394" d="M51 0Q46 4 46 7Q46 9 215 357T388 709Q391 716 416 716Q439 716 444 709Q447 705 616 357T786 7Q786 4 781 0H51ZM507 344L384 596L137 92L383 91H630Q630 93 507 344Z" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(833,0)"><path data-c="1D461" d="M26 385Q19 392 19 395Q19 399 22 411T27 425Q29 430 36 430T87 431H140L159 511Q162 522 166 540T173 566T179 586T187 603T197 615T211 624T229 626Q247 625 254 615T261 596Q261 589 252 549T232 470L222 433Q222 431 272 431H323Q330 424 330 420Q330 398 317 385H210L174 240Q135 80 135 68Q135 26 162 26Q197 26 230 60T283 144Q285 150 288 151T303 153H307Q322 153 322 145Q322 142 319 133Q314 117 301 95T267 48T216 6T155 -11Q125 -11 98 4T59 56Q57 64 57 83V101L92 241Q127 382 128 383Q128 385 77 385H26Z" style="stroke-width: 3;"/></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mi mathvariant="normal">Δ</mi><mi>t</mi></math></mjx-assistive-mml></mjx-container> la duración del fotograma, entonces</p>
<mjx-container tabindex="0" class="MathJax" jax="SVG" display="true" style="direction: ltr; display: block; text-align: center; margin: 1em 0; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -2.149ex;" xmlns="http://www.w3.org/2000/svg" width="62.104ex" height="5.43ex" role="img" focusable="false" viewBox="0 -1450 27450 2400" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mi"><path data-c="2113" d="M345 104T349 104T361 95T369 80T352 59Q268 -20 206 -20Q170 -20 146 3T113 53T99 104L94 129Q94 130 79 116T48 86T28 70Q22 70 15 79T7 94Q7 98 12 103T58 147L91 179V185Q91 186 91 191T92 200Q92 282 128 400T223 612T336 705Q397 705 397 636V627Q397 453 194 233Q185 223 180 218T174 211T171 208T165 201L163 186Q159 142 159 123Q159 17 208 17Q228 17 253 30T293 56T335 94Q345 104 349 104ZM360 634Q360 655 354 661T336 668Q328 668 322 666T302 645T272 592Q252 547 229 467T192 330L179 273Q179 272 186 280T204 300T221 322Q327 453 355 590Q360 612 360 634Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(694.8,0)"><path data-c="2190" d="M944 261T944 250T929 230H165Q167 228 182 216T211 189T244 152T277 96T303 25Q308 7 308 0Q308 -11 288 -11Q281 -11 278 -11T272 -7T267 2T263 21Q245 94 195 151T73 236Q58 242 55 247Q55 254 59 257T73 264Q121 283 158 314T215 375T247 434T264 480L267 497Q269 503 270 505T275 509T288 511Q308 511 308 500Q308 493 303 475Q293 438 278 406T246 352T215 315T185 287T165 270H929Q944 261 944 250Z" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(1972.6,0)"><path data-c="2113" d="M345 104T349 104T361 95T369 80T352 59Q268 -20 206 -20Q170 -20 146 3T113 53T99 104L94 129Q94 130 79 116T48 86T28 70Q22 70 15 79T7 94Q7 98 12 103T58 147L91 179V185Q91 186 91 191T92 200Q92 282 128 400T223 612T336 705Q397 705 397 636V627Q397 453 194 233Q185 223 180 218T174 211T171 208T165 201L163 186Q159 142 159 123Q159 17 208 17Q228 17 253 30T293 56T335 94Q345 104 349 104ZM360 634Q360 655 354 661T336 668Q328 668 322 666T302 645T272 592Q252 547 229 467T192 330L179 273Q179 272 186 280T204 300T221 322Q327 453 355 590Q360 612 360 634Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(2611.8,0)"><path data-c="2B" d="M56 237T56 250T70 270H369V420L370 570Q380 583 389 583Q402 583 409 568V270H707Q722 262 722 250T707 230H409V-68Q401 -82 391 -82H389H387Q375 -82 369 -68V230H70Q56 237 56 250Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(3612,0)"><path data-c="28" d="M94 250Q94 319 104 381T127 488T164 576T202 643T244 695T277 729T302 750H315H319Q333 750 333 741Q333 738 316 720T275 667T226 581T184 443T167 250T184 58T225 -81T274 -167T316 -220T333 -241Q333 -250 318 -250H315H302L274 -226Q180 -141 137 -14T94 250Z" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(4001,0)"><path data-c="1D44E" d="M33 157Q33 258 109 349T280 441Q331 441 370 392Q386 422 416 422Q429 422 439 414T449 394Q449 381 412 234T374 68Q374 43 381 35T402 26Q411 27 422 35Q443 55 463 131Q469 151 473 152Q475 153 483 153H487Q506 153 506 144Q506 138 501 117T481 63T449 13Q436 0 417 -8Q409 -10 393 -10Q359 -10 336 5T306 36L300 51Q299 52 296 50Q294 48 292 46Q233 -10 172 -10Q117 -10 75 30T33 157ZM351 328Q351 334 346 350T323 385T277 405Q242 405 210 374T160 293Q131 214 119 129Q119 126 119 118T118 106Q118 61 136 44T179 26Q217 26 254 59T298 110Q300 114 325 217T351 328Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(4752.2,0)"><path data-c="2212" d="M84 237T84 250T98 270H679Q694 262 694 250T679 230H98Q84 237 84 250Z" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(5752.4,0)"><path data-c="2113" d="M345 104T349 104T361 95T369 80T352 59Q268 -20 206 -20Q170 -20 146 3T113 53T99 104L94 129Q94 130 79 116T48 86T28 70Q22 70 15 79T7 94Q7 98 12 103T58 147L91 179V185Q91 186 91 191T92 200Q92 282 128 400T223 612T336 705Q397 705 397 636V627Q397 453 194 233Q185 223 180 218T174 211T171 208T165 201L163 186Q159 142 159 123Q159 17 208 17Q228 17 253 30T293 56T335 94Q345 104 349 104ZM360 634Q360 655 354 661T336 668Q328 668 322 666T302 645T272 592Q252 547 229 467T192 330L179 273Q179 272 186 280T204 300T221 322Q327 453 355 590Q360 612 360 634Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(6169.4,0)"><path data-c="29" d="M60 749L64 750Q69 750 74 750H86L114 726Q208 641 251 514T294 250Q294 182 284 119T261 12T224 -76T186 -143T145 -194T113 -227T90 -246Q87 -249 86 -250H74Q66 -250 63 -250T58 -247T55 -238Q56 -237 66 -225Q221 -64 221 250T66 725Q56 737 55 738Q55 746 60 749Z" style="stroke-width: 3;"/></g><g data-mml-node="TeXAtom" data-mjx-texclass="ORD" transform="translate(6558.4,0)"><g data-mml-node="mo" transform="translate(0 -0.5)"><path data-c="28" d="M152 251Q152 646 388 850H416Q422 844 422 841Q422 837 403 816T357 753T302 649T255 482T236 250Q236 124 255 19T301 -147T356 -251T403 -315T422 -340Q422 -343 416 -349H388Q359 -325 332 -296T271 -213T212 -97T170 56T152 251Z" style="stroke-width: 3;"/></g></g><g data-mml-node="mn" transform="translate(7016.4,0)"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(7738.7,0)"><path data-c="2212" d="M84 237T84 250T98 270H679Q694 262 694 250T679 230H98Q84 237 84 250Z" style="stroke-width: 3;"/></g><g data-mml-node="msup" transform="translate(8738.9,0)"><g data-mml-node="mi"><path data-c="1D452" d="M39 168Q39 225 58 272T107 350T174 402T244 433T307 442H310Q355 442 388 420T421 355Q421 265 310 237Q261 224 176 223Q139 223 138 221Q138 219 132 186T125 128Q125 81 146 54T209 26T302 45T394 111Q403 121 406 121Q410 121 419 112T429 98T420 82T390 55T344 24T281 -1T205 -11Q126 -11 83 42T39 168ZM373 353Q367 405 305 405Q272 405 244 391T199 357T170 316T154 280T149 261Q149 260 169 260Q282 260 327 284T373 353Z" style="stroke-width: 3;"/></g><g data-mml-node="TeXAtom" transform="translate(499,413) scale(0.707)" data-mjx-texclass="ORD"><g data-mml-node="mo"><path data-c="2212" d="M84 237T84 250T98 270H679Q694 262 694 250T679 230H98Q84 237 84 250Z" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(778,0)"><path data-c="1D458" d="M121 647Q121 657 125 670T137 683Q138 683 209 688T282 694Q294 694 294 686Q294 679 244 477Q194 279 194 272Q213 282 223 291Q247 309 292 354T362 415Q402 442 438 442Q468 442 485 423T503 369Q503 344 496 327T477 302T456 291T438 288Q418 288 406 299T394 328Q394 353 410 369T442 390L458 393Q446 405 434 405H430Q398 402 367 380T294 316T228 255Q230 254 243 252T267 246T293 238T320 224T342 206T359 180T365 147Q365 130 360 106T354 66Q354 26 381 26Q429 26 459 145Q461 153 479 153H483Q499 153 499 144Q499 139 496 130Q455 -11 378 -11Q333 -11 305 15T277 90Q277 108 280 121T283 145Q283 167 269 183T234 206T200 217T182 220H180Q168 178 159 139T145 81T136 44T129 20T122 7T111 -2Q98 -11 83 -11Q66 -11 57 -1T48 16Q48 26 85 176T158 471L195 616Q196 629 188 632T149 637H144Q134 637 131 637T124 640T121 647Z" style="stroke-width: 3;"/></g><g data-mml-node="mstyle" transform="translate(1299,0) scale(1.414)"><g data-mml-node="mspace"/></g><g data-mml-node="mi" transform="translate(1535.2,0)"><path data-c="394" d="M51 0Q46 4 46 7Q46 9 215 357T388 709Q391 716 416 716Q439 716 444 709Q447 705 616 357T786 7Q786 4 781 0H51ZM507 344L384 596L137 92L383 91H630Q630 93 507 344Z" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(2368.2,0)"><path data-c="1D461" d="M26 385Q19 392 19 395Q19 399 22 411T27 425Q29 430 36 430T87 431H140L159 511Q162 522 166 540T173 566T179 586T187 603T197 615T211 624T229 626Q247 625 254 615T261 596Q261 589 252 549T232 470L222 433Q222 431 272 431H323Q330 424 330 420Q330 398 317 385H210L174 240Q135 80 135 68Q135 26 162 26Q197 26 230 60T283 144Q285 150 288 151T303 153H307Q322 153 322 145Q322 142 319 133Q314 117 301 95T267 48T216 6T155 -11Q125 -11 98 4T59 56Q57 64 57 83V101L92 241Q127 382 128 383Q128 385 77 385H26Z" style="stroke-width: 3;"/></g></g></g><g data-mml-node="TeXAtom" data-mjx-texclass="ORD" transform="translate(11217.7,0)"><g data-mml-node="mo" transform="translate(0 -0.5)"><path data-c="29" d="M305 251Q305 -145 69 -349H56Q43 -349 39 -347T35 -338Q37 -333 60 -307T108 -239T160 -136T204 27T221 250T204 473T160 636T108 740T60 807T35 839Q35 850 50 850H56H69Q197 743 256 566Q305 425 305 251Z" style="stroke-width: 3;"/></g></g><g data-mml-node="mo" transform="translate(11675.7,0)"><path data-c="2C" d="M78 35T78 60T94 103T137 121Q165 121 187 96T210 8Q210 -27 201 -60T180 -117T154 -158T130 -185T117 -194Q113 -194 104 -185T95 -172Q95 -168 106 -156T131 -126T157 -76T173 -3V9L172 8Q170 7 167 6T161 3T152 1T140 0Q113 0 96 17Z" style="stroke-width: 3;"/></g><g data-mml-node="mstyle" transform="translate(11953.7,0)"><g data-mml-node="mspace"/></g><g data-mml-node="mi" transform="translate(14120.4,0)"><path data-c="1D458" d="M121 647Q121 657 125 670T137 683Q138 683 209 688T282 694Q294 694 294 686Q294 679 244 477Q194 279 194 272Q213 282 223 291Q247 309 292 354T362 415Q402 442 438 442Q468 442 485 423T503 369Q503 344 496 327T477 302T456 291T438 288Q418 288 406 299T394 328Q394 353 410 369T442 390L458 393Q446 405 434 405H430Q398 402 367 380T294 316T228 255Q230 254 243 252T267 246T293 238T320 224T342 206T359 180T365 147Q365 130 360 106T354 66Q354 26 381 26Q429 26 459 145Q461 153 479 153H483Q499 153 499 144Q499 139 496 130Q455 -11 378 -11Q333 -11 305 15T277 90Q277 108 280 121T283 145Q283 167 269 183T234 206T200 217T182 220H180Q168 178 159 139T145 81T136 44T129 20T122 7T111 -2Q98 -11 83 -11Q66 -11 57 -1T48 16Q48 26 85 176T158 471L195 616Q196 629 188 632T149 637H144Q134 637 131 637T124 640T121 647Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(14919.2,0)"><path data-c="3D" d="M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z" style="stroke-width: 3;"/></g><g data-mml-node="mrow" transform="translate(15974.9,0)"><g data-mml-node="mo" transform="translate(0 -0.5)"><path data-c="7B" d="M618 -943L612 -949H582L568 -943Q472 -903 411 -841T332 -703Q327 -682 327 -653T325 -350Q324 -28 323 -18Q317 24 301 61T264 124T221 171T179 205T147 225T132 234Q130 238 130 250Q130 255 130 258T131 264T132 267T134 269T139 272T144 275Q207 308 256 367Q310 436 323 519Q324 529 325 851Q326 1124 326 1154T332 1205Q369 1358 566 1443L582 1450H612L618 1444V1429Q618 1413 616 1411L608 1406Q599 1402 585 1393T552 1372T515 1343T479 1305T449 1257T429 1200Q425 1180 425 1152T423 851Q422 579 422 549T416 498Q407 459 388 424T346 364T297 318T250 284T214 264T197 254L188 251L205 242Q290 200 345 138T416 3Q421 -18 421 -48T423 -349Q423 -397 423 -472Q424 -677 428 -694Q429 -697 429 -699Q434 -722 443 -743T465 -782T491 -816T519 -845T548 -868T574 -886T595 -899T610 -908L616 -910Q618 -912 618 -928V-943Z" style="stroke-width: 3;"/></g><g data-mml-node="mtable" transform="translate(750,0)"><g data-mml-node="mtr" transform="translate(0,700)"><g data-mml-node="mtd"><g data-mml-node="msub"><g data-mml-node="mi"><path data-c="1D458" d="M121 647Q121 657 125 670T137 683Q138 683 209 688T282 694Q294 694 294 686Q294 679 244 477Q194 279 194 272Q213 282 223 291Q247 309 292 354T362 415Q402 442 438 442Q468 442 485 423T503 369Q503 344 496 327T477 302T456 291T438 288Q418 288 406 299T394 328Q394 353 410 369T442 390L458 393Q446 405 434 405H430Q398 402 367 380T294 316T228 255Q230 254 243 252T267 246T293 238T320 224T342 206T359 180T365 147Q365 130 360 106T354 66Q354 26 381 26Q429 26 459 145Q461 153 479 153H483Q499 153 499 144Q499 139 496 130Q455 -11 378 -11Q333 -11 305 15T277 90Q277 108 280 121T283 145Q283 167 269 183T234 206T200 217T182 220H180Q168 178 159 139T145 81T136 44T129 20T122 7T111 -2Q98 -11 83 -11Q66 -11 57 -1T48 16Q48 26 85 176T158 471L195 616Q196 629 188 632T149 637H144Q134 637 131 637T124 640T121 647Z" style="stroke-width: 3;"/></g><g data-mml-node="TeXAtom" transform="translate(554,-150) scale(0.707)" data-mjx-texclass="ORD"><g data-mml-node="mtext"><path data-c="69" d="M69 609Q69 637 87 653T131 669Q154 667 171 652T188 609Q188 579 171 564T129 549Q104 549 87 564T69 609ZM247 0Q232 3 143 3Q132 3 106 3T56 1L34 0H26V46H42Q70 46 91 49Q100 53 102 60T104 102V205V293Q104 345 102 359T88 378Q74 385 41 385H30V408Q30 431 32 431L42 432Q52 433 70 434T106 436Q123 437 142 438T171 441T182 442H185V62Q190 52 197 50T232 46H255V0H247Z" style="stroke-width: 3;"/><path data-c="6E" d="M41 46H55Q94 46 102 60V68Q102 77 102 91T102 122T103 161T103 203Q103 234 103 269T102 328V351Q99 370 88 376T43 385H25V408Q25 431 27 431L37 432Q47 433 65 434T102 436Q119 437 138 438T167 441T178 442H181V402Q181 364 182 364T187 369T199 384T218 402T247 421T285 437Q305 442 336 442Q450 438 463 329Q464 322 464 190V104Q464 66 466 59T477 49Q498 46 526 46H542V0H534L510 1Q487 2 460 2T422 3Q319 3 310 0H302V46H318Q379 46 379 62Q380 64 380 200Q379 335 378 343Q372 371 358 385T334 402T308 404Q263 404 229 370Q202 343 195 315T187 232V168V108Q187 78 188 68T191 55T200 49Q221 46 249 46H265V0H257L234 1Q210 2 183 2T145 3Q42 3 33 0H25V46H41Z" transform="translate(278,0)" style="stroke-width: 3;"/></g></g></g></g><g data-mml-node="mtd" transform="translate(2625.8,0)"><g data-mml-node="mi"><path data-c="1D44E" d="M33 157Q33 258 109 349T280 441Q331 441 370 392Q386 422 416 422Q429 422 439 414T449 394Q449 381 412 234T374 68Q374 43 381 35T402 26Q411 27 422 35Q443 55 463 131Q469 151 473 152Q475 153 483 153H487Q506 153 506 144Q506 138 501 117T481 63T449 13Q436 0 417 -8Q409 -10 393 -10Q359 -10 336 5T306 36L300 51Q299 52 296 50Q294 48 292 46Q233 -10 172 -10Q117 -10 75 30T33 157ZM351 328Q351 334 346 350T323 385T277 405Q242 405 210 374T160 293Q131 214 119 129Q119 126 119 118T118 106Q118 61 136 44T179 26Q217 26 254 59T298 110Q300 114 325 217T351 328Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(806.8,0)"><path data-c="2264" d="M674 636Q682 636 688 630T694 615T687 601Q686 600 417 472L151 346L399 228Q687 92 691 87Q694 81 694 76Q694 58 676 56H670L382 192Q92 329 90 331Q83 336 83 348Q84 359 96 365Q104 369 382 500T665 634Q669 636 674 636ZM84 -118Q84 -108 99 -98H678Q694 -104 694 -118Q694 -130 679 -138H98Q84 -131 84 -118Z" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(1862.6,0)"><path data-c="2113" d="M345 104T349 104T361 95T369 80T352 59Q268 -20 206 -20Q170 -20 146 3T113 53T99 104L94 129Q94 130 79 116T48 86T28 70Q22 70 15 79T7 94Q7 98 12 103T58 147L91 179V185Q91 186 91 191T92 200Q92 282 128 400T223 612T336 705Q397 705 397 636V627Q397 453 194 233Q185 223 180 218T174 211T171 208T165 201L163 186Q159 142 159 123Q159 17 208 17Q228 17 253 30T293 56T335 94Q345 104 349 104ZM360 634Q360 655 354 661T336 668Q328 668 322 666T302 645T272 592Q252 547 229 467T192 330L179 273Q179 272 186 280T204 300T221 322Q327 453 355 590Q360 612 360 634Z" style="stroke-width: 3;"/></g></g></g><g data-mml-node="mtr" transform="translate(0,-700)"><g data-mml-node="mtd"><g data-mml-node="msub"><g data-mml-node="mi"><path data-c="1D458" d="M121 647Q121 657 125 670T137 683Q138 683 209 688T282 694Q294 694 294 686Q294 679 244 477Q194 279 194 272Q213 282 223 291Q247 309 292 354T362 415Q402 442 438 442Q468 442 485 423T503 369Q503 344 496 327T477 302T456 291T438 288Q418 288 406 299T394 328Q394 353 410 369T442 390L458 393Q446 405 434 405H430Q398 402 367 380T294 316T228 255Q230 254 243 252T267 246T293 238T320 224T342 206T359 180T365 147Q365 130 360 106T354 66Q354 26 381 26Q429 26 459 145Q461 153 479 153H483Q499 153 499 144Q499 139 496 130Q455 -11 378 -11Q333 -11 305 15T277 90Q277 108 280 121T283 145Q283 167 269 183T234 206T200 217T182 220H180Q168 178 159 139T145 81T136 44T129 20T122 7T111 -2Q98 -11 83 -11Q66 -11 57 -1T48 16Q48 26 85 176T158 471L195 616Q196 629 188 632T149 637H144Q134 637 131 637T124 640T121 647Z" style="stroke-width: 3;"/></g><g data-mml-node="TeXAtom" transform="translate(554,-150) scale(0.707)" data-mjx-texclass="ORD"><g data-mml-node="mtext"><path data-c="6F" d="M28 214Q28 309 93 378T250 448Q340 448 405 380T471 215Q471 120 407 55T250 -10Q153 -10 91 57T28 214ZM250 30Q372 30 372 193V225V250Q372 272 371 288T364 326T348 362T317 390T268 410Q263 411 252 411Q222 411 195 399Q152 377 139 338T126 246V226Q126 130 145 91Q177 30 250 30Z" style="stroke-width: 3;"/><path data-c="75" d="M383 58Q327 -10 256 -10H249Q124 -10 105 89Q104 96 103 226Q102 335 102 348T96 369Q86 385 36 385H25V408Q25 431 27 431L38 432Q48 433 67 434T105 436Q122 437 142 438T172 441T184 442H187V261Q188 77 190 64Q193 49 204 40Q224 26 264 26Q290 26 311 35T343 58T363 90T375 120T379 144Q379 145 379 161T380 201T380 248V315Q380 361 370 372T320 385H302V431Q304 431 378 436T457 442H464V264Q464 84 465 81Q468 61 479 55T524 46H542V0Q540 0 467 -5T390 -11H383V58Z" transform="translate(500,0)" style="stroke-width: 3;"/><path data-c="74" d="M27 422Q80 426 109 478T141 600V615H181V431H316V385H181V241Q182 116 182 100T189 68Q203 29 238 29Q282 29 292 100Q293 108 293 146V181H333V146V134Q333 57 291 17Q264 -10 221 -10Q187 -10 162 2T124 33T105 68T98 100Q97 107 97 248V385H18V422H27Z" transform="translate(1056,0)" style="stroke-width: 3;"/></g></g></g></g><g data-mml-node="mtd" transform="translate(2625.8,0)"><g data-mml-node="mi"><path data-c="1D44E" d="M33 157Q33 258 109 349T280 441Q331 441 370 392Q386 422 416 422Q429 422 439 414T449 394Q449 381 412 234T374 68Q374 43 381 35T402 26Q411 27 422 35Q443 55 463 131Q469 151 473 152Q475 153 483 153H487Q506 153 506 144Q506 138 501 117T481 63T449 13Q436 0 417 -8Q409 -10 393 -10Q359 -10 336 5T306 36L300 51Q299 52 296 50Q294 48 292 46Q233 -10 172 -10Q117 -10 75 30T33 157ZM351 328Q351 334 346 350T323 385T277 405Q242 405 210 374T160 293Q131 214 119 129Q119 126 119 118T118 106Q118 61 136 44T179 26Q217 26 254 59T298 110Q300 114 325 217T351 328Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(806.8,0)"><path data-c="3E" d="M84 520Q84 528 88 533T96 539L99 540Q106 540 253 471T544 334L687 265Q694 260 694 250T687 235Q685 233 395 96L107 -40H101Q83 -38 83 -20Q83 -19 83 -17Q82 -10 98 -1Q117 9 248 71Q326 108 378 132L626 250L378 368Q90 504 86 509Q84 513 84 520Z" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(1862.6,0)"><path data-c="2113" d="M345 104T349 104T361 95T369 80T352 59Q268 -20 206 -20Q170 -20 146 3T113 53T99 104L94 129Q94 130 79 116T48 86T28 70Q22 70 15 79T7 94Q7 98 12 103T58 147L91 179V185Q91 186 91 191T92 200Q92 282 128 400T223 612T336 705Q397 705 397 636V627Q397 453 194 233Q185 223 180 218T174 211T171 208T165 201L163 186Q159 142 159 123Q159 17 208 17Q228 17 253 30T293 56T335 94Q345 104 349 104ZM360 634Q360 655 354 661T336 668Q328 668 322 666T302 645T272 592Q252 547 229 467T192 330L179 273Q179 272 186 280T204 300T221 322Q327 453 355 590Q360 612 360 634Z" style="stroke-width: 3;"/></g></g></g></g><g data-mml-node="mo" transform="translate(5655.3,0) translate(0 250)"/></g><g data-mml-node="mo" transform="translate(21630.3,0)"><path data-c="2C" d="M78 35T78 60T94 103T137 121Q165 121 187 96T210 8Q210 -27 201 -60T180 -117T154 -158T130 -185T117 -194Q113 -194 104 -185T95 -172Q95 -168 106 -156T131 -126T157 -76T173 -3V9L172 8Q170 7 167 6T161 3T152 1T140 0Q113 0 96 17Z" style="stroke-width: 3;"/></g><g data-mml-node="mstyle" transform="translate(21908.3,0)"><g data-mml-node="mspace"/></g><g data-mml-node="msub" transform="translate(23074.9,0)"><g data-mml-node="mi"><path data-c="1D458" d="M121 647Q121 657 125 670T137 683Q138 683 209 688T282 694Q294 694 294 686Q294 679 244 477Q194 279 194 272Q213 282 223 291Q247 309 292 354T362 415Q402 442 438 442Q468 442 485 423T503 369Q503 344 496 327T477 302T456 291T438 288Q418 288 406 299T394 328Q394 353 410 369T442 390L458 393Q446 405 434 405H430Q398 402 367 380T294 316T228 255Q230 254 243 252T267 246T293 238T320 224T342 206T359 180T365 147Q365 130 360 106T354 66Q354 26 381 26Q429 26 459 145Q461 153 479 153H483Q499 153 499 144Q499 139 496 130Q455 -11 378 -11Q333 -11 305 15T277 90Q277 108 280 121T283 145Q283 167 269 183T234 206T200 217T182 220H180Q168 178 159 139T145 81T136 44T129 20T122 7T111 -2Q98 -11 83 -11Q66 -11 57 -1T48 16Q48 26 85 176T158 471L195 616Q196 629 188 632T149 637H144Q134 637 131 637T124 640T121 647Z" style="stroke-width: 3;"/></g><g data-mml-node="TeXAtom" transform="translate(554,-150) scale(0.707)" data-mjx-texclass="ORD"><g data-mml-node="mtext"><path data-c="69" d="M69 609Q69 637 87 653T131 669Q154 667 171 652T188 609Q188 579 171 564T129 549Q104 549 87 564T69 609ZM247 0Q232 3 143 3Q132 3 106 3T56 1L34 0H26V46H42Q70 46 91 49Q100 53 102 60T104 102V205V293Q104 345 102 359T88 378Q74 385 41 385H30V408Q30 431 32 431L42 432Q52 433 70 434T106 436Q123 437 142 438T171 441T182 442H185V62Q190 52 197 50T232 46H255V0H247Z" style="stroke-width: 3;"/><path data-c="6E" d="M41 46H55Q94 46 102 60V68Q102 77 102 91T102 122T103 161T103 203Q103 234 103 269T102 328V351Q99 370 88 376T43 385H25V408Q25 431 27 431L37 432Q47 433 65 434T102 436Q119 437 138 438T167 441T178 442H181V402Q181 364 182 364T187 369T199 384T218 402T247 421T285 437Q305 442 336 442Q450 438 463 329Q464 322 464 190V104Q464 66 466 59T477 49Q498 46 526 46H542V0H534L510 1Q487 2 460 2T422 3Q319 3 310 0H302V46H318Q379 46 379 62Q380 64 380 200Q379 335 378 343Q372 371 358 385T334 402T308 404Q263 404 229 370Q202 343 195 315T187 232V168V108Q187 78 188 68T191 55T200 49Q221 46 249 46H265V0H257L234 1Q210 2 183 2T145 3Q42 3 33 0H25V46H41Z" transform="translate(278,0)" style="stroke-width: 3;"/></g></g></g><g data-mml-node="mo" transform="translate(24546.4,0)"><path data-c="226B" d="M55 539T55 547T60 561T74 567Q81 567 207 498Q297 449 365 412Q633 265 636 261Q639 255 639 250Q639 241 626 232Q614 224 365 88Q83 -65 79 -66Q76 -67 73 -67Q65 -67 60 -61T55 -47Q55 -39 61 -33Q62 -33 95 -15T193 39T320 109L321 110H322L323 111H324L325 112L326 113H327L329 114H330L331 115H332L333 116L334 117H335L336 118H337L338 119H339L340 120L341 121H342L343 122H344L345 123H346L347 124L348 125H349L351 126H352L353 127H354L355 128L356 129H357L358 130H359L360 131H361L362 132L363 133H364L365 134H366L367 135H368L369 136H370L371 137L372 138H373L374 139H375L376 140L378 141L576 251Q63 530 62 533Q55 539 55 547ZM360 539T360 547T365 561T379 567Q386 567 512 498Q602 449 670 412Q938 265 941 261Q944 255 944 250Q944 241 931 232Q919 224 670 88Q388 -65 384 -66Q381 -67 378 -67Q370 -67 365 -61T360 -47Q360 -39 366 -33Q367 -33 400 -15T498 39T625 109L626 110H627L628 111H629L630 112L631 113H632L634 114H635L636 115H637L638 116L639 117H640L641 118H642L643 119H644L645 120L646 121H647L648 122H649L650 123H651L652 124L653 125H654L656 126H657L658 127H659L660 128L661 129H662L663 130H664L665 131H666L667 132L668 133H669L670 134H671L672 135H673L674 136H675L676 137L677 138H678L679 139H680L681 140L683 141L881 251Q368 530 367 533Q360 539 360 547Z" style="stroke-width: 3;"/></g><g data-mml-node="msub" transform="translate(25824.2,0)"><g data-mml-node="mi"><path data-c="1D458" d="M121 647Q121 657 125 670T137 683Q138 683 209 688T282 694Q294 694 294 686Q294 679 244 477Q194 279 194 272Q213 282 223 291Q247 309 292 354T362 415Q402 442 438 442Q468 442 485 423T503 369Q503 344 496 327T477 302T456 291T438 288Q418 288 406 299T394 328Q394 353 410 369T442 390L458 393Q446 405 434 405H430Q398 402 367 380T294 316T228 255Q230 254 243 252T267 246T293 238T320 224T342 206T359 180T365 147Q365 130 360 106T354 66Q354 26 381 26Q429 26 459 145Q461 153 479 153H483Q499 153 499 144Q499 139 496 130Q455 -11 378 -11Q333 -11 305 15T277 90Q277 108 280 121T283 145Q283 167 269 183T234 206T200 217T182 220H180Q168 178 159 139T145 81T136 44T129 20T122 7T111 -2Q98 -11 83 -11Q66 -11 57 -1T48 16Q48 26 85 176T158 471L195 616Q196 629 188 632T149 637H144Q134 637 131 637T124 640T121 647Z" style="stroke-width: 3;"/></g><g data-mml-node="TeXAtom" transform="translate(554,-150) scale(0.707)" data-mjx-texclass="ORD"><g data-mml-node="mtext"><path data-c="6F" d="M28 214Q28 309 93 378T250 448Q340 448 405 380T471 215Q471 120 407 55T250 -10Q153 -10 91 57T28 214ZM250 30Q372 30 372 193V225V250Q372 272 371 288T364 326T348 362T317 390T268 410Q263 411 252 411Q222 411 195 399Q152 377 139 338T126 246V226Q126 130 145 91Q177 30 250 30Z" style="stroke-width: 3;"/><path data-c="75" d="M383 58Q327 -10 256 -10H249Q124 -10 105 89Q104 96 103 226Q102 335 102 348T96 369Q86 385 36 385H25V408Q25 431 27 431L38 432Q48 433 67 434T105 436Q122 437 142 438T172 441T184 442H187V261Q188 77 190 64Q193 49 204 40Q224 26 264 26Q290 26 311 35T343 58T363 90T375 120T379 144Q379 145 379 161T380 201T380 248V315Q380 361 370 372T320 385H302V431Q304 431 378 436T457 442H464V264Q464 84 465 81Q468 61 479 55T524 46H542V0Q540 0 467 -5T390 -11H383V58Z" transform="translate(500,0)" style="stroke-width: 3;"/><path data-c="74" d="M27 422Q80 426 109 478T141 600V615H181V431H316V385H181V241Q182 116 182 100T189 68Q203 29 238 29Q282 29 292 100Q293 108 293 146V181H333V146V134Q333 57 291 17Q264 -10 221 -10Q187 -10 162 2T124 33T105 68T98 100Q97 107 97 248V385H18V422H27Z" transform="translate(1056,0)" style="stroke-width: 3;"/></g></g></g></g></g></svg><mjx-assistive-mml unselectable="on" display="block" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; overflow: hidden; width: 100%;"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><mi>ℓ</mi><mo stretchy="false">←</mo><mi>ℓ</mi><mo>+</mo><mo stretchy="false">(</mo><mi>a</mi><mo>−</mo><mi>ℓ</mi><mo stretchy="false">)</mo><mrow data-mjx-texclass="ORD"><mo minsize="1.2em" maxsize="1.2em">(</mo></mrow><mn>1</mn><mo>−</mo><msup><mi>e</mi><mrow data-mjx-texclass="ORD"><mo>−</mo><mi>k</mi><mstyle scriptlevel="0"><mspace width="0.167em"/></mstyle><mi mathvariant="normal">Δ</mi><mi>t</mi></mrow></msup><mrow data-mjx-texclass="ORD"><mo minsize="1.2em" maxsize="1.2em">)</mo></mrow><mo>,</mo><mstyle scriptlevel="0"><mspace width="2em"/></mstyle><mi>k</mi><mo>=</mo><mrow data-mjx-texclass="INNER"><mo data-mjx-texclass="OPEN">{</mo><mtable columnalign="left left" columnspacing="1em" rowspacing="0.4em 0.2em"><mtr><mtd><msub><mi>k</mi><mrow data-mjx-texclass="ORD"><mtext>in</mtext></mrow></msub></mtd><mtd><mi>a</mi><mo>≤</mo><mi>ℓ</mi></mtd></mtr><mtr><mtd><msub><mi>k</mi><mrow data-mjx-texclass="ORD"><mtext>out</mtext></mrow></msub></mtd><mtd><mi>a</mi><mo>&gt;</mo><mi>ℓ</mi></mtd></mtr></mtable><mo data-mjx-texclass="CLOSE" fence="true" stretchy="true" symmetric="true"/></mrow><mo>,</mo><mstyle scriptlevel="0"><mspace width="1em"/></mstyle><msub><mi>k</mi><mrow data-mjx-texclass="ORD"><mtext>in</mtext></mrow></msub><mo>≫</mo><msub><mi>k</mi><mrow data-mjx-texclass="ORD"><mtext>out</mtext></mrow></msub></math></mjx-assistive-mml></mjx-container><p>y la rama de salida suave solo se ejecuta cuando el espacio libre se ha mantenido durante el tiempo de espera <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.029ex;" xmlns="http://www.w3.org/2000/svg" width="1.17ex" height="1.005ex" role="img" focusable="false" viewBox="0 -431 517 444" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mi"><path data-c="1D70F" d="M39 284Q18 284 18 294Q18 301 45 338T99 398Q134 425 164 429Q170 431 332 431Q492 431 497 429Q517 424 517 402Q517 388 508 376T485 360Q479 358 389 358T299 356Q298 355 283 274T251 109T233 20Q228 5 215 -4T186 -13Q153 -13 153 20V30L203 192Q214 228 227 272T248 336L254 357Q254 358 208 358Q206 358 197 358T183 359Q105 359 61 295Q56 287 53 286T39 284Z" style="stroke-width: 3;"/></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mi>τ</mi></math></mjx-assistive-mml></mjx-container>. La forma <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.186ex;" xmlns="http://www.w3.org/2000/svg" width="9.505ex" height="2.152ex" role="img" focusable="false" viewBox="0 -869.3 4201.3 951.3" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mn"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(722.2,0)"><path data-c="2212" d="M84 237T84 250T98 270H679Q694 262 694 250T679 230H98Q84 237 84 250Z" style="stroke-width: 3;"/></g><g data-mml-node="msup" transform="translate(1722.4,0)"><g data-mml-node="mi"><path data-c="1D452" d="M39 168Q39 225 58 272T107 350T174 402T244 433T307 442H310Q355 442 388 420T421 355Q421 265 310 237Q261 224 176 223Q139 223 138 221Q138 219 132 186T125 128Q125 81 146 54T209 26T302 45T394 111Q403 121 406 121Q410 121 419 112T429 98T420 82T390 55T344 24T281 -1T205 -11Q126 -11 83 42T39 168ZM373 353Q367 405 305 405Q272 405 244 391T199 357T170 316T154 280T149 261Q149 260 169 260Q282 260 327 284T373 353Z" style="stroke-width: 3;"/></g><g data-mml-node="TeXAtom" transform="translate(499,363) scale(0.707)" data-mjx-texclass="ORD"><g data-mml-node="mo"><path data-c="2212" d="M84 237T84 250T98 270H679Q694 262 694 250T679 230H98Q84 237 84 250Z" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(778,0)"><path data-c="1D458" d="M121 647Q121 657 125 670T137 683Q138 683 209 688T282 694Q294 694 294 686Q294 679 244 477Q194 279 194 272Q213 282 223 291Q247 309 292 354T362 415Q402 442 438 442Q468 442 485 423T503 369Q503 344 496 327T477 302T456 291T438 288Q418 288 406 299T394 328Q394 353 410 369T442 390L458 393Q446 405 434 405H430Q398 402 367 380T294 316T228 255Q230 254 243 252T267 246T293 238T320 224T342 206T359 180T365 147Q365 130 360 106T354 66Q354 26 381 26Q429 26 459 145Q461 153 479 153H483Q499 153 499 144Q499 139 496 130Q455 -11 378 -11Q333 -11 305 15T277 90Q277 108 280 121T283 145Q283 167 269 183T234 206T200 217T182 220H180Q168 178 159 139T145 81T136 44T129 20T122 7T111 -2Q98 -11 83 -11Q66 -11 57 -1T48 16Q48 26 85 176T158 471L195 616Q196 629 188 632T149 637H144Q134 637 131 637T124 640T121 647Z" style="stroke-width: 3;"/></g><g data-mml-node="mstyle" transform="translate(1299,0) scale(1.414)"><g data-mml-node="mspace"/></g><g data-mml-node="mi" transform="translate(1535.2,0)"><path data-c="394" d="M51 0Q46 4 46 7Q46 9 215 357T388 709Q391 716 416 716Q439 716 444 709Q447 705 616 357T786 7Q786 4 781 0H51ZM507 344L384 596L137 92L383 91H630Q630 93 507 344Z" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(2368.2,0)"><path data-c="1D461" d="M26 385Q19 392 19 395Q19 399 22 411T27 425Q29 430 36 430T87 431H140L159 511Q162 522 166 540T173 566T179 586T187 603T197 615T211 624T229 626Q247 625 254 615T261 596Q261 589 252 549T232 470L222 433Q222 431 272 431H323Q330 424 330 420Q330 398 317 385H210L174 240Q135 80 135 68Q135 26 162 26Q197 26 230 60T283 144Q285 150 288 151T303 153H307Q322 153 322 145Q322 142 319 133Q314 117 301 95T267 48T216 6T155 -11Q125 -11 98 4T59 56Q57 64 57 83V101L92 241Q127 382 128 383Q128 385 77 385H26Z" style="stroke-width: 3;"/></g></g></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mn>1</mn><mo>−</mo><msup><mi>e</mi><mrow data-mjx-texclass="ORD"><mo>−</mo><mi>k</mi><mstyle scriptlevel="0"><mspace width="0.167em"/></mstyle><mi mathvariant="normal">Δ</mi><mi>t</mi></mrow></msup></math></mjx-assistive-mml></mjx-container> importa por algo más que su aspecto elegante. Fija la constante temporal de respuesta en <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.566ex;" xmlns="http://www.w3.org/2000/svg" width="3.441ex" height="2.262ex" role="img" focusable="false" viewBox="0 -750 1521 1000" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mn"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" style="stroke-width: 3;"/></g><g data-mml-node="TeXAtom" data-mjx-texclass="ORD" transform="translate(500,0)"><g data-mml-node="mo"><path data-c="2F" d="M423 750Q432 750 438 744T444 730Q444 725 271 248T92 -240Q85 -250 75 -250Q68 -250 62 -245T56 -231Q56 -221 230 257T407 740Q411 750 423 750Z" style="stroke-width: 3;"/></g></g><g data-mml-node="mi" transform="translate(1000,0)"><path data-c="1D458" d="M121 647Q121 657 125 670T137 683Q138 683 209 688T282 694Q294 694 294 686Q294 679 244 477Q194 279 194 272Q213 282 223 291Q247 309 292 354T362 415Q402 442 438 442Q468 442 485 423T503 369Q503 344 496 327T477 302T456 291T438 288Q418 288 406 299T394 328Q394 353 410 369T442 390L458 393Q446 405 434 405H430Q398 402 367 380T294 316T228 255Q230 254 243 252T267 246T293 238T320 224T342 206T359 180T365 147Q365 130 360 106T354 66Q354 26 381 26Q429 26 459 145Q461 153 479 153H483Q499 153 499 144Q499 139 496 130Q455 -11 378 -11Q333 -11 305 15T277 90Q277 108 280 121T283 145Q283 167 269 183T234 206T200 217T182 220H180Q168 178 159 139T145 81T136 44T129 20T122 7T111 -2Q98 -11 83 -11Q66 -11 57 -1T48 16Q48 26 85 176T158 471L195 616Q196 629 188 632T149 637H144Q134 637 131 637T124 640T121 647Z" style="stroke-width: 3;"/></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mn>1</mn><mrow data-mjx-texclass="ORD"><mo>/</mo></mrow><mi>k</mi></math></mjx-assistive-mml></mjx-container> con independencia de la frecuencia de fotogramas, de modo que la cámara se siente igual a 30 que a 144 fotogramas por segundo, mientras que la mezcla constante ingenua <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.566ex;" xmlns="http://www.w3.org/2000/svg" width="16.286ex" height="2.262ex" role="img" focusable="false" viewBox="0 -750 7198.4 1000" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mi"><path data-c="2113" d="M345 104T349 104T361 95T369 80T352 59Q268 -20 206 -20Q170 -20 146 3T113 53T99 104L94 129Q94 130 79 116T48 86T28 70Q22 70 15 79T7 94Q7 98 12 103T58 147L91 179V185Q91 186 91 191T92 200Q92 282 128 400T223 612T336 705Q397 705 397 636V627Q397 453 194 233Q185 223 180 218T174 211T171 208T165 201L163 186Q159 142 159 123Q159 17 208 17Q228 17 253 30T293 56T335 94Q345 104 349 104ZM360 634Q360 655 354 661T336 668Q328 668 322 666T302 645T272 592Q252 547 229 467T192 330L179 273Q179 272 186 280T204 300T221 322Q327 453 355 590Q360 612 360 634Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(694.8,0)"><path data-c="2190" d="M944 261T944 250T929 230H165Q167 228 182 216T211 189T244 152T277 96T303 25Q308 7 308 0Q308 -11 288 -11Q281 -11 278 -11T272 -7T267 2T263 21Q245 94 195 151T73 236Q58 242 55 247Q55 254 59 257T73 264Q121 283 158 314T215 375T247 434T264 480L267 497Q269 503 270 505T275 509T288 511Q308 511 308 500Q308 493 303 475Q293 438 278 406T246 352T215 315T185 287T165 270H929Q944 261 944 250Z" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(1972.6,0)"><path data-c="2113" d="M345 104T349 104T361 95T369 80T352 59Q268 -20 206 -20Q170 -20 146 3T113 53T99 104L94 129Q94 130 79 116T48 86T28 70Q22 70 15 79T7 94Q7 98 12 103T58 147L91 179V185Q91 186 91 191T92 200Q92 282 128 400T223 612T336 705Q397 705 397 636V627Q397 453 194 233Q185 223 180 218T174 211T171 208T165 201L163 186Q159 142 159 123Q159 17 208 17Q228 17 253 30T293 56T335 94Q345 104 349 104ZM360 634Q360 655 354 661T336 668Q328 668 322 666T302 645T272 592Q252 547 229 467T192 330L179 273Q179 272 186 280T204 300T221 322Q327 453 355 590Q360 612 360 634Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(2611.8,0)"><path data-c="2B" d="M56 237T56 250T70 270H369V420L370 570Q380 583 389 583Q402 583 409 568V270H707Q722 262 722 250T707 230H409V-68Q401 -82 391 -82H389H387Q375 -82 369 -68V230H70Q56 237 56 250Z" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(3612,0)"><path data-c="1D6FC" d="M34 156Q34 270 120 356T309 442Q379 442 421 402T478 304Q484 275 485 237V208Q534 282 560 374Q564 388 566 390T582 393Q603 393 603 385Q603 376 594 346T558 261T497 161L486 147L487 123Q489 67 495 47T514 26Q528 28 540 37T557 60Q559 67 562 68T577 70Q597 70 597 62Q597 56 591 43Q579 19 556 5T512 -10H505Q438 -10 414 62L411 69L400 61Q390 53 370 41T325 18T267 -2T203 -11Q124 -11 79 39T34 156ZM208 26Q257 26 306 47T379 90L403 112Q401 255 396 290Q382 405 304 405Q235 405 183 332Q156 292 139 224T121 120Q121 71 146 49T208 26Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(4252,0)"><path data-c="28" d="M94 250Q94 319 104 381T127 488T164 576T202 643T244 695T277 729T302 750H315H319Q333 750 333 741Q333 738 316 720T275 667T226 581T184 443T167 250T184 58T225 -81T274 -167T316 -220T333 -241Q333 -250 318 -250H315H302L274 -226Q180 -141 137 -14T94 250Z" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(4641,0)"><path data-c="1D44E" d="M33 157Q33 258 109 349T280 441Q331 441 370 392Q386 422 416 422Q429 422 439 414T449 394Q449 381 412 234T374 68Q374 43 381 35T402 26Q411 27 422 35Q443 55 463 131Q469 151 473 152Q475 153 483 153H487Q506 153 506 144Q506 138 501 117T481 63T449 13Q436 0 417 -8Q409 -10 393 -10Q359 -10 336 5T306 36L300 51Q299 52 296 50Q294 48 292 46Q233 -10 172 -10Q117 -10 75 30T33 157ZM351 328Q351 334 346 350T323 385T277 405Q242 405 210 374T160 293Q131 214 119 129Q119 126 119 118T118 106Q118 61 136 44T179 26Q217 26 254 59T298 110Q300 114 325 217T351 328Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(5392.2,0)"><path data-c="2212" d="M84 237T84 250T98 270H679Q694 262 694 250T679 230H98Q84 237 84 250Z" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(6392.4,0)"><path data-c="2113" d="M345 104T349 104T361 95T369 80T352 59Q268 -20 206 -20Q170 -20 146 3T113 53T99 104L94 129Q94 130 79 116T48 86T28 70Q22 70 15 79T7 94Q7 98 12 103T58 147L91 179V185Q91 186 91 191T92 200Q92 282 128 400T223 612T336 705Q397 705 397 636V627Q397 453 194 233Q185 223 180 218T174 211T171 208T165 201L163 186Q159 142 159 123Q159 17 208 17Q228 17 253 30T293 56T335 94Q345 104 349 104ZM360 634Q360 655 354 661T336 668Q328 668 322 666T302 645T272 592Q252 547 229 467T192 330L179 273Q179 272 186 280T204 300T221 322Q327 453 355 590Q360 612 360 634Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(6809.4,0)"><path data-c="29" d="M60 749L64 750Q69 750 74 750H86L114 726Q208 641 251 514T294 250Q294 182 284 119T261 12T224 -76T186 -143T145 -194T113 -227T90 -246Q87 -249 86 -250H74Q66 -250 63 -250T58 -247T55 -238Q56 -237 66 -225Q221 -64 221 250T66 725Q56 737 55 738Q55 746 60 749Z" style="stroke-width: 3;"/></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mi>ℓ</mi><mo stretchy="false">←</mo><mi>ℓ</mi><mo>+</mo><mi>α</mi><mo stretchy="false">(</mo><mi>a</mi><mo>−</mo><mi>ℓ</mi><mo stretchy="false">)</mo></math></mjx-assistive-mml></mjx-container> se movería con brusquedad en una máquina rápida y con pesadez en una lenta.</p>
<p>El último comportamiento está pensado para los interiores estrechos que dieron origen a toda esta parte. Cuando el brazo se acorta tanto que la cámara queda justo encima del jugador, ocultamos su propio avatar y dejamos que la vista se sitúe cerca de la primera persona. Es lo que hace Breath of the Wild en un santuario estrecho y el recurso al que recurren la mayoría de los juegos en tercera persona al quedar arrinconados, porque la alternativa —una cámara encajada contra una pared y mirando la nuca de un personaje— no sirve de nada. El rig expone una sola bandera para ello, y el bucle del mundo la consulta y alterna la visibilidad del avatar local. Con menos de un metro de brazo estás, en la práctica, en primera persona, se respetan las paredes y, en cuanto retrocedes hasta una sala con espacio, el avatar reaparece gradualmente y el brazo se extiende.</p>
<h2 id="lo-siguiente-que-se-conecta" tabindex="-1">Lo siguiente que se conecta <a class="header-anchor" href="#lo-siguiente-que-se-conecta" aria-label="Permalink to &quot;Lo siguiente que se conecta&quot;"></a></h2>
<p>El colisionador del terreno se publica hoy y es la mitad difícil, porque el terreno está por todas partes y un campo de distancias es algo incómodo de sondear. Los objetos y las estructuras de edificios procedentes de los prototipos de creación son la mitad fácil, y el contrato ya está preparado para ellos. Un segundo colisionador, uno de trazado de rayos, lanza un rayo desde el pivote hacia la cámara contra una lista de mallas e informa del impacto más cercano del mismo modo que el colisionador del terreno. La versión económica lanza un solo rayo, lo cual basta hasta que aumenta la cantidad de objetos, y la mejora consiste en sustituir el rayo por una esfera barrida mediante three-mesh-bvh, la biblioteca de Garrett Johnson que envuelve una malla en una jerarquía de volúmenes delimitadores para que las consultas espaciales se ejecuten en tiempo logarítmico en lugar de recurrir a la fuerza bruta. En cualquier caso, el rig no cambia. Consulta una lista más larga de colisionadores y toma el impacto más cercano, que es precisamente la razón por la que construimos primero el contrato y después los colisionadores.</p>
<h2 id="tecnologia-mencionada-en-este-capitulo" tabindex="-1">Tecnología mencionada en este capítulo <a class="header-anchor" href="#tecnologia-mencionada-en-este-capitulo" aria-label="Permalink to &quot;Tecnología mencionada en este capítulo&quot;"></a></h2>
<p><strong>Un brazo que posee un único valor.</strong> El rig de cámara es un posprocesado sobre OrbitControls, no su sustituto. Es dueño de la longitud del brazo y deja el giro horizontal, la inclinación, el zoom y la gestión de gestos en manos del controlador orbital en el que ya confiábamos. La integración consta de dos llamadas que enmarcan la actualización: <code>beforeControls()</code> restaura la distancia completa del fotograma anterior para que los cálculos orbitales lean el zoom real del usuario en lugar de confundir el acortamiento causado por una colisión con un acercamiento de cámara, y <code>afterControls(dt)</code> resuelve la colisión y escribe la posición que se renderizará. Sin ese par, la cámara se desploma sobre el jugador en unos pocos fotogramas.</p>
<p><strong>Un contrato de colisionadores conectables.</strong> Un colisionador es cualquier objeto con un <code>probe</code> que responde a la pregunta «¿qué distancia puede recorrer la cámara desde el pivote a lo largo de este rayo antes de que la bloquees?». El rig consulta todos los colisionadores y toma el impacto más cercano, sin saber si el obstáculo es terreno, un objeto o una pared, siguiendo la misma disciplina de poseer una sola cosa que el <a href="/es/blog/2026-05-15-open-world-browser-part-29-pluggable-character.html">controlador de personaje conectable</a> empleaba para la locomoción. La sonda es una esfera barrida dimensionada para contener el plano cercano, no un rayo fino, de modo que las esquinas del frustum nunca atraviesen una superficie que el rayo central no detectaría. Su radio se deriva de la proyección: la distancia hasta una esquina del plano cercano, <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.212ex;" xmlns="http://www.w3.org/2000/svg" width="14.705ex" height="2.398ex" role="img" focusable="false" viewBox="0 -966.5 6499.5 1060" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="msqrt"><g transform="translate(853,0)"><g data-mml-node="msup"><g data-mml-node="mi"><path data-c="1D45B" d="M21 287Q22 293 24 303T36 341T56 388T89 425T135 442Q171 442 195 424T225 390T231 369Q231 367 232 367L243 378Q304 442 382 442Q436 442 469 415T503 336T465 179T427 52Q427 26 444 26Q450 26 453 27Q482 32 505 65T540 145Q542 153 560 153Q580 153 580 145Q580 144 576 130Q568 101 554 73T508 17T439 -10Q392 -10 371 17T350 73Q350 92 386 193T423 345Q423 404 379 404H374Q288 404 229 303L222 291L189 157Q156 26 151 16Q138 -11 108 -11Q95 -11 87 -5T76 7T74 17Q74 30 112 180T152 343Q153 348 153 366Q153 405 129 405Q91 405 66 305Q60 285 60 284Q58 278 41 278H27Q21 284 21 287Z" style="stroke-width: 3;"/></g><g data-mml-node="mn" transform="translate(633,289) scale(0.707)"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"/></g></g><g data-mml-node="mo" transform="translate(1258.8,0)"><path data-c="2B" d="M56 237T56 250T70 270H369V420L370 570Q380 583 389 583Q402 583 409 568V270H707Q722 262 722 250T707 230H409V-68Q401 -82 391 -82H389H387Q375 -82 369 -68V230H70Q56 237 56 250Z" style="stroke-width: 3;"/></g><g data-mml-node="msup" transform="translate(2259,0)"><g data-mml-node="mi"><path data-c="1D464" d="M580 385Q580 406 599 424T641 443Q659 443 674 425T690 368Q690 339 671 253Q656 197 644 161T609 80T554 12T482 -11Q438 -11 404 5T355 48Q354 47 352 44Q311 -11 252 -11Q226 -11 202 -5T155 14T118 53T104 116Q104 170 138 262T173 379Q173 380 173 381Q173 390 173 393T169 400T158 404H154Q131 404 112 385T82 344T65 302T57 280Q55 278 41 278H27Q21 284 21 287Q21 293 29 315T52 366T96 418T161 441Q204 441 227 416T250 358Q250 340 217 250T184 111Q184 65 205 46T258 26Q301 26 334 87L339 96V119Q339 122 339 128T340 136T341 143T342 152T345 165T348 182T354 206T362 238T373 281Q402 395 406 404Q419 431 449 431Q468 431 475 421T483 402Q483 389 454 274T422 142Q420 131 420 107V100Q420 85 423 71T442 42T487 26Q558 26 600 148Q609 171 620 213T632 273Q632 306 619 325T593 357T580 385Z" style="stroke-width: 3;"/></g><g data-mml-node="mn" transform="translate(749,289) scale(0.707)"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"/></g></g><g data-mml-node="mo" transform="translate(3633.8,0)"><path data-c="2B" d="M56 237T56 250T70 270H369V420L370 570Q380 583 389 583Q402 583 409 568V270H707Q722 262 722 250T707 230H409V-68Q401 -82 391 -82H389H387Q375 -82 369 -68V230H70Q56 237 56 250Z" style="stroke-width: 3;"/></g><g data-mml-node="msup" transform="translate(4634,0)"><g data-mml-node="mi"><path data-c="210E" d="M137 683Q138 683 209 688T282 694Q294 694 294 685Q294 674 258 534Q220 386 220 383Q220 381 227 388Q288 442 357 442Q411 442 444 415T478 336Q478 285 440 178T402 50Q403 36 407 31T422 26Q450 26 474 56T513 138Q516 149 519 151T535 153Q555 153 555 145Q555 144 551 130Q535 71 500 33Q466 -10 419 -10H414Q367 -10 346 17T325 74Q325 90 361 192T398 345Q398 404 354 404H349Q266 404 205 306L198 293L164 158Q132 28 127 16Q114 -11 83 -11Q69 -11 59 -2T48 16Q48 30 121 320L195 616Q195 629 188 632T149 637H128Q122 643 122 645T124 664Q129 683 137 683Z" style="stroke-width: 3;"/></g><g data-mml-node="mn" transform="translate(609,289) scale(0.707)"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"/></g></g></g><g data-mml-node="mo" transform="translate(0,106.5)"><path data-c="221A" d="M95 178Q89 178 81 186T72 200T103 230T169 280T207 309Q209 311 212 311H213Q219 311 227 294T281 177Q300 134 312 108L397 -77Q398 -77 501 136T707 565T814 786Q820 800 834 800Q841 800 846 794T853 782V776L620 293L385 -193Q381 -200 366 -200Q357 -200 354 -197Q352 -195 256 15L160 225L144 214Q129 202 113 190T95 178Z" style="stroke-width: 3;"/></g><rect width="5646.5" height="60" x="853" y="846.5"/></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><msqrt><msup><mi>n</mi><mn>2</mn></msup><mo>+</mo><msup><mi>w</mi><mn>2</mn></msup><mo>+</mo><msup><mi>h</mi><mn>2</mn></msup></msqrt></math></mjx-assistive-mml></mjx-container>, multiplicada por un margen de seguridad; además, se vuelve a calcular cada vez que cambian el campo de visión, la relación de aspecto o el plano cercano.</p>
<p><strong>Una sonda de terreno basada en distancias con signo que respeta salientes y cuevas.</strong> Como el terreno es un <a href="/es/blog/2026-02-25-open-world-browser-part-07-marching-cubes.html">campo de distancias con signo</a> en lugar de un mapa de alturas, la misma sonda que detiene la cámara contra una ladera también la detiene ante el techo de una cueva, un caso que un trazado de rayos sobre un mapa de alturas no puede detectar por su propia estructura. La marcha es un trazado de esferas al estilo de Hart: avanza una fracción subrelajada del margen indicado por el campo y queda limitada por ambos extremos, porque las regiones de mapa de alturas indican separación vertical en lugar de distancia verdadera y exageran cuánto puede moverse la cámara por una pendiente, por lo que un paso completo saltaría una cresta. Una pasada de despenetración guiada por el gradiente actúa como red de seguridad y recupera la vista cuando se esculpe el suelo bajo la cámara.</p>
<p><strong>Amortiguación asimétrica con temporizador de espera.</strong> El brazo entra rápidamente cuando aparece un oclusor y sale con suavidad cuando desaparece, y solo después de un breve periodo de espacio libre continuo, por lo que pasar rápidamente junto a un poste de valla nunca hace que la cámara se abalance. Por debajo de un umbral de contracción, el rig activa el estado de casi primera persona y el bucle del mundo oculta el avatar local, la solución habitual para interiores estrechos en lugar de dejar la cámara enterrada en una pared.</p>
<h2 id="referencias" tabindex="-1">Referencias <a class="header-anchor" href="#referencias" aria-label="Permalink to &quot;Referencias&quot;"></a></h2>
<p>El planteamiento del control de cámara como una restricción de visibilidad procede de Marc Christie y Patrick Olivier, <a href="https://people.irisa.fr/Marc.Christie/Publications/2008/CON08.html" target="_blank" rel="noreferrer"><em>Control de cámara en gráficos por computadora</em></a> (Computer Graphics Forum, 2008). La marcha por campos de distancias procede de John C. Hart, <a href="https://graphics.stanford.edu/courses/cs348b-20-spring-content/uploads/hart.pdf" target="_blank" rel="noreferrer"><em>Trazado de esferas: un método geométrico para el trazado de rayos con antialiasing de superficies implícitas</em></a> (The Visual Computer, 1996). El patrón de brazo con muelle y su colisión mediante una esfera de sondeo están documentados en <a href="https://dev.epicgames.com/documentation/en-us/unreal-engine/using-spring-arm-components-in-unreal-engine" target="_blank" rel="noreferrer">Componente Spring Arm</a> de Epic y en <a href="https://docs.unity3d.com/Packages/com.unity.cinemachine@3.1/manual/CinemachineDeoccluder.html" target="_blank" rel="noreferrer">Desoclusor de Cinemachine</a> y <a href="https://docs.unity3d.com/Packages/com.unity.cinemachine@3.1/manual/CinemachineThirdPersonFollow.html" target="_blank" rel="noreferrer">Seguimiento en tercera persona</a> de Unity. La intuición sobre el movimiento y la amortiguación procede de Mark Haigh-Hutchinson, <em>Cámaras en tiempo real</em> (Morgan Kaufmann, 2009), y de Itay Keren, <a href="https://www.gamedeveloper.com/design/scroll-back-the-theory-and-practice-of-cameras-in-side-scrollers" target="_blank" rel="noreferrer"><em>Desplazarse hacia atrás: teoría y práctica de las cámaras en juegos de desplazamiento lateral</em></a> (GDC 2015). La vía de mejora para el colisionador de mallas es <a href="https://github.com/gkjohnson/three-mesh-bvh" target="_blank" rel="noreferrer">three-mesh-bvh</a>, de Garrett Johnson.</p>
<hr>
<p>Parte 30 de 30.
Anterior: <a href="/es/blog/2026-05-15-open-world-browser-part-29-pluggable-character.html">Parte 29 - Un controlador, cualquier cuerpo</a>
Guía de la serie: <a href="/es/blog/2026-02-25-open-world-browser-series-guide.html">/es/blog/2026-02-25-open-world-browser-series-guide</a></p>
]]></content:encoded>
            <enclosure url="https://cdn.cinevva.com/blog/why-webgpu-engine-hero.jpg" length="0" type="image/jpg"/>
        </item>
        <item>
            <title><![CDATA[No renderices la hierba detrás de la colina: descarte de oclusión basado en el terreno]]></title>
            <link>https://app.cinevva.com/es/blog/2026-05-19-terrain-occlusion-culling</link>
            <guid>https://app.cinevva.com/es/blog/2026-05-19-terrain-occlusion-culling</guid>
            <pubDate>Tue, 19 May 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Ocho técnicas de descarte de oclusión evaluadas para un mundo abierto en el navegador, la que gana porque nuestro terreno es un mapa de alturas y un prototipo interactivo que te permite compararlas mediante pruebas A/B en tu propia escena.]]></description>
            <content:encoded><![CDATA[<h1 id="no-renderices-la-hierba-detras-de-la-colina-descarte-de-oclusion-basado-en-el-terreno" tabindex="-1">No renderices la hierba detrás de la colina: descarte de oclusión basado en el terreno <a class="header-anchor" href="#no-renderices-la-hierba-detras-de-la-colina-descarte-de-oclusion-basado-en-el-terreno" aria-label="Permalink to &quot;No renderices la hierba detrás de la colina: descarte de oclusión basado en el terreno&quot;"></a></h1>
<p><em>Por <a href="/es/about.html">Oleg Sidorkin</a>, CTO y cofundador de Cinevva</em></p>
<p>La <a href="/es/blog/2026-05-14-open-world-browser-part-28-grass-and-occlusion.html">parte 28</a> presentó el prototipo 57 y comparó sus cuatro rutas de descarte en un par de párrafos. Esta es la versión larga: por qué elegimos esas cuatro, cuáles eran las otras cuatro y el razonamiento detrás de la que vamos a lanzar.</p>
<p>Hay una colina entre la cámara y un prado. No necesitas renderizar el prado. Todos los motores AAA modernos lo saben. La mayoría de los motores 3D para navegadores no, incluido el nuestro hasta la semana pasada.</p>
<p>Esta publicación es el resultado de investigar el tema como es debido, contrastarlo con nuestra base de código real, crear un prototipo funcional y evaluar las técnicas según cuánto nos ayudan <em>específicamente a nosotros</em>, teniendo en cuenta que hoy publicamos para WebGL y mañana para WebGPU.</p>
<p>Puedes probar el prototipo interactivo de abajo antes de seguir leyendo. <kbd>T</kbd>/<kbd>Y</kbd>/<kbd>U</kbd>/<kbd>I</kbd> cambian entre las rutas de descarte, <kbd>C</kbd> recorre las cámaras predefinidas y <kbd>B</kbd> pinta en rojo y en modo alámbrico los chunks que se ocultan para que puedas ver qué elimina la prueba. El HUD indica cuántas instancias descarta cada etapa.</p>
<div style="position:relative;padding-bottom:62%;height:0;overflow:hidden;border-radius:8px;margin:1.5rem 0;border:1px solid rgba(255,255,255,0.08)">
<iframe src="/es/spikes/57-terrain-occlusion/" title="Prototipo 57: descarte de oclusión del terreno" style="position:absolute;top:0;left:0;width:100%;height:100%;border:0;background:#1a1f2a" loading="lazy" allowfullscreen></iframe>
</div>
<p><a href="/es/spikes/57-terrain-occlusion/" target="_blank">Abrir el prototipo 57 en una pestaña nueva ↗</a> · <a href="/es/blog/spike-source?spike=57-terrain-occlusion">Ver el código fuente</a></p>
<h2 id="lo-que-hace-hoy-nuestro-motor-y-lo-que-no" tabindex="-1">Lo que hace hoy nuestro motor (y lo que no) <a class="header-anchor" href="#lo-que-hace-hoy-nuestro-motor-y-lo-que-no" aria-label="Permalink to &quot;Lo que hace hoy nuestro motor (y lo que no)&quot;"></a></h2>
<p>Nuestro gestor de chunks en streaming carga alrededor del jugador un anillo de chunks de 64 m con tres niveles de LOD. Cada chunk contiene árboles instanciados distribuidos sobre el mapa de alturas. La lógica de descarte, que reside en <code>Chunk.updateObjectVisibility</code>, es una simple comprobación de distancia: los árboles a menos de 60 m se renderizan con la malla completa, los que están entre 60 m y 140 m se renderizan como billboards y, más allá, no se renderiza nada.</p>
<p>Ese descarte pasa por alto dos enormes categorías de trabajo desperdiciado:</p>
<ol>
<li>Todo lo que está dentro del disco de 60 m <em>pero detrás de la cámara</em>. Volvemos a ordenar el búfer de instancias cada vez que el jugador se mueve más de 4 m, pero no comprobamos el frustum de visión, así que, en promedio, enviamos la mitad del disco a la GPU solo para que se recorte después de la transformación de vértices.</li>
<li>Todo lo que está dentro del disco de 60 m <em>pero detrás de una colina</em>. Nuestro terreno tiene 80 m de rango vertical y muchos valles. Cuando la cámara está en un valle, la cresta más cercana oculta geométricamente la mayor parte de la vegetación situada dentro del radio de descarte. Aun así, la dibujamos.</li>
</ol>
<p>La segunda categoría es el tema central de esta publicación. También es la que los motores AAA resuelven con una serie de técnicas ingeniosas que, a primera vista, no se trasladan fácilmente al navegador.</p>
<div style="position:relative;padding-bottom:56.25%;height:0;overflow:hidden;border-radius:8px;margin:1.5rem 0">
<iframe src="https://www.youtube.com/embed/wavnKZNSYqU" style="position:absolute;top:0;left:0;width:100%;height:100%;border:0" allow="accelerometer;autoplay;clipboard-write;encrypted-media;gyroscope;picture-in-picture" allowfullscreen></iframe>
</div>
<p><em>Gilbert Sanders, de Guerrilla, explica cómo Horizon Zero Dawn renderiza la vegetación de su mundo abierto. La cadena de descarte ocupa los últimos 20 minutos y es una clase magistral sobre por qué «dibujar menos» supera a «dibujar más rápido».</em></p>
<h2 id="ocho-tecnicas-evaluadas-para-nuestro-caso" tabindex="-1">Ocho técnicas evaluadas para nuestro caso <a class="header-anchor" href="#ocho-tecnicas-evaluadas-para-nuestro-caso" aria-label="Permalink to &quot;Ocho técnicas evaluadas para nuestro caso&quot;"></a></h2>
<p>Estudié la cadena moderna de descarte de oclusión y evalué cada componente según cuánto ayuda a un mundo abierto procedural, basado en un mapa de alturas y ejecutado en el navegador. Dos ejes: valor (cuánto trabajo innecesario elimina en nuestra escena) y coste (esfuerzo de ingeniería, además de cuánto nos obliga a cambiar de nuestra arquitectura). El razonamiento completo está en el archivo de investigación que respalda esta publicación; esta es la versión resumida.</p>
<p><strong>1. Descarte por frustum para cada instancia. Valor alto, coste bajo.</strong> Ahora mismo no comprobamos en absoluto el frustum para nuestra vegetación instanciada. Añadirlo reduce aproximadamente a la mitad el trabajo en cualquier vista, cuesta unas treinta líneas de código y se puede lanzar hoy en WebGL. Es, con diferencia, la mayor mejora barata, y deberíamos haberla implementado hace meses.</p>
<p><strong>2. Trazado de rayos del horizonte sobre el mapa de alturas. Valor alto, coste bajo-medio.</strong> Se hace avanzar un rayo desde la cámara hasta cada instancia candidata, muestreando la altura del terreno a lo largo del trayecto. Si en algún punto el terreno se eleva por encima del rayo, la instancia está ocluida. Funciona precisamente porque nuestro mundo es un mapa de alturas, lo que reduce la visibilidad a un problema 1D a lo largo de la dirección horizontal. La versión densa tiene una complejidad O(pasos) por instancia y por fotograma. La versión acelerada (el siguiente punto) la reduce a O(log pasos).</p>
<p><strong>3. Aceleración mediante una pirámide de alturas máximas. Valor alto, coste medio.</strong> Un mipmap 2D del mapa de alturas donde cada texel almacena la altura máxima del terreno dentro de su área. Permite que el trazado de rayos del horizonte avance a grandes saltos cuando el entorno es llano y solo refine sobre las colinas. Esta es la estructura que hace que la técnica 2 sea barata en producción.</p>
<p><strong>4. Oclusión mediante Z jerárquico (Hi-Z / HZB). Valor alto, coste alto.</strong> Se crea un mipmap del búfer de profundidad, se proyectan los límites de cada instancia al espacio de pantalla y se comparan con el nivel de mip adecuado. Es el estándar moderno en la GPU, utilizado por Nanite de Unreal, la geometría virtual de Bevy y la adaptación de VTK a WebGPU. Funciona para todo, no solo para el terreno, pero requiere WebGPU, llamadas de dibujo indirectas y un pase de cómputo. Compensa cuando renderizamos millones de briznas de hierba, no miles de árboles.</p>
<p><strong>5. Hi-Z de dos pases (al estilo de Nanite). Mejora marginal respecto a la técnica 4, coste alto.</strong> Se vuelve a renderizar la profundidad del fotograma actual después del primer pase para evitar el artefacto de desoclusión de un fotograma. Solo merece la pena cuando hemos avanzado lo suficiente en la ruta controlada por la GPU como para que el coste sea incremental.</p>
<p><strong>6. Rasterizador de oclusión por software (Frostbite/Intel MOC). Valor medio, coste alto.</strong> Rasteriza en la CPU un búfer de profundidad de baja resolución para los oclusores grandes. Latencia de lectura nula. Las implementaciones de referencia están escritas en C++ con AVX/SSE; adaptarlas a WASM es un proyecto de verdad, y nuestro trazado de rayos sobre el mapa de alturas consigue la mayoría de las mismas mejoras con una fracción del trabajo.</p>
<p><strong>7. PVS precalculado. Valor bajo, coste alto.</strong> Es fantástico para los mapas estáticos de la era de Quake. Nuestro terreno es procedural e infinito, así que cualquier preprocesamiento tendría que hacerse durante el streaming de chunks, lo que cuesta aproximadamente lo mismo que calcular la visibilidad en tiempo de ejecución. Lo descartamos.</p>
<p><strong>8. Descarte del horizonte al estilo de Cesium. Ningún valor para nosotros, coste medio.</strong> Está diseñado para elipsoides planetarios. Nuestro mundo es más o menos plano y está acotado; las matemáticas no son aplicables y la técnica no haría nada o produciría falsos descartes. Lo descartamos.</p>
<p>Así que: implementaremos ahora las técnicas 1 y 2+3 en la CPU y con WebGL. Planificaremos la técnica 4 para la migración a WebGPU. Omitiremos el resto.</p>
<h2 id="por-que-gana-el-trazado-de-rayos-sobre-el-mapa-de-alturas-para-terrenos-en-el-navegador" tabindex="-1">Por qué gana el trazado de rayos sobre el mapa de alturas para terrenos en el navegador <a class="header-anchor" href="#por-que-gana-el-trazado-de-rayos-sobre-el-mapa-de-alturas-para-terrenos-en-el-navegador" aria-label="Permalink to &quot;Por qué gana el trazado de rayos sobre el mapa de alturas para terrenos en el navegador&quot;"></a></h2>
<p>El consejo habitual en cualquier charla moderna sobre renderizado es «crea un búfer Hi-Z». El <a href="https://www.youtube.com/watch?v=eviSykqSUUw" target="_blank" rel="noreferrer">análisis detallado de Nanite presentado por Brian Karis en SIGGRAPH 2021</a> es la referencia canónica y deberías verlo al menos una vez.</p>
<div style="position:relative;padding-bottom:56.25%;height:0;overflow:hidden;border-radius:8px;margin:1.5rem 0">
<iframe src="https://www.youtube.com/embed/eviSykqSUUw" style="position:absolute;top:0;left:0;width:100%;height:100%;border:0" allow="accelerometer;autoplay;clipboard-write;encrypted-media;gyroscope;picture-in-picture" allowfullscreen></iframe>
</div>
<p>Es la respuesta correcta para un motor que ya ejecuta todo mediante llamadas de dibujo indirectas controladas por la GPU. La mayoría de los motores para navegadores, incluido el nuestro, no son ese tipo de motor. Tenemos búferes de instancias en la CPU, llamadas de dibujo de WebGL y ninguna etapa de cómputo. Incorporar Hi-Z a esa arquitectura implicaría migrar simultáneamente a WebGPU, reescribir el pipeline de vegetación para usar llamadas de dibujo indirectas y añadir un pase de creación de la pirámide de profundidad. Eso supone un trimestre de trabajo solo para obtener el primer fotograma que demuestre la idea.</p>
<p>El trazado de rayos sobre el mapa de alturas funciona en la CPU, con WebGL y con los datos que ya tenemos. Aprovecha un hecho sobre nuestro mundo que los motores AAA no pueden aprovechar: <strong>nuestros oclusores se describen mediante una función de altura 1D</strong>. Muestrear esa función a lo largo de un rayo requiere dos consultas a un array y una multiplicación. Un búfer Hi-Z tendría que descubrir el mismo hecho píxel a píxel.</p>
<p>La técnica se publicó por primera vez como «Horizon Occlusion Culling for Hierarchical Terrains» en IEEE Visualization 2002 (<a href="https://saksagan.ceng.metu.edu.tr/courses/ceng591/RAPORLAR/HacerYalim.pdf" target="_blank" rel="noreferrer">PDF</a>). Se ha mantenido en el repertorio durante dos décadas porque tiene las características adecuadas: es barata cuando el terreno es llano, costosa solo donde hay colinas reales y trivialmente paralelizable.</p>
<h2 id="la-piramide-de-alturas-maximas-ilustrada" tabindex="-1">La pirámide de alturas máximas, ilustrada <a class="header-anchor" href="#la-piramide-de-alturas-maximas-ilustrada" aria-label="Permalink to &quot;La pirámide de alturas máximas, ilustrada&quot;"></a></h2>
<p>El trazado de rayos básico muestrea <code>terrainHeight</code> en unos 24 puntos a lo largo de cada rayo y se detiene en cuanto el terreno lo cruza. Eso funciona bien para miles de árboles. Se viene abajo con cientos de miles de briznas de hierba.</p>
<p>La solución es un mipmap del mapa de alturas en el que cada texel almacena la altura <strong>máxima</strong> dentro de su área:</p>
<div class="language- vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span>nivel 0 (256×256, 2,25 m por texel): altura máx. de 4×4 muestras con desplazamiento aleatorio</span></span>
<span class="line"><span>nivel 1 (128×128, 4,5 m  por texel): máx.(0,0), máx.(1,0), máx.(0,1), máx.(1,1)</span></span>
<span class="line"><span>nivel 2 ( 64×64,  9,0 m por texel): la misma reducción un nivel por encima</span></span>
<span class="line"><span>...</span></span>
<span class="line"><span>nivel 8 (   1×1,  576 m por texel): máximo global</span></span></code></pre>
</div><p>Cuando el segmento del rayo es largo y llano, se muestrea un nivel grueso: una sola consulta indica «ningún punto del terreno en este cuadrado de 9 m supera nunca los 12 m de altitud y el rayo está allí a 30 m, así que continúa». Solo cuando un texel grueso indica que «el terreno <em>podría</em> estar por encima del rayo» se desciende un nivel para refinar. Toda la estructura ocupa unos pocos cientos de KB y se construye en decenas de milisegundos.</p>
<p>En forma de diagrama:</p>
<div class="language- vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span>                                        rayo desde el ojo</span></span>
<span class="line"><span>       ojo 1,7 m                      o────────────────────────►</span></span>
<span class="line"><span>              o─────────────────────·─·─·─·─·─·────────────────</span></span>
<span class="line"><span>              │                      \                         │</span></span>
<span class="line"><span>              │ nivel 3 (paso enorme) \ nivel 0 (refinamiento)│</span></span>
<span class="line"><span>              │ «nada supera los 8 m»  \ «¡colina de 9 m!»    │</span></span>
<span class="line"><span>              │                          \                     │</span></span>
<span class="line"><span>        ──────┴────────────/▔▔▔\─────────/▔▔▔▔▔\───────────────</span></span>
<span class="line"><span>                              colina A (8 m) colina B (12 m)</span></span>
<span class="line"><span>                                               ↑</span></span>
<span class="line"><span>                                         bloquea aquí</span></span></code></pre>
</div><p>Para el segmento del rayo que pasa cerca de la colina A, la consulta del nivel 3 («la altura máxima en esta caja de 18 m de ancho es de 8 m») ya nos indica que el rayo, a una altitud de 1,7 m más unos metros de ascenso, está despejado. Saltamos 36 m de recorrido con una sola consulta. Sobre la colina B, el nivel 3 indica «el máximo aquí es de 12 m»; descendemos y el nivel 0 indica «sí, hay 12 m en este texel exacto», por lo que descartamos la instancia.</p>
<p>La construcción de la pirámide está en <code>height-pyramid.mjs</code>, y las rutas de descarte que la utilizan están en <code>cull.mjs</code>. Ambos archivos se pueden consultar en el <a href="/es/blog/spike-source.html?spike=57-terrain-occlusion">navegador del código fuente del prototipo</a>.</p>
<h2 id="lo-que-muestra-realmente-el-prototipo" tabindex="-1">Lo que muestra realmente el prototipo <a class="header-anchor" href="#lo-que-muestra-realmente-el-prototipo" aria-label="Permalink to &quot;Lo que muestra realmente el prototipo&quot;"></a></h2>
<p>Abre arriba el prototipo 57 y recorre las cuatro rutas:</p>
<ul>
<li><strong>T0</strong> es lo que hace hoy la versión de producción. Solo distancia. Desde C1 (el fondo del valle), el HUD indica unas 12 000 briznas de hierba visibles.</li>
<li><strong>T1</strong> añade descarte por frustum para cada instancia. El número de elementos visibles se reduce aproximadamente a la mitad porque todo lo que está detrás de la cámara o fuera de los laterales se descarta antes de llegar a la GPU.</li>
<li><strong>T2</strong> añade el trazado de rayos por fuerza bruta sobre el mapa de alturas. En C1, el número se reduce otro 60-80 %, porque la mayor parte del campo está al otro lado de la cresta más cercana. La columna Cull-ms aumenta porque muestreamos <code>terrainHeight</code> unas 24 veces por instancia.</li>
<li><strong>T3</strong> sustituye la fuerza bruta por la pirámide de alturas máximas. Cull-ms vuelve a valores cercanos a T1 sin perder la mejora de visibilidad. Esta es la ruta que realmente puedes lanzar.</li>
</ul>
<p>El patrón coincide con lo observado en los motores de producción. La serie de Acerola en dos partes sobre el renderizado de hierba (<a href="https://www.youtube.com/watch?v=Y0Ko0kvwfgA" target="_blank" rel="noreferrer">¿Cómo renderizan los juegos tanta hierba?</a>, <a href="https://www.youtube.com/watch?v=PNvlqsXdQic" target="_blank" rel="noreferrer">Lo que hice para optimizar la hierba de mi juego</a>) es la explicación más accesible de YouTube sobre por qué conviene invertir el trabajo de ingeniería en la etapa de descarte y no en la de sombreado.</p>
<div style="position:relative;padding-bottom:56.25%;height:0;overflow:hidden;border-radius:8px;margin:1.5rem 0">
<iframe src="https://www.youtube.com/embed/Y0Ko0kvwfgA" style="position:absolute;top:0;left:0;width:100%;height:100%;border:0" allow="accelerometer;autoplay;clipboard-write;encrypted-media;gyroscope;picture-in-picture" allowfullscreen></iframe>
</div>
<h2 id="la-camara-c3-y-el-caso-problematico-de-la-«cima»" tabindex="-1">La cámara C3 y el caso problemático de la «cima» <a class="header-anchor" href="#la-camara-c3-y-el-caso-problematico-de-la-«cima»" aria-label="Permalink to &quot;La cámara C3 y el caso problemático de la «cima»&quot;"></a></h2>
<p>La tercera cámara predefinida del prototipo coloca la cámara en lo alto de una colina, mirando hacia el área de juego. En este caso, el descarte del horizonte apenas hace nada porque no hay terreno entre la cámara y la mayor parte del mundo. El HUD muestra que T2/T3 reducen el número de elementos visibles quizá entre un 5 % y un 10 % respecto a T1.</p>
<p>Eso es una característica, no un error. La técnica deja de funcionar exactamente donde debe hacerlo: cuando no hay nada que ocluya. El descarte por frustum sigue haciendo trabajo útil, el descarte por distancia sigue limitando el presupuesto y la prueba del horizonte pasa de forma natural a no hacer nada. Si implementas esto, debes comprobar que el caso en el que no se hace nada también sea barato; por eso la pirámide de alturas máximas importa incluso cuando no se va a descartar ningún rayo: a menudo, el nivel más grueso basta para confirmar que «nada está bloqueado».</p>
<h2 id="lo-siguiente-que-vamos-a-lanzar" tabindex="-1">Lo siguiente que vamos a lanzar <a class="header-anchor" href="#lo-siguiente-que-vamos-a-lanzar" aria-label="Permalink to &quot;Lo siguiente que vamos a lanzar&quot;"></a></h2>
<p>Hay tres cosas que hacer, en este orden.</p>
<p>Primero, trasladar T1 y T3 a <code>Chunk.updateObjectVisibility</code> en producción. La pirámide debe residir un nivel más arriba, en el gestor de chunks, porque abarca más de un chunk. El descarte permanece en <code>Chunk</code> para que el procesamiento por lotes existente para cada chunk siga funcionando. Esfuerzo estimado: un día, incluidas las pruebas.
Segundo, haremos lo mismo con la hierba una vez que la tengamos. El prototipo actual distribuye 12 000 briznas por un área de juego de 576 m; la densidad de producción debería ser aproximadamente un orden de magnitud mayor. Las rutas de descarte en CPU procesan 12 000 en menos de un milisegundo, y la aceleración mediante la pirámide es lo que permite mantener ese rendimiento con 120 000.</p>
<p>Tercero, cuando migremos a <code>THREE.WebGPURenderer</code>, trasladaremos el mismo bucle a un shader de cómputo. Los metadatos se convierten en un búfer de almacenamiento. El descarte escribe los argumentos de <code>drawIndirect</code>. La pirámide se carga como una textura 2D con la reducción por máximos ya incorporada. La estructura del código permanece prácticamente idéntica, que es precisamente la idea: no estamos apostando la migración a un algoritmo nuevo, sino trasladando un algoritmo que ya tenemos a una pista más rápida.</p>
<p>Guerrilla presentó la versión para GPU de este enfoque en el sistema de colocación procedimental de Horizon Zero Dawn; la canalización de renderizado importa menos que las estructuras de datos, y las suyas tienen la misma forma:</p>
<div style="position:relative;padding-bottom:56.25%;height:0;overflow:hidden;border-radius:8px;margin:1.5rem 0">
<iframe src="https://www.youtube.com/embed/ToCozpl1sYY" style="position:absolute;top:0;left:0;width:100%;height:100%;border:0" allow="accelerometer;autoplay;clipboard-write;encrypted-media;gyroscope;picture-in-picture" allowfullscreen></iframe>
</div>
<p>Hi-Z seguirá mereciendo su lugar cuando incorporemos edificios y elementos densos que ocluyan en direcciones que el mapa de alturas no puede describir. Pero la pirámide del mapa de alturas seguirá en la canalización porque es estrictamente más barata que Hi-Z para las instancias pegadas al terreno, y la hierba que cruza la silueta de una cresta es precisamente el caso que Hi-Z peor resuelve.</p>
<h2 id="referencias" tabindex="-1">Referencias <a class="header-anchor" href="#referencias" aria-label="Permalink to &quot;Referencias&quot;"></a></h2>
<p>La justificación completa, ordenada por prioridad, y las decisiones arquitectónicas aparecen más arriba; estas son las fuentes canónicas de cada técnica, aproximadamente en el orden en que aparecen en la pila.</p>
<ul>
<li>Yalim y Akman, <a href="https://saksagan.ceng.metu.edu.tr/courses/ceng591/RAPORLAR/HacerYalim.pdf" target="_blank" rel="noreferrer">Descarte de oclusión por horizonte para terrenos jerárquicos</a> (IEEE Visualization 2002, el artículo original sobre descarte por horizonte del terreno).</li>
<li>Turitzin, <a href="https://miketuritzin.com/post/hierarchical-depth-buffers/" target="_blank" rel="noreferrer">Búferes de profundidad jerárquicos</a> (la explicación más clara sobre cómo se construyen y consultan las cadenas de niveles mip de Hi-Z).</li>
<li>VKGuide, <a href="https://vkguide.dev/docs/gpudriven/compute_culling/" target="_blank" rel="noreferrer">Descarte basado en cómputo</a> (referencia de la canalización de descarte controlada por GPU; la adaptación a WebGPU es mecánica).</li>
<li>Kruskonja, <a href="https://medium.com/@mil_kru/two-pass-occlusion-culling-4100edcad501" target="_blank" rel="noreferrer">Descarte de oclusión en dos pasadas</a> (la arquitectura al estilo de Nanite explicada fuera de las diapositivas de Epic).</li>
<li>Karis et al., <a href="https://www.youtube.com/watch?v=eviSykqSUUw" target="_blank" rel="noreferrer">Nanite: análisis en profundidad (SIGGRAPH 2021)</a> (la referencia moderna de cómo es el descarte controlado por GPU a escala AAA).</li>
<li>Karis, <a href="https://www.youtube.com/watch?v=NRnj_lnpORU" target="_blank" rel="noreferrer">Ponencia principal de HPG 2022: el camino hacia Nanite</a> (un contexto más amplio sobre por qué importa la etapa de descarte).</li>
<li>Sanders, <a href="https://www.youtube.com/watch?v=wavnKZNSYqU" target="_blank" rel="noreferrer">Entre la tecnología y el arte: la vegetación de Horizon Zero Dawn</a> (la pila completa de descarte de vegetación AAA).</li>
<li>Guerrilla, <a href="https://www.youtube.com/watch?v=ToCozpl1sYY" target="_blank" rel="noreferrer">Colocación procedimental en tiempo de ejecución basada en GPU en Horizon Zero Dawn</a> (colocación de instancias y visibilidad por instancia).</li>
<li>Scthe, <a href="https://github.com/Scthe/nanite-webgpu" target="_blank" rel="noreferrer">Nanite WebGPU</a> (una implementación de referencia en WebGPU, con HZB incluido).</li>
<li>Kitware, <a href="https://www.kitware.com/webgpu-occlusion-culling-in-vtk/" target="_blank" rel="noreferrer">Descarte de oclusión con WebGPU en VTK</a> (el primer HZB de producción ejecutado en el navegador del que tengo constancia).</li>
<li>Acerola, <a href="https://www.youtube.com/watch?v=Y0Ko0kvwfgA" target="_blank" rel="noreferrer">¿Cómo renderizan los juegos tanta hierba?</a> y <a href="https://www.youtube.com/watch?v=PNvlqsXdQic" target="_blank" rel="noreferrer">Lo que hice para optimizar la hierba de mi juego</a> (el recorrido accesible en YouTube).</li>
<li>RasterGrid, <a href="https://www.rastergrid.com/blog/2010/10/hierarchical-z-map-based-occlusion-culling/" target="_blank" rel="noreferrer">Descarte de oclusión basado en mapas Hi-Z</a> (la introducción a Hi-Z que sigue siendo la referencia canónica).</li>
<li>Intel, <a href="https://www.intel.com/content/www/us/en/developer/articles/technical/masked-software-occlusion-culling.html" target="_blank" rel="noreferrer">Descarte de oclusión por software con máscaras</a> (la familia de rasterizadores para CPU, por si alguna vez decides que la opción n.º 6 merece la pena).</li>
</ul>
]]></content:encoded>
            <enclosure url="https://cdn.cinevva.com/blog/why-webgpu-engine-hero.jpg" length="0" type="image/jpg"/>
        </item>
        <item>
            <title><![CDATA[Construyendo un mundo abierto en el navegador, parte 29: Un controlador, cualquier cuerpo]]></title>
            <link>https://app.cinevva.com/es/blog/2026-05-15-open-world-browser-part-29-pluggable-character</link>
            <guid>https://app.cinevva.com/es/blog/2026-05-15-open-world-browser-part-29-pluggable-character</guid>
            <pubDate>Fri, 15 May 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[El spike 58 construye un controlador de personajes en el que el motor de físicas no sabe nada sobre caminar, nadar o planear. Cada comportamiento es un controlador conectable, el mismo motor controla al jugador, a un caballo montable y a un PNJ autónomo, y todo funciona sin interfaz gráfica en Node. El spike 59 le acopla un avatar con animaciones retargeteadas sin tocar ningún controlador, y el spike 60 le acopla un paquete de Synty que no necesita ningún retargeting, tras un selector de clips que se puede probar con tests unitarios.]]></description>
            <content:encoded><![CDATA[<h1 id="construyendo-un-mundo-abierto-en-el-navegador-parte-29-un-controlador-cualquier-cuerpo" tabindex="-1">Construyendo un mundo abierto en el navegador, parte 29: Un controlador, cualquier cuerpo <a class="header-anchor" href="#construyendo-un-mundo-abierto-en-el-navegador-parte-29-un-controlador-cualquier-cuerpo" aria-label="Permalink to &quot;Construyendo un mundo abierto en el navegador, parte 29: Un controlador, cualquier cuerpo&quot;"></a></h1>
<p><em>Por <a href="/es/about.html">Oleg Sidorkin</a>, CTO y cofundador de Cinevva</em></p>
<p>¿Acabas de llegar? Consulta la <a href="/es/blog/2026-02-25-open-world-browser-series-guide.html">guía de la serie</a>. Explica qué es un spike y enlaza todas las partes.</p>
<p>La <a href="/es/blog/2026-05-14-open-world-browser-part-28-grass-and-occlusion.html">parte 28</a> trató sobre la hierba y la oclusión. Veintiocho partes construyeron un mundo en el que estar: terreno que puedes interpretar, agua en la que puedes nadar, vegetación que se mantiene convincente hasta el horizonte y un servidor que recuerda lo que cambiaste. Esta parte trata sobre aquello que se mueve por todo ese mundo, y es la culminación de todo el motor, porque el objetivo no es crear un controlador para el jugador. Es crear un controlador al que no le importe qué cuerpo controla, de dónde proceden sus animaciones ni si quien está al mando es una persona o una IA. El spike 58 construye el movimiento como una pila de comportamientos conectables sobre un motor de físicas que no sabe nada sobre locomoción y después demuestra la arquitectura ejecutando tres cuerpos diferentes con una instancia del mismo motor. El spike 59 acopla un avatar real con animaciones retargeteadas a ese controlador sin cambiar ni una sola línea. El spike 60 acopla un paquete de animaciones distinto que no necesita ningún retargeting y extrae la lógica de selección de clips para convertirla en algo que realmente se puede probar.</p>
<h2 id="un-motor-de-fisicas-que-no-sabe-nada-sobre-caminar" tabindex="-1">Un motor de físicas que no sabe nada sobre caminar <a class="header-anchor" href="#un-motor-de-fisicas-que-no-sabe-nada-sobre-caminar" aria-label="Permalink to &quot;Un motor de físicas que no sabe nada sobre caminar&quot;"></a></h2>
<div style="position:relative;padding-bottom:56.25%;height:0;overflow:hidden;border-radius:8px;margin:1.5rem 0;border:1px solid rgba(255,255,255,0.12)">
<iframe src="/es/spikes/58-pluggable-character/" title="Spike 58: personaje conectable" style="position:absolute;top:0;left:0;width:100%;height:100%;border:0;background:#000" loading="lazy" allowfullscreen></iframe>
</div>
<p><a href="/es/spikes/58-pluggable-character/" target="_blank">Abrir el spike 58 en una pestaña nueva ↗</a> · <a href="/es/blog/spike-source?spike=58-pluggable-character">Ver código fuente</a></p>
<p>La regla de diseño es estricta, y ese es precisamente el objetivo: el motor de cápsulas no posee ninguna lógica de locomoción. Ni caminar, ni correr, ni saltar, ni fricción, ni límite de velocidad máxima, ni siquiera gravedad. Integra una cápsula cinemática contra el terreno y nada más. Cada comportamiento de locomoción —caminar, deslizarse, planear, escalar, nadar, agacharse o gestionar la resistencia— vive en un controlador autocontenido registrado en el motor. En cada fotograma, el motor actualiza todos los controladores, pregunta a cada uno si quiere tomar el control y permite que el candidato con mayor prioridad escriba la velocidad. Caminar no tiene ningún estatus especial. Es simplemente el controlador de menor prioridad que siempre responde que sí, por lo que actúa como comportamiento predeterminado cuando no se activa ningún otro. Un controlador consta de seis funciones pequeñas: un <code>tick</code> que actualiza su propio estado interno en cada fotograma aunque no esté activo; un predicado puro <code>wantsControl</code> que reclama el fotograma; un <code>applyForces</code>, ejecutado únicamente por el ganador, que escribe la velocidad y aplica su propia gravedad si la necesita; además de los opcionales <code>onEnter</code>, <code>onExit</code> y <code>stateName</code>. El controlador de natación devuelve <code>ownsCollision: true</code> desde <code>applyForces</code> para hacerse cargo de la gestión del terreno, porque, de lo contrario, su resorte de flotabilidad entraría en conflicto con el ajuste de los pies al suelo del motor.</p>
<p>Incluso las cosas que no son locomoción terminan filtrándose a través de ese contrato, y eso fue lo que obligó a introducir la siguiente idea: los canales. Un diseño anterior de un solo canal pasaba todo por un único arbitraje, lo que significaba que un monitor de resistencia o una postura agachada tenían que fingir que eran locomoción y después rechazar el control mediante un truco en el que <code>wantsControl</code> devolvía falso, solo para poder realizar su contabilidad interna. La solución divide los controladores en canales con nombre que arbitran de forma independiente y se aplican en un orden fijo: recursos, después postura y, por último, locomoción. Los recursos se ejecutan primero porque sus escrituras, como la reducción de resistencia, son leídas por los demás. La postura se ejecuta en segundo lugar porque la reducción de altura de la cápsula al agacharse debe aplicarse antes de que el controlador de marcha la lea para limitar la velocidad máxima. La locomoción se ejecuta al final y controla la escritura de velocidad de cada fotograma. Así, un observador de resistencia, un modificador de agachado y un controlador de natación activo pueden coexistir limpiamente, cada uno en su propio canal, sin que ningún controlador tenga que mentir sobre lo que es. La demo visualiza todo esto mediante una cápsula básica que cambia de color según el controlador activo, para que puedas observar cómo se produce el arbitraje: el verde de caminar cambia a naranja en una pendiente pronunciada cuando toma el control el deslizamiento, a cian en el lago cuando gana la natación y a crema en el aire cuando pulsas la tecla de planeo.</p>
<h2 id="un-motor-tres-cuerpos" tabindex="-1">Un motor, tres cuerpos <a class="header-anchor" href="#un-motor-tres-cuerpos" aria-label="Permalink to &quot;Un motor, tres cuerpos&quot;"></a></h2>
<p>La verdadera prueba de que «no posee ninguna lógica de locomoción» no es el jugador. Es comprobar si el mismo motor, sin modificar, puede controlar algo que ni siquiera sea un jugador. <code>createCapsuleEngine</code> es una fábrica pura sin estado a nivel de módulo, sin singletons y sin efectos secundarios por instancia, por lo que el spike la instancia tres veces. El jugador es una instancia con el conjunto completo de controladores. Un caballo montable es una segunda instancia que solo registra un controlador de marcha, lo que convierte la idea completa en algo literal: el repertorio de movimientos de un cuerpo viene determinado únicamente por los controladores que registraste. Por eso, el caballo es más rápido en terreno llano y físicamente no puede escalar, nadar ni planear, porque esos controladores nunca se añadieron. Un PNJ autónomo es una tercera instancia, actualizada en cada fotograma junto con el jugador y dirigida por un controlador de deambulación que genera sus propias entradas para que el cuerpo se desplace por sí mismo sin manos sobre el teclado. El motor nunca llega a saber que uno de sus cuerpos es un caballo ni que otro está controlado por IA. Todos son el mismo integrador de cápsulas con listas de controladores diferentes.</p>
<p>Montar es la única pieza que vive deliberadamente fuera del motor. Intercambiar el control entre el jugador y el caballo implica coordinar dos motores, y un controlador se ejecuta dentro de un único motor y no puede ver más allá de ese límite. Por tanto, la lógica para montar reside en el nivel del anfitrión: es una pequeña máquina de estados que decide qué motor avanza en este fotograma, congela el otro, desplaza suavemente al jinete hasta la silla mediante un smoothstep de tres cuartos de segundo e indica a la cámara qué cuerpo debe seguir. La fábrica del motor nunca se entera de nada de esto. Esa es la frontera que la arquitectura establece y respeta. Los comportamientos que pertenecen a un cuerpo son controladores; la coordinación entre cuerpos es responsabilidad del anfitrión. Mantener ambos conceptos separados es la razón por la que añadir un cuarto o un cuadragésimo cuerpo no requeriría nada nuevo.</p>
<h2 id="probado-sin-navegador" tabindex="-1">Probado sin navegador <a class="header-anchor" href="#probado-sin-navegador" aria-label="Permalink to &quot;Probado sin navegador&quot;"></a></h2>
<p>Como el motor no accede a <code>window</code>, <code>document</code> ni Three.js, todo puede ejecutarse sin interfaz gráfica. El spike incluye un arnés de pruebas para Node que simula la interfaz del terreno, hace avanzar el motor fotograma a fotograma con entradas programadas y comprueba el estado resultante. Así, las regresiones que resultan penosas de detectar jugando se capturan mediante un script: la transición de salto y aterrizaje, los umbrales de entrada y salida de la natación, la desactivación automática de la escalada cuando una superficie se nivela y las tasas de consumo de resistencia. Alimentar el motor dos veces con la misma secuencia de entradas e intervalos de tiempo, y comprobar que el estado de salida sea idéntico byte a byte, fija el motor como determinista, que es la propiedad de la que dependerá en el futuro una versión en red. Merece la pena conservar una regresión detectada por el arnés: al pasar de terreno transitable a una pendiente demasiado pronunciada para caminar, antes se activaba el controlador de deslizamiento y el jugador rebotaba cuesta arriba. La solución fue una condición de descenso. El deslizamiento solo comienza si la cápsula está cayendo realmente sobre la pendiente, por lo que caminar horizontalmente contra una superficie inclinada ahora bloquea limpiamente al jugador en lugar de hacerlo deslizarse. La prueba que comprueba que «caminar contra una pendiente no transitable bloquea al jugador» garantiza que siga siendo así.</p>
<h2 id="conectar-un-avatar-real-sin-tocar-los-controladores" tabindex="-1">Conectar un avatar real sin tocar los controladores <a class="header-anchor" href="#conectar-un-avatar-real-sin-tocar-los-controladores" aria-label="Permalink to &quot;Conectar un avatar real sin tocar los controladores&quot;"></a></h2>
<div style="position:relative;padding-bottom:56.25%;height:0;overflow:hidden;border-radius:8px;margin:1.5rem 0;border:1px solid rgba(255,255,255,0.12)">
<iframe src="/es/spikes/59-pluggable-with-avatar/" title="Spike 59: sistema conectable con avatar" style="position:absolute;top:0;left:0;width:100%;height:100%;border:0;background:#000" loading="lazy" allowfullscreen></iframe>
</div>
<p><a href="/es/spikes/59-pluggable-with-avatar/" target="_blank">Abrir el spike 59 en una pestaña nueva ↗</a> · <a href="/es/blog/spike-source?spike=59-pluggable-with-avatar">Ver código fuente</a></p>
<p>El spike 59 comprueba si la capa de controladores está realmente desacoplada del cuerpo. Sustituye la cápsula de colores por un personaje real con esqueleto, el rig FBX 3MIKE con clips de Quaternius Universal Animation Library retargeteados sobre él, y los controladores no cambian en absoluto. El punto de unión es una única cadena. Cada controlador ya comunica un nombre de estado mediante <code>stateName</code>: idle, walk, run, jump, fall, land, slide, glide, swim y swimIdle. La capa del avatar asigna ese nombre a un clip retargeteado mediante una tabla de alias y realiza una transición por fundido al cambiar. El controlador de marcha elige dinámicamente su propio subestado a partir del contacto con el suelo, la velocidad vertical y la velocidad horizontal. De este modo, un único controlador de marcha gestiona los estados de reposo, caminar, correr, saltar, caer y aterrizar, y el avatar se limita a seguir el nombre comunicado. Como este spike es para un solo jugador, el avatar elimina la indirección mediante enteros de red y la abstracción de múltiples personajes de los spikes de red anteriores, y asigna el nombre del estado directamente a un clip. La prueba es que toda la mejora visual, desde una cápsula hasta un humano con rig, no modificó ni una sola línea del código de locomoción, que es exactamente la ventaja que debe ofrecer un controlador conectable.</p>
<h2 id="un-paquete-que-no-necesita-retargeting-y-un-selector-que-puedes-probar" tabindex="-1">Un paquete que no necesita retargeting y un selector que puedes probar <a class="header-anchor" href="#un-paquete-que-no-necesita-retargeting-y-un-selector-que-puedes-probar" aria-label="Permalink to &quot;Un paquete que no necesita retargeting y un selector que puedes probar&quot;"></a></h2>
<div style="position:relative;padding-bottom:56.25%;height:0;overflow:hidden;border-radius:8px;margin:1.5rem 0;border:1px solid rgba(255,255,255,0.12)">
<iframe src="/es/spikes/60-polygon-animations/" title="Spike 60: animaciones POLYGON" style="position:absolute;top:0;left:0;width:100%;height:100%;border:0;background:#000" loading="lazy" allowfullscreen></iframe>
</div>
<p><a href="/es/spikes/60-polygon-animations/" target="_blank">Abrir el spike 60 en una pestaña nueva ↗</a> · <a href="/es/blog/spike-source?spike=60-polygon-animations">Ver código fuente</a></p>
<p>El spike 60 conecta un tercer cuerpo, el paquete POLYGON Base Locomotion de Synty, y el cargador es casi inexistente. Cada clip se distribuye como un FBX independiente que contiene una copia integrada del mismo esqueleto de Synty junto con una animación horneada. Como el rig del personaje y todos los clips utilizan nombres de huesos idénticos, basta con tomar el clip de <code>fbx.animations[0]</code> y reproducirlo directamente en el mezclador del personaje, sin que intervenga ninguna biblioteca de retargeting. Three.js resuelve los destinos de las pistas de animación por el nombre del hueso, no por la identidad del objeto, así que un paquete del estilo de Synty o Mixamo creado para el rig correspondiente funciona directamente. Ese es el contraste deliberado con la ruta de UAL del spike anterior, que requiere un retargeting pesado porque los clips de origen y el rig de destino se crearon para esqueletos diferentes. El mismo controlador, el mismo punto de unión mediante nombres de estado y dos pipelines de animación completamente distintos detrás.</p>
<p>La otra mitad del spike 60 consiste en hacer comprobable la lógica de selección de clips. Elegir qué clip reproducir está lleno de umbrales subjetivos, y esa lógica estaba enterrada dentro de la capa del avatar, junto a FBXLoader y el DOM, donde no se podía probar. El spike extrae el selector a funciones puras que no acceden ni a Three.js ni a la ventana: reciben un registro simple del jugador —velocidad, velocidad horizontal, orientación, contacto con el suelo, normal del terreno y velocidad de impacto— y un sustituto de la acción del clip, y devuelven una cadena con el alias del clip. Esto permite que los umbrales existan como constantes con nombre y verificadas mediante aserciones. El salto se divide en variantes caminando, corriendo y esprintando mediante intervalos de velocidad alineados con el umbral real de esprintar del controlador de marcha; los aterrizajes se dividen en suaves, medios y fuertes según la velocidad de impacto; las variantes de clips cuesta arriba y cuesta abajo se activan a partir del producto escalar de la proyección sobre la pendiente, con una zona muerta que usa el clip para terreno llano por debajo de unos siete grados; una transición de reposo a locomoción siempre se resuelve hacia delante para que arrancar desde parado nunca reproduzca un clip hacia atrás; y una transición de parada está condicionada por un tiempo mínimo dentro del bucle, porque los clips de parada según la fase de los pies de Synty contienen aproximadamente un segundo de desaceleración creada de antemano que resulta ridícula si se añade a un paso que el jugador apenas llegó a dar. Un pequeño estabilizador de estados retrasa el estado de caída durante unos fotogramas para que una pérdida de contacto con el suelo de un solo fotograma al cruzar una junta no haga parpadear la animación. Extraer todo esto de la envoltura de renderizado permite probar las reglas con tests unitarios sin GPU, aplicando la misma disciplina de ejecución sin interfaz gráfica que recibió el propio motor en el spike 58. Esa es la diferencia entre ajustar las sensaciones de locomoción a base de conjeturas y poder definirlas con precisión.</p>
<h2 id="tecnologia-mencionada-en-este-capitulo" tabindex="-1">Tecnología mencionada en este capítulo <a class="header-anchor" href="#tecnologia-mencionada-en-este-capitulo" aria-label="Permalink to &quot;Tecnología mencionada en este capítulo&quot;"></a></h2>
<p><strong>Un motor de físicas sin locomoción.</strong> El motor de cápsulas integra un cuerpo cinemático contra el terreno y no posee lógica para caminar, correr, saltar, aplicar fricción, limitar la velocidad ni aplicar gravedad. Cada comportamiento es un controlador registrado que expone <code>tick</code>, <code>wantsControl</code>, <code>applyForces</code> y, opcionalmente, <code>onEnter</code>/<code>onExit</code>/<code>stateName</code>. Caminar es simplemente el comportamiento predeterminado de menor prioridad que siempre responde que sí, y un controlador puede devolver <code>ownsCollision: true</code> para hacerse cargo de la gestión del terreno. El controlador de natación lo hace para que su resorte de flotabilidad no entre en conflicto con el ajuste de los pies al suelo.</p>
<p><strong>Canales de arbitraje independientes.</strong> Los controladores se registran en canales con nombre —recursos, postura y locomoción— que arbitran por separado y se aplican en un orden fijo. Así, observadores como la resistencia y modificadores como agacharse coexisten con la locomoción activa en lugar de fingir que toman el control para después rechazarlo. Las escrituras de recursos, como la resistencia, son leídas por la postura y la locomoción; las escrituras de postura, como la altura de la cápsula al agacharse, son leídas por el límite de velocidad de la locomoción; la locomoción se ejecuta al final y controla la escritura de velocidad.
<strong>Una fábrica, muchos cuerpos.</strong> <code>createCapsuleEngine</code> es una fábrica pura sin singletons, por lo que el mismo motor controla al jugador, un caballo montable que solo puede caminar y un PNJ con dirección autónoma alimentado mediante entradas sintéticas. El repertorio de movimientos de un cuerpo viene determinado exactamente por el conjunto de controladores registrados, así que el caballo no puede trepar ni nadar porque esos controladores nunca se añadieron. La lógica para montar reside en el nivel del host, no en un controlador, porque coordina dos motores que no pueden acceder el uno al otro. Consulta <a href="/es/guides/landscape-generation-browser.html#gpu-driven-lod-with-webgpu">LOD controlado por GPU</a>.</p>
<p><strong>Pruebas deterministas sin interfaz gráfica.</strong> El motor no accede a <code>window</code>, <code>document</code> ni Three.js, por lo que un entorno de pruebas de Node lo controla fotograma a fotograma y comprueba el salto y aterrizaje, los umbrales de natación, la desactivación automática de la escalada y el consumo de resistencia. Reproducir dos veces una entrada idéntica y comprobar que la salida también sea idéntica demuestra el determinismo, y una prueba de regresión fija el umbral de descenso que impide que un desplazamiento horizontal contra una pendiente pronunciada haga que el jugador se deslice hacia atrás.</p>
<p><strong>Vinculación de avatares independiente del cuerpo con un selector verificable.</strong> Los controladores devuelven una cadena con el nombre del estado y la capa visual la asigna a un clip, por lo que sustituir una cápsula por un avatar 3MIKE + UAL con retargeting no requiere modificar el código de locomoción. Los clips de Synty POLYGON comparten los nombres de los huesos con el rig y se reproducen sin retargeting (Three.js vincula las pistas por el nombre del hueso), a diferencia del costoso retargeting de la ruta UAL. El selector de clips se extrae en funciones puras con constantes con nombre para los intervalos de velocidad de salto, la intensidad del aterrizaje, las variantes de proyección sobre pendientes, una transición desde reposo siempre hacia delante, una duración mínima de protección para la transición de parada y un filtro antirrebote del estado de caída, de modo que las sensaciones de locomoción puedan probarse mediante tests unitarios en lugar de ajustarse a ojo.</p>
<hr>
<p>Parte 29 de 30.
Anterior: <a href="/es/blog/2026-05-14-open-world-browser-part-28-grass-and-occlusion.html">Parte 28 - Hierba hasta el horizonte y un terreno que se oculta a sí mismo</a>
Siguiente: <a href="/es/blog/2026-06-04-open-world-browser-part-30-collision-aware-camera.html">Parte 30 - Una cámara que respeta las paredes</a>
Guía de la serie: <a href="/es/blog/2026-02-25-open-world-browser-series-guide.html">/blog/2026-02-25-open-world-browser-series-guide</a></p>
]]></content:encoded>
            <enclosure url="https://cdn.cinevva.com/blog/why-webgpu-engine-hero.jpg" length="0" type="image/jpg"/>
        </item>
        <item>
            <title><![CDATA[Construir un mundo abierto en el navegador, parte 28: Hierba hasta el horizonte y terreno que se oculta a sí mismo]]></title>
            <link>https://app.cinevva.com/es/blog/2026-05-14-open-world-browser-part-28-grass-and-occlusion</link>
            <guid>https://app.cinevva.com/es/blog/2026-05-14-open-world-browser-part-28-grass-and-occlusion</guid>
            <pubDate>Thu, 14 May 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[El Spike 56 consigue que medio millón de matas de hierba parezcan un campo en lugar de confeti verde mediante un único kernel de cómputo y un truco de quads cruzados. El Spike 57 compara cuatro formas de descartar lo que oculta una colina y descubre que la vía acelerada también es la geométricamente correcta.]]></description>
            <content:encoded><![CDATA[<h1 id="construir-un-mundo-abierto-en-el-navegador-parte-28-hierba-hasta-el-horizonte-y-terreno-que-se-oculta-a-si-mismo" tabindex="-1">Construir un mundo abierto en el navegador, parte 28: Hierba hasta el horizonte y terreno que se oculta a sí mismo <a class="header-anchor" href="#construir-un-mundo-abierto-en-el-navegador-parte-28-hierba-hasta-el-horizonte-y-terreno-que-se-oculta-a-si-mismo" aria-label="Permalink to &quot;Construir un mundo abierto en el navegador, parte 28: Hierba hasta el horizonte y terreno que se oculta a sí mismo&quot;"></a></h1>
<p><em>Por <a href="/es/about.html">Oleg Sidorkin</a>, CTO y cofundador de Cinevva</em></p>
<p>¿Acabas de llegar? Consulta la <a href="/es/blog/2026-02-25-open-world-browser-series-guide.html">guía de la serie</a>. Explica qué es un spike y enlaza todas las partes.</p>
<p>La <a href="/es/blog/2026-05-13-open-world-browser-part-27-island-and-terrain.html">parte 27</a> construyó la isla y le dio un suelo que no parece repetitivo. Esta parte trata los dos elementos que hacen que un terreno parezca habitado en vez de vacío. El Spike 56 se ocupa de la hierba, el detalle superficial que convierte una ladera texturizada en un lugar por el que caminarías, y el problema consiste en lograr que un campo parezca un campo en lugar de un conjunto de trazos dispersos. El Spike 57 aborda lo contrario a dibujar más: no dibujar lo que una colina ya está ocultando. Y el resultado interesante es que la forma rápida de comprobarlo también resultó ser la correcta.</p>
<h2 id="hierba-que-parece-un-campo-no-confeti" tabindex="-1">Hierba que parece un campo, no confeti <a class="header-anchor" href="#hierba-que-parece-un-campo-no-confeti" aria-label="Permalink to &quot;Hierba que parece un campo, no confeti&quot;"></a></h2>
<div style="position:relative;padding-bottom:56.25%;height:0;overflow:hidden;border-radius:8px;margin:1.5rem 0;border:1px solid rgba(255,255,255,0.12)">
<iframe src="/es/spikes/56-grass/" title="Spike 56: Hierba" style="position:absolute;top:0;left:0;width:100%;height:100%;border:0;background:#000" loading="lazy" allowfullscreen></iframe>
</div>
<p><a href="/es/spikes/56-grass/" target="_blank">Abrir el Spike 56 en una pestaña nueva ↗</a> · <a href="/es/blog/spike-source?spike=56-grass">Ver código fuente</a></p>
<p>La decisión fundamental es geométrica. Una única brizna fina y afilada ocupa menos de un píxel desde la mayoría de los ángulos de cámara, así que medio millón de briznas planas parecen confeti verde disperso en vez de un campo. La solución es una mata de quads cruzados: tres quads afilados rotados sesenta grados entre sí alrededor del eje vertical local, de modo que, desde cualquier dirección de visión, al menos uno quede casi perpendicular a la cámara y cada instancia cubra aproximadamente tres anchuras de brizna de área real en pantalla. Esa es la diferencia entre ver trazos verdes y ver hierba.</p>
<p>Un kernel de cómputo de WebGPU coloca cada mata una sola vez durante la inicialización. Convierte mediante hash el índice de instancia en cinco flujos aleatorios descorrelacionados, elige una posición XZ dentro del área, muestrea la altura del terreno a partir del mismo FBM que utiliza la malla de suelo de la CPU —un port a TSL con un mod que conserva el signo para que los valores coincidan exactamente y las briznas descansen sobre la superficie en vez de flotar sobre ella—, calcula una normal mediante diferencias centrales y genera una anchura, una altura y un tono para cada mata. En el lado del renderizado se usa un grafo de vértices TSL que omite por completo la matriz de instancia y escribe directamente en el espacio de recorte: escala el quad cruzado unitario, rota el eje vertical local hasta alinearlo con la normal del terreno mediante la fórmula de Rodrigues y lo traslada a la posición de la mata. El LOD por distancia se obtiene gratis y sin una pasada de descarte, porque el grafo de vértices multiplica la altura de la mata por <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.566ex;" xmlns="http://www.w3.org/2000/svg" width="38.925ex" height="2.262ex" role="img" focusable="false" viewBox="0 -750 17204.8 1000" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mn"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(722.2,0)"><path data-c="2212" d="M84 237T84 250T98 270H679Q694 262 694 250T679 230H98Q84 237 84 250Z" style="stroke-width: 3;"/></g><g data-mml-node="mtext" transform="translate(1722.4,0)"><path data-c="73" d="M295 316Q295 356 268 385T190 414Q154 414 128 401Q98 382 98 349Q97 344 98 336T114 312T157 287Q175 282 201 278T245 269T277 256Q294 248 310 236T342 195T359 133Q359 71 321 31T198 -10H190Q138 -10 94 26L86 19L77 10Q71 4 65 -1L54 -11H46H42Q39 -11 33 -5V74V132Q33 153 35 157T45 162H54Q66 162 70 158T75 146T82 119T101 77Q136 26 198 26Q295 26 295 104Q295 133 277 151Q257 175 194 187T111 210Q75 227 54 256T33 318Q33 357 50 384T93 424T143 442T187 447H198Q238 447 268 432L283 424L292 431Q302 440 314 448H322H326Q329 448 335 442V310L329 304H301Q295 310 295 316Z" style="stroke-width: 3;"/><path data-c="6D" d="M41 46H55Q94 46 102 60V68Q102 77 102 91T102 122T103 161T103 203Q103 234 103 269T102 328V351Q99 370 88 376T43 385H25V408Q25 431 27 431L37 432Q47 433 65 434T102 436Q119 437 138 438T167 441T178 442H181V402Q181 364 182 364T187 369T199 384T218 402T247 421T285 437Q305 442 336 442Q351 442 364 440T387 434T406 426T421 417T432 406T441 395T448 384T452 374T455 366L457 361L460 365Q463 369 466 373T475 384T488 397T503 410T523 422T546 432T572 439T603 442Q729 442 740 329Q741 322 741 190V104Q741 66 743 59T754 49Q775 46 803 46H819V0H811L788 1Q764 2 737 2T699 3Q596 3 587 0H579V46H595Q656 46 656 62Q657 64 657 200Q656 335 655 343Q649 371 635 385T611 402T585 404Q540 404 506 370Q479 343 472 315T464 232V168V108Q464 78 465 68T468 55T477 49Q498 46 526 46H542V0H534L510 1Q487 2 460 2T422 3Q319 3 310 0H302V46H318Q379 46 379 62Q380 64 380 200Q379 335 378 343Q372 371 358 385T334 402T308 404Q263 404 229 370Q202 343 195 315T187 232V168V108Q187 78 188 68T191 55T200 49Q221 46 249 46H265V0H257L234 1Q210 2 183 2T145 3Q42 3 33 0H25V46H41Z" transform="translate(394,0)" style="stroke-width: 3;"/><path data-c="6F" d="M28 214Q28 309 93 378T250 448Q340 448 405 380T471 215Q471 120 407 55T250 -10Q153 -10 91 57T28 214ZM250 30Q372 30 372 193V225V250Q372 272 371 288T364 326T348 362T317 390T268 410Q263 411 252 411Q222 411 195 399Q152 377 139 338T126 246V226Q126 130 145 91Q177 30 250 30Z" transform="translate(1227,0)" style="stroke-width: 3;"/><path data-c="6F" d="M28 214Q28 309 93 378T250 448Q340 448 405 380T471 215Q471 120 407 55T250 -10Q153 -10 91 57T28 214ZM250 30Q372 30 372 193V225V250Q372 272 371 288T364 326T348 362T317 390T268 410Q263 411 252 411Q222 411 195 399Q152 377 139 338T126 246V226Q126 130 145 91Q177 30 250 30Z" transform="translate(1727,0)" style="stroke-width: 3;"/><path data-c="74" d="M27 422Q80 426 109 478T141 600V615H181V431H316V385H181V241Q182 116 182 100T189 68Q203 29 238 29Q282 29 292 100Q293 108 293 146V181H333V146V134Q333 57 291 17Q264 -10 221 -10Q187 -10 162 2T124 33T105 68T98 100Q97 107 97 248V385H18V422H27Z" transform="translate(2227,0)" style="stroke-width: 3;"/><path data-c="68" d="M41 46H55Q94 46 102 60V68Q102 77 102 91T102 124T102 167T103 217T103 272T103 329Q103 366 103 407T103 482T102 542T102 586T102 603Q99 622 88 628T43 637H25V660Q25 683 27 683L37 684Q47 685 66 686T103 688Q120 689 140 690T170 693T181 694H184V367Q244 442 328 442Q451 442 463 329Q464 322 464 190V104Q464 66 466 59T477 49Q498 46 526 46H542V0H534L510 1Q487 2 460 2T422 3Q319 3 310 0H302V46H318Q379 46 379 62Q380 64 380 200Q379 335 378 343Q372 371 358 385T334 402T308 404Q263 404 229 370Q202 343 195 315T187 232V168V108Q187 78 188 68T191 55T200 49Q221 46 249 46H265V0H257L234 1Q210 2 183 2T145 3Q42 3 33 0H25V46H41Z" transform="translate(2616,0)" style="stroke-width: 3;"/><path data-c="73" d="M295 316Q295 356 268 385T190 414Q154 414 128 401Q98 382 98 349Q97 344 98 336T114 312T157 287Q175 282 201 278T245 269T277 256Q294 248 310 236T342 195T359 133Q359 71 321 31T198 -10H190Q138 -10 94 26L86 19L77 10Q71 4 65 -1L54 -11H46H42Q39 -11 33 -5V74V132Q33 153 35 157T45 162H54Q66 162 70 158T75 146T82 119T101 77Q136 26 198 26Q295 26 295 104Q295 133 277 151Q257 175 194 187T111 210Q75 227 54 256T33 318Q33 357 50 384T93 424T143 442T187 447H198Q238 447 268 432L283 424L292 431Q302 440 314 448H322H326Q329 448 335 442V310L329 304H301Q295 310 295 316Z" transform="translate(3172,0)" style="stroke-width: 3;"/><path data-c="74" d="M27 422Q80 426 109 478T141 600V615H181V431H316V385H181V241Q182 116 182 100T189 68Q203 29 238 29Q282 29 292 100Q293 108 293 146V181H333V146V134Q333 57 291 17Q264 -10 221 -10Q187 -10 162 2T124 33T105 68T98 100Q97 107 97 248V385H18V422H27Z" transform="translate(3566,0)" style="stroke-width: 3;"/><path data-c="65" d="M28 218Q28 273 48 318T98 391T163 433T229 448Q282 448 320 430T378 380T406 316T415 245Q415 238 408 231H126V216Q126 68 226 36Q246 30 270 30Q312 30 342 62Q359 79 369 104L379 128Q382 131 395 131H398Q415 131 415 121Q415 117 412 108Q393 53 349 21T250 -11Q155 -11 92 58T28 218ZM333 275Q322 403 238 411H236Q228 411 220 410T195 402T166 381T143 340T127 274V267H333V275Z" transform="translate(3955,0)" style="stroke-width: 3;"/><path data-c="70" d="M36 -148H50Q89 -148 97 -134V-126Q97 -119 97 -107T97 -77T98 -38T98 6T98 55T98 106Q98 140 98 177T98 243T98 296T97 335T97 351Q94 370 83 376T38 385H20V408Q20 431 22 431L32 432Q42 433 61 434T98 436Q115 437 135 438T165 441T176 442H179V416L180 390L188 397Q247 441 326 441Q407 441 464 377T522 216Q522 115 457 52T310 -11Q242 -11 190 33L182 40V-45V-101Q182 -128 184 -134T195 -145Q216 -148 244 -148H260V-194H252L228 -193Q205 -192 178 -192T140 -191Q37 -191 28 -194H20V-148H36ZM424 218Q424 292 390 347T305 402Q234 402 182 337V98Q222 26 294 26Q345 26 384 80T424 218Z" transform="translate(4399,0)" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(6677.4,0)"><path data-c="28" d="M94 250Q94 319 104 381T127 488T164 576T202 643T244 695T277 729T302 750H315H319Q333 750 333 741Q333 738 316 720T275 667T226 581T184 443T167 250T184 58T225 -81T274 -167T316 -220T333 -241Q333 -250 318 -250H315H302L274 -226Q180 -141 137 -14T94 250Z" style="stroke-width: 3;"/></g><g data-mml-node="mtext" transform="translate(7066.4,0)"><path data-c="66" d="M273 0Q255 3 146 3Q43 3 34 0H26V46H42Q70 46 91 49Q99 52 103 60Q104 62 104 224V385H33V431H104V497L105 564L107 574Q126 639 171 668T266 704Q267 704 275 704T289 705Q330 702 351 679T372 627Q372 604 358 590T321 576T284 590T270 627Q270 647 288 667H284Q280 668 273 668Q245 668 223 647T189 592Q183 572 182 497V431H293V385H185V225Q185 63 186 61T189 57T194 54T199 51T206 49T213 48T222 47T231 47T241 46T251 46H282V0H273Z" style="stroke-width: 3;"/><path data-c="61" d="M137 305T115 305T78 320T63 359Q63 394 97 421T218 448Q291 448 336 416T396 340Q401 326 401 309T402 194V124Q402 76 407 58T428 40Q443 40 448 56T453 109V145H493V106Q492 66 490 59Q481 29 455 12T400 -6T353 12T329 54V58L327 55Q325 52 322 49T314 40T302 29T287 17T269 6T247 -2T221 -8T190 -11Q130 -11 82 20T34 107Q34 128 41 147T68 188T116 225T194 253T304 268H318V290Q318 324 312 340Q290 411 215 411Q197 411 181 410T156 406T148 403Q170 388 170 359Q170 334 154 320ZM126 106Q126 75 150 51T209 26Q247 26 276 49T315 109Q317 116 318 175Q318 233 317 233Q309 233 296 232T251 223T193 203T147 166T126 106Z" transform="translate(306,0)" style="stroke-width: 3;"/><path data-c="64" d="M376 495Q376 511 376 535T377 568Q377 613 367 624T316 637H298V660Q298 683 300 683L310 684Q320 685 339 686T376 688Q393 689 413 690T443 693T454 694H457V390Q457 84 458 81Q461 61 472 55T517 46H535V0Q533 0 459 -5T380 -11H373V44L365 37Q307 -11 235 -11Q158 -11 96 50T34 215Q34 315 97 378T244 442Q319 442 376 393V495ZM373 342Q328 405 260 405Q211 405 173 369Q146 341 139 305T131 211Q131 155 138 120T173 59Q203 26 251 26Q322 26 373 103V342Z" transform="translate(806,0)" style="stroke-width: 3;"/><path data-c="65" d="M28 218Q28 273 48 318T98 391T163 433T229 448Q282 448 320 430T378 380T406 316T415 245Q415 238 408 231H126V216Q126 68 226 36Q246 30 270 30Q312 30 342 62Q359 79 369 104L379 128Q382 131 395 131H398Q415 131 415 121Q415 117 412 108Q393 53 349 21T250 -11Q155 -11 92 58T28 218ZM333 275Q322 403 238 411H236Q228 411 220 410T195 402T166 381T143 340T127 274V267H333V275Z" transform="translate(1362,0)" style="stroke-width: 3;"/><path data-c="4E" d="M42 46Q74 48 94 56T118 69T128 86V634H124Q114 637 52 637H25V683H232L235 680Q237 679 322 554T493 303L578 178V598Q572 608 568 613T544 627T492 637H475V683H483Q498 680 600 680Q706 680 715 683H724V637H707Q634 633 622 598L621 302V6L614 0H600Q585 0 582 3T481 150T282 443T171 605V345L172 86Q183 50 257 46H274V0H265Q250 3 150 3Q48 3 33 0H25V46H42Z" transform="translate(1806,0)" style="stroke-width: 3;"/><path data-c="65" d="M28 218Q28 273 48 318T98 391T163 433T229 448Q282 448 320 430T378 380T406 316T415 245Q415 238 408 231H126V216Q126 68 226 36Q246 30 270 30Q312 30 342 62Q359 79 369 104L379 128Q382 131 395 131H398Q415 131 415 121Q415 117 412 108Q393 53 349 21T250 -11Q155 -11 92 58T28 218ZM333 275Q322 403 238 411H236Q228 411 220 410T195 402T166 381T143 340T127 274V267H333V275Z" transform="translate(2556,0)" style="stroke-width: 3;"/><path data-c="61" d="M137 305T115 305T78 320T63 359Q63 394 97 421T218 448Q291 448 336 416T396 340Q401 326 401 309T402 194V124Q402 76 407 58T428 40Q443 40 448 56T453 109V145H493V106Q492 66 490 59Q481 29 455 12T400 -6T353 12T329 54V58L327 55Q325 52 322 49T314 40T302 29T287 17T269 6T247 -2T221 -8T190 -11Q130 -11 82 20T34 107Q34 128 41 147T68 188T116 225T194 253T304 268H318V290Q318 324 312 340Q290 411 215 411Q197 411 181 410T156 406T148 403Q170 388 170 359Q170 334 154 320ZM126 106Q126 75 150 51T209 26Q247 26 276 49T315 109Q317 116 318 175Q318 233 317 233Q309 233 296 232T251 223T193 203T147 166T126 106Z" transform="translate(3000,0)" style="stroke-width: 3;"/><path data-c="72" d="M36 46H50Q89 46 97 60V68Q97 77 97 91T98 122T98 161T98 203Q98 234 98 269T98 328L97 351Q94 370 83 376T38 385H20V408Q20 431 22 431L32 432Q42 433 60 434T96 436Q112 437 131 438T160 441T171 442H174V373Q213 441 271 441H277Q322 441 343 419T364 373Q364 352 351 337T313 322Q288 322 276 338T263 372Q263 381 265 388T270 400T273 405Q271 407 250 401Q234 393 226 386Q179 341 179 207V154Q179 141 179 127T179 101T180 81T180 66V61Q181 59 183 57T188 54T193 51T200 49T207 48T216 47T225 47T235 46T245 46H276V0H267Q249 3 140 3Q37 3 28 0H20V46H36Z" transform="translate(3500,0)" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(10958.4,0)"><path data-c="2C" d="M78 35T78 60T94 103T137 121Q165 121 187 96T210 8Q210 -27 201 -60T180 -117T154 -158T130 -185T117 -194Q113 -194 104 -185T95 -172Q95 -168 106 -156T131 -126T157 -76T173 -3V9L172 8Q170 7 167 6T161 3T152 1T140 0Q113 0 96 17Z" style="stroke-width: 3;"/></g><g data-mml-node="mtext" transform="translate(11403.1,0)"><path data-c="66" d="M273 0Q255 3 146 3Q43 3 34 0H26V46H42Q70 46 91 49Q99 52 103 60Q104 62 104 224V385H33V431H104V497L105 564L107 574Q126 639 171 668T266 704Q267 704 275 704T289 705Q330 702 351 679T372 627Q372 604 358 590T321 576T284 590T270 627Q270 647 288 667H284Q280 668 273 668Q245 668 223 647T189 592Q183 572 182 497V431H293V385H185V225Q185 63 186 61T189 57T194 54T199 51T206 49T213 48T222 47T231 47T241 46T251 46H282V0H273Z" style="stroke-width: 3;"/><path data-c="61" d="M137 305T115 305T78 320T63 359Q63 394 97 421T218 448Q291 448 336 416T396 340Q401 326 401 309T402 194V124Q402 76 407 58T428 40Q443 40 448 56T453 109V145H493V106Q492 66 490 59Q481 29 455 12T400 -6T353 12T329 54V58L327 55Q325 52 322 49T314 40T302 29T287 17T269 6T247 -2T221 -8T190 -11Q130 -11 82 20T34 107Q34 128 41 147T68 188T116 225T194 253T304 268H318V290Q318 324 312 340Q290 411 215 411Q197 411 181 410T156 406T148 403Q170 388 170 359Q170 334 154 320ZM126 106Q126 75 150 51T209 26Q247 26 276 49T315 109Q317 116 318 175Q318 233 317 233Q309 233 296 232T251 223T193 203T147 166T126 106Z" transform="translate(306,0)" style="stroke-width: 3;"/><path data-c="64" d="M376 495Q376 511 376 535T377 568Q377 613 367 624T316 637H298V660Q298 683 300 683L310 684Q320 685 339 686T376 688Q393 689 413 690T443 693T454 694H457V390Q457 84 458 81Q461 61 472 55T517 46H535V0Q533 0 459 -5T380 -11H373V44L365 37Q307 -11 235 -11Q158 -11 96 50T34 215Q34 315 97 378T244 442Q319 442 376 393V495ZM373 342Q328 405 260 405Q211 405 173 369Q146 341 139 305T131 211Q131 155 138 120T173 59Q203 26 251 26Q322 26 373 103V342Z" transform="translate(806,0)" style="stroke-width: 3;"/><path data-c="65" d="M28 218Q28 273 48 318T98 391T163 433T229 448Q282 448 320 430T378 380T406 316T415 245Q415 238 408 231H126V216Q126 68 226 36Q246 30 270 30Q312 30 342 62Q359 79 369 104L379 128Q382 131 395 131H398Q415 131 415 121Q415 117 412 108Q393 53 349 21T250 -11Q155 -11 92 58T28 218ZM333 275Q322 403 238 411H236Q228 411 220 410T195 402T166 381T143 340T127 274V267H333V275Z" transform="translate(1362,0)" style="stroke-width: 3;"/><path data-c="46" d="M128 619Q121 626 117 628T101 631T58 634H25V680H582V676Q584 670 596 560T610 444V440H570V444Q563 493 561 501Q555 538 543 563T516 601T477 622T431 631T374 633H334H286Q252 633 244 631T233 621Q232 619 232 490V363H284Q287 363 303 363T327 364T349 367T372 373T389 385Q407 403 410 459V480H450V200H410V221Q407 276 389 296Q381 303 371 307T348 313T327 316T303 317T284 317H232V189L233 61Q240 54 245 52T270 48T333 46H360V0H348Q324 3 182 3Q51 3 36 0H25V46H58Q100 47 109 49T128 61V619Z" transform="translate(1806,0)" style="stroke-width: 3;"/><path data-c="61" d="M137 305T115 305T78 320T63 359Q63 394 97 421T218 448Q291 448 336 416T396 340Q401 326 401 309T402 194V124Q402 76 407 58T428 40Q443 40 448 56T453 109V145H493V106Q492 66 490 59Q481 29 455 12T400 -6T353 12T329 54V58L327 55Q325 52 322 49T314 40T302 29T287 17T269 6T247 -2T221 -8T190 -11Q130 -11 82 20T34 107Q34 128 41 147T68 188T116 225T194 253T304 268H318V290Q318 324 312 340Q290 411 215 411Q197 411 181 410T156 406T148 403Q170 388 170 359Q170 334 154 320ZM126 106Q126 75 150 51T209 26Q247 26 276 49T315 109Q317 116 318 175Q318 233 317 233Q309 233 296 232T251 223T193 203T147 166T126 106Z" transform="translate(2459,0)" style="stroke-width: 3;"/><path data-c="72" d="M36 46H50Q89 46 97 60V68Q97 77 97 91T98 122T98 161T98 203Q98 234 98 269T98 328L97 351Q94 370 83 376T38 385H20V408Q20 431 22 431L32 432Q42 433 60 434T96 436Q112 437 131 438T160 441T171 442H174V373Q213 441 271 441H277Q322 441 343 419T364 373Q364 352 351 337T313 322Q288 322 276 338T263 372Q263 381 265 388T270 400T273 405Q271 407 250 401Q234 393 226 386Q179 341 179 207V154Q179 141 179 127T179 101T180 81T180 66V61Q181 59 183 57T188 54T193 51T200 49T207 48T216 47T225 47T235 46T245 46H276V0H267Q249 3 140 3Q37 3 28 0H20V46H36Z" transform="translate(2959,0)" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(14754.1,0)"><path data-c="2C" d="M78 35T78 60T94 103T137 121Q165 121 187 96T210 8Q210 -27 201 -60T180 -117T154 -158T130 -185T117 -194Q113 -194 104 -185T95 -172Q95 -168 106 -156T131 -126T157 -76T173 -3V9L172 8Q170 7 167 6T161 3T152 1T140 0Q113 0 96 17Z" style="stroke-width: 3;"/></g><g data-mml-node="mtext" transform="translate(15198.8,0)"><path data-c="64" d="M376 495Q376 511 376 535T377 568Q377 613 367 624T316 637H298V660Q298 683 300 683L310 684Q320 685 339 686T376 688Q393 689 413 690T443 693T454 694H457V390Q457 84 458 81Q461 61 472 55T517 46H535V0Q533 0 459 -5T380 -11H373V44L365 37Q307 -11 235 -11Q158 -11 96 50T34 215Q34 315 97 378T244 442Q319 442 376 393V495ZM373 342Q328 405 260 405Q211 405 173 369Q146 341 139 305T131 211Q131 155 138 120T173 59Q203 26 251 26Q322 26 373 103V342Z" style="stroke-width: 3;"/><path data-c="69" d="M69 609Q69 637 87 653T131 669Q154 667 171 652T188 609Q188 579 171 564T129 549Q104 549 87 564T69 609ZM247 0Q232 3 143 3Q132 3 106 3T56 1L34 0H26V46H42Q70 46 91 49Q100 53 102 60T104 102V205V293Q104 345 102 359T88 378Q74 385 41 385H30V408Q30 431 32 431L42 432Q52 433 70 434T106 436Q123 437 142 438T171 441T182 442H185V62Q190 52 197 50T232 46H255V0H247Z" transform="translate(556,0)" style="stroke-width: 3;"/><path data-c="73" d="M295 316Q295 356 268 385T190 414Q154 414 128 401Q98 382 98 349Q97 344 98 336T114 312T157 287Q175 282 201 278T245 269T277 256Q294 248 310 236T342 195T359 133Q359 71 321 31T198 -10H190Q138 -10 94 26L86 19L77 10Q71 4 65 -1L54 -11H46H42Q39 -11 33 -5V74V132Q33 153 35 157T45 162H54Q66 162 70 158T75 146T82 119T101 77Q136 26 198 26Q295 26 295 104Q295 133 277 151Q257 175 194 187T111 210Q75 227 54 256T33 318Q33 357 50 384T93 424T143 442T187 447H198Q238 447 268 432L283 424L292 431Q302 440 314 448H322H326Q329 448 335 442V310L329 304H301Q295 310 295 316Z" transform="translate(834,0)" style="stroke-width: 3;"/><path data-c="74" d="M27 422Q80 426 109 478T141 600V615H181V431H316V385H181V241Q182 116 182 100T189 68Q203 29 238 29Q282 29 292 100Q293 108 293 146V181H333V146V134Q333 57 291 17Q264 -10 221 -10Q187 -10 162 2T124 33T105 68T98 100Q97 107 97 248V385H18V422H27Z" transform="translate(1228,0)" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(16815.8,0)"><path data-c="29" d="M60 749L64 750Q69 750 74 750H86L114 726Q208 641 251 514T294 250Q294 182 284 119T261 12T224 -76T186 -143T145 -194T113 -227T90 -246Q87 -249 86 -250H74Q66 -250 63 -250T58 -247T55 -238Q56 -237 66 -225Q221 -64 221 250T66 725Q56 737 55 738Q55 746 60 749Z" style="stroke-width: 3;"/></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mn>1</mn><mo>−</mo><mtext>smoothstep</mtext><mo stretchy="false">(</mo><mtext>fadeNear</mtext><mo>,</mo><mtext>fadeFar</mtext><mo>,</mo><mtext>dist</mtext><mo stretchy="false">)</mo></math></mjx-assistive-mml></mjx-container>; así, las matas lejanas se aplanan hasta tener altura cero y dejan de consumir relleno. El viento consta de dos octavas de seno y coseno sobre las coordenadas XZ de la mata en el mundo más el tiempo, se aplica horizontalmente y queda limitado por la fracción de altura para que la base permanezca anclada mientras se mueven las puntas. Además, una ligera inclinación dependiente de la cámara orienta cada mata hacia el espectador para que se abra en perspectiva en vez de parecer una tarjeta plana.</p>
<p>La fórmula de color procede del shader URP de Breath of the Wild creado por NedMakesGames: sombreado plano con el color de la brizna interpolado desde un tono de raíz hasta otro de punta a lo largo de la fracción de altura; a su vez, los tonos de raíz y punta se interpolan entre dos paletas mediante el valor de tono de cada mata. Esto produce el aspecto moteado de dos tonos que tiene un campo de hierba real de BotW. La iluminación difusa compara la normal del terreno con el sol e incluye un mínimo de luz ambiental, porque las normales de cada quad cruzado son demasiado ruidosas para sombrearlas individualmente con un estilo visual estilizado. Todo el campo se dibuja en una sola llamada y se coloca y anima por completo en la GPU.</p>
<h2 id="cuatro-formas-de-descartar-lo-que-oculta-una-colina" tabindex="-1">Cuatro formas de descartar lo que oculta una colina <a class="header-anchor" href="#cuatro-formas-de-descartar-lo-que-oculta-una-colina" aria-label="Permalink to &quot;Cuatro formas de descartar lo que oculta una colina&quot;"></a></h2>
<div style="position:relative;padding-bottom:56.25%;height:0;overflow:hidden;border-radius:8px;margin:1.5rem 0;border:1px solid rgba(255,255,255,0.12)">
<iframe src="/es/spikes/57-terrain-occlusion/" title="Spike 57: Oclusión del terreno" style="position:absolute;top:0;left:0;width:100%;height:100%;border:0;background:#000" loading="lazy" allowfullscreen></iframe>
</div>
<p><a href="/es/spikes/57-terrain-occlusion/" target="_blank">Abrir el Spike 57 en una pestaña nueva ↗</a> · <a href="/es/blog/spike-source?spike=57-terrain-occlusion">Ver código fuente</a></p>
<p>El Spike 57 compara cuatro métodos de descarte sobre el mismo mundo procedimental que transmite por streaming el cliente de producción, escalado verticalmente 1,8 veces para que las colinas oculten de verdad el follaje. T0 solo tiene en cuenta la distancia, igual que el sistema de visibilidad de chunks que ya utiliza la versión publicada. T1 añade descarte por frustum, la mejora barata más importante, que elimina todo lo que queda fuera del cono de visión. T2 añade una prueba de horizonte que tiene en cuenta el terreno: recorre un rayo desde el ojo hasta cada instancia y la rechaza si el mapa de alturas supera el rayo en algún punto del trayecto, de modo que un árbol situado detrás de una cresta se descarta aunque esté dentro del frustum. T3 conserva la misma prueba de horizonte, pero la acelera mediante una pirámide de alturas máximas. T4 traslada toda la prueba de distancia, frustum y horizonte a un kernel de cómputo TSL que escribe una escala de visibilidad por instancia, leída por el material del follaje para colapsar los vértices ocultos. Un contador que mantiene la visibilidad durante dos fotogramas suaviza el parpadeo de un solo fotograma que se produce cuando un punto de muestreo cae justo dentro o fuera de un texel al mover ligeramente la cámara. Se mantiene corto deliberadamente, porque una duración mayor ocultaría errores algorítmicos en lugar de corregirlos.</p>
<p>La pirámide es donde el spike demuestra su valor, y la lección consiste en hacer que la prueba coincida con lo que realmente aparece en pantalla. El terreno renderizado es una malla de triángulos con vértices situados en una cuadrícula fija de dos metros, y entre los vértices el rasterizador interpola linealmente. Por tanto, la altura máxima real renderizada dentro de cualquier rectángulo es el máximo de los vértices que contiene, nunca el pico del ruido continuo situado entre ellos. Si la pirámide de oclusión muestrea el ruido en una cuadrícula más fina, encuentra picos fantasma que la malla nunca muestra y empieza a bloquear rayos que la cámara puede ver atravesar claramente. Por eso, los texeles de la base de la pirámide se sitúan exactamente sobre la cuadrícula de vértices y cada uno almacena el máximo de sus cuatro vértices de esquina. Los niveles superiores son reducciones máximas 2x2 convencionales, lo que hace que la pirámide sea exacta respecto a la malla renderizada. Para la prueba del rayo en cada paso, el código muestrea deliberadamente la malla por puntos mediante interpolación bilineal en vez de consultar la pirámide, porque una consulta AABB más pequeña que un texel devuelve el máximo de todo el texel y eleva la altura varios metros en crestas pronunciadas. Ese es precisamente el tipo de oclusión excesiva que ocultaría elementos visibles.</p>
<p>El resultado sorprendente es que T2, la referencia por fuerza bruta, es el método incorrecto. Como T2 muestrea directamente por puntos el ruido continuo, detecta picos entre vértices de la malla que nunca se renderizan, por lo que produce una ligera oclusión excesiva y oculta follaje que el jugador sí puede ver. El método de la pirámide es más rápido, gracias a la reducción AABB de <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.566ex;" xmlns="http://www.w3.org/2000/svg" width="8.764ex" height="2.262ex" role="img" focusable="false" viewBox="0 -750 3873.7 1000" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mi"><path data-c="1D442" d="M740 435Q740 320 676 213T511 42T304 -22Q207 -22 138 35T51 201Q50 209 50 244Q50 346 98 438T227 601Q351 704 476 704Q514 704 524 703Q621 689 680 617T740 435ZM637 476Q637 565 591 615T476 665Q396 665 322 605Q242 542 200 428T157 216Q157 126 200 73T314 19Q404 19 485 98T608 313Q637 408 637 476Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(763,0)"><path data-c="28" d="M94 250Q94 319 104 381T127 488T164 576T202 643T244 695T277 729T302 750H315H319Q333 750 333 741Q333 738 316 720T275 667T226 581T184 443T167 250T184 58T225 -81T274 -167T316 -220T333 -241Q333 -250 318 -250H315H302L274 -226Q180 -141 137 -14T94 250Z" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(1152,0)"><path data-c="6C" d="M42 46H56Q95 46 103 60V68Q103 77 103 91T103 124T104 167T104 217T104 272T104 329Q104 366 104 407T104 482T104 542T103 586T103 603Q100 622 89 628T44 637H26V660Q26 683 28 683L38 684Q48 685 67 686T104 688Q121 689 141 690T171 693T182 694H185V379Q185 62 186 60Q190 52 198 49Q219 46 247 46H263V0H255L232 1Q209 2 183 2T145 3T107 3T57 1L34 0H26V46H42Z" style="stroke-width: 3;"/><path data-c="6F" d="M28 214Q28 309 93 378T250 448Q340 448 405 380T471 215Q471 120 407 55T250 -10Q153 -10 91 57T28 214ZM250 30Q372 30 372 193V225V250Q372 272 371 288T364 326T348 362T317 390T268 410Q263 411 252 411Q222 411 195 399Q152 377 139 338T126 246V226Q126 130 145 91Q177 30 250 30Z" transform="translate(278,0)" style="stroke-width: 3;"/><path data-c="67" d="M329 409Q373 453 429 453Q459 453 472 434T485 396Q485 382 476 371T449 360Q416 360 412 390Q410 404 415 411Q415 412 416 414V415Q388 412 363 393Q355 388 355 386Q355 385 359 381T368 369T379 351T388 325T392 292Q392 230 343 187T222 143Q172 143 123 171Q112 153 112 133Q112 98 138 81Q147 75 155 75T227 73Q311 72 335 67Q396 58 431 26Q470 -13 470 -72Q470 -139 392 -175Q332 -206 250 -206Q167 -206 107 -175Q29 -140 29 -75Q29 -39 50 -15T92 18L103 24Q67 55 67 108Q67 155 96 193Q52 237 52 292Q52 355 102 398T223 442Q274 442 318 416L329 409ZM299 343Q294 371 273 387T221 404Q192 404 171 388T145 343Q142 326 142 292Q142 248 149 227T179 192Q196 182 222 182Q244 182 260 189T283 207T294 227T299 242Q302 258 302 292T299 343ZM403 -75Q403 -50 389 -34T348 -11T299 -2T245 0H218Q151 0 138 -6Q118 -15 107 -34T95 -74Q95 -84 101 -97T122 -127T170 -155T250 -167Q319 -167 361 -139T403 -75Z" transform="translate(778,0)" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(2430,0)"><path data-c="2061" d="" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(2596.7,0)"><path data-c="1D441" d="M234 637Q231 637 226 637Q201 637 196 638T191 649Q191 676 202 682Q204 683 299 683Q376 683 387 683T401 677Q612 181 616 168L670 381Q723 592 723 606Q723 633 659 637Q635 637 635 648Q635 650 637 660Q641 676 643 679T653 683Q656 683 684 682T767 680Q817 680 843 681T873 682Q888 682 888 672Q888 650 880 642Q878 637 858 637Q787 633 769 597L620 7Q618 0 599 0Q585 0 582 2Q579 5 453 305L326 604L261 344Q196 88 196 79Q201 46 268 46H278Q284 41 284 38T282 19Q278 6 272 0H259Q228 2 151 2Q123 2 100 2T63 2T46 1Q31 1 31 10Q31 14 34 26T39 40Q41 46 62 46Q130 49 150 85Q154 91 221 362L289 634Q287 635 234 637Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(3484.7,0)"><path data-c="29" d="M60 749L64 750Q69 750 74 750H86L114 726Q208 641 251 514T294 250Q294 182 284 119T261 12T224 -76T186 -143T145 -194T113 -227T90 -246Q87 -249 86 -250H74Q66 -250 63 -250T58 -247T55 -238Q56 -237 66 -225Q221 -64 221 250T66 725Q56 737 55 738Q55 746 60 749Z" style="stroke-width: 3;"/></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mi>O</mi><mo stretchy="false">(</mo><mi>log</mi><mo data-mjx-texclass="NONE">⁡</mo><mi>N</mi><mo stretchy="false">)</mo></math></mjx-assistive-mml></mjx-container> para las pruebas a nivel de chunk, y también más correcto geométricamente, porque solo puede devolver alturas que la malla muestra realmente. Esa es la idea central del spike: la estructura acelerada no es una concesión de calidad a cambio de velocidad, sino la versión que coincide con la realidad. El descarte de chunks ejecuta una prueba de cinco puntos por chunk —las cuatro esquinas superiores más el centro a la altura máxima del chunk— y excluye del conjunto de oclusores la huella de cada propio chunk para que nunca se ocluya a sí mismo. El método recomendado para producción es T4: enviar los metadatos de instancia y el campo de alturas a búferes de almacenamiento y ejecutar el mismo bucle en un shader de cómputo con dibujo indirecto, puesto que el renderizador ya está migrando a WebGPU.</p>
<h2 id="tecnologia-mencionada-en-este-capitulo" tabindex="-1">Tecnología mencionada en este capítulo <a class="header-anchor" href="#tecnologia-mencionada-en-este-capitulo" aria-label="Permalink to &quot;Tecnología mencionada en este capítulo&quot;"></a></h2>
<p><strong>Hierba de GPU con quads cruzados.</strong> Tres quads afilados rotados sesenta grados entre sí por mata garantizan que uno quede casi perpendicular desde cualquier ángulo, de modo que medio millón de instancias parezcan un campo en vez de confeti de menos de un píxel. Un kernel de cómputo coloca cada mata —altura del terreno FBM muestreada con el mismo mod que conserva el signo que utiliza la malla de la CPU, normal por diferencias centrales, tamaño y tono por mata— y un grafo de vértices TSL omite la matriz de instancia para escalar, rotar mediante Rodrigues hasta la normal, trasladar y aplicar viento limitado por la altura. El LOD por distancia es gratis: las matas colapsan hasta una altura cero mediante <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.566ex;" xmlns="http://www.w3.org/2000/svg" width="38.925ex" height="2.262ex" role="img" focusable="false" viewBox="0 -750 17204.8 1000" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mn"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(722.2,0)"><path data-c="2212" d="M84 237T84 250T98 270H679Q694 262 694 250T679 230H98Q84 237 84 250Z" style="stroke-width: 3;"/></g><g data-mml-node="mtext" transform="translate(1722.4,0)"><path data-c="73" d="M295 316Q295 356 268 385T190 414Q154 414 128 401Q98 382 98 349Q97 344 98 336T114 312T157 287Q175 282 201 278T245 269T277 256Q294 248 310 236T342 195T359 133Q359 71 321 31T198 -10H190Q138 -10 94 26L86 19L77 10Q71 4 65 -1L54 -11H46H42Q39 -11 33 -5V74V132Q33 153 35 157T45 162H54Q66 162 70 158T75 146T82 119T101 77Q136 26 198 26Q295 26 295 104Q295 133 277 151Q257 175 194 187T111 210Q75 227 54 256T33 318Q33 357 50 384T93 424T143 442T187 447H198Q238 447 268 432L283 424L292 431Q302 440 314 448H322H326Q329 448 335 442V310L329 304H301Q295 310 295 316Z" style="stroke-width: 3;"/><path data-c="6D" d="M41 46H55Q94 46 102 60V68Q102 77 102 91T102 122T103 161T103 203Q103 234 103 269T102 328V351Q99 370 88 376T43 385H25V408Q25 431 27 431L37 432Q47 433 65 434T102 436Q119 437 138 438T167 441T178 442H181V402Q181 364 182 364T187 369T199 384T218 402T247 421T285 437Q305 442 336 442Q351 442 364 440T387 434T406 426T421 417T432 406T441 395T448 384T452 374T455 366L457 361L460 365Q463 369 466 373T475 384T488 397T503 410T523 422T546 432T572 439T603 442Q729 442 740 329Q741 322 741 190V104Q741 66 743 59T754 49Q775 46 803 46H819V0H811L788 1Q764 2 737 2T699 3Q596 3 587 0H579V46H595Q656 46 656 62Q657 64 657 200Q656 335 655 343Q649 371 635 385T611 402T585 404Q540 404 506 370Q479 343 472 315T464 232V168V108Q464 78 465 68T468 55T477 49Q498 46 526 46H542V0H534L510 1Q487 2 460 2T422 3Q319 3 310 0H302V46H318Q379 46 379 62Q380 64 380 200Q379 335 378 343Q372 371 358 385T334 402T308 404Q263 404 229 370Q202 343 195 315T187 232V168V108Q187 78 188 68T191 55T200 49Q221 46 249 46H265V0H257L234 1Q210 2 183 2T145 3Q42 3 33 0H25V46H41Z" transform="translate(394,0)" style="stroke-width: 3;"/><path data-c="6F" d="M28 214Q28 309 93 378T250 448Q340 448 405 380T471 215Q471 120 407 55T250 -10Q153 -10 91 57T28 214ZM250 30Q372 30 372 193V225V250Q372 272 371 288T364 326T348 362T317 390T268 410Q263 411 252 411Q222 411 195 399Q152 377 139 338T126 246V226Q126 130 145 91Q177 30 250 30Z" transform="translate(1227,0)" style="stroke-width: 3;"/><path data-c="6F" d="M28 214Q28 309 93 378T250 448Q340 448 405 380T471 215Q471 120 407 55T250 -10Q153 -10 91 57T28 214ZM250 30Q372 30 372 193V225V250Q372 272 371 288T364 326T348 362T317 390T268 410Q263 411 252 411Q222 411 195 399Q152 377 139 338T126 246V226Q126 130 145 91Q177 30 250 30Z" transform="translate(1727,0)" style="stroke-width: 3;"/><path data-c="74" d="M27 422Q80 426 109 478T141 600V615H181V431H316V385H181V241Q182 116 182 100T189 68Q203 29 238 29Q282 29 292 100Q293 108 293 146V181H333V146V134Q333 57 291 17Q264 -10 221 -10Q187 -10 162 2T124 33T105 68T98 100Q97 107 97 248V385H18V422H27Z" transform="translate(2227,0)" style="stroke-width: 3;"/><path data-c="68" d="M41 46H55Q94 46 102 60V68Q102 77 102 91T102 124T102 167T103 217T103 272T103 329Q103 366 103 407T103 482T102 542T102 586T102 603Q99 622 88 628T43 637H25V660Q25 683 27 683L37 684Q47 685 66 686T103 688Q120 689 140 690T170 693T181 694H184V367Q244 442 328 442Q451 442 463 329Q464 322 464 190V104Q464 66 466 59T477 49Q498 46 526 46H542V0H534L510 1Q487 2 460 2T422 3Q319 3 310 0H302V46H318Q379 46 379 62Q380 64 380 200Q379 335 378 343Q372 371 358 385T334 402T308 404Q263 404 229 370Q202 343 195 315T187 232V168V108Q187 78 188 68T191 55T200 49Q221 46 249 46H265V0H257L234 1Q210 2 183 2T145 3Q42 3 33 0H25V46H41Z" transform="translate(2616,0)" style="stroke-width: 3;"/><path data-c="73" d="M295 316Q295 356 268 385T190 414Q154 414 128 401Q98 382 98 349Q97 344 98 336T114 312T157 287Q175 282 201 278T245 269T277 256Q294 248 310 236T342 195T359 133Q359 71 321 31T198 -10H190Q138 -10 94 26L86 19L77 10Q71 4 65 -1L54 -11H46H42Q39 -11 33 -5V74V132Q33 153 35 157T45 162H54Q66 162 70 158T75 146T82 119T101 77Q136 26 198 26Q295 26 295 104Q295 133 277 151Q257 175 194 187T111 210Q75 227 54 256T33 318Q33 357 50 384T93 424T143 442T187 447H198Q238 447 268 432L283 424L292 431Q302 440 314 448H322H326Q329 448 335 442V310L329 304H301Q295 310 295 316Z" transform="translate(3172,0)" style="stroke-width: 3;"/><path data-c="74" d="M27 422Q80 426 109 478T141 600V615H181V431H316V385H181V241Q182 116 182 100T189 68Q203 29 238 29Q282 29 292 100Q293 108 293 146V181H333V146V134Q333 57 291 17Q264 -10 221 -10Q187 -10 162 2T124 33T105 68T98 100Q97 107 97 248V385H18V422H27Z" transform="translate(3566,0)" style="stroke-width: 3;"/><path data-c="65" d="M28 218Q28 273 48 318T98 391T163 433T229 448Q282 448 320 430T378 380T406 316T415 245Q415 238 408 231H126V216Q126 68 226 36Q246 30 270 30Q312 30 342 62Q359 79 369 104L379 128Q382 131 395 131H398Q415 131 415 121Q415 117 412 108Q393 53 349 21T250 -11Q155 -11 92 58T28 218ZM333 275Q322 403 238 411H236Q228 411 220 410T195 402T166 381T143 340T127 274V267H333V275Z" transform="translate(3955,0)" style="stroke-width: 3;"/><path data-c="70" d="M36 -148H50Q89 -148 97 -134V-126Q97 -119 97 -107T97 -77T98 -38T98 6T98 55T98 106Q98 140 98 177T98 243T98 296T97 335T97 351Q94 370 83 376T38 385H20V408Q20 431 22 431L32 432Q42 433 61 434T98 436Q115 437 135 438T165 441T176 442H179V416L180 390L188 397Q247 441 326 441Q407 441 464 377T522 216Q522 115 457 52T310 -11Q242 -11 190 33L182 40V-45V-101Q182 -128 184 -134T195 -145Q216 -148 244 -148H260V-194H252L228 -193Q205 -192 178 -192T140 -191Q37 -191 28 -194H20V-148H36ZM424 218Q424 292 390 347T305 402Q234 402 182 337V98Q222 26 294 26Q345 26 384 80T424 218Z" transform="translate(4399,0)" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(6677.4,0)"><path data-c="28" d="M94 250Q94 319 104 381T127 488T164 576T202 643T244 695T277 729T302 750H315H319Q333 750 333 741Q333 738 316 720T275 667T226 581T184 443T167 250T184 58T225 -81T274 -167T316 -220T333 -241Q333 -250 318 -250H315H302L274 -226Q180 -141 137 -14T94 250Z" style="stroke-width: 3;"/></g><g data-mml-node="mtext" transform="translate(7066.4,0)"><path data-c="66" d="M273 0Q255 3 146 3Q43 3 34 0H26V46H42Q70 46 91 49Q99 52 103 60Q104 62 104 224V385H33V431H104V497L105 564L107 574Q126 639 171 668T266 704Q267 704 275 704T289 705Q330 702 351 679T372 627Q372 604 358 590T321 576T284 590T270 627Q270 647 288 667H284Q280 668 273 668Q245 668 223 647T189 592Q183 572 182 497V431H293V385H185V225Q185 63 186 61T189 57T194 54T199 51T206 49T213 48T222 47T231 47T241 46T251 46H282V0H273Z" style="stroke-width: 3;"/><path data-c="61" d="M137 305T115 305T78 320T63 359Q63 394 97 421T218 448Q291 448 336 416T396 340Q401 326 401 309T402 194V124Q402 76 407 58T428 40Q443 40 448 56T453 109V145H493V106Q492 66 490 59Q481 29 455 12T400 -6T353 12T329 54V58L327 55Q325 52 322 49T314 40T302 29T287 17T269 6T247 -2T221 -8T190 -11Q130 -11 82 20T34 107Q34 128 41 147T68 188T116 225T194 253T304 268H318V290Q318 324 312 340Q290 411 215 411Q197 411 181 410T156 406T148 403Q170 388 170 359Q170 334 154 320ZM126 106Q126 75 150 51T209 26Q247 26 276 49T315 109Q317 116 318 175Q318 233 317 233Q309 233 296 232T251 223T193 203T147 166T126 106Z" transform="translate(306,0)" style="stroke-width: 3;"/><path data-c="64" d="M376 495Q376 511 376 535T377 568Q377 613 367 624T316 637H298V660Q298 683 300 683L310 684Q320 685 339 686T376 688Q393 689 413 690T443 693T454 694H457V390Q457 84 458 81Q461 61 472 55T517 46H535V0Q533 0 459 -5T380 -11H373V44L365 37Q307 -11 235 -11Q158 -11 96 50T34 215Q34 315 97 378T244 442Q319 442 376 393V495ZM373 342Q328 405 260 405Q211 405 173 369Q146 341 139 305T131 211Q131 155 138 120T173 59Q203 26 251 26Q322 26 373 103V342Z" transform="translate(806,0)" style="stroke-width: 3;"/><path data-c="65" d="M28 218Q28 273 48 318T98 391T163 433T229 448Q282 448 320 430T378 380T406 316T415 245Q415 238 408 231H126V216Q126 68 226 36Q246 30 270 30Q312 30 342 62Q359 79 369 104L379 128Q382 131 395 131H398Q415 131 415 121Q415 117 412 108Q393 53 349 21T250 -11Q155 -11 92 58T28 218ZM333 275Q322 403 238 411H236Q228 411 220 410T195 402T166 381T143 340T127 274V267H333V275Z" transform="translate(1362,0)" style="stroke-width: 3;"/><path data-c="4E" d="M42 46Q74 48 94 56T118 69T128 86V634H124Q114 637 52 637H25V683H232L235 680Q237 679 322 554T493 303L578 178V598Q572 608 568 613T544 627T492 637H475V683H483Q498 680 600 680Q706 680 715 683H724V637H707Q634 633 622 598L621 302V6L614 0H600Q585 0 582 3T481 150T282 443T171 605V345L172 86Q183 50 257 46H274V0H265Q250 3 150 3Q48 3 33 0H25V46H42Z" transform="translate(1806,0)" style="stroke-width: 3;"/><path data-c="65" d="M28 218Q28 273 48 318T98 391T163 433T229 448Q282 448 320 430T378 380T406 316T415 245Q415 238 408 231H126V216Q126 68 226 36Q246 30 270 30Q312 30 342 62Q359 79 369 104L379 128Q382 131 395 131H398Q415 131 415 121Q415 117 412 108Q393 53 349 21T250 -11Q155 -11 92 58T28 218ZM333 275Q322 403 238 411H236Q228 411 220 410T195 402T166 381T143 340T127 274V267H333V275Z" transform="translate(2556,0)" style="stroke-width: 3;"/><path data-c="61" d="M137 305T115 305T78 320T63 359Q63 394 97 421T218 448Q291 448 336 416T396 340Q401 326 401 309T402 194V124Q402 76 407 58T428 40Q443 40 448 56T453 109V145H493V106Q492 66 490 59Q481 29 455 12T400 -6T353 12T329 54V58L327 55Q325 52 322 49T314 40T302 29T287 17T269 6T247 -2T221 -8T190 -11Q130 -11 82 20T34 107Q34 128 41 147T68 188T116 225T194 253T304 268H318V290Q318 324 312 340Q290 411 215 411Q197 411 181 410T156 406T148 403Q170 388 170 359Q170 334 154 320ZM126 106Q126 75 150 51T209 26Q247 26 276 49T315 109Q317 116 318 175Q318 233 317 233Q309 233 296 232T251 223T193 203T147 166T126 106Z" transform="translate(3000,0)" style="stroke-width: 3;"/><path data-c="72" d="M36 46H50Q89 46 97 60V68Q97 77 97 91T98 122T98 161T98 203Q98 234 98 269T98 328L97 351Q94 370 83 376T38 385H20V408Q20 431 22 431L32 432Q42 433 60 434T96 436Q112 437 131 438T160 441T171 442H174V373Q213 441 271 441H277Q322 441 343 419T364 373Q364 352 351 337T313 322Q288 322 276 338T263 372Q263 381 265 388T270 400T273 405Q271 407 250 401Q234 393 226 386Q179 341 179 207V154Q179 141 179 127T179 101T180 81T180 66V61Q181 59 183 57T188 54T193 51T200 49T207 48T216 47T225 47T235 46T245 46H276V0H267Q249 3 140 3Q37 3 28 0H20V46H36Z" transform="translate(3500,0)" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(10958.4,0)"><path data-c="2C" d="M78 35T78 60T94 103T137 121Q165 121 187 96T210 8Q210 -27 201 -60T180 -117T154 -158T130 -185T117 -194Q113 -194 104 -185T95 -172Q95 -168 106 -156T131 -126T157 -76T173 -3V9L172 8Q170 7 167 6T161 3T152 1T140 0Q113 0 96 17Z" style="stroke-width: 3;"/></g><g data-mml-node="mtext" transform="translate(11403.1,0)"><path data-c="66" d="M273 0Q255 3 146 3Q43 3 34 0H26V46H42Q70 46 91 49Q99 52 103 60Q104 62 104 224V385H33V431H104V497L105 564L107 574Q126 639 171 668T266 704Q267 704 275 704T289 705Q330 702 351 679T372 627Q372 604 358 590T321 576T284 590T270 627Q270 647 288 667H284Q280 668 273 668Q245 668 223 647T189 592Q183 572 182 497V431H293V385H185V225Q185 63 186 61T189 57T194 54T199 51T206 49T213 48T222 47T231 47T241 46T251 46H282V0H273Z" style="stroke-width: 3;"/><path data-c="61" d="M137 305T115 305T78 320T63 359Q63 394 97 421T218 448Q291 448 336 416T396 340Q401 326 401 309T402 194V124Q402 76 407 58T428 40Q443 40 448 56T453 109V145H493V106Q492 66 490 59Q481 29 455 12T400 -6T353 12T329 54V58L327 55Q325 52 322 49T314 40T302 29T287 17T269 6T247 -2T221 -8T190 -11Q130 -11 82 20T34 107Q34 128 41 147T68 188T116 225T194 253T304 268H318V290Q318 324 312 340Q290 411 215 411Q197 411 181 410T156 406T148 403Q170 388 170 359Q170 334 154 320ZM126 106Q126 75 150 51T209 26Q247 26 276 49T315 109Q317 116 318 175Q318 233 317 233Q309 233 296 232T251 223T193 203T147 166T126 106Z" transform="translate(306,0)" style="stroke-width: 3;"/><path data-c="64" d="M376 495Q376 511 376 535T377 568Q377 613 367 624T316 637H298V660Q298 683 300 683L310 684Q320 685 339 686T376 688Q393 689 413 690T443 693T454 694H457V390Q457 84 458 81Q461 61 472 55T517 46H535V0Q533 0 459 -5T380 -11H373V44L365 37Q307 -11 235 -11Q158 -11 96 50T34 215Q34 315 97 378T244 442Q319 442 376 393V495ZM373 342Q328 405 260 405Q211 405 173 369Q146 341 139 305T131 211Q131 155 138 120T173 59Q203 26 251 26Q322 26 373 103V342Z" transform="translate(806,0)" style="stroke-width: 3;"/><path data-c="65" d="M28 218Q28 273 48 318T98 391T163 433T229 448Q282 448 320 430T378 380T406 316T415 245Q415 238 408 231H126V216Q126 68 226 36Q246 30 270 30Q312 30 342 62Q359 79 369 104L379 128Q382 131 395 131H398Q415 131 415 121Q415 117 412 108Q393 53 349 21T250 -11Q155 -11 92 58T28 218ZM333 275Q322 403 238 411H236Q228 411 220 410T195 402T166 381T143 340T127 274V267H333V275Z" transform="translate(1362,0)" style="stroke-width: 3;"/><path data-c="46" d="M128 619Q121 626 117 628T101 631T58 634H25V680H582V676Q584 670 596 560T610 444V440H570V444Q563 493 561 501Q555 538 543 563T516 601T477 622T431 631T374 633H334H286Q252 633 244 631T233 621Q232 619 232 490V363H284Q287 363 303 363T327 364T349 367T372 373T389 385Q407 403 410 459V480H450V200H410V221Q407 276 389 296Q381 303 371 307T348 313T327 316T303 317T284 317H232V189L233 61Q240 54 245 52T270 48T333 46H360V0H348Q324 3 182 3Q51 3 36 0H25V46H58Q100 47 109 49T128 61V619Z" transform="translate(1806,0)" style="stroke-width: 3;"/><path data-c="61" d="M137 305T115 305T78 320T63 359Q63 394 97 421T218 448Q291 448 336 416T396 340Q401 326 401 309T402 194V124Q402 76 407 58T428 40Q443 40 448 56T453 109V145H493V106Q492 66 490 59Q481 29 455 12T400 -6T353 12T329 54V58L327 55Q325 52 322 49T314 40T302 29T287 17T269 6T247 -2T221 -8T190 -11Q130 -11 82 20T34 107Q34 128 41 147T68 188T116 225T194 253T304 268H318V290Q318 324 312 340Q290 411 215 411Q197 411 181 410T156 406T148 403Q170 388 170 359Q170 334 154 320ZM126 106Q126 75 150 51T209 26Q247 26 276 49T315 109Q317 116 318 175Q318 233 317 233Q309 233 296 232T251 223T193 203T147 166T126 106Z" transform="translate(2459,0)" style="stroke-width: 3;"/><path data-c="72" d="M36 46H50Q89 46 97 60V68Q97 77 97 91T98 122T98 161T98 203Q98 234 98 269T98 328L97 351Q94 370 83 376T38 385H20V408Q20 431 22 431L32 432Q42 433 60 434T96 436Q112 437 131 438T160 441T171 442H174V373Q213 441 271 441H277Q322 441 343 419T364 373Q364 352 351 337T313 322Q288 322 276 338T263 372Q263 381 265 388T270 400T273 405Q271 407 250 401Q234 393 226 386Q179 341 179 207V154Q179 141 179 127T179 101T180 81T180 66V61Q181 59 183 57T188 54T193 51T200 49T207 48T216 47T225 47T235 46T245 46H276V0H267Q249 3 140 3Q37 3 28 0H20V46H36Z" transform="translate(2959,0)" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(14754.1,0)"><path data-c="2C" d="M78 35T78 60T94 103T137 121Q165 121 187 96T210 8Q210 -27 201 -60T180 -117T154 -158T130 -185T117 -194Q113 -194 104 -185T95 -172Q95 -168 106 -156T131 -126T157 -76T173 -3V9L172 8Q170 7 167 6T161 3T152 1T140 0Q113 0 96 17Z" style="stroke-width: 3;"/></g><g data-mml-node="mtext" transform="translate(15198.8,0)"><path data-c="64" d="M376 495Q376 511 376 535T377 568Q377 613 367 624T316 637H298V660Q298 683 300 683L310 684Q320 685 339 686T376 688Q393 689 413 690T443 693T454 694H457V390Q457 84 458 81Q461 61 472 55T517 46H535V0Q533 0 459 -5T380 -11H373V44L365 37Q307 -11 235 -11Q158 -11 96 50T34 215Q34 315 97 378T244 442Q319 442 376 393V495ZM373 342Q328 405 260 405Q211 405 173 369Q146 341 139 305T131 211Q131 155 138 120T173 59Q203 26 251 26Q322 26 373 103V342Z" style="stroke-width: 3;"/><path data-c="69" d="M69 609Q69 637 87 653T131 669Q154 667 171 652T188 609Q188 579 171 564T129 549Q104 549 87 564T69 609ZM247 0Q232 3 143 3Q132 3 106 3T56 1L34 0H26V46H42Q70 46 91 49Q100 53 102 60T104 102V205V293Q104 345 102 359T88 378Q74 385 41 385H30V408Q30 431 32 431L42 432Q52 433 70 434T106 436Q123 437 142 438T171 441T182 442H185V62Q190 52 197 50T232 46H255V0H247Z" transform="translate(556,0)" style="stroke-width: 3;"/><path data-c="73" d="M295 316Q295 356 268 385T190 414Q154 414 128 401Q98 382 98 349Q97 344 98 336T114 312T157 287Q175 282 201 278T245 269T277 256Q294 248 310 236T342 195T359 133Q359 71 321 31T198 -10H190Q138 -10 94 26L86 19L77 10Q71 4 65 -1L54 -11H46H42Q39 -11 33 -5V74V132Q33 153 35 157T45 162H54Q66 162 70 158T75 146T82 119T101 77Q136 26 198 26Q295 26 295 104Q295 133 277 151Q257 175 194 187T111 210Q75 227 54 256T33 318Q33 357 50 384T93 424T143 442T187 447H198Q238 447 268 432L283 424L292 431Q302 440 314 448H322H326Q329 448 335 442V310L329 304H301Q295 310 295 316Z" transform="translate(834,0)" style="stroke-width: 3;"/><path data-c="74" d="M27 422Q80 426 109 478T141 600V615H181V431H316V385H181V241Q182 116 182 100T189 68Q203 29 238 29Q282 29 292 100Q293 108 293 146V181H333V146V134Q333 57 291 17Q264 -10 221 -10Q187 -10 162 2T124 33T105 68T98 100Q97 107 97 248V385H18V422H27Z" transform="translate(1228,0)" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(16815.8,0)"><path data-c="29" d="M60 749L64 750Q69 750 74 750H86L114 726Q208 641 251 514T294 250Q294 182 284 119T261 12T224 -76T186 -143T145 -194T113 -227T90 -246Q87 -249 86 -250H74Q66 -250 63 -250T58 -247T55 -238Q56 -237 66 -225Q221 -64 221 250T66 725Q56 737 55 738Q55 746 60 749Z" style="stroke-width: 3;"/></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mn>1</mn><mo>−</mo><mtext>smoothstep</mtext><mo stretchy="false">(</mo><mtext>fadeNear</mtext><mo>,</mo><mtext>fadeFar</mtext><mo>,</mo><mtext>dist</mtext><mo stretchy="false">)</mo></math></mjx-assistive-mml></mjx-container>. El color sigue la fórmula de BotW de NedMakesGames: un degradado de la raíz a la punta sobre dos paletas mezcladas según el tono. Consulta <a href="/es/guides/landscape-generation-browser.html#gpu-driven-lod-with-webgpu">LOD controlado por GPU</a>.</p>
<p><strong>Descarte por oclusión del horizonte del terreno.</strong> Cuatro métodos comparados sobre el mundo de producción: distancia; más frustum; más una prueba de rayos sobre el mapa de alturas que rechaza instancias situadas detrás de una cresta; más una pirámide de alturas máximas que la acelera; y un port completo a cómputo TSL. La pirámide muestrea exactamente sobre la cuadrícula de vértices de dos metros que tesela la malla —texel base = máximo de los cuatro vértices de esquina, seguido de reducciones máximas 2x2 hacia arriba—, por lo que solo devuelve alturas que el rasterizador muestra realmente.</p>
<p><strong>Acelerado y correcto, no una concesión.</strong> El muestreo por puntos del ruido continuo —el método T2 por fuerza bruta— encuentra picos entre vértices de la malla que nunca se renderizan y oculta en exceso follaje visible. La pirámide basada en la cuadrícula de vértices es más rápida —reducción AABB de <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.566ex;" xmlns="http://www.w3.org/2000/svg" width="8.764ex" height="2.262ex" role="img" focusable="false" viewBox="0 -750 3873.7 1000" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mi"><path data-c="1D442" d="M740 435Q740 320 676 213T511 42T304 -22Q207 -22 138 35T51 201Q50 209 50 244Q50 346 98 438T227 601Q351 704 476 704Q514 704 524 703Q621 689 680 617T740 435ZM637 476Q637 565 591 615T476 665Q396 665 322 605Q242 542 200 428T157 216Q157 126 200 73T314 19Q404 19 485 98T608 313Q637 408 637 476Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(763,0)"><path data-c="28" d="M94 250Q94 319 104 381T127 488T164 576T202 643T244 695T277 729T302 750H315H319Q333 750 333 741Q333 738 316 720T275 667T226 581T184 443T167 250T184 58T225 -81T274 -167T316 -220T333 -241Q333 -250 318 -250H315H302L274 -226Q180 -141 137 -14T94 250Z" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(1152,0)"><path data-c="6C" d="M42 46H56Q95 46 103 60V68Q103 77 103 91T103 124T104 167T104 217T104 272T104 329Q104 366 104 407T104 482T104 542T103 586T103 603Q100 622 89 628T44 637H26V660Q26 683 28 683L38 684Q48 685 67 686T104 688Q121 689 141 690T171 693T182 694H185V379Q185 62 186 60Q190 52 198 49Q219 46 247 46H263V0H255L232 1Q209 2 183 2T145 3T107 3T57 1L34 0H26V46H42Z" style="stroke-width: 3;"/><path data-c="6F" d="M28 214Q28 309 93 378T250 448Q340 448 405 380T471 215Q471 120 407 55T250 -10Q153 -10 91 57T28 214ZM250 30Q372 30 372 193V225V250Q372 272 371 288T364 326T348 362T317 390T268 410Q263 411 252 411Q222 411 195 399Q152 377 139 338T126 246V226Q126 130 145 91Q177 30 250 30Z" transform="translate(278,0)" style="stroke-width: 3;"/><path data-c="67" d="M329 409Q373 453 429 453Q459 453 472 434T485 396Q485 382 476 371T449 360Q416 360 412 390Q410 404 415 411Q415 412 416 414V415Q388 412 363 393Q355 388 355 386Q355 385 359 381T368 369T379 351T388 325T392 292Q392 230 343 187T222 143Q172 143 123 171Q112 153 112 133Q112 98 138 81Q147 75 155 75T227 73Q311 72 335 67Q396 58 431 26Q470 -13 470 -72Q470 -139 392 -175Q332 -206 250 -206Q167 -206 107 -175Q29 -140 29 -75Q29 -39 50 -15T92 18L103 24Q67 55 67 108Q67 155 96 193Q52 237 52 292Q52 355 102 398T223 442Q274 442 318 416L329 409ZM299 343Q294 371 273 387T221 404Q192 404 171 388T145 343Q142 326 142 292Q142 248 149 227T179 192Q196 182 222 182Q244 182 260 189T283 207T294 227T299 242Q302 258 302 292T299 343ZM403 -75Q403 -50 389 -34T348 -11T299 -2T245 0H218Q151 0 138 -6Q118 -15 107 -34T95 -74Q95 -84 101 -97T122 -127T170 -155T250 -167Q319 -167 361 -139T403 -75Z" transform="translate(778,0)" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(2430,0)"><path data-c="2061" d="" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(2596.7,0)"><path data-c="1D441" d="M234 637Q231 637 226 637Q201 637 196 638T191 649Q191 676 202 682Q204 683 299 683Q376 683 387 683T401 677Q612 181 616 168L670 381Q723 592 723 606Q723 633 659 637Q635 637 635 648Q635 650 637 660Q641 676 643 679T653 683Q656 683 684 682T767 680Q817 680 843 681T873 682Q888 682 888 672Q888 650 880 642Q878 637 858 637Q787 633 769 597L620 7Q618 0 599 0Q585 0 582 2Q579 5 453 305L326 604L261 344Q196 88 196 79Q201 46 268 46H278Q284 41 284 38T282 19Q278 6 272 0H259Q228 2 151 2Q123 2 100 2T63 2T46 1Q31 1 31 10Q31 14 34 26T39 40Q41 46 62 46Q130 49 150 85Q154 91 221 362L289 634Q287 635 234 637Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(3484.7,0)"><path data-c="29" d="M60 749L64 750Q69 750 74 750H86L114 726Q208 641 251 514T294 250Q294 182 284 119T261 12T224 -76T186 -143T145 -194T113 -227T90 -246Q87 -249 86 -250H74Q66 -250 63 -250T58 -247T55 -238Q56 -237 66 -225Q221 -64 221 250T66 725Q56 737 55 738Q55 746 60 749Z" style="stroke-width: 3;"/></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mi>O</mi><mo stretchy="false">(</mo><mi>log</mi><mo data-mjx-texclass="NONE">⁡</mo><mi>N</mi><mo stretchy="false">)</mo></math></mjx-assistive-mml></mjx-container>— y geométricamente exacta. Por eso, las pruebas de rayos por paso muestrean la malla bilinealmente en vez de consultar el máximo por texel de la pirámide, que elevaría las alturas varios metros en crestas pronunciadas. El descarte de chunks utiliza una prueba de cinco puntos y excluye la huella de cada propio chunk para que nunca se ocluya a sí mismo. El método de producción envía los metadatos y el campo de alturas a búferes de almacenamiento para realizar el descarte en un shader de cómputo con dibujo indirecto.</p>
<hr>
<p>Parte 28 de 29.
Anterior: <a href="/es/blog/2026-05-13-open-world-browser-part-27-island-and-terrain.html">Parte 27 - Una isla creada con ruido y un suelo que parece suelo</a>
Siguiente: <a href="/es/blog/2026-05-15-open-world-browser-part-29-pluggable-character.html">Parte 29 - Un controlador, cualquier cuerpo</a>
Guía de la serie: <a href="/es/blog/2026-02-25-open-world-browser-series-guide.html">/es/blog/2026-02-25-open-world-browser-series-guide</a></p>
]]></content:encoded>
            <enclosure url="https://cdn.cinevva.com/blog/why-webgpu-engine-hero.jpg" length="0" type="image/jpg"/>
        </item>
        <item>
            <title><![CDATA[Construir un mundo abierto en el navegador, parte 27: Una isla creada con ruido y un suelo que parece real]]></title>
            <link>https://app.cinevva.com/es/blog/2026-05-13-open-world-browser-part-27-island-and-terrain</link>
            <guid>https://app.cinevva.com/es/blog/2026-05-13-open-world-browser-part-27-island-and-terrain</guid>
            <pubDate>Wed, 13 May 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[El Spike 54 crea una isla creíble únicamente a partir de ruido: FBM con deformación de dominio modelado mediante una atenuación radial, seguido de erosión hidráulica que excava redes de drenaje reales y, por último, biomas asignados según la elevación y la humedad. El Spike 55 resuelve el problema más antiguo de las texturas, la tesela que se repite, con cuatro modos de muestreo y el que realmente gana.]]></description>
            <content:encoded><![CDATA[<h1 id="construir-un-mundo-abierto-en-el-navegador-parte-27-una-isla-creada-con-ruido-y-un-suelo-que-parece-real" tabindex="-1">Construir un mundo abierto en el navegador, parte 27: Una isla creada con ruido y un suelo que parece real <a class="header-anchor" href="#construir-un-mundo-abierto-en-el-navegador-parte-27-una-isla-creada-con-ruido-y-un-suelo-que-parece-real" aria-label="Permalink to &quot;Construir un mundo abierto en el navegador, parte 27: Una isla creada con ruido y un suelo que parece real&quot;"></a></h1>
<p><em>Por <a href="/es/about.html">Oleg Sidorkin</a>, CTO y cofundador de Cinevva</em></p>
<p>¿Acabas de llegar? Consulta la <a href="/es/blog/2026-02-25-open-world-browser-series-guide.html">guía de la serie</a>. Explica qué es un spike y contiene enlaces a todas las partes.</p>
<p>La <a href="/es/blog/2026-05-12-open-world-browser-part-26-water.html">parte 26</a> 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.</p>
<h2 id="una-costa-que-el-ruido-por-si-solo-no-puede-darte" tabindex="-1">Una costa que el ruido por sí solo no puede darte <a class="header-anchor" href="#una-costa-que-el-ruido-por-si-solo-no-puede-darte" aria-label="Permalink to &quot;Una costa que el ruido por sí solo no puede darte&quot;"></a></h2>
<div style="position:relative;padding-bottom:56.25%;height:0;overflow:hidden;border-radius:8px;margin:1.5rem 0;border:1px solid rgba(255,255,255,0.12)">
<iframe src="/es/spikes/54-procgen-island/" title="Spike 54: Isla procedural" style="position:absolute;top:0;left:0;width:100%;height:100%;border:0;background:#000" loading="lazy" allowfullscreen></iframe>
</div>
<p><a href="/es/spikes/54-procgen-island/" target="_blank">Abrir el Spike 54 en una pestaña nueva ↗</a> · <a href="/es/blog/spike-source?spike=54-procgen-island">Ver el código fuente</a></p>
<p>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, <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.566ex;" xmlns="http://www.w3.org/2000/svg" width="19.194ex" height="2.283ex" role="img" focusable="false" viewBox="0 -759 8483.9 1009" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="msup"><g data-mml-node="mi"><path data-c="1D45D" d="M23 287Q24 290 25 295T30 317T40 348T55 381T75 411T101 433T134 442Q209 442 230 378L240 387Q302 442 358 442Q423 442 460 395T497 281Q497 173 421 82T249 -10Q227 -10 210 -4Q199 1 187 11T168 28L161 36Q160 35 139 -51T118 -138Q118 -144 126 -145T163 -148H188Q194 -155 194 -157T191 -175Q188 -187 185 -190T172 -194Q170 -194 161 -194T127 -193T65 -192Q-5 -192 -24 -194H-32Q-39 -187 -39 -183Q-37 -156 -26 -148H-6Q28 -147 33 -136Q36 -130 94 103T155 350Q156 355 156 364Q156 405 131 405Q109 405 94 377T71 316T59 280Q57 278 43 278H29Q23 284 23 287ZM178 102Q200 26 252 26Q282 26 310 49T356 107Q374 141 392 215T411 325V331Q411 405 350 405Q339 405 328 402T306 393T286 380T269 365T254 350T243 336T235 326L232 322Q232 321 229 308T218 264T204 212Q178 106 178 102Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(536,363) scale(0.707)"><path data-c="2032" d="M79 43Q73 43 52 49T30 61Q30 68 85 293T146 528Q161 560 198 560Q218 560 240 545T262 501Q262 496 260 486Q259 479 173 263T84 45T79 43Z" style="stroke-width: 3;"/></g></g><g data-mml-node="mo" transform="translate(1058.2,0)"><path data-c="3D" d="M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(2114,0)"><path data-c="1D45D" d="M23 287Q24 290 25 295T30 317T40 348T55 381T75 411T101 433T134 442Q209 442 230 378L240 387Q302 442 358 442Q423 442 460 395T497 281Q497 173 421 82T249 -10Q227 -10 210 -4Q199 1 187 11T168 28L161 36Q160 35 139 -51T118 -138Q118 -144 126 -145T163 -148H188Q194 -155 194 -157T191 -175Q188 -187 185 -190T172 -194Q170 -194 161 -194T127 -193T65 -192Q-5 -192 -24 -194H-32Q-39 -187 -39 -183Q-37 -156 -26 -148H-6Q28 -147 33 -136Q36 -130 94 103T155 350Q156 355 156 364Q156 405 131 405Q109 405 94 377T71 316T59 280Q57 278 43 278H29Q23 284 23 287ZM178 102Q200 26 252 26Q282 26 310 49T356 107Q374 141 392 215T411 325V331Q411 405 350 405Q339 405 328 402T306 393T286 380T269 365T254 350T243 336T235 326L232 322Q232 321 229 308T218 264T204 212Q178 106 178 102Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(2839.2,0)"><path data-c="2B" d="M56 237T56 250T70 270H369V420L370 570Q380 583 389 583Q402 583 409 568V270H707Q722 262 722 250T707 230H409V-68Q401 -82 391 -82H389H387Q375 -82 369 -68V230H70Q56 237 56 250Z" style="stroke-width: 3;"/></g><g data-mml-node="mtext" transform="translate(3839.5,0)"><path data-c="6E" d="M41 46H55Q94 46 102 60V68Q102 77 102 91T102 122T103 161T103 203Q103 234 103 269T102 328V351Q99 370 88 376T43 385H25V408Q25 431 27 431L37 432Q47 433 65 434T102 436Q119 437 138 438T167 441T178 442H181V402Q181 364 182 364T187 369T199 384T218 402T247 421T285 437Q305 442 336 442Q450 438 463 329Q464 322 464 190V104Q464 66 466 59T477 49Q498 46 526 46H542V0H534L510 1Q487 2 460 2T422 3Q319 3 310 0H302V46H318Q379 46 379 62Q380 64 380 200Q379 335 378 343Q372 371 358 385T334 402T308 404Q263 404 229 370Q202 343 195 315T187 232V168V108Q187 78 188 68T191 55T200 49Q221 46 249 46H265V0H257L234 1Q210 2 183 2T145 3Q42 3 33 0H25V46H41Z" style="stroke-width: 3;"/><path data-c="6F" d="M28 214Q28 309 93 378T250 448Q340 448 405 380T471 215Q471 120 407 55T250 -10Q153 -10 91 57T28 214ZM250 30Q372 30 372 193V225V250Q372 272 371 288T364 326T348 362T317 390T268 410Q263 411 252 411Q222 411 195 399Q152 377 139 338T126 246V226Q126 130 145 91Q177 30 250 30Z" transform="translate(556,0)" style="stroke-width: 3;"/><path data-c="69" d="M69 609Q69 637 87 653T131 669Q154 667 171 652T188 609Q188 579 171 564T129 549Q104 549 87 564T69 609ZM247 0Q232 3 143 3Q132 3 106 3T56 1L34 0H26V46H42Q70 46 91 49Q100 53 102 60T104 102V205V293Q104 345 102 359T88 378Q74 385 41 385H30V408Q30 431 32 431L42 432Q52 433 70 434T106 436Q123 437 142 438T171 441T182 442H185V62Q190 52 197 50T232 46H255V0H247Z" transform="translate(1056,0)" style="stroke-width: 3;"/><path data-c="73" d="M295 316Q295 356 268 385T190 414Q154 414 128 401Q98 382 98 349Q97 344 98 336T114 312T157 287Q175 282 201 278T245 269T277 256Q294 248 310 236T342 195T359 133Q359 71 321 31T198 -10H190Q138 -10 94 26L86 19L77 10Q71 4 65 -1L54 -11H46H42Q39 -11 33 -5V74V132Q33 153 35 157T45 162H54Q66 162 70 158T75 146T82 119T101 77Q136 26 198 26Q295 26 295 104Q295 133 277 151Q257 175 194 187T111 210Q75 227 54 256T33 318Q33 357 50 384T93 424T143 442T187 447H198Q238 447 268 432L283 424L292 431Q302 440 314 448H322H326Q329 448 335 442V310L329 304H301Q295 310 295 316Z" transform="translate(1334,0)" style="stroke-width: 3;"/><path data-c="65" d="M28 218Q28 273 48 318T98 391T163 433T229 448Q282 448 320 430T378 380T406 316T415 245Q415 238 408 231H126V216Q126 68 226 36Q246 30 270 30Q312 30 342 62Q359 79 369 104L379 128Q382 131 395 131H398Q415 131 415 121Q415 117 412 108Q393 53 349 21T250 -11Q155 -11 92 58T28 218ZM333 275Q322 403 238 411H236Q228 411 220 410T195 402T166 381T143 340T127 274V267H333V275Z" transform="translate(1728,0)" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(6011.5,0)"><path data-c="28" d="M94 250Q94 319 104 381T127 488T164 576T202 643T244 695T277 729T302 750H315H319Q333 750 333 741Q333 738 316 720T275 667T226 581T184 443T167 250T184 58T225 -81T274 -167T316 -220T333 -241Q333 -250 318 -250H315H302L274 -226Q180 -141 137 -14T94 250Z" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(6400.5,0)"><path data-c="1D45D" d="M23 287Q24 290 25 295T30 317T40 348T55 381T75 411T101 433T134 442Q209 442 230 378L240 387Q302 442 358 442Q423 442 460 395T497 281Q497 173 421 82T249 -10Q227 -10 210 -4Q199 1 187 11T168 28L161 36Q160 35 139 -51T118 -138Q118 -144 126 -145T163 -148H188Q194 -155 194 -157T191 -175Q188 -187 185 -190T172 -194Q170 -194 161 -194T127 -193T65 -192Q-5 -192 -24 -194H-32Q-39 -187 -39 -183Q-37 -156 -26 -148H-6Q28 -147 33 -136Q36 -130 94 103T155 350Q156 355 156 364Q156 405 131 405Q109 405 94 377T71 316T59 280Q57 278 43 278H29Q23 284 23 287ZM178 102Q200 26 252 26Q282 26 310 49T356 107Q374 141 392 215T411 325V331Q411 405 350 405Q339 405 328 402T306 393T286 380T269 365T254 350T243 336T235 326L232 322Q232 321 229 308T218 264T204 212Q178 106 178 102Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(6903.5,0)"><path data-c="29" d="M60 749L64 750Q69 750 74 750H86L114 726Q208 641 251 514T294 250Q294 182 284 119T261 12T224 -76T186 -143T145 -194T113 -227T90 -246Q87 -249 86 -250H74Q66 -250 63 -250T58 -247T55 -238Q56 -237 66 -225Q221 -64 221 250T66 725Q56 737 55 738Q55 746 60 749Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(7514.7,0)"><path data-c="22C5" d="M78 250Q78 274 95 292T138 310Q162 310 180 294T199 251Q199 226 182 208T139 190T96 207T78 250Z" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(8014.9,0)"><path data-c="1D460" d="M131 289Q131 321 147 354T203 415T300 442Q362 442 390 415T419 355Q419 323 402 308T364 292Q351 292 340 300T328 326Q328 342 337 354T354 372T367 378Q368 378 368 379Q368 382 361 388T336 399T297 405Q249 405 227 379T204 326Q204 301 223 291T278 274T330 259Q396 230 396 163Q396 135 385 107T352 51T289 7T195 -10Q118 -10 86 19T53 87Q53 126 74 143T118 160Q133 160 146 151T160 120Q160 94 142 76T111 58Q109 57 108 57T107 55Q108 52 115 47T146 34T201 27Q237 27 263 38T301 66T318 97T323 122Q323 150 302 164T254 181T195 196T148 231Q131 256 131 289Z" style="stroke-width: 3;"/></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><msup><mi>p</mi><mo data-mjx-alternate="1">′</mo></msup><mo>=</mo><mi>p</mi><mo>+</mo><mtext>noise</mtext><mo stretchy="false">(</mo><mi>p</mi><mo stretchy="false">)</mo><mo>⋅</mo><mi>s</mi></math></mjx-assistive-mml></mjx-container>, 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 <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.025ex;" xmlns="http://www.w3.org/2000/svg" width="2.453ex" height="1.956ex" role="img" focusable="false" viewBox="0 -853.7 1084.4 864.7" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="msup"><g data-mml-node="mi"><path data-c="1D452" d="M39 168Q39 225 58 272T107 350T174 402T244 433T307 442H310Q355 442 388 420T421 355Q421 265 310 237Q261 224 176 223Q139 223 138 221Q138 219 132 186T125 128Q125 81 146 54T209 26T302 45T394 111Q403 121 406 121Q410 121 419 112T429 98T420 82T390 55T344 24T281 -1T205 -11Q126 -11 83 42T39 168ZM373 353Q367 405 305 405Q272 405 244 391T199 357T170 316T154 280T149 261Q149 260 169 260Q282 260 327 284T373 353Z" style="stroke-width: 3;"/></g><g data-mml-node="TeXAtom" transform="translate(499,363) scale(0.707)" data-mjx-texclass="ORD"><g data-mml-node="mstyle" transform="scale(1.414)"><g data-mml-node="mspace"/></g><g data-mml-node="mi" transform="translate(236.2,0)"><path data-c="1D458" d="M121 647Q121 657 125 670T137 683Q138 683 209 688T282 694Q294 694 294 686Q294 679 244 477Q194 279 194 272Q213 282 223 291Q247 309 292 354T362 415Q402 442 438 442Q468 442 485 423T503 369Q503 344 496 327T477 302T456 291T438 288Q418 288 406 299T394 328Q394 353 410 369T442 390L458 393Q446 405 434 405H430Q398 402 367 380T294 316T228 255Q230 254 243 252T267 246T293 238T320 224T342 206T359 180T365 147Q365 130 360 106T354 66Q354 26 381 26Q429 26 459 145Q461 153 479 153H483Q499 153 499 144Q499 139 496 130Q455 -11 378 -11Q333 -11 305 15T277 90Q277 108 280 121T283 145Q283 167 269 183T234 206T200 217T182 220H180Q168 178 159 139T145 81T136 44T129 20T122 7T111 -2Q98 -11 83 -11Q66 -11 57 -1T48 16Q48 26 85 176T158 471L195 616Q196 629 188 632T149 637H144Q134 637 131 637T124 640T121 647Z" style="stroke-width: 3;"/></g></g></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><msup><mi>e</mi><mrow data-mjx-texclass="ORD"><mstyle scriptlevel="0"><mspace width="0.167em"/></mstyle><mi>k</mi></mrow></msup></math></mjx-assistive-mml></mjx-container>, 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, <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -1.467ex;" xmlns="http://www.w3.org/2000/svg" width="21.741ex" height="4.208ex" role="img" focusable="false" viewBox="0 -1211.5 9609.7 1860" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mi"><path data-c="1D451" d="M366 683Q367 683 438 688T511 694Q523 694 523 686Q523 679 450 384T375 83T374 68Q374 26 402 26Q411 27 422 35Q443 55 463 131Q469 151 473 152Q475 153 483 153H487H491Q506 153 506 145Q506 140 503 129Q490 79 473 48T445 8T417 -8Q409 -10 393 -10Q359 -10 336 5T306 36L300 51Q299 52 296 50Q294 48 292 46Q233 -10 172 -10Q117 -10 75 30T33 157Q33 205 53 255T101 341Q148 398 195 420T280 442Q336 442 364 400Q369 394 369 396Q370 400 396 505T424 616Q424 629 417 632T378 637H357Q351 643 351 645T353 664Q358 683 366 683ZM352 326Q329 405 277 405Q242 405 210 374T160 293Q131 214 119 129Q119 126 119 118T118 106Q118 61 136 44T179 26Q233 26 290 98L298 109L352 326Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(797.8,0)"><path data-c="3D" d="M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(1853.6,0)"><path data-c="6D" d="M41 46H55Q94 46 102 60V68Q102 77 102 91T102 122T103 161T103 203Q103 234 103 269T102 328V351Q99 370 88 376T43 385H25V408Q25 431 27 431L37 432Q47 433 65 434T102 436Q119 437 138 438T167 441T178 442H181V402Q181 364 182 364T187 369T199 384T218 402T247 421T285 437Q305 442 336 442Q351 442 364 440T387 434T406 426T421 417T432 406T441 395T448 384T452 374T455 366L457 361L460 365Q463 369 466 373T475 384T488 397T503 410T523 422T546 432T572 439T603 442Q729 442 740 329Q741 322 741 190V104Q741 66 743 59T754 49Q775 46 803 46H819V0H811L788 1Q764 2 737 2T699 3Q596 3 587 0H579V46H595Q656 46 656 62Q657 64 657 200Q656 335 655 343Q649 371 635 385T611 402T585 404Q540 404 506 370Q479 343 472 315T464 232V168V108Q464 78 465 68T468 55T477 49Q498 46 526 46H542V0H534L510 1Q487 2 460 2T422 3Q319 3 310 0H302V46H318Q379 46 379 62Q380 64 380 200Q379 335 378 343Q372 371 358 385T334 402T308 404Q263 404 229 370Q202 343 195 315T187 232V168V108Q187 78 188 68T191 55T200 49Q221 46 249 46H265V0H257L234 1Q210 2 183 2T145 3Q42 3 33 0H25V46H41Z" style="stroke-width: 3;"/><path data-c="69" d="M69 609Q69 637 87 653T131 669Q154 667 171 652T188 609Q188 579 171 564T129 549Q104 549 87 564T69 609ZM247 0Q232 3 143 3Q132 3 106 3T56 1L34 0H26V46H42Q70 46 91 49Q100 53 102 60T104 102V205V293Q104 345 102 359T88 378Q74 385 41 385H30V408Q30 431 32 431L42 432Q52 433 70 434T106 436Q123 437 142 438T171 441T182 442H185V62Q190 52 197 50T232 46H255V0H247Z" transform="translate(833,0)" style="stroke-width: 3;"/><path data-c="6E" d="M41 46H55Q94 46 102 60V68Q102 77 102 91T102 122T103 161T103 203Q103 234 103 269T102 328V351Q99 370 88 376T43 385H25V408Q25 431 27 431L37 432Q47 433 65 434T102 436Q119 437 138 438T167 441T178 442H181V402Q181 364 182 364T187 369T199 384T218 402T247 421T285 437Q305 442 336 442Q450 438 463 329Q464 322 464 190V104Q464 66 466 59T477 49Q498 46 526 46H542V0H534L510 1Q487 2 460 2T422 3Q319 3 310 0H302V46H318Q379 46 379 62Q380 64 380 200Q379 335 378 343Q372 371 358 385T334 402T308 404Q263 404 229 370Q202 343 195 315T187 232V168V108Q187 78 188 68T191 55T200 49Q221 46 249 46H265V0H257L234 1Q210 2 183 2T145 3Q42 3 33 0H25V46H41Z" transform="translate(1111,0)" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(3520.6,0)"><path data-c="28" d="M94 250Q94 319 104 381T127 488T164 576T202 643T244 695T277 729T302 750H315H319Q333 750 333 741Q333 738 316 720T275 667T226 581T184 443T167 250T184 58T225 -81T274 -167T316 -220T333 -241Q333 -250 318 -250H315H302L274 -226Q180 -141 137 -14T94 250Z" style="stroke-width: 3;"/></g><g data-mml-node="mn" transform="translate(3909.6,0)"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(4409.6,0)"><path data-c="2C" d="M78 35T78 60T94 103T137 121Q165 121 187 96T210 8Q210 -27 201 -60T180 -117T154 -158T130 -185T117 -194Q113 -194 104 -185T95 -172Q95 -168 106 -156T131 -126T157 -76T173 -3V9L172 8Q170 7 167 6T161 3T152 1T140 0Q113 0 96 17Z" style="stroke-width: 3;"/></g><g data-mml-node="msqrt" transform="translate(4854.2,0)"><g transform="translate(1020,0)"><g data-mml-node="msubsup"><g data-mml-node="mi"><path data-c="1D45B" d="M21 287Q22 293 24 303T36 341T56 388T89 425T135 442Q171 442 195 424T225 390T231 369Q231 367 232 367L243 378Q304 442 382 442Q436 442 469 415T503 336T465 179T427 52Q427 26 444 26Q450 26 453 27Q482 32 505 65T540 145Q542 153 560 153Q580 153 580 145Q580 144 576 130Q568 101 554 73T508 17T439 -10Q392 -10 371 17T350 73Q350 92 386 193T423 345Q423 404 379 404H374Q288 404 229 303L222 291L189 157Q156 26 151 16Q138 -11 108 -11Q95 -11 87 -5T76 7T74 17Q74 30 112 180T152 343Q153 348 153 366Q153 405 129 405Q91 405 66 305Q60 285 60 284Q58 278 41 278H27Q21 284 21 287Z" style="stroke-width: 3;"/></g><g data-mml-node="mn" transform="translate(633,289) scale(0.707)"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(633,-247) scale(0.707)"><path data-c="1D465" d="M52 289Q59 331 106 386T222 442Q257 442 286 424T329 379Q371 442 430 442Q467 442 494 420T522 361Q522 332 508 314T481 292T458 288Q439 288 427 299T415 328Q415 374 465 391Q454 404 425 404Q412 404 406 402Q368 386 350 336Q290 115 290 78Q290 50 306 38T341 26Q378 26 414 59T463 140Q466 150 469 151T485 153H489Q504 153 504 145Q504 144 502 134Q486 77 440 33T333 -11Q263 -11 227 52Q186 -10 133 -10H127Q78 -10 57 16T35 71Q35 103 54 123T99 143Q142 143 142 101Q142 81 130 66T107 46T94 41L91 40Q91 39 97 36T113 29T132 26Q168 26 194 71Q203 87 217 139T245 247T261 313Q266 340 266 352Q266 380 251 392T217 404Q177 404 142 372T93 290Q91 281 88 280T72 278H58Q52 284 52 289Z" style="stroke-width: 3;"/></g></g><g data-mml-node="mo" transform="translate(1309.7,0)"><path data-c="2B" d="M56 237T56 250T70 270H369V420L370 570Q380 583 389 583Q402 583 409 568V270H707Q722 262 722 250T707 230H409V-68Q401 -82 391 -82H389H387Q375 -82 369 -68V230H70Q56 237 56 250Z" style="stroke-width: 3;"/></g><g data-mml-node="msubsup" transform="translate(2309.9,0)"><g data-mml-node="mi"><path data-c="1D45B" d="M21 287Q22 293 24 303T36 341T56 388T89 425T135 442Q171 442 195 424T225 390T231 369Q231 367 232 367L243 378Q304 442 382 442Q436 442 469 415T503 336T465 179T427 52Q427 26 444 26Q450 26 453 27Q482 32 505 65T540 145Q542 153 560 153Q580 153 580 145Q580 144 576 130Q568 101 554 73T508 17T439 -10Q392 -10 371 17T350 73Q350 92 386 193T423 345Q423 404 379 404H374Q288 404 229 303L222 291L189 157Q156 26 151 16Q138 -11 108 -11Q95 -11 87 -5T76 7T74 17Q74 30 112 180T152 343Q153 348 153 366Q153 405 129 405Q91 405 66 305Q60 285 60 284Q58 278 41 278H27Q21 284 21 287Z" style="stroke-width: 3;"/></g><g data-mml-node="mn" transform="translate(633,289) scale(0.707)"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(633,-247) scale(0.707)"><path data-c="1D466" d="M21 287Q21 301 36 335T84 406T158 442Q199 442 224 419T250 355Q248 336 247 334Q247 331 231 288T198 191T182 105Q182 62 196 45T238 27Q261 27 281 38T312 61T339 94Q339 95 344 114T358 173T377 247Q415 397 419 404Q432 431 462 431Q475 431 483 424T494 412T496 403Q496 390 447 193T391 -23Q363 -106 294 -155T156 -205Q111 -205 77 -183T43 -117Q43 -95 50 -80T69 -58T89 -48T106 -45Q150 -45 150 -87Q150 -107 138 -122T115 -142T102 -147L99 -148Q101 -153 118 -160T152 -167H160Q177 -167 186 -165Q219 -156 247 -127T290 -65T313 -9T321 21L315 17Q309 13 296 6T270 -6Q250 -11 231 -11Q185 -11 150 11T104 82Q103 89 103 113Q103 170 138 262T173 379Q173 380 173 381Q173 390 173 393T169 400T158 404H154Q131 404 112 385T82 344T65 302T57 280Q55 278 41 278H27Q21 284 21 287Z" style="stroke-width: 3;"/></g></g></g><g data-mml-node="mo" transform="translate(0,1.5)"><path data-c="221A" d="M1001 1150Q1017 1150 1020 1132Q1020 1127 741 244L460 -643Q453 -650 436 -650H424Q423 -647 423 -645T421 -640T419 -631T415 -617T408 -594T399 -560T385 -512T367 -448T343 -364T312 -259L203 119L138 41L111 67L212 188L264 248L472 -474L983 1140Q988 1150 1001 1150Z" style="stroke-width: 3;"/></g><rect width="3346.5" height="60" x="1020" y="1091.5"/></g><g data-mml-node="mo" transform="translate(9220.7,0)"><path data-c="29" d="M60 749L64 750Q69 750 74 750H86L114 726Q208 641 251 514T294 250Q294 182 284 119T261 12T224 -76T186 -143T145 -194T113 -227T90 -246Q87 -249 86 -250H74Q66 -250 63 -250T58 -247T55 -238Q56 -237 66 -225Q221 -64 221 250T66 725Q56 737 55 738Q55 746 60 749Z" style="stroke-width: 3;"/></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mi>d</mi><mo>=</mo><mo data-mjx-texclass="OP" movablelimits="true">min</mo><mo stretchy="false">(</mo><mn>1</mn><mo>,</mo><msqrt><msubsup><mi>n</mi><mi>x</mi><mn>2</mn></msubsup><mo>+</mo><msubsup><mi>n</mi><mi>y</mi><mn>2</mn></msubsup></msqrt><mo stretchy="false">)</mo></math></mjx-assistive-mml></mjx-container>, y se mezcla la elevación hacia <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.186ex;" xmlns="http://www.w3.org/2000/svg" width="5.073ex" height="1.756ex" role="img" focusable="false" viewBox="0 -694 2242.4 776" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mn"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(722.2,0)"><path data-c="2212" d="M84 237T84 250T98 270H679Q694 262 694 250T679 230H98Q84 237 84 250Z" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(1722.4,0)"><path data-c="1D451" d="M366 683Q367 683 438 688T511 694Q523 694 523 686Q523 679 450 384T375 83T374 68Q374 26 402 26Q411 27 422 35Q443 55 463 131Q469 151 473 152Q475 153 483 153H487H491Q506 153 506 145Q506 140 503 129Q490 79 473 48T445 8T417 -8Q409 -10 393 -10Q359 -10 336 5T306 36L300 51Q299 52 296 50Q294 48 292 46Q233 -10 172 -10Q117 -10 75 30T33 157Q33 205 53 255T101 341Q148 398 195 420T280 442Q336 442 364 400Q369 394 369 396Q370 400 396 505T424 616Q424 629 417 632T378 637H357Q351 643 351 645T353 664Q358 683 366 683ZM352 326Q329 405 277 405Q242 405 210 374T160 293Q131 214 119 129Q119 126 119 118T118 106Q118 61 136 44T179 26Q233 26 290 98L298 109L352 326Z" style="stroke-width: 3;"/></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mn>1</mn><mo>−</mo><mi>d</mi></math></mjx-assistive-mml></mjx-container> 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.</p>
<p>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.</p>
<h2 id="erosion-en-la-gpu-y-rios-que-saben-donde-estan" tabindex="-1">Erosión en la GPU y ríos que saben dónde están <a class="header-anchor" href="#erosion-en-la-gpu-y-rios-que-saben-donde-estan" aria-label="Permalink to &quot;Erosión en la GPU y ríos que saben dónde están&quot;"></a></h2>
<p>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 <code>i32</code> 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 <code>atomicAdd</code> y <code>atomicSub</code> 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 <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.05ex;" xmlns="http://www.w3.org/2000/svg" width="5.513ex" height="2.005ex" role="img" focusable="false" viewBox="0 -864 2436.6 886" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="msup"><g data-mml-node="mn"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" style="stroke-width: 3;"/><path data-c="30" d="M96 585Q152 666 249 666Q297 666 345 640T423 548Q460 465 460 320Q460 165 417 83Q397 41 362 16T301 -15T250 -22Q224 -22 198 -16T137 16T82 83Q39 165 39 320Q39 494 96 585ZM321 597Q291 629 250 629Q208 629 178 597Q153 571 145 525T137 333Q137 175 145 125T181 46Q209 16 250 16Q290 16 318 46Q347 76 354 130T362 333Q362 478 354 524T321 597Z" transform="translate(500,0)" style="stroke-width: 3;"/><path data-c="30" d="M96 585Q152 666 249 666Q297 666 345 640T423 548Q460 465 460 320Q460 165 417 83Q397 41 362 16T301 -15T250 -22Q224 -22 198 -16T137 16T82 83Q39 165 39 320Q39 494 96 585ZM321 597Q291 629 250 629Q208 629 178 597Q153 571 145 525T137 333Q137 175 145 125T181 46Q209 16 250 16Q290 16 318 46Q347 76 354 130T362 333Q362 478 354 524T321 597Z" transform="translate(1000,0)" style="stroke-width: 3;"/><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" transform="translate(1500,0)" style="stroke-width: 3;"/></g><g data-mml-node="mn" transform="translate(2033,393.1) scale(0.707)"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"/></g></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><msup><mn>1001</mn><mn>2</mn></msup></math></mjx-assistive-mml></mjx-container> 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.</p>
<p>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, <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.466ex;" xmlns="http://www.w3.org/2000/svg" width="17.709ex" height="2.036ex" role="img" focusable="false" viewBox="0 -694 7827.4 900" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mtext"><path data-c="6D" d="M41 46H55Q94 46 102 60V68Q102 77 102 91T102 122T103 161T103 203Q103 234 103 269T102 328V351Q99 370 88 376T43 385H25V408Q25 431 27 431L37 432Q47 433 65 434T102 436Q119 437 138 438T167 441T178 442H181V402Q181 364 182 364T187 369T199 384T218 402T247 421T285 437Q305 442 336 442Q351 442 364 440T387 434T406 426T421 417T432 406T441 395T448 384T452 374T455 366L457 361L460 365Q463 369 466 373T475 384T488 397T503 410T523 422T546 432T572 439T603 442Q729 442 740 329Q741 322 741 190V104Q741 66 743 59T754 49Q775 46 803 46H819V0H811L788 1Q764 2 737 2T699 3Q596 3 587 0H579V46H595Q656 46 656 62Q657 64 657 200Q656 335 655 343Q649 371 635 385T611 402T585 404Q540 404 506 370Q479 343 472 315T464 232V168V108Q464 78 465 68T468 55T477 49Q498 46 526 46H542V0H534L510 1Q487 2 460 2T422 3Q319 3 310 0H302V46H318Q379 46 379 62Q380 64 380 200Q379 335 378 343Q372 371 358 385T334 402T308 404Q263 404 229 370Q202 343 195 315T187 232V168V108Q187 78 188 68T191 55T200 49Q221 46 249 46H265V0H257L234 1Q210 2 183 2T145 3Q42 3 33 0H25V46H41Z" style="stroke-width: 3;"/><path data-c="69" d="M69 609Q69 637 87 653T131 669Q154 667 171 652T188 609Q188 579 171 564T129 549Q104 549 87 564T69 609ZM247 0Q232 3 143 3Q132 3 106 3T56 1L34 0H26V46H42Q70 46 91 49Q100 53 102 60T104 102V205V293Q104 345 102 359T88 378Q74 385 41 385H30V408Q30 431 32 431L42 432Q52 433 70 434T106 436Q123 437 142 438T171 441T182 442H185V62Q190 52 197 50T232 46H255V0H247Z" transform="translate(833,0)" style="stroke-width: 3;"/><path data-c="6E" d="M41 46H55Q94 46 102 60V68Q102 77 102 91T102 122T103 161T103 203Q103 234 103 269T102 328V351Q99 370 88 376T43 385H25V408Q25 431 27 431L37 432Q47 433 65 434T102 436Q119 437 138 438T167 441T178 442H181V402Q181 364 182 364T187 369T199 384T218 402T247 421T285 437Q305 442 336 442Q450 438 463 329Q464 322 464 190V104Q464 66 466 59T477 49Q498 46 526 46H542V0H534L510 1Q487 2 460 2T422 3Q319 3 310 0H302V46H318Q379 46 379 62Q380 64 380 200Q379 335 378 343Q372 371 358 385T334 402T308 404Q263 404 229 370Q202 343 195 315T187 232V168V108Q187 78 188 68T191 55T200 49Q221 46 249 46H265V0H257L234 1Q210 2 183 2T145 3Q42 3 33 0H25V46H41Z" transform="translate(1111,0)" style="stroke-width: 3;"/><path data-c="4E" d="M42 46Q74 48 94 56T118 69T128 86V634H124Q114 637 52 637H25V683H232L235 680Q237 679 322 554T493 303L578 178V598Q572 608 568 613T544 627T492 637H475V683H483Q498 680 600 680Q706 680 715 683H724V637H707Q634 633 622 598L621 302V6L614 0H600Q585 0 582 3T481 150T282 443T171 605V345L172 86Q183 50 257 46H274V0H265Q250 3 150 3Q48 3 33 0H25V46H42Z" transform="translate(1667,0)" style="stroke-width: 3;"/><path data-c="65" d="M28 218Q28 273 48 318T98 391T163 433T229 448Q282 448 320 430T378 380T406 316T415 245Q415 238 408 231H126V216Q126 68 226 36Q246 30 270 30Q312 30 342 62Q359 79 369 104L379 128Q382 131 395 131H398Q415 131 415 121Q415 117 412 108Q393 53 349 21T250 -11Q155 -11 92 58T28 218ZM333 275Q322 403 238 411H236Q228 411 220 410T195 402T166 381T143 340T127 274V267H333V275Z" transform="translate(2417,0)" style="stroke-width: 3;"/><path data-c="69" d="M69 609Q69 637 87 653T131 669Q154 667 171 652T188 609Q188 579 171 564T129 549Q104 549 87 564T69 609ZM247 0Q232 3 143 3Q132 3 106 3T56 1L34 0H26V46H42Q70 46 91 49Q100 53 102 60T104 102V205V293Q104 345 102 359T88 378Q74 385 41 385H30V408Q30 431 32 431L42 432Q52 433 70 434T106 436Q123 437 142 438T171 441T182 442H185V62Q190 52 197 50T232 46H255V0H247Z" transform="translate(2861,0)" style="stroke-width: 3;"/><path data-c="67" d="M329 409Q373 453 429 453Q459 453 472 434T485 396Q485 382 476 371T449 360Q416 360 412 390Q410 404 415 411Q415 412 416 414V415Q388 412 363 393Q355 388 355 386Q355 385 359 381T368 369T379 351T388 325T392 292Q392 230 343 187T222 143Q172 143 123 171Q112 153 112 133Q112 98 138 81Q147 75 155 75T227 73Q311 72 335 67Q396 58 431 26Q470 -13 470 -72Q470 -139 392 -175Q332 -206 250 -206Q167 -206 107 -175Q29 -140 29 -75Q29 -39 50 -15T92 18L103 24Q67 55 67 108Q67 155 96 193Q52 237 52 292Q52 355 102 398T223 442Q274 442 318 416L329 409ZM299 343Q294 371 273 387T221 404Q192 404 171 388T145 343Q142 326 142 292Q142 248 149 227T179 192Q196 182 222 182Q244 182 260 189T283 207T294 227T299 242Q302 258 302 292T299 343ZM403 -75Q403 -50 389 -34T348 -11T299 -2T245 0H218Q151 0 138 -6Q118 -15 107 -34T95 -74Q95 -84 101 -97T122 -127T170 -155T250 -167Q319 -167 361 -139T403 -75Z" transform="translate(3139,0)" style="stroke-width: 3;"/><path data-c="68" d="M41 46H55Q94 46 102 60V68Q102 77 102 91T102 124T102 167T103 217T103 272T103 329Q103 366 103 407T103 482T102 542T102 586T102 603Q99 622 88 628T43 637H25V660Q25 683 27 683L37 684Q47 685 66 686T103 688Q120 689 140 690T170 693T181 694H184V367Q244 442 328 442Q451 442 463 329Q464 322 464 190V104Q464 66 466 59T477 49Q498 46 526 46H542V0H534L510 1Q487 2 460 2T422 3Q319 3 310 0H302V46H318Q379 46 379 62Q380 64 380 200Q379 335 378 343Q372 371 358 385T334 402T308 404Q263 404 229 370Q202 343 195 315T187 232V168V108Q187 78 188 68T191 55T200 49Q221 46 249 46H265V0H257L234 1Q210 2 183 2T145 3Q42 3 33 0H25V46H41Z" transform="translate(3639,0)" style="stroke-width: 3;"/><path data-c="62" d="M307 -11Q234 -11 168 55L158 37Q156 34 153 28T147 17T143 10L138 1L118 0H98V298Q98 599 97 603Q94 622 83 628T38 637H20V660Q20 683 22 683L32 684Q42 685 61 686T98 688Q115 689 135 690T165 693T176 694H179V543Q179 391 180 391L183 394Q186 397 192 401T207 411T228 421T254 431T286 439T323 442Q401 442 461 379T522 216Q522 115 458 52T307 -11ZM182 98Q182 97 187 90T196 79T206 67T218 55T233 44T250 35T271 29T295 26Q330 26 363 46T412 113Q424 148 424 212Q424 287 412 323Q385 405 300 405Q270 405 239 390T188 347L182 339V98Z" transform="translate(4195,0)" style="stroke-width: 3;"/><path data-c="6F" d="M28 214Q28 309 93 378T250 448Q340 448 405 380T471 215Q471 120 407 55T250 -10Q153 -10 91 57T28 214ZM250 30Q372 30 372 193V225V250Q372 272 371 288T364 326T348 362T317 390T268 410Q263 411 252 411Q222 411 195 399Q152 377 139 338T126 246V226Q126 130 145 91Q177 30 250 30Z" transform="translate(4751,0)" style="stroke-width: 3;"/><path data-c="75" d="M383 58Q327 -10 256 -10H249Q124 -10 105 89Q104 96 103 226Q102 335 102 348T96 369Q86 385 36 385H25V408Q25 431 27 431L38 432Q48 433 67 434T105 436Q122 437 142 438T172 441T184 442H187V261Q188 77 190 64Q193 49 204 40Q224 26 264 26Q290 26 311 35T343 58T363 90T375 120T379 144Q379 145 379 161T380 201T380 248V315Q380 361 370 372T320 385H302V431Q304 431 378 436T457 442H464V264Q464 84 465 81Q468 61 479 55T524 46H542V0Q540 0 467 -5T390 -11H383V58Z" transform="translate(5251,0)" style="stroke-width: 3;"/><path data-c="72" d="M36 46H50Q89 46 97 60V68Q97 77 97 91T98 122T98 161T98 203Q98 234 98 269T98 328L97 351Q94 370 83 376T38 385H20V408Q20 431 22 431L32 432Q42 433 60 434T96 436Q112 437 131 438T160 441T171 442H174V373Q213 441 271 441H277Q322 441 343 419T364 373Q364 352 351 337T313 322Q288 322 276 338T263 372Q263 381 265 388T270 400T273 405Q271 407 250 401Q234 393 226 386Q179 341 179 207V154Q179 141 179 127T179 101T180 81T180 66V61Q181 59 183 57T188 54T193 51T200 49T207 48T216 47T225 47T235 46T245 46H276V0H267Q249 3 140 3Q37 3 28 0H20V46H36Z" transform="translate(5807,0)" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(6421.2,0)"><path data-c="2B" d="M56 237T56 250T70 270H369V420L370 570Q380 583 389 583Q402 583 409 568V270H707Q722 262 722 250T707 230H409V-68Q401 -82 391 -82H389H387Q375 -82 369 -68V230H70Q56 237 56 250Z" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(7421.4,0)"><path data-c="1D716" d="M227 -11Q149 -11 95 41T40 174Q40 262 87 322Q121 367 173 396T287 430Q289 431 329 431H367Q382 426 382 411Q382 385 341 385H325H312Q191 385 154 277L150 265H327Q340 256 340 246Q340 228 320 219H138V217Q128 187 128 143Q128 77 160 52T231 26Q258 26 284 36T326 57T343 68Q350 68 354 58T358 39Q358 36 357 35Q354 31 337 21T289 0T227 -11Z" style="stroke-width: 3;"/></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mtext>minNeighbour</mtext><mo>+</mo><mi>ϵ</mi></math></mjx-assistive-mml></mjx-container>, 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.</p>
<h2 id="la-tesela-que-no-deja-de-repetirse" tabindex="-1">La tesela que no deja de repetirse <a class="header-anchor" href="#la-tesela-que-no-deja-de-repetirse" aria-label="Permalink to &quot;La tesela que no deja de repetirse&quot;"></a></h2>
<div style="position:relative;padding-bottom:56.25%;height:0;overflow:hidden;border-radius:8px;margin:1.5rem 0;border:1px solid rgba(255,255,255,0.12)">
<iframe src="/es/spikes/55-terrain-shading/" title="Spike 55: Sombreado del terreno" style="position:absolute;top:0;left:0;width:100%;height:100%;border:0;background:#000" loading="lazy" allowfullscreen></iframe>
</div>
<p><a href="/es/spikes/55-terrain-shading/" target="_blank">Abrir el Spike 55 en una pestaña nueva ↗</a> · <a href="/es/blog/spike-source?spike=55-terrain-shading">Ver el código fuente</a></p>
<p>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 <code>plain</code>: 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.</p>
<p>Los otros tres modos son distintos ataques contra la repetición. El modo <code>hex-linear</code> 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 <code>hex-vp</code> 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, <code>iq-untiled</code>, 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.</p>
<p>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 <code>abs(normalWorld)</code> 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.</p>
<h2 id="tecnologia-mencionada-en-este-capitulo" tabindex="-1">Tecnología mencionada en este capítulo <a class="header-anchor" href="#tecnologia-mencionada-en-este-capitulo" aria-label="Permalink to &quot;Tecnología mencionada en este capítulo&quot;"></a></h2>
<p><strong>Generación de mapas de alturas mediante recetas apiladas.</strong> Las recetas de Red Blob Games combinan ruido sin procesar para convertirlo en terreno: FBM con deformación de dominio (<mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.566ex;" xmlns="http://www.w3.org/2000/svg" width="19.194ex" height="2.283ex" role="img" focusable="false" viewBox="0 -759 8483.9 1009" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="msup"><g data-mml-node="mi"><path data-c="1D45D" d="M23 287Q24 290 25 295T30 317T40 348T55 381T75 411T101 433T134 442Q209 442 230 378L240 387Q302 442 358 442Q423 442 460 395T497 281Q497 173 421 82T249 -10Q227 -10 210 -4Q199 1 187 11T168 28L161 36Q160 35 139 -51T118 -138Q118 -144 126 -145T163 -148H188Q194 -155 194 -157T191 -175Q188 -187 185 -190T172 -194Q170 -194 161 -194T127 -193T65 -192Q-5 -192 -24 -194H-32Q-39 -187 -39 -183Q-37 -156 -26 -148H-6Q28 -147 33 -136Q36 -130 94 103T155 350Q156 355 156 364Q156 405 131 405Q109 405 94 377T71 316T59 280Q57 278 43 278H29Q23 284 23 287ZM178 102Q200 26 252 26Q282 26 310 49T356 107Q374 141 392 215T411 325V331Q411 405 350 405Q339 405 328 402T306 393T286 380T269 365T254 350T243 336T235 326L232 322Q232 321 229 308T218 264T204 212Q178 106 178 102Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(536,363) scale(0.707)"><path data-c="2032" d="M79 43Q73 43 52 49T30 61Q30 68 85 293T146 528Q161 560 198 560Q218 560 240 545T262 501Q262 496 260 486Q259 479 173 263T84 45T79 43Z" style="stroke-width: 3;"/></g></g><g data-mml-node="mo" transform="translate(1058.2,0)"><path data-c="3D" d="M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(2114,0)"><path data-c="1D45D" d="M23 287Q24 290 25 295T30 317T40 348T55 381T75 411T101 433T134 442Q209 442 230 378L240 387Q302 442 358 442Q423 442 460 395T497 281Q497 173 421 82T249 -10Q227 -10 210 -4Q199 1 187 11T168 28L161 36Q160 35 139 -51T118 -138Q118 -144 126 -145T163 -148H188Q194 -155 194 -157T191 -175Q188 -187 185 -190T172 -194Q170 -194 161 -194T127 -193T65 -192Q-5 -192 -24 -194H-32Q-39 -187 -39 -183Q-37 -156 -26 -148H-6Q28 -147 33 -136Q36 -130 94 103T155 350Q156 355 156 364Q156 405 131 405Q109 405 94 377T71 316T59 280Q57 278 43 278H29Q23 284 23 287ZM178 102Q200 26 252 26Q282 26 310 49T356 107Q374 141 392 215T411 325V331Q411 405 350 405Q339 405 328 402T306 393T286 380T269 365T254 350T243 336T235 326L232 322Q232 321 229 308T218 264T204 212Q178 106 178 102Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(2839.2,0)"><path data-c="2B" d="M56 237T56 250T70 270H369V420L370 570Q380 583 389 583Q402 583 409 568V270H707Q722 262 722 250T707 230H409V-68Q401 -82 391 -82H389H387Q375 -82 369 -68V230H70Q56 237 56 250Z" style="stroke-width: 3;"/></g><g data-mml-node="mtext" transform="translate(3839.5,0)"><path data-c="6E" d="M41 46H55Q94 46 102 60V68Q102 77 102 91T102 122T103 161T103 203Q103 234 103 269T102 328V351Q99 370 88 376T43 385H25V408Q25 431 27 431L37 432Q47 433 65 434T102 436Q119 437 138 438T167 441T178 442H181V402Q181 364 182 364T187 369T199 384T218 402T247 421T285 437Q305 442 336 442Q450 438 463 329Q464 322 464 190V104Q464 66 466 59T477 49Q498 46 526 46H542V0H534L510 1Q487 2 460 2T422 3Q319 3 310 0H302V46H318Q379 46 379 62Q380 64 380 200Q379 335 378 343Q372 371 358 385T334 402T308 404Q263 404 229 370Q202 343 195 315T187 232V168V108Q187 78 188 68T191 55T200 49Q221 46 249 46H265V0H257L234 1Q210 2 183 2T145 3Q42 3 33 0H25V46H41Z" style="stroke-width: 3;"/><path data-c="6F" d="M28 214Q28 309 93 378T250 448Q340 448 405 380T471 215Q471 120 407 55T250 -10Q153 -10 91 57T28 214ZM250 30Q372 30 372 193V225V250Q372 272 371 288T364 326T348 362T317 390T268 410Q263 411 252 411Q222 411 195 399Q152 377 139 338T126 246V226Q126 130 145 91Q177 30 250 30Z" transform="translate(556,0)" style="stroke-width: 3;"/><path data-c="69" d="M69 609Q69 637 87 653T131 669Q154 667 171 652T188 609Q188 579 171 564T129 549Q104 549 87 564T69 609ZM247 0Q232 3 143 3Q132 3 106 3T56 1L34 0H26V46H42Q70 46 91 49Q100 53 102 60T104 102V205V293Q104 345 102 359T88 378Q74 385 41 385H30V408Q30 431 32 431L42 432Q52 433 70 434T106 436Q123 437 142 438T171 441T182 442H185V62Q190 52 197 50T232 46H255V0H247Z" transform="translate(1056,0)" style="stroke-width: 3;"/><path data-c="73" d="M295 316Q295 356 268 385T190 414Q154 414 128 401Q98 382 98 349Q97 344 98 336T114 312T157 287Q175 282 201 278T245 269T277 256Q294 248 310 236T342 195T359 133Q359 71 321 31T198 -10H190Q138 -10 94 26L86 19L77 10Q71 4 65 -1L54 -11H46H42Q39 -11 33 -5V74V132Q33 153 35 157T45 162H54Q66 162 70 158T75 146T82 119T101 77Q136 26 198 26Q295 26 295 104Q295 133 277 151Q257 175 194 187T111 210Q75 227 54 256T33 318Q33 357 50 384T93 424T143 442T187 447H198Q238 447 268 432L283 424L292 431Q302 440 314 448H322H326Q329 448 335 442V310L329 304H301Q295 310 295 316Z" transform="translate(1334,0)" style="stroke-width: 3;"/><path data-c="65" d="M28 218Q28 273 48 318T98 391T163 433T229 448Q282 448 320 430T378 380T406 316T415 245Q415 238 408 231H126V216Q126 68 226 36Q246 30 270 30Q312 30 342 62Q359 79 369 104L379 128Q382 131 395 131H398Q415 131 415 121Q415 117 412 108Q393 53 349 21T250 -11Q155 -11 92 58T28 218ZM333 275Q322 403 238 411H236Q228 411 220 410T195 402T166 381T143 340T127 274V267H333V275Z" transform="translate(1728,0)" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(6011.5,0)"><path data-c="28" d="M94 250Q94 319 104 381T127 488T164 576T202 643T244 695T277 729T302 750H315H319Q333 750 333 741Q333 738 316 720T275 667T226 581T184 443T167 250T184 58T225 -81T274 -167T316 -220T333 -241Q333 -250 318 -250H315H302L274 -226Q180 -141 137 -14T94 250Z" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(6400.5,0)"><path data-c="1D45D" d="M23 287Q24 290 25 295T30 317T40 348T55 381T75 411T101 433T134 442Q209 442 230 378L240 387Q302 442 358 442Q423 442 460 395T497 281Q497 173 421 82T249 -10Q227 -10 210 -4Q199 1 187 11T168 28L161 36Q160 35 139 -51T118 -138Q118 -144 126 -145T163 -148H188Q194 -155 194 -157T191 -175Q188 -187 185 -190T172 -194Q170 -194 161 -194T127 -193T65 -192Q-5 -192 -24 -194H-32Q-39 -187 -39 -183Q-37 -156 -26 -148H-6Q28 -147 33 -136Q36 -130 94 103T155 350Q156 355 156 364Q156 405 131 405Q109 405 94 377T71 316T59 280Q57 278 43 278H29Q23 284 23 287ZM178 102Q200 26 252 26Q282 26 310 49T356 107Q374 141 392 215T411 325V331Q411 405 350 405Q339 405 328 402T306 393T286 380T269 365T254 350T243 336T235 326L232 322Q232 321 229 308T218 264T204 212Q178 106 178 102Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(6903.5,0)"><path data-c="29" d="M60 749L64 750Q69 750 74 750H86L114 726Q208 641 251 514T294 250Q294 182 284 119T261 12T224 -76T186 -143T145 -194T113 -227T90 -246Q87 -249 86 -250H74Q66 -250 63 -250T58 -247T55 -238Q56 -237 66 -225Q221 -64 221 250T66 725Q56 737 55 738Q55 746 60 749Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(7514.7,0)"><path data-c="22C5" d="M78 250Q78 274 95 292T138 310Q162 310 180 294T199 251Q199 226 182 208T139 190T96 207T78 250Z" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(8014.9,0)"><path data-c="1D460" d="M131 289Q131 321 147 354T203 415T300 442Q362 442 390 415T419 355Q419 323 402 308T364 292Q351 292 340 300T328 326Q328 342 337 354T354 372T367 378Q368 378 368 379Q368 382 361 388T336 399T297 405Q249 405 227 379T204 326Q204 301 223 291T278 274T330 259Q396 230 396 163Q396 135 385 107T352 51T289 7T195 -10Q118 -10 86 19T53 87Q53 126 74 143T118 160Q133 160 146 151T160 120Q160 94 142 76T111 58Q109 57 108 57T107 55Q108 52 115 47T146 34T201 27Q237 27 263 38T301 66T318 97T323 122Q323 150 302 164T254 181T195 196T148 231Q131 256 131 289Z" style="stroke-width: 3;"/></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><msup><mi>p</mi><mo data-mjx-alternate="1">′</mo></msup><mo>=</mo><mi>p</mi><mo>+</mo><mtext>noise</mtext><mo stretchy="false">(</mo><mi>p</mi><mo stretchy="false">)</mo><mo>⋅</mo><mi>s</mi></math></mjx-assistive-mml></mjx-container>) para crear crestas orgánicas, redistribución <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.025ex;" xmlns="http://www.w3.org/2000/svg" width="2.453ex" height="1.956ex" role="img" focusable="false" viewBox="0 -853.7 1084.4 864.7" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="msup"><g data-mml-node="mi"><path data-c="1D452" d="M39 168Q39 225 58 272T107 350T174 402T244 433T307 442H310Q355 442 388 420T421 355Q421 265 310 237Q261 224 176 223Q139 223 138 221Q138 219 132 186T125 128Q125 81 146 54T209 26T302 45T394 111Q403 121 406 121Q410 121 419 112T429 98T420 82T390 55T344 24T281 -1T205 -11Q126 -11 83 42T39 168ZM373 353Q367 405 305 405Q272 405 244 391T199 357T170 316T154 280T149 261Q149 260 169 260Q282 260 327 284T373 353Z" style="stroke-width: 3;"/></g><g data-mml-node="TeXAtom" transform="translate(499,363) scale(0.707)" data-mjx-texclass="ORD"><g data-mml-node="mstyle" transform="scale(1.414)"><g data-mml-node="mspace"/></g><g data-mml-node="mi" transform="translate(236.2,0)"><path data-c="1D458" d="M121 647Q121 657 125 670T137 683Q138 683 209 688T282 694Q294 694 294 686Q294 679 244 477Q194 279 194 272Q213 282 223 291Q247 309 292 354T362 415Q402 442 438 442Q468 442 485 423T503 369Q503 344 496 327T477 302T456 291T438 288Q418 288 406 299T394 328Q394 353 410 369T442 390L458 393Q446 405 434 405H430Q398 402 367 380T294 316T228 255Q230 254 243 252T267 246T293 238T320 224T342 206T359 180T365 147Q365 130 360 106T354 66Q354 26 381 26Q429 26 459 145Q461 153 479 153H483Q499 153 499 144Q499 139 496 130Q455 -11 378 -11Q333 -11 305 15T277 90Q277 108 280 121T283 145Q283 167 269 183T234 206T200 217T182 220H180Q168 178 159 139T145 81T136 44T129 20T122 7T111 -2Q98 -11 83 -11Q66 -11 57 -1T48 16Q48 26 85 176T158 471L195 616Q196 629 188 632T149 637H144Q134 637 131 637T124 640T121 647Z" style="stroke-width: 3;"/></g></g></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><msup><mi>e</mi><mrow data-mjx-texclass="ORD"><mstyle scriptlevel="0"><mspace width="0.167em"/></mstyle><mi>k</mi></mrow></msup></math></mjx-assistive-mml></mjx-container> para obtener valles planos y picos escarpados, y una atenuación radial euclídea mezclada hacia <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.186ex;" xmlns="http://www.w3.org/2000/svg" width="5.073ex" height="1.756ex" role="img" focusable="false" viewBox="0 -694 2242.4 776" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mn"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(722.2,0)"><path data-c="2212" d="M84 237T84 250T98 270H679Q694 262 694 250T679 230H98Q84 237 84 250Z" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(1722.4,0)"><path data-c="1D451" d="M366 683Q367 683 438 688T511 694Q523 694 523 686Q523 679 450 384T375 83T374 68Q374 26 402 26Q411 27 422 35Q443 55 463 131Q469 151 473 152Q475 153 483 153H487H491Q506 153 506 145Q506 140 503 129Q490 79 473 48T445 8T417 -8Q409 -10 393 -10Q359 -10 336 5T306 36L300 51Q299 52 296 50Q294 48 292 46Q233 -10 172 -10Q117 -10 75 30T33 157Q33 205 53 255T101 341Q148 398 195 420T280 442Q336 442 364 400Q369 394 369 396Q370 400 396 505T424 616Q424 629 417 632T378 637H357Q351 643 351 645T353 664Q358 683 366 683ZM352 326Q329 405 277 405Q242 405 210 374T160 293Q131 214 119 129Q119 126 119 118T118 106Q118 61 136 44T179 26Q233 26 290 98L298 109L352 326Z" style="stroke-width: 3;"/></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mn>1</mn><mo>−</mo><mi>d</mi></math></mjx-assistive-mml></mjx-container> 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 <a href="/es/guides/landscape-generation-browser.html">generación de paisajes</a>.</p>
<p><strong>Erosión hidráulica en CPU y GPU.</strong> 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 <code>i32</code> con una escala de un millón, de modo que las gotas puedan aplicar <code>atomicAdd</code>/<code>atomicSub</code> 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 <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.05ex;" xmlns="http://www.w3.org/2000/svg" width="5.513ex" height="2.005ex" role="img" focusable="false" viewBox="0 -864 2436.6 886" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="msup"><g data-mml-node="mn"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" style="stroke-width: 3;"/><path data-c="30" d="M96 585Q152 666 249 666Q297 666 345 640T423 548Q460 465 460 320Q460 165 417 83Q397 41 362 16T301 -15T250 -22Q224 -22 198 -16T137 16T82 83Q39 165 39 320Q39 494 96 585ZM321 597Q291 629 250 629Q208 629 178 597Q153 571 145 525T137 333Q137 175 145 125T181 46Q209 16 250 16Q290 16 318 46Q347 76 354 130T362 333Q362 478 354 524T321 597Z" transform="translate(500,0)" style="stroke-width: 3;"/><path data-c="30" d="M96 585Q152 666 249 666Q297 666 345 640T423 548Q460 465 460 320Q460 165 417 83Q397 41 362 16T301 -15T250 -22Q224 -22 198 -16T137 16T82 83Q39 165 39 320Q39 494 96 585ZM321 597Q291 629 250 629Q208 629 178 597Q153 571 145 525T137 333Q137 175 145 125T181 46Q209 16 250 16Q290 16 318 46Q347 76 354 130T362 333Q362 478 354 524T321 597Z" transform="translate(1000,0)" style="stroke-width: 3;"/><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" transform="translate(1500,0)" style="stroke-width: 3;"/></g><g data-mml-node="mn" transform="translate(2033,393.1) scale(0.707)"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"/></g></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><msup><mn>1001</mn><mn>2</mn></msup></math></mjx-assistive-mml></mjx-container>, y genera las posiciones iniciales mediante un generador Mulberry32 determinista.</p>
<p><strong>Drenaje D8 con rellenado de depresiones.</strong> 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 <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.466ex;" xmlns="http://www.w3.org/2000/svg" width="17.709ex" height="2.036ex" role="img" focusable="false" viewBox="0 -694 7827.4 900" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mtext"><path data-c="6D" d="M41 46H55Q94 46 102 60V68Q102 77 102 91T102 122T103 161T103 203Q103 234 103 269T102 328V351Q99 370 88 376T43 385H25V408Q25 431 27 431L37 432Q47 433 65 434T102 436Q119 437 138 438T167 441T178 442H181V402Q181 364 182 364T187 369T199 384T218 402T247 421T285 437Q305 442 336 442Q351 442 364 440T387 434T406 426T421 417T432 406T441 395T448 384T452 374T455 366L457 361L460 365Q463 369 466 373T475 384T488 397T503 410T523 422T546 432T572 439T603 442Q729 442 740 329Q741 322 741 190V104Q741 66 743 59T754 49Q775 46 803 46H819V0H811L788 1Q764 2 737 2T699 3Q596 3 587 0H579V46H595Q656 46 656 62Q657 64 657 200Q656 335 655 343Q649 371 635 385T611 402T585 404Q540 404 506 370Q479 343 472 315T464 232V168V108Q464 78 465 68T468 55T477 49Q498 46 526 46H542V0H534L510 1Q487 2 460 2T422 3Q319 3 310 0H302V46H318Q379 46 379 62Q380 64 380 200Q379 335 378 343Q372 371 358 385T334 402T308 404Q263 404 229 370Q202 343 195 315T187 232V168V108Q187 78 188 68T191 55T200 49Q221 46 249 46H265V0H257L234 1Q210 2 183 2T145 3Q42 3 33 0H25V46H41Z" style="stroke-width: 3;"/><path data-c="69" d="M69 609Q69 637 87 653T131 669Q154 667 171 652T188 609Q188 579 171 564T129 549Q104 549 87 564T69 609ZM247 0Q232 3 143 3Q132 3 106 3T56 1L34 0H26V46H42Q70 46 91 49Q100 53 102 60T104 102V205V293Q104 345 102 359T88 378Q74 385 41 385H30V408Q30 431 32 431L42 432Q52 433 70 434T106 436Q123 437 142 438T171 441T182 442H185V62Q190 52 197 50T232 46H255V0H247Z" transform="translate(833,0)" style="stroke-width: 3;"/><path data-c="6E" d="M41 46H55Q94 46 102 60V68Q102 77 102 91T102 122T103 161T103 203Q103 234 103 269T102 328V351Q99 370 88 376T43 385H25V408Q25 431 27 431L37 432Q47 433 65 434T102 436Q119 437 138 438T167 441T178 442H181V402Q181 364 182 364T187 369T199 384T218 402T247 421T285 437Q305 442 336 442Q450 438 463 329Q464 322 464 190V104Q464 66 466 59T477 49Q498 46 526 46H542V0H534L510 1Q487 2 460 2T422 3Q319 3 310 0H302V46H318Q379 46 379 62Q380 64 380 200Q379 335 378 343Q372 371 358 385T334 402T308 404Q263 404 229 370Q202 343 195 315T187 232V168V108Q187 78 188 68T191 55T200 49Q221 46 249 46H265V0H257L234 1Q210 2 183 2T145 3Q42 3 33 0H25V46H41Z" transform="translate(1111,0)" style="stroke-width: 3;"/><path data-c="4E" d="M42 46Q74 48 94 56T118 69T128 86V634H124Q114 637 52 637H25V683H232L235 680Q237 679 322 554T493 303L578 178V598Q572 608 568 613T544 627T492 637H475V683H483Q498 680 600 680Q706 680 715 683H724V637H707Q634 633 622 598L621 302V6L614 0H600Q585 0 582 3T481 150T282 443T171 605V345L172 86Q183 50 257 46H274V0H265Q250 3 150 3Q48 3 33 0H25V46H42Z" transform="translate(1667,0)" style="stroke-width: 3;"/><path data-c="65" d="M28 218Q28 273 48 318T98 391T163 433T229 448Q282 448 320 430T378 380T406 316T415 245Q415 238 408 231H126V216Q126 68 226 36Q246 30 270 30Q312 30 342 62Q359 79 369 104L379 128Q382 131 395 131H398Q415 131 415 121Q415 117 412 108Q393 53 349 21T250 -11Q155 -11 92 58T28 218ZM333 275Q322 403 238 411H236Q228 411 220 410T195 402T166 381T143 340T127 274V267H333V275Z" transform="translate(2417,0)" style="stroke-width: 3;"/><path data-c="69" d="M69 609Q69 637 87 653T131 669Q154 667 171 652T188 609Q188 579 171 564T129 549Q104 549 87 564T69 609ZM247 0Q232 3 143 3Q132 3 106 3T56 1L34 0H26V46H42Q70 46 91 49Q100 53 102 60T104 102V205V293Q104 345 102 359T88 378Q74 385 41 385H30V408Q30 431 32 431L42 432Q52 433 70 434T106 436Q123 437 142 438T171 441T182 442H185V62Q190 52 197 50T232 46H255V0H247Z" transform="translate(2861,0)" style="stroke-width: 3;"/><path data-c="67" d="M329 409Q373 453 429 453Q459 453 472 434T485 396Q485 382 476 371T449 360Q416 360 412 390Q410 404 415 411Q415 412 416 414V415Q388 412 363 393Q355 388 355 386Q355 385 359 381T368 369T379 351T388 325T392 292Q392 230 343 187T222 143Q172 143 123 171Q112 153 112 133Q112 98 138 81Q147 75 155 75T227 73Q311 72 335 67Q396 58 431 26Q470 -13 470 -72Q470 -139 392 -175Q332 -206 250 -206Q167 -206 107 -175Q29 -140 29 -75Q29 -39 50 -15T92 18L103 24Q67 55 67 108Q67 155 96 193Q52 237 52 292Q52 355 102 398T223 442Q274 442 318 416L329 409ZM299 343Q294 371 273 387T221 404Q192 404 171 388T145 343Q142 326 142 292Q142 248 149 227T179 192Q196 182 222 182Q244 182 260 189T283 207T294 227T299 242Q302 258 302 292T299 343ZM403 -75Q403 -50 389 -34T348 -11T299 -2T245 0H218Q151 0 138 -6Q118 -15 107 -34T95 -74Q95 -84 101 -97T122 -127T170 -155T250 -167Q319 -167 361 -139T403 -75Z" transform="translate(3139,0)" style="stroke-width: 3;"/><path data-c="68" d="M41 46H55Q94 46 102 60V68Q102 77 102 91T102 124T102 167T103 217T103 272T103 329Q103 366 103 407T103 482T102 542T102 586T102 603Q99 622 88 628T43 637H25V660Q25 683 27 683L37 684Q47 685 66 686T103 688Q120 689 140 690T170 693T181 694H184V367Q244 442 328 442Q451 442 463 329Q464 322 464 190V104Q464 66 466 59T477 49Q498 46 526 46H542V0H534L510 1Q487 2 460 2T422 3Q319 3 310 0H302V46H318Q379 46 379 62Q380 64 380 200Q379 335 378 343Q372 371 358 385T334 402T308 404Q263 404 229 370Q202 343 195 315T187 232V168V108Q187 78 188 68T191 55T200 49Q221 46 249 46H265V0H257L234 1Q210 2 183 2T145 3Q42 3 33 0H25V46H41Z" transform="translate(3639,0)" style="stroke-width: 3;"/><path data-c="62" d="M307 -11Q234 -11 168 55L158 37Q156 34 153 28T147 17T143 10L138 1L118 0H98V298Q98 599 97 603Q94 622 83 628T38 637H20V660Q20 683 22 683L32 684Q42 685 61 686T98 688Q115 689 135 690T165 693T176 694H179V543Q179 391 180 391L183 394Q186 397 192 401T207 411T228 421T254 431T286 439T323 442Q401 442 461 379T522 216Q522 115 458 52T307 -11ZM182 98Q182 97 187 90T196 79T206 67T218 55T233 44T250 35T271 29T295 26Q330 26 363 46T412 113Q424 148 424 212Q424 287 412 323Q385 405 300 405Q270 405 239 390T188 347L182 339V98Z" transform="translate(4195,0)" style="stroke-width: 3;"/><path data-c="6F" d="M28 214Q28 309 93 378T250 448Q340 448 405 380T471 215Q471 120 407 55T250 -10Q153 -10 91 57T28 214ZM250 30Q372 30 372 193V225V250Q372 272 371 288T364 326T348 362T317 390T268 410Q263 411 252 411Q222 411 195 399Q152 377 139 338T126 246V226Q126 130 145 91Q177 30 250 30Z" transform="translate(4751,0)" style="stroke-width: 3;"/><path data-c="75" d="M383 58Q327 -10 256 -10H249Q124 -10 105 89Q104 96 103 226Q102 335 102 348T96 369Q86 385 36 385H25V408Q25 431 27 431L38 432Q48 433 67 434T105 436Q122 437 142 438T172 441T184 442H187V261Q188 77 190 64Q193 49 204 40Q224 26 264 26Q290 26 311 35T343 58T363 90T375 120T379 144Q379 145 379 161T380 201T380 248V315Q380 361 370 372T320 385H302V431Q304 431 378 436T457 442H464V264Q464 84 465 81Q468 61 479 55T524 46H542V0Q540 0 467 -5T390 -11H383V58Z" transform="translate(5251,0)" style="stroke-width: 3;"/><path data-c="72" d="M36 46H50Q89 46 97 60V68Q97 77 97 91T98 122T98 161T98 203Q98 234 98 269T98 328L97 351Q94 370 83 376T38 385H20V408Q20 431 22 431L32 432Q42 433 60 434T96 436Q112 437 131 438T160 441T171 442H174V373Q213 441 271 441H277Q322 441 343 419T364 373Q364 352 351 337T313 322Q288 322 276 338T263 372Q263 381 265 388T270 400T273 405Q271 407 250 401Q234 393 226 386Q179 341 179 207V154Q179 141 179 127T179 101T180 81T180 66V61Q181 59 183 57T188 54T193 51T200 49T207 48T216 47T225 47T235 46T245 46H276V0H267Q249 3 140 3Q37 3 28 0H20V46H36Z" transform="translate(5807,0)" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(6421.2,0)"><path data-c="2B" d="M56 237T56 250T70 270H369V420L370 570Q380 583 389 583Q402 583 409 568V270H707Q722 262 722 250T707 230H409V-68Q401 -82 391 -82H389H387Q375 -82 369 -68V230H70Q56 237 56 250Z" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(7421.4,0)"><path data-c="1D716" d="M227 -11Q149 -11 95 41T40 174Q40 262 87 322Q121 367 173 396T287 430Q289 431 329 431H367Q382 426 382 411Q382 385 341 385H325H312Q191 385 154 277L150 265H327Q340 256 340 246Q340 228 320 219H138V217Q128 187 128 143Q128 77 160 52T231 26Q258 26 284 36T326 57T343 68Q350 68 354 58T358 39Q358 36 357 35Q354 31 337 21T289 0T227 -11Z" style="stroke-width: 3;"/></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mtext>minNeighbour</mtext><mo>+</mo><mi>ϵ</mi></math></mjx-assistive-mml></mjx-container> (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.</p>
<p><strong>Cuatro formas de romper la repetición de texturas.</strong> Sobre geometría e iluminación idénticas: <code>plain</code> (una muestra, con un teselado evidente), <code>hex-linear</code> (cuadrícula triangular de Heitz-Neyret, cuya mezcla lineal deja un patrón triangular), <code>hex-vp</code> (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 <code>iq-untiled</code> (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 <code>abs(normalWorld)</code> 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 <a href="/es/guides/landscape-generation-browser.html#terrain-materials">materiales de terreno</a>.</p>
<hr>
<p>Parte 27 de 29.
Anterior: <a href="/es/blog/2026-05-12-open-world-browser-part-26-water.html">Parte 26 - Tres formas de crear agua</a>
Siguiente: <a href="/es/blog/2026-05-14-open-world-browser-part-28-grass-and-occlusion.html">Parte 28 - Hierba hasta el horizonte y un suelo que se oculta a sí mismo</a>
Guía de la serie: <a href="/es/blog/2026-02-25-open-world-browser-series-guide.html">/es/blog/2026-02-25-open-world-browser-series-guide</a></p>
]]></content:encoded>
            <enclosure url="https://cdn.cinevva.com/blog/why-webgpu-engine-hero.jpg" length="0" type="image/jpg"/>
        </item>
        <item>
            <title><![CDATA[Construir un mundo abierto en el navegador, parte 26: Tres formas de crear agua]]></title>
            <link>https://app.cinevva.com/es/blog/2026-05-12-open-world-browser-part-26-water</link>
            <guid>https://app.cinevva.com/es/blog/2026-05-12-open-world-browser-part-26-water</guid>
            <pubDate>Tue, 12 May 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[El experimento 51 creó agua con reflejos en espacio de pantalla y chocó con su límite fundamental: no puede reflejar lo que la cámara nunca vio. El experimento 52 cambió a un espejo planar, el patrón que utilizan todos los juegos publicados, y eliminó un error que se comía los reflejos oscuros. El experimento 53 incorporó una biblioteca de agua lista para producción para ver qué aspecto tiene un resultado terminado.]]></description>
            <content:encoded><![CDATA[<h1 id="construir-un-mundo-abierto-en-el-navegador-parte-26-tres-formas-de-crear-agua" tabindex="-1">Construir un mundo abierto en el navegador, parte 26: Tres formas de crear agua <a class="header-anchor" href="#construir-un-mundo-abierto-en-el-navegador-parte-26-tres-formas-de-crear-agua" aria-label="Permalink to &quot;Construir un mundo abierto en el navegador, parte 26: Tres formas de crear agua&quot;"></a></h1>
<p><em>Por <a href="/es/about.html">Oleg Sidorkin</a>, CTO y cofundador de Cinevva</em></p>
<p>¿Acabas de llegar? Consulta la <a href="/es/blog/2026-02-25-open-world-browser-series-guide.html">guía de la serie</a>. Explica qué es un experimento y contiene enlaces a todas las partes.</p>
<p>La <a href="/es/blog/2026-05-10-open-world-browser-part-25-universal-characters.html">parte 25</a> vistió a los avatares. Esta parte trata sobre el agua, y consta de tres experimentos porque el agua es la superficie en la que un atajo barato y la solución correcta parecen idénticos en una captura de pantalla, pero completamente distintos en movimiento. El experimento 51 genera reflejos mediante el espacio de pantalla, la opción tentadora, y choca de frente con su limitación inherente. El experimento 52 cambia al método que utilizan realmente todos los juegos publicados. El experimento 53 incorpora una biblioteca de agua terminada para ver lo lejos que estamos de poder considerarlo «listo». Los tres comparten una misma capa de refracción, por lo que la única variable que cambia entre los dos primeros es cómo se calcula el reflejo.</p>
<h2 id="reflejos-a-partir-de-la-pantalla-que-ya-tienes" tabindex="-1">Reflejos a partir de la pantalla que ya tienes <a class="header-anchor" href="#reflejos-a-partir-de-la-pantalla-que-ya-tienes" aria-label="Permalink to &quot;Reflejos a partir de la pantalla que ya tienes&quot;"></a></h2>
<div style="position:relative;padding-bottom:56.25%;height:0;overflow:hidden;border-radius:8px;margin:1.5rem 0;border:1px solid rgba(255,255,255,0.12)">
<iframe src="/es/spikes/51-water-ssr-caustics/" title="Experimento 51: Agua con SSR" style="position:absolute;top:0;left:0;width:100%;height:100%;border:0;background:#000" loading="lazy" allowfullscreen></iframe>
</div>
<p><a href="/es/spikes/51-water-ssr-caustics/" target="_blank">Abrir el experimento 51 en una pestaña nueva ↗</a> · <a href="/es/blog/spike-source?spike=51-water-ssr-caustics">Ver el código fuente</a></p>
<p>Los reflejos en espacio de pantalla reutilizan el fotograma que ya has renderizado. Para cada píxel del agua, reflejas el rayo de visión sobre la superficie, haces avanzar ese rayo reflejado por el búfer de profundidad y, cuando el rayo pasa por detrás de una superficie registrada, has encontrado lo que refleja el agua, muestreado directamente desde el búfer de color. La adaptación sigue línea por línea el <code>SSRNode</code> de three.js, que a su vez sigue la introducción a SSR de lettier. El avance es un recorrido DDA en espacio de pantalla: se proyectan el inicio y el final del rayo a coordenadas de píxel y se avanza por el eje que sea más largo, con una muestra por píxel. La profundidad del rayo reflejado en cada paso necesita una interpolación con corrección de perspectiva, <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -1.238ex;" xmlns="http://www.w3.org/2000/svg" width="14.984ex" height="3.195ex" role="img" focusable="false" viewBox="0 -864.9 6622.8 1412" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mfrac"><g data-mml-node="mn" transform="translate(3134.6,394) scale(0.707)"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" style="stroke-width: 3;"/></g><g data-mml-node="mrow" transform="translate(220,-370.3) scale(0.707)"><g data-mml-node="mn"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" style="stroke-width: 3;"/></g><g data-mml-node="TeXAtom" data-mjx-texclass="ORD" transform="translate(500,0)"><g data-mml-node="mo"><path data-c="2F" d="M423 750Q432 750 438 744T444 730Q444 725 271 248T92 -240Q85 -250 75 -250Q68 -250 62 -245T56 -231Q56 -221 230 257T407 740Q411 750 423 750Z" style="stroke-width: 3;"/></g></g><g data-mml-node="msub" transform="translate(1000,0)"><g data-mml-node="mi"><path data-c="1D467" d="M347 338Q337 338 294 349T231 360Q211 360 197 356T174 346T162 335T155 324L153 320Q150 317 138 317Q117 317 117 325Q117 330 120 339Q133 378 163 406T229 440Q241 442 246 442Q271 442 291 425T329 392T367 375Q389 375 411 408T434 441Q435 442 449 442H462Q468 436 468 434Q468 430 463 420T449 399T432 377T418 358L411 349Q368 298 275 214T160 106L148 94L163 93Q185 93 227 82T290 71Q328 71 360 90T402 140Q406 149 409 151T424 153Q443 153 443 143Q443 138 442 134Q425 72 376 31T278 -11Q252 -11 232 6T193 40T155 57Q111 57 76 -3Q70 -11 59 -11H54H41Q35 -5 35 -2Q35 13 93 84Q132 129 225 214T340 322Q352 338 347 338Z" style="stroke-width: 3;"/></g><g data-mml-node="mn" transform="translate(498,-150) scale(0.707)"><path data-c="30" d="M96 585Q152 666 249 666Q297 666 345 640T423 548Q460 465 460 320Q460 165 417 83Q397 41 362 16T301 -15T250 -22Q224 -22 198 -16T137 16T82 83Q39 165 39 320Q39 494 96 585ZM321 597Q291 629 250 629Q208 629 178 597Q153 571 145 525T137 333Q137 175 145 125T181 46Q209 16 250 16Q290 16 318 46Q347 76 354 130T362 333Q362 478 354 524T321 597Z" style="stroke-width: 3;"/></g></g><g data-mml-node="mo" transform="translate(1901.6,0)"><path data-c="2B" d="M56 237T56 250T70 270H369V420L370 570Q380 583 389 583Q402 583 409 568V270H707Q722 262 722 250T707 230H409V-68Q401 -82 391 -82H389H387Q375 -82 369 -68V230H70Q56 237 56 250Z" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(2679.6,0)"><path data-c="1D460" d="M131 289Q131 321 147 354T203 415T300 442Q362 442 390 415T419 355Q419 323 402 308T364 292Q351 292 340 300T328 326Q328 342 337 354T354 372T367 378Q368 378 368 379Q368 382 361 388T336 399T297 405Q249 405 227 379T204 326Q204 301 223 291T278 274T330 259Q396 230 396 163Q396 135 385 107T352 51T289 7T195 -10Q118 -10 86 19T53 87Q53 126 74 143T118 160Q133 160 146 151T160 120Q160 94 142 76T111 58Q109 57 108 57T107 55Q108 52 115 47T146 34T201 27Q237 27 263 38T301 66T318 97T323 122Q323 150 302 164T254 181T195 196T148 231Q131 256 131 289Z" style="stroke-width: 3;"/></g><g data-mml-node="mstyle" transform="translate(3148.6,0) scale(1.414)"><g data-mml-node="mspace"/></g><g data-mml-node="mo" transform="translate(3384.7,0)"><path data-c="28" d="M94 250Q94 319 104 381T127 488T164 576T202 643T244 695T277 729T302 750H315H319Q333 750 333 741Q333 738 316 720T275 667T226 581T184 443T167 250T184 58T225 -81T274 -167T316 -220T333 -241Q333 -250 318 -250H315H302L274 -226Q180 -141 137 -14T94 250Z" style="stroke-width: 3;"/></g><g data-mml-node="mn" transform="translate(3773.7,0)"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" style="stroke-width: 3;"/></g><g data-mml-node="TeXAtom" data-mjx-texclass="ORD" transform="translate(4273.7,0)"><g data-mml-node="mo"><path data-c="2F" d="M423 750Q432 750 438 744T444 730Q444 725 271 248T92 -240Q85 -250 75 -250Q68 -250 62 -245T56 -231Q56 -221 230 257T407 740Q411 750 423 750Z" style="stroke-width: 3;"/></g></g><g data-mml-node="msub" transform="translate(4773.7,0)"><g data-mml-node="mi"><path data-c="1D467" d="M347 338Q337 338 294 349T231 360Q211 360 197 356T174 346T162 335T155 324L153 320Q150 317 138 317Q117 317 117 325Q117 330 120 339Q133 378 163 406T229 440Q241 442 246 442Q271 442 291 425T329 392T367 375Q389 375 411 408T434 441Q435 442 449 442H462Q468 436 468 434Q468 430 463 420T449 399T432 377T418 358L411 349Q368 298 275 214T160 106L148 94L163 93Q185 93 227 82T290 71Q328 71 360 90T402 140Q406 149 409 151T424 153Q443 153 443 143Q443 138 442 134Q425 72 376 31T278 -11Q252 -11 232 6T193 40T155 57Q111 57 76 -3Q70 -11 59 -11H54H41Q35 -5 35 -2Q35 13 93 84Q132 129 225 214T340 322Q352 338 347 338Z" style="stroke-width: 3;"/></g><g data-mml-node="mn" transform="translate(498,-150) scale(0.707)"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" style="stroke-width: 3;"/></g></g><g data-mml-node="mo" transform="translate(5675.3,0)"><path data-c="2212" d="M84 237T84 250T98 270H679Q694 262 694 250T679 230H98Q84 237 84 250Z" style="stroke-width: 3;"/></g><g data-mml-node="mn" transform="translate(6453.3,0)"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" style="stroke-width: 3;"/></g><g data-mml-node="TeXAtom" data-mjx-texclass="ORD" transform="translate(6953.3,0)"><g data-mml-node="mo"><path data-c="2F" d="M423 750Q432 750 438 744T444 730Q444 725 271 248T92 -240Q85 -250 75 -250Q68 -250 62 -245T56 -231Q56 -221 230 257T407 740Q411 750 423 750Z" style="stroke-width: 3;"/></g></g><g data-mml-node="msub" transform="translate(7453.3,0)"><g data-mml-node="mi"><path data-c="1D467" d="M347 338Q337 338 294 349T231 360Q211 360 197 356T174 346T162 335T155 324L153 320Q150 317 138 317Q117 317 117 325Q117 330 120 339Q133 378 163 406T229 440Q241 442 246 442Q271 442 291 425T329 392T367 375Q389 375 411 408T434 441Q435 442 449 442H462Q468 436 468 434Q468 430 463 420T449 399T432 377T418 358L411 349Q368 298 275 214T160 106L148 94L163 93Q185 93 227 82T290 71Q328 71 360 90T402 140Q406 149 409 151T424 153Q443 153 443 143Q443 138 442 134Q425 72 376 31T278 -11Q252 -11 232 6T193 40T155 57Q111 57 76 -3Q70 -11 59 -11H54H41Q35 -5 35 -2Q35 13 93 84Q132 129 225 214T340 322Q352 338 347 338Z" style="stroke-width: 3;"/></g><g data-mml-node="mn" transform="translate(498,-150) scale(0.707)"><path data-c="30" d="M96 585Q152 666 249 666Q297 666 345 640T423 548Q460 465 460 320Q460 165 417 83Q397 41 362 16T301 -15T250 -22Q224 -22 198 -16T137 16T82 83Q39 165 39 320Q39 494 96 585ZM321 597Q291 629 250 629Q208 629 178 597Q153 571 145 525T137 333Q137 175 145 125T181 46Q209 16 250 16Q290 16 318 46Q347 76 354 130T362 333Q362 478 354 524T321 597Z" style="stroke-width: 3;"/></g></g><g data-mml-node="mo" transform="translate(8354.8,0)"><path data-c="29" d="M60 749L64 750Q69 750 74 750H86L114 726Q208 641 251 514T294 250Q294 182 284 119T261 12T224 -76T186 -143T145 -194T113 -227T90 -246Q87 -249 86 -250H74Q66 -250 63 -250T58 -247T55 -238Q56 -237 66 -225Q221 -64 221 250T66 725Q56 737 55 738Q55 746 60 749Z" style="stroke-width: 3;"/></g></g><rect width="6382.8" height="60" x="120" y="220"/></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mfrac><mn>1</mn><mrow><mn>1</mn><mrow data-mjx-texclass="ORD"><mo>/</mo></mrow><msub><mi>z</mi><mn>0</mn></msub><mo>+</mo><mi>s</mi><mstyle scriptlevel="0"><mspace width="0.167em"/></mstyle><mo stretchy="false">(</mo><mn>1</mn><mrow data-mjx-texclass="ORD"><mo>/</mo></mrow><msub><mi>z</mi><mn>1</mn></msub><mo>−</mo><mn>1</mn><mrow data-mjx-texclass="ORD"><mo>/</mo></mrow><msub><mi>z</mi><mn>0</mn></msub><mo stretchy="false">)</mo></mrow></mfrac></math></mjx-assistive-mml></mjx-container>, porque interpolar linealmente la Z de vista es sencillamente incorrecto y produce intersecciones en lugares equivocados.</p>
<p>Dos cosas hacen que esto sea utilizable en lugar de una presentación de diapositivas. El recorrido grueso está limitado a 64 pasos, porque, de lo contrario, un rayo largo proyectado a lo largo de mil píxeles ejecutaría cientos de iteraciones por fragmento, y un plano de agua con un millón de fragmentos multiplicado por cientos de iteraciones y por varias muestras de textura da como resultado una escena a 30 fps. La calidad controla la zancada efectiva dentro de ese límite, en lugar del número de iteraciones. Y como un recorrido grueso limitado deja bandas visibles en forma de escalones, un refinamiento binario de seis iteraciones biseca el intervalo entre el último fallo y la intersección, lo que proporciona una precisión de subpaso 64 veces mayor, suficiente para que los fragmentos de agua vecinos dejen de fijarse en la misma posición de intersección gruesa. Una comprobación final de distancia entre punto y línea confirma que el candidato está realmente sobre el rayo de reflexión y no solo a la misma profundidad, con una tolerancia de grosor que se ajusta automáticamente a la anchura en espacio de vista de un píxel a esa profundidad: más estricta de cerca y más permisiva de lejos.</p>
<p>La parte honesta de este experimento está escrita en sus propios comentarios: SSR no puede reflejar lo que la cámara principal nunca muestreó. La parte inferior de un árbol, cualquier cosa que esté fuera de pantalla o cualquier cosa ocluida no existe en los búferes, así que no puede aparecer en el reflejo. Esa es la «pérdida de información del lado incorrecto» que ninguna mejora de calidad del recorrido puede solucionar, y es exactamente la razón por la que existe el siguiente experimento.</p>
<h2 id="el-espejo-que-no-puede-mentir" tabindex="-1">El espejo que no puede mentir <a class="header-anchor" href="#el-espejo-que-no-puede-mentir" aria-label="Permalink to &quot;El espejo que no puede mentir&quot;"></a></h2>
<div style="position:relative;padding-bottom:56.25%;height:0;overflow:hidden;border-radius:8px;margin:1.5rem 0;border:1px solid rgba(255,255,255,0.12)">
<iframe src="/es/spikes/52-water-planar/" title="Experimento 52: Agua planar" style="position:absolute;top:0;left:0;width:100%;height:100%;border:0;background:#000" loading="lazy" allowfullscreen></iframe>
</div>
<p><a href="/es/spikes/52-water-planar/" target="_blank">Abrir el experimento 52 en una pestaña nueva ↗</a> · <a href="/es/blog/spike-source?spike=52-water-planar">Ver el código fuente</a></p>
<p>Un reflejo planar renderiza la escena una segunda vez desde una cámara reflejada respecto al plano del agua, hacia un destino fuera de pantalla que el shader del agua muestrea. Este es el patrón canónico, el que utilizan UE5 Water, el propio <code>WaterMesh</code> de three.js, ABZÛ y Sea of Thieves, porque dispone de todos los píxeles de la escena, incluida la geometría que SSR nunca puede ver. En TSL resulta casi anticlimático: <code>reflector()</code> asigna la cámara auxiliar reflejada y su destino de renderizado, añades su destino a la malla para que se actualice en cada fotograma y muestreas su color. Cuando incorporemos las olas, el reflejo ondulará al añadir un desplazamiento de distorsión al nodo UV del reflector, que es exactamente la línea que utiliza <code>WaterMesh</code>.</p>
<p>El error que merece la pena registrar estaba en la red de seguridad, no en el espejo. Una versión anterior mezclaba la salida del reflector con un cielo procedimental como alternativa, ponderada según la magnitud del color reflejado, basándose en la teoría de que un reflejo cercano a cero significaba que el destino no contenía nada allí. Pero una sombra oscura bajo el dosel también tiene una magnitud baja, por lo que la limitación nunca alcanzaba su intensidad máxima y esos píxeles realmente oscuros acababan mezclados con el cielo luminoso. El síntoma detectado por el usuario era preciso: en modo de depuración, el destino del espejo sin procesar mostraba árboles oscuros perfectos, mientras que el renderizado compuesto presentaba reflejos desvaídos, y el diagnóstico fue que el shader «hace desaparecer los colores oscuros». La solución fue eliminar código. El destino del reflector es fiable después del primer fotograma, así que no hace falta ninguna alternativa. Ambos experimentos comparten la misma refracción subyacente: muestrear la escena detrás de la superficie, reconstruir a qué profundidad bajo la línea de flotación se encuentra cada píxel y aplicar una extinción de Beer-Lambert por canal para que el rojo desaparezca tras unos pocos metros mientras el azul persiste, con una máscara de cielo para que la imagen de fondo del plano lejano no reciba niebla. El efecto Fresnel de Schlick mezcla refracción cuando miras directamente hacia abajo dentro del agua y reflejo cuando miras a través de ella.</p>
<h2 id="que-aspecto-tiene-un-resultado-terminado" tabindex="-1">Qué aspecto tiene un resultado terminado <a class="header-anchor" href="#que-aspecto-tiene-un-resultado-terminado" aria-label="Permalink to &quot;Qué aspecto tiene un resultado terminado&quot;"></a></h2>
<div style="position:relative;padding-bottom:56.25%;height:0;overflow:hidden;border-radius:8px;margin:1.5rem 0;border:1px solid rgba(255,255,255,0.12)">
<iframe src="/es/spikes/53-water-pro/" title="Experimento 53: Agua profesional" style="position:absolute;top:0;left:0;width:100%;height:100%;border:0;background:#000" loading="lazy" allowfullscreen></iframe>
</div>
<p><a href="/es/spikes/53-water-pro/" target="_blank">Abrir el experimento 53 en una pestaña nueva ↗</a> · <a href="/es/blog/spike-source?spike=53-water-pro">Ver el código fuente</a></p>
<p>El experimento 53 es la comprobación entre desarrollar o comprar. Incorpora <code>threejs-water-pro</code> tal como se distribuye, con su preajuste tropical, su clipmap oceánico predeterminado, seguimiento de cámara y cielo de Rayleigh, y carga la misma isla glTF que utiliza la demostración de la propia biblioteca. El objetivo es ver la distancia entre un shader de agua plana creado a mano y un sistema oceánico completo, y esa distancia es grande: este tiene un sistema de flotabilidad que muestrea la altura de las olas en varios puntos bajo el casco de un barco para que cabecee y se balancee en lugar de limitarse a subir y bajar, un generador de estelas, espuma en la costa y la superficie, y una pasada de máscara que impide renderizar agua dentro del casco para que las ondas no atraviesen la cubierta.</p>
<p>La integración reveló el tipo de detalle que solo se aprende usando una biblioteca en lugar de leyendo su README. El preajuste hace referencia a las texturas de espuma por nombre de archivo, pero cargarlas es responsabilidad de quien usa la biblioteca; sin ellas, la costa parece un borde duro en la línea de flotación en lugar de olas rompiendo. La isla está situada de modo que su geometría submarina desciende más allá del fondo oceánico, permitiendo que la malla del fondo de la biblioteca oculte el anillo exterior del modelo sin dejar visible el borde del plano. Este es el patrón previsto por la biblioteca: aportar un modelo 3D, no sintetizar el terreno. Además, el antialiasing está desactivado deliberadamente en el renderizador a favor de una pasada FXAA de posprocesado, porque MSAA mezcla los fragmentos de borde con el fondo antes de que se aplique la niebla atmosférica basada en profundidad, lo que deja una franja oscura y fina allí donde la geometría se encuentra con la niebla. Resolver el aliasing después de la niebla, en lugar de antes, elimina esa franja. Lo que esto reduce es el riesgo de la propia decisión: un océano para producción es un sistema grande y especializado y, en los casos en que necesitamos uno, adoptar una biblioteca mantenida es mejor que reconstruir desde cero las estelas, la flotabilidad y la espuma, mientras que el shader de espejo planar del experimento 52 sigue siendo la solución adecuada para las masas de agua interiores más pequeñas que un creador coloca en su propio mundo.</p>
<h2 id="tecnologia-mencionada-en-este-capitulo" tabindex="-1">Tecnología mencionada en este capítulo <a class="header-anchor" href="#tecnologia-mencionada-en-este-capitulo" aria-label="Permalink to &quot;Tecnología mencionada en este capítulo&quot;"></a></h2>
<p><strong>Agua con reflejos en espacio de pantalla.</strong> Un rayo de visión reflejado recorre el búfer de profundidad en espacio de pantalla mediante DDA, utilizando interpolación 1/z con corrección de perspectiva, un límite estricto de pasos para acotar el coste por fragmento y una pasada de refinamiento binario para eliminar las bandas que deja un recorrido limitado. Una confirmación de punto a línea con un grosor ajustado según la profundidad rechaza intersecciones falsas. El límite absoluto del método es que solo puede reflejar la geometría que la cámara principal ya ha muestreado, por lo que las superficies fuera de pantalla y del lado incorrecto nunca aparecen. Consulta <a href="/es/guides/landscape-generation-browser.html#terrain-materials">materiales del terreno</a>.</p>
<p><strong>Reflejo de espejo planar.</strong> Una cámara auxiliar reflejada respecto al plano del agua renderiza la escena en un destino fuera de pantalla que muestrea el shader del agua, lo que proporciona reflejos perfectos a nivel de píxel, incluida la geometría que SSR no puede ver. Este es el patrón que utilizan UE5 Water y <code>WaterMesh</code> de three.js, con la distorsión de las olas aplicada como desplazamiento al nodo UV del reflector. Una alternativa de cielo ponderada por magnitud borraba erróneamente los píxeles oscuros del reflejo; el destino del reflector es fiable después del primer fotograma, así que la solución fue eliminar esa alternativa.</p>
<p><strong>Refracción con tinte de profundidad de Beer-Lambert.</strong> Ambos shaders muestrean la escena detrás de la superficie, reconstruyen la profundidad de cada píxel del fondo bajo la línea de flotación y aplican extinción exponencial por canal —el rojo desaparece en cuestión de metros, mientras que el azul persiste— compuesta hacia un color de niebla acuática, con una máscara de cielo para que el plano lejano no reciba niebla. El efecto Fresnel de Schlick mezcla refracción en incidencia normal con reflejo en ángulos rasantes.</p>
<p><strong>Adopción de una biblioteca de agua para producción.</strong> <code>threejs-water-pro</code> incluye un clipmap oceánico, cielo de Rayleigh, flotabilidad multipunto para el cabeceo y balanceo de barcos, estelas, espuma y una pasada de máscara para el casco. Los detalles del lado del consumidor importan: las texturas de espuma deben cargarse explícitamente, la geometría submarina de la isla debe descender más allá del fondo oceánico para que este oculte sus bordes y el antialiasing debe ejecutarse como una pasada FXAA de posprocesado, en lugar de utilizar MSAA, para evitar una franja oscura de niebla en los bordes de la geometría.</p>
<hr>
<p>Parte 26 de 29.
Anterior: <a href="/es/blog/2026-05-10-open-world-browser-part-25-universal-characters.html">Parte 25 - Un esqueleto, todos los atuendos</a>
Siguiente: <a href="/es/blog/2026-05-13-open-world-browser-part-27-island-and-terrain.html">Parte 27 - Una isla creada con ruido y un suelo que parece suelo</a>
Guía de la serie: <a href="/es/blog/2026-02-25-open-world-browser-series-guide.html">/es/blog/2026-02-25-open-world-browser-series-guide</a></p>
]]></content:encoded>
            <enclosure url="https://cdn.cinevva.com/blog/why-webgpu-engine-hero.jpg" length="0" type="image/jpg"/>
        </item>
        <item>
            <title><![CDATA[Cómo vencen los motores modernos el sobredibujado del follaje]]></title>
            <link>https://app.cinevva.com/es/blog/2026-05-11-foliage-overdraw</link>
            <guid>https://app.cinevva.com/es/blog/2026-05-11-foliage-overdraw</guid>
            <pubDate>Mon, 11 May 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Prepasadas Z, impostores octaédricos, descarte de clústeres gestionado por GPU, alfa con hash, búferes de visibilidad y sombras mediante campos de distancia: el conjunto de técnicas que reduce un sobredibujado del follaje de 8-15x a 1-2x en escenas de bosques densos.]]></description>
            <content:encoded><![CDATA[<h1 id="como-vencen-los-motores-modernos-el-sobredibujado-del-follaje" tabindex="-1">Cómo vencen los motores modernos el sobredibujado del follaje <a class="header-anchor" href="#como-vencen-los-motores-modernos-el-sobredibujado-del-follaje" aria-label="Permalink to &quot;Cómo vencen los motores modernos el sobredibujado del follaje&quot;"></a></h1>
<p><em>Por <a href="/es/about.html">Oleg Sidorkin</a>, CTO y cofundador de Cinevva</em></p>
<img src="/img/blog/foliage_overdraw_hero.webp" alt="Dosel de un bosque denso con tarjetas de hojas superpuestas y apiladas unas detrás de otras frente a un sol poniente, lo que sugiere un sobredibujado intenso" style="width:100%;border-radius:8px;margin:1.5rem 0" />
<p>Un bosque es una de las peores cosas que se le puede pedir renderizar a una GPU. Cada hoja es un cuadrilátero texturizado recortado mediante una máscara alfa. Decenas de esos cuadriláteros se apilan unos sobre otros a lo largo de cada rayo de visión. El rasterizador no tiene forma de saber de antemano qué fragmentos superarán la prueba alfa, por lo que la optimización estándar de Z temprana que aligera las escenas opacas queda desactivada en su mayor parte. El resultado es que un solo píxel de la pantalla puede ejecutar el shader completo de las hojas 10 o 15 veces antes de completar el fotograma. Eso es el sobredibujado del follaje, y es el componente más costoso de un fotograma de mundo abierto en cualquier juego publicado durante la última década.</p>
<p>La buena noticia es que es un problema resuelto. No en el sentido de que alguien lo haya arreglado con un único truco, sino en el de que existe un conjunto de siete u ocho técnicas que, combinadas, reducen el sobredibujado efectivo de 8-15x en un bosque denso a 1-2x. Todos los motores modernos incluyen alguna versión de este conjunto. Veamos qué contiene, por qué existe cada componente y cuáles son las referencias canónicas de cada uno.</p>
<h2 id="_1-por-que-el-sobredibujado-del-follaje-es-tan-costoso" tabindex="-1">1. Por qué el sobredibujado del follaje es tan costoso <a class="header-anchor" href="#_1-por-que-el-sobredibujado-del-follaje-es-tan-costoso" aria-label="Permalink to &quot;1. Por qué el sobredibujado del follaje es tan costoso&quot;"></a></h2>
<p>En una escena opaca típica, la GPU realiza un rechazo temprano por profundidad: antes incluso de que se ejecute el shader de píxeles, el hardware consulta el búfer de profundidad existente y omite los fragmentos que ya están detrás de algo. Esto es prácticamente gratuito y es lo que mantiene bajo control el coste de la geometría densa.</p>
<p>El follaje con prueba alfa rompe este proceso. El shader de fragmentos tiene que ejecutarse de verdad para evaluar la textura alfa y llamar a <code>discard</code> (o <code>clip</code>) en los píxeles excluidos por la máscara. El hardware no puede saber si se descartará un fragmento hasta después de ejecutar el shader, por lo que, en la mayoría de las GPU, usar <code>discard</code> en cualquier parte de un shader desactiva por completo la Z temprana para esa llamada de dibujo. En las GPU basadas en mosaicos (dispositivos móviles, serie M y algunas consolas), puede desactivar Hi-Z y la compresión de profundidad para todo el fotograma. El shader de píxeles se ejecuta una vez por cada triángulo que cubre un píxel, y la mayoría de esas evaluaciones terminan en un descarte.</p>
<p>Apila 10 cuadriláteros de hojas frente a un solo píxel de la pantalla y el shader de las hojas se ejecutará 10 veces. Multiplícalo por 4 millones de píxeles y el coste será brutal. El artículo de Marco Salvi <a href="https://therealmjp.github.io/posts/to-earlyz-or-not-to-earlyz/" target="_blank" rel="noreferrer">To Early-Z, or Not To Early-Z</a> es la introducción más accesible a por qué sucede esto en el nivel del hardware, y es el lugar adecuado para empezar si nunca te lo habías planteado.</p>
<img src="/img/blog/foliage_overdraw_layers.webp" alt="Vista lateral del rayo de un único píxel de la pantalla atravesando doce tarjetas de hojas superpuestas, con cada tarjeta resaltada para mostrar los fragmentos apilados con prueba alfa" style="width:100%;border-radius:8px;margin:1.5rem 0" />
<h2 id="_2-la-prepasada-de-profundidad-para-geometria-enmascarada" tabindex="-1">2. La prepasada de profundidad para geometría enmascarada <a class="header-anchor" href="#_2-la-prepasada-de-profundidad-para-geometria-enmascarada" aria-label="Permalink to &quot;2. La prepasada de profundidad para geometría enmascarada&quot;"></a></h2>
<p>La mayor mejora individual, y la técnica que incluyen todos los motores modernos, consiste en dividir el dibujado del follaje en dos pasadas. La primera pasada solo escribe la profundidad, con un shader mínimo que realiza la prueba alfa, descarta los píxeles enmascarados y no escribe nada más. La segunda pasada renderiza el material completo con la prueba de profundidad configurada como «igual» y la escritura de profundidad desactivada. Ahora, cada píxel visible sombrea la BRDF completa exactamente una vez, sin importar cuántos cuadriláteros de hojas haya apilados detrás.</p>
<p>Esto puede parecer el doble de trabajo porque se procesan los mismos triángulos dos veces, pero el shader de la prepasada es tan barato —una muestra de textura, un descarte y una escritura de profundidad— que el ahorro en la pasada principal supera con creces el coste adicional. En un bosque denso, la pasada principal pasa de ejecutar el shader completo de las hojas entre 10 y 15 veces por píxel a ejecutarlo exactamente una vez.</p>
<p>Unreal, Frostbite, Decima y las ramas modernas de Rage y Dunia hacen esto. También es la razón principal por la que los materiales enmascarados siguen siendo más baratos que los materiales translúcidos en cualquiera de estos motores.</p>
<p>Análisis en profundidad:</p>
<ul>
<li>Pettineo, <a href="https://therealmjp.github.io/posts/to-earlyz-or-not-to-earlyz/" target="_blank" rel="noreferrer">To Early-Z, or Not To Early-Z</a> (el artículo canónico sobre cómo interactúa <code>discard</code> con Hi-Z y la Z temprana).</li>
<li>Wihlidal, <a href="http://www.frostbite.com/2016/03/optimizing-the-graphics-pipeline-with-compute/" target="_blank" rel="noreferrer">Optimizing the Graphics Pipeline with Compute</a> (GDC 2016, la arquitectura de Frostbite de prepasada de profundidad y descarte dirigido por la prepasada).</li>
<li>Sanders, <a href="https://www.gdcvault.com/play/1025066/Between-Tech-and-Art-The" target="_blank" rel="noreferrer">Between Tech and Art: The Vegetation of Horizon Zero Dawn</a> (GDC 2018, con el renderizado de follaje en dos pasadas de Decima).</li>
<li>Persson, <a href="http://www.humus.name/index.php?page=News&amp;ID=255" target="_blank" rel="noreferrer">A couple of notes about Z</a> (sigue siendo una de las explicaciones más claras de la prueba de profundidad «igual» y de la rentabilidad de una prepasada).</li>
</ul>
<h2 id="_3-lod-agresivos-e-impostores-octaedricos" tabindex="-1">3. LOD agresivos e impostores octaédricos <a class="header-anchor" href="#_3-lod-agresivos-e-impostores-octaedricos" aria-label="Permalink to &quot;3. LOD agresivos e impostores octaédricos&quot;"></a></h2>
<p>La segunda mayor mejora consiste en no dibujar las hojas en absoluto cuando no hace falta. Los recursos de follaje incluyen varios niveles de LOD. El más cercano es la malla completa con tarjetas individuales para cada hoja. A media distancia, las hojas se agrupan en tarjetas compuestas más densas —un grupo de 30 hojas se convierte en una tarjeta texturizada con la misma silueta—. Más allá de un umbral de distancia, el árbol entero se convierte en un <em>impostor</em>: una pequeña pieza de geometría texturizada con vistas prerenderizadas del árbol desde múltiples ángulos.</p>
<p>El formato moderno es el <strong>impostor octaédrico</strong>: una pieza geométrica de 8 caras texturizada con un atlas de vistas capturadas desde puntos de una esfera mediante mapeado octaédrico. Durante la ejecución, el shader elige las dos o tres vistas prerenderizadas más cercanas según la dirección de la cámara y mezcla entre ellas. El resultado es un sustituto de pocos triángulos que parece tridimensional desde cualquier ángulo y que puede tener sombreado correcto, mapas de normales e incluso animación por viento. La implementación de Ryan Brucks, originalmente un plugin de la comunidad y ahora parte de Unreal, es la referencia. Los bosques de mil millones de árboles de Microsoft Flight Simulator son esencialmente impostores octaédricos en todas partes salvo cerca de la cámara.</p>
<p>La mayor ventaja estructural es que los impostores son <em>opacos o casi opacos</em> a distancia. La tarjeta compuesta por 30 hojas es un solo cuadrilátero enmascarado en lugar de 30. El impostor del árbol entero tiene unas pocas caras, no miles. El sobredibujado a larga distancia se reduce a casi nada.</p>
<p>Análisis en profundidad:</p>
<ul>
<li>Brucks, <a href="https://shaderbits.com/blog/octahedral-impostors" target="_blank" rel="noreferrer">Octahedral Impostors</a> (la referencia canónica, con las matemáticas y la implementación para UE).</li>
<li>Halen, <a href="https://dev.epicgames.com/community/learning/tutorials/JmL3/octahedral-impostors-unreal-engine" target="_blank" rel="noreferrer">Octahedral Impostors in Unreal Engine</a> (el flujo de trabajo integrado en UE).</li>
<li>Häggström, <a href="https://www.diva-portal.org/smash/get/diva2:1135856/FULLTEXT01.pdf" target="_blank" rel="noreferrer">Real-Time Rendering of Vegetation</a> (una tesis clara que cubre las cadenas de LOD, los impostores y las matemáticas subyacentes).</li>
<li>Crytek, <a href="http://developer.nvidia.com/gpugems/gpugems3/part-i-geometry/chapter-4-next-generation-speedtree-rendering" target="_blank" rel="noreferrer">SpeedTree integration in CryEngine 3</a> (GPU Gems 3, aún la mejor introducción a las cadenas de LOD para árboles).</li>
</ul>
<h2 id="_4-descarte-de-clusteres-gestionado-por-gpu" tabindex="-1">4. Descarte de clústeres gestionado por GPU <a class="header-anchor" href="#_4-descarte-de-clusteres-gestionado-por-gpu" aria-label="Permalink to &quot;4. Descarte de clústeres gestionado por GPU&quot;"></a></h2>
<p>Incluso con una prepasada de profundidad, la propia prepasada tiene un coste: todavía debe <em>procesar</em> cada triángulo de cada árbol visible —o potencialmente visible—. Los motores modernos reducen ese coste mediante el descarte de clústeres gestionado por GPU, que elimina grupos enteros de triángulos antes de que lleguen al rasterizador.</p>
<p>La canalización funciona así: cada malla se divide previamente en clústeres de 64 o 128 triángulos con una caja delimitadora ajustada y un cono de normales. Durante el renderizado, un shader de cómputo recorre la lista de instancias, comprueba cada instancia contra el frustum, después comprueba contra el frustum cada clúster de cada instancia visible y, por último, realiza una <em>prueba de oclusión Hi-Z</em> de cada clúster superviviente contra la pirámide de profundidad del fotograma anterior. Las ramas completas de los árboles que quedan ocultas detrás de una colina o delante de otro árbol se descartan antes de que se ejecute ningún shader de vértices. El resultado es una lista compacta de argumentos del tipo «dibuja estos clústeres», enviada directamente a una única llamada <code>DrawIndirect</code>.</p>
<p>Esto es lo que permite renderizar un bosque de 10 000 árboles en milisegundos en lugar de segundos. La charla de Ubisoft sobre Assassin's Creed Unity presentó esta canalización en un entorno de producción —entre un 20 y un 40 % de triángulos descartados, entre un 30 y un 80 % de triángulos de sombras descartados y 10 veces más instancias en pantalla que en la generación anterior—, y la charla de Wihlidal sobre Frostbite la llevó aún más lejos. Nanite de UE5 es el resultado visible de esta evolución: descarte de clústeres hasta el nivel del píxel.</p>
<p>Análisis en profundidad:</p>
<ul>
<li>Haar y Aaltonen, <a href="https://advances.realtimerendering.com/s2015/aaltonenhaar_siggraph2015_combined_final_footer_220dpi.pdf" target="_blank" rel="noreferrer">GPU-Driven Rendering Pipelines</a> (SIGGRAPH 2015, la charla fundacional sobre Assassin's Creed Unity).</li>
<li>Wihlidal, <a href="http://www.frostbite.com/2016/03/optimizing-the-graphics-pipeline-with-compute/" target="_blank" rel="noreferrer">Optimizing the Graphics Pipeline with Compute</a> (GDC 2016, la prepasada gestionada por GPU de Frostbite).</li>
<li>Karis, Stubbe y Wihlidal, <a href="https://advances.realtimerendering.com/s2021/Karis_Nanite_SIGGRAPH_Advances_2021_final.pdf" target="_blank" rel="noreferrer">A Deep Dive into Nanite Virtualized Geometry</a> (SIGGRAPH 2021, descarte de clústeres con granularidad de meshlet).</li>
<li>Liktor, <a href="https://research.activision.com/publications/2021/09/geometry-rendering-pipeline-architecture-at-activision" target="_blank" rel="noreferrer">Geometry Rendering Pipeline Architecture at Activision</a> (la versión de Call of Duty del descarte de clústeres, 2021).</li>
</ul>
<h2 id="_5-ordenacion-de-instancias-y-clusteres-de-delante-hacia-atras" tabindex="-1">5. Ordenación de instancias y clústeres de delante hacia atrás <a class="header-anchor" href="#_5-ordenacion-de-instancias-y-clusteres-de-delante-hacia-atras" aria-label="Permalink to &quot;5. Ordenación de instancias y clústeres de delante hacia atrás&quot;"></a></h2>
<p>Cuando la prepasada cumple su función, el <em>orden</em> empieza a importar. La prepasada escribe la profundidad, pero solo para los fragmentos que superan la prueba alfa. Si primero dibujas la parte trasera del bosque y al final la delantera, cada fragmento delantero sobrescribe uno trasero, y el shader de la prepasada sigue ejecutándose para la parte trasera. Si dibujas de delante hacia atrás, cada llamada sucesiva llena una parte mayor del búfer de profundidad con valores más pequeños, y Hi-Z rechaza cada vez más fragmentos traseros antes de que se ejecute el shader.</p>
<p>Por eso casi todos los motores modernos ordenan las instancias de follaje por distancia a la cámara antes de emitir la prepasada. La ordenación es barata —unos cientos de miles de instancias en la GPU mediante una ordenación radix— y convierte la propia prepasada en una operación que se va reduciendo a sí misma. Por el mismo motivo, el descarte a nivel de clúster ordena con granularidad de meshlet. La prepasada de profundidad y la ordenación de delante hacia atrás forman una de esas parejas en las que cada técnica es buena por separado, pero la combinación es excelente.</p>
<p>Análisis en profundidad:</p>
<ul>
<li>Persson, <a href="http://www.humus.name/Articles/Persson_DepthInDepth.pdf" target="_blank" rel="noreferrer">Depth in-depth</a> (notas arquitectónicas sobre la ordenación del búfer de profundidad, la rentabilidad de una prepasada y el comportamiento de Hi-Z).</li>
<li>Giesen, <a href="https://fgiesen.wordpress.com/2011/07/04/a-trip-through-the-graphics-pipeline-2011-part-7/" target="_blank" rel="noreferrer">A trip through the graphics pipeline</a> (la explicación técnica detallada de cómo depende la tasa de rechazo de Hi-Z del orden de dibujado).</li>
<li>Wihlidal, <a href="http://www.frostbite.com/2016/03/optimizing-the-graphics-pipeline-with-compute/" target="_blank" rel="noreferrer">Optimizing the Graphics Pipeline with Compute</a> (GDC 2016, incluye la ordenación de instancias en la GPU de Frostbite).</li>
</ul>
<h2 id="_6-transiciones-de-lod-con-tramado-y-alfa-con-hash" tabindex="-1">6. Transiciones de LOD con tramado y alfa con hash <a class="header-anchor" href="#_6-transiciones-de-lod-con-tramado-y-alfa-con-hash" aria-label="Permalink to &quot;6. Transiciones de LOD con tramado y alfa con hash&quot;"></a></h2>
<p>La otra gran trampa son los fundidos. La forma ingenua de realizar la transición entre dos LOD —o de hacer aparecer o desaparecer gradualmente una instancia a medida que se acerca la cámara— es la mezcla alfa. Pero la geometría mezclada no puede escribir en el búfer de profundidad, lo que envía cada árbol en transición a la lenta ruta de translúcidos y rompe la prepasada. La solución es mantener la geometría en la ruta enmascarada y realizar el fundido <em>dentro de la prueba alfa</em>.</p>
<p>Dos técnicas principales:</p>
<ul>
<li>Las <strong>transiciones de LOD con tramado</strong> muestrean un patrón de Bayer de 4x4 u 8x8 —o una textura de ruido azul en el espacio de pantalla— y lo usan como modificador del umbral por píxel. En un árbol con una mezcla del 50 %, sobrevive un patrón ajedrezado de píxeles; los píxeles ausentes los rellena el patrón complementario del siguiente LOD. El TAA convierte el patrón en una transición suave a lo largo de dos o tres fotogramas. Es barato, estable y se integra con todo lo demás en el motor.</li>
<li>La <strong>prueba alfa con hash</strong> (Wyman y McGuire, I3D 2017) sustituye el umbral alfa fijo de 0,5 por un umbral con hash por píxel en [0,1). La geometría alfa distante que normalmente desaparecería por completo —porque el alfa con mipmapping cae por debajo de 0,5— conserva una dispersión estable de píxeles supervivientes. De nuevo, el TAA se encarga de suavizar el resultado.</li>
</ul>
<p>Ambas técnicas mantienen el follaje en la ruta opaca o enmascarada donde funciona la prepasada de profundidad, por lo que no hay que asumir el coste completo del renderizado translúcido solo para hacer aparecer algo gradualmente. <strong>Alfa a cobertura</strong> es el equivalente de la época del MSAA: convierte el alfa en una máscara de cobertura de subpíxeles y obtiene transparencia parcial sin abandonar la ruta enmascarada. El inconveniente es que A2C solo destaca de verdad con MSAA, que la mayoría de los renderizadores diferidos modernos ya no utilizan.</p>
<p>Análisis en profundidad:</p>
<ul>
<li>Wyman y McGuire, <a href="https://research.nvidia.com/labs/rtr/publication/wyman2017hashed/" target="_blank" rel="noreferrer">Hashed Alpha Testing</a> (I3D 2017, el artículo canónico sobre alfa con hash).</li>
<li>Castaño, <a href="http://the-witness.net/news/2010/09/computing-alpha-mipmaps/" target="_blank" rel="noreferrer">Computing Alpha Mipmaps</a> (blog de The Witness, la forma correcta de generar mipmaps para texturas con prueba alfa sin que los árboles lejanos desaparezcan).</li>
<li>Yuksel, <a href="https://cemyuksel.com/research/alphadistribution/alpha_distribution.pdf" target="_blank" rel="noreferrer">Alpha Distribution for Alpha Testing</a> (una mejora más reciente para los mipmaps alfa).</li>
<li>NVIDIA, <a href="https://developer.nvidia.com/content/transparency-or-translucency-rendering" target="_blank" rel="noreferrer">Anti-Aliased Alpha Testing</a> (un repaso de A2C, alfa con hash y alternativas con tramado).</li>
</ul>
<h2 id="_7-reduccion-del-coste-de-sombreado-en-pixeles-enmascarados" tabindex="-1">7. Reducción del coste de sombreado en píxeles enmascarados <a class="header-anchor" href="#_7-reduccion-del-coste-de-sombreado-en-pixeles-enmascarados" aria-label="Permalink to &quot;7. Reducción del coste de sombreado en píxeles enmascarados&quot;"></a></h2>
<p>Incluso con una prepasada perfecta y un descarte perfecto, todavía hay que sombrear una vez cada píxel visible del follaje. Los motores también reducen ese coste:</p>
<ul>
<li><strong>BRDF más barato</strong>. El follaje es mate y realmente no necesita una ruta especular Cook-Torrance completa. Basta con una reflexión difusa Lambertiana envuelta y una aproximación especular de una sola línea.</li>
<li><strong>Mapas de normales de menor frecuencia</strong>. Las hojas ya tienen mucho ruido visual. Un mapa de normales de 256x256 se ve igual que uno de 1024x1024 a distancias de observación habituales y ahorra ancho de banda.</li>
<li><strong>Sin paralaje, anisotropía ni capa transparente</strong>. El menú de funciones PBR se desactiva para las hojas.</li>
<li><strong>Transmisión fina de dos caras</strong> en lugar de dispersión subsuperficial completa. Las hojas transmiten la luz desde detrás, pero puede simularse con un único producto escalar de contraluz.</li>
<li><strong>Sombreado a media resolución</strong> en algunos motores. El follaje se sombrea a una tasa de 1/4 o 1/2 píxel y luego se reescala. El ruido estocástico del TAA oculta el remuestreo.</li>
<li><strong>Omitir texturas de detalle y calcomanías</strong> en materiales enmascarados de forma predeterminada.</li>
</ul>
<p>Cada una de estas optimizaciones supone una pequeña mejora por separado. Combinadas, los shaders de follaje enmascarado pueden ejecutarse entre 2 y 3 veces más rápido que el material opaco equivalente.</p>
<p>Análisis en profundidad:</p>
<ul>
<li>Lagarde y de Rousiers, <a href="https://seblagarde.wordpress.com/2015/07/14/siggraph-2014-moving-frostbite-to-physically-based-rendering/" target="_blank" rel="noreferrer">Migración de Frostbite al renderizado basado en física 3.0, secciones sobre follaje y translucidez</a> (SIGGRAPH 2014, los ajustes PBR de referencia para materiales finos de dos caras).</li>
<li>Jimenez, <a href="https://www.iryoku.com/stare-into-the-future" target="_blank" rel="noreferrer">Renderizado de personajes de nueva generación</a> (las matemáticas de Lambert envuelto y translucidez posterior, creadas originalmente para la piel pero adaptadas ampliamente a las hojas).</li>
<li>Sanders, <a href="https://www.gdcvault.com/play/1025066/Between-Tech-and-Art-The" target="_blank" rel="noreferrer">Entre la tecnología y el arte: la vegetación de Horizon Zero Dawn</a> (GDC 2018, con las simplificaciones del shader de follaje de Decima).</li>
</ul>
<h2 id="_8-buferes-de-visibilidad-y-nanite-para-materiales-enmascarados" tabindex="-1">8. Búferes de visibilidad y Nanite para materiales enmascarados <a class="header-anchor" href="#_8-buferes-de-visibilidad-y-nanite-para-materiales-enmascarados" aria-label="Permalink to &quot;8. Búferes de visibilidad y Nanite para materiales enmascarados&quot;"></a></h2>
<p>La solución más limpia al sobredibujado es <em>desacoplar por completo el sombreado de la rasterización</em>. Un búfer de visibilidad rasteriza la geometría en un búfer ligero (solo el ID del triángulo y el ID de la instancia por píxel) y luego ejecuta el material completo como un pase diferido que lee el búfer de visibilidad y sombrea cada píxel exactamente una vez. Por diseño, no hay sobredibujado en la etapa de sombreado. El artículo de Burns y Hunt de 2013 presentó esta técnica; Nanite de UE5 es su implementación con calidad de producción, incluso para follaje enmascarado desde UE 5.5.</p>
<p>La particularidad de Nanite es que lo hace con geometría virtualizada a nivel de clúster, por lo que el propio rasterizador utiliza una ruta de software para triángulos de tamaño inferior a un píxel y mantiene limitado el sobredibujado. Los materiales enmascarados de Nanite necesitan la función de «rasterización programable»: la prueba alfa se ejecuta durante el pase del búfer de visibilidad, pero el sombreado del material sigue realizándose una sola vez por píxel visible durante la resolución diferida. El resultado es que el follaje muy denso de Nanite, antes conocido por su lentitud con materiales enmascarados, ahora es competitivo con los materiales opacos o incluso más barato, porque el sobredibujado durante el sombreado es nulo. Hay una contrapartida: a menudo es mejor procesar geometría de árboles <em>opaca</em> y con muchos polígonos mediante Nanite que conservar árboles de pocas caras construidos con tarjetas enmascaradas, porque la ruta enmascarada añade el coste de la rasterización programable.</p>
<p>Análisis en profundidad:</p>
<ul>
<li>Burns y Hunt, <a href="http://jcgt.org/published/0002/02/04/" target="_blank" rel="noreferrer">El búfer de visibilidad: un enfoque de sombreado diferido eficiente para la caché</a> (JCGT 2013, el artículo original).</li>
<li>Karis, Stubbe, Wihlidal, <a href="https://advances.realtimerendering.com/s2021/Karis_Nanite_SIGGRAPH_Advances_2021_final.pdf" target="_blank" rel="noreferrer">Análisis en profundidad de la geometría virtualizada de Nanite</a> (SIGGRAPH 2021, la arquitectura de producción).</li>
<li>Epic, <a href="https://media.gdcvault.com/gdc2024/Slides/GDC+slide+presentations/Nanite+GPU+Driven+Materials.pdf" target="_blank" rel="noreferrer">Materiales de Nanite controlados por la GPU</a> (GDC 2024, con la canalización de materiales enmascarados y rasterización programable).</li>
<li><a href="https://www.sctheblog.com/blog/nanite-materials-notes/" target="_blank" rel="noreferrer">Notas de «Materiales de Nanite controlados por la GPU»</a> (una explicación clara de terceros sobre la misma charla).</li>
</ul>
<h2 id="_9-representaciones-de-sombras-separadas-para-el-follaje" tabindex="-1">9. Representaciones de sombras separadas para el follaje <a class="header-anchor" href="#_9-representaciones-de-sombras-separadas-para-el-follaje" aria-label="Permalink to &quot;9. Representaciones de sombras separadas para el follaje&quot;"></a></h2>
<p>Los mapas de sombras para follaje con prueba alfa son el segundo problema de sombras más costoso de cualquier fotograma de mundo abierto, después de las cascadas grandes. Cada cascada necesita su propio prepase de profundidad, cada prepase ejecuta la prueba alfa y el coste se acumula rápidamente entre 4 cascadas y decenas de frustos de luz. Por eso, la mayoría de los motores no renderizan las sombras del follaje del mismo modo que su color.</p>
<p>Sustituciones habituales:</p>
<ul>
<li><strong>Sombras mediante campos de distancia de malla</strong> (UE Lumen, motores personalizados). Cada malla tiene un campo de distancia con signo precalculado. Un breve trazado de conos a través del SDF produce una sombra suave sin tocar nunca la malla con prueba alfa. Resulta especialmente adecuado para los árboles porque el SDF captura la silueta de la copa como una única masa sólida e ignora el detalle de cada hoja.</li>
<li><strong>Cascadas de menor resolución para el follaje</strong>. Las sombras del follaje se escriben en una sección a media resolución y se amplían mediante un filtrado sensible a los bordes. El ojo no percibe la pérdida de resolución porque las sombras ya son suaves.</li>
<li><strong>Mapas de sombras de alfa a cobertura con MSAA</strong>. En los motores que aún utilizan MSAA en su ruta de sombras, A2C produce sombras de follaje con bordes suaves sin el coste completo de la prueba alfa.</li>
<li><strong>Sombras de cápsula para el tronco y las ramas grandes</strong>, campo de distancia para la copa y prueba alfa completa solo en la cascada más cercana. Se emplean representaciones distintas para diferentes distancias y se combinan en el pase de iluminación.</li>
<li><strong>Distancia de desactivación de WPO</strong>. El desplazamiento de posición en el mundo impulsado por el viento se desactiva más allá de un umbral para que los datos de sombras almacenados en caché sigan siendo válidos entre fotogramas. Los mapas de sombras virtuales de UE dependen en gran medida de esta técnica.</li>
</ul>
<p>Análisis en profundidad:</p>
<ul>
<li>Epic, <a href="https://dev.epicgames.com/documentation/unreal-engine/distance-field-soft-shadows-in-unreal-engine" target="_blank" rel="noreferrer">Sombras suaves mediante campos de distancia en Unreal Engine</a> (la referencia de UE para las sombras mediante campos de distancia de malla).</li>
<li>Wright, <a href="https://advances.realtimerendering.com/s2022/SIGGRAPH2022-Advances-Lumen-Wright%20et%20al.pdf" target="_blank" rel="noreferrer">Lumen: iluminación global en tiempo real en Unreal Engine 5</a> (SIGGRAPH 2022, con la integración de los SDF de malla de Lumen para el follaje).</li>
<li>Epic, <a href="https://dev.epicgames.com/documentation/en-us/unreal-engine/virtual-shadow-maps-in-unreal-engine" target="_blank" rel="noreferrer">Mapas de sombras virtuales</a> (la arquitectura moderna de sombras de UE5, con las reglas específicas del follaje para desactivar WPO y gestionar la caché).</li>
<li>Persson, <a href="https://www.humus.name/index.php?page=3D&amp;ID=81" target="_blank" rel="noreferrer">Mapas de sombras en cascada prácticos</a> (la referencia aún vigente sobre CSM, con notas acerca de los emisores de sombras con prueba alfa).</li>
</ul>
<h2 id="_10-viento-animacion-y-cache-de-sombras" tabindex="-1">10. Viento, animación y caché de sombras <a class="header-anchor" href="#_10-viento-animacion-y-cache-de-sombras" aria-label="Permalink to &quot;10. Viento, animación y caché de sombras&quot;"></a></h2>
<p>Un problema relacionado y sutil: la mayor parte del follaje se mueve. La animación de vértices impulsada por el viento (World Position Offset en UE y sus equivalentes en Frostbite y Decima) hace que la geometría del follaje no sea estable entre fotogramas, lo cual rompe la caché de sombras y la reproyección. Los motores modernos combaten esto de dos formas:</p>
<ul>
<li><strong>Limitar WPO a cierta distancia</strong>. Más allá de un umbral, la amplitud de la animación del viento se reduce gradualmente hasta cero. De todos modos, el ojo no puede apreciar el balanceo a tanta distancia, y las cachés de sombras siguen siendo válidas.</li>
<li><strong>Incorporar el viento a los límites del clúster</strong>. Las cajas delimitadoras de los clústeres se amplían según el desplazamiento WPO máximo, de modo que el descarte siga siendo conservador sin volver a cargar datos en cada fotograma.</li>
<li><strong>Desfases por instancia</strong>. Los árboles idénticos utilizan una semilla aleatoria por instancia para desfasar la animación del viento, de modo que un bosque no se balancee al unísono sin tener que pagar una animación única para cada árbol.</li>
</ul>
<p>Este es el tipo de detalle que no aparece en las listas de técnicas, pero que en la práctica marca la diferencia entre un bosque de 3 ms y uno de 9 ms.</p>
<p>Análisis en profundidad:</p>
<ul>
<li>Sanders, <a href="https://www.gdcvault.com/play/1025066/Between-Tech-and-Art-The" target="_blank" rel="noreferrer">Entre la tecnología y el arte: la vegetación de Horizon Zero Dawn</a> (GDC 2018, con la canalización de animación del viento y la caché de sombras de Decima).</li>
<li>McAuley, <a href="https://www.gdcvault.com/play/1022235/Rendering-the-World-of-Far" target="_blank" rel="noreferrer">Renderizado del mundo de Far Cry 4</a> (GDC 2015, incluye el muestreo de la cuadrícula de viento para la vegetación).</li>
<li>Epic, <a href="https://dev.epicgames.com/community/learning/tutorials/qLk6/unreal-engine-virtual-shadow-maps" target="_blank" rel="noreferrer">Follaje y mapas de sombras virtuales</a> (las recomendaciones de la comunidad de UE5 sobre la distancia de desactivación de WPO y la caché de VSM).</li>
</ul>
<h2 id="_11-las-matematicas-combinadas" tabindex="-1">11. Las matemáticas combinadas <a class="header-anchor" href="#_11-las-matematicas-combinadas" aria-label="Permalink to &quot;11. Las matemáticas combinadas&quot;"></a></h2>
<p>Ninguna de estas técnicas es una solución mágica. Lo interesante es lo que sucede al combinarlas:</p>
<ul>
<li>Un pase de follaje enmascarado ingenuo en una escena de bosque denso presenta un sobredibujado efectivo de entre 8 y 15 veces. Cada píxel visible ejecuta el shader de hojas entre 8 y 15 veces.</li>
<li>Al añadir un prepase de profundidad, el pase principal baja a un sobredibujado de ~1x, pero el propio prepase todavía toca toda la geometría.</li>
<li>Al añadir ordenación de delante hacia atrás, el prepase empieza a descartar trabajo por sí mismo.</li>
<li>Al añadir descarte por GPU a nivel de clúster, el prepase solo toca lo que podría llegar a ser visible.</li>
<li>Al añadir cadenas de LOD e impostores, la <em>cantidad</em> de cuadriláteros visibles se reduce en un orden de magnitud más allá de 30 m.</li>
<li>Al añadir la ruta de búfer de visibilidad/Nanite, la etapa de sombreado se ejecuta realmente una sola vez por píxel, incluso con una superposición densa.</li>
<li>Al añadir sombras mediante campos de distancia, el coste de las sombras deja de escalar con la prueba alfa.</li>
</ul>
<p>El resultado principal, repetido en las charlas enlazadas anteriormente: el sobredibujado efectivo se desploma de 8-15x a 1-2x, y el coste total del follaje por fotograma se reduce entre 4 y 6 veces en una escena de bosque denso. Esa es la razón por la que los juegos modernos de mundo abierto pueden renderizar bosques a más de 60 fps en hardware de consumo.</p>
<img src="/img/blog/foliage_overdraw_pipeline.webp" alt="Diagrama que muestra la canalización de renderizado del follaje como cinco etapas apiladas: descarte por GPU, prepase ordenado, pase de color enmascarado con profundidad igual, sombreado mediante búfer de visibilidad y una ruta separada de sombras mediante campos de distancia" style="width:100%;border-radius:8px;margin:1.5rem 0" />
<h2 id="_12-que-significa-esto-para-el-navegador" tabindex="-1">12. Qué significa esto para el navegador <a class="header-anchor" href="#_12-que-significa-esto-para-el-navegador" aria-label="Permalink to &quot;12. Qué significa esto para el navegador&quot;"></a></h2>
<p>La mayor parte de este conjunto de técnicas se adapta limpiamente a WebGPU. Ya hemos implementado descarte controlado por la GPU, despacho indirecto, oclusión Hi-Z y prepases ordenados de delante hacia atrás en el <a href="/es/blog/2026-02-25-open-world-browser-series-guide.html">motor de mundo abierto para navegadores</a>. El prepase de profundidad para geometría enmascarada es sencillo: WebGPU admite pruebas de igualdad de profundidad y <code>discard</code> en shaders de fragmentos, con las mismas salvedades respecto a early-Z. Los impostores octaédricos se trasladan de forma mecánica; las matemáticas se reducen al desplegado de esfera a octaedro y la indexación del atlas.</p>
<p>Las partes más difíciles son las modernas. Un búfer de visibilidad en WebGPU implica escribir un ID de triángulo de 32 bits en un destino de renderizado y resolver los materiales en un pase de cómputo a pantalla completa; los componentes necesarios existen, pero su orquestación es compleja. Las sombras mediante campos de distancia de malla requieren una textura 3D por recurso y un trazado de conos corto, dos cosas que están al alcance de WebGPU. El alfa con hash y los LOD con tramado requieren una sola función de shader cada uno.</p>
<p>El camino que debe seguir el follaje en el navegador es el mismo que el del resto de este conjunto tecnológico: lanzar primero las técnicas baratas y robustas (prepase, instancias ordenadas, LOD, impostores y alfa con hash) y añadir después la maquinaria pesada (búfer de visibilidad y sombras mediante SDF de malla). El nivel mínimo del hardware para navegadores por fin es lo bastante alto como para que no haya ninguna razón arquitectónica por la que un bosque de WebGPU no pueda verse y funcionar como uno de consola. Solo quedan razones de ingeniería, y las razones de ingeniería son las que nos gustan.</p>
<h2 id="lecturas-adicionales-sobre-todo-el-conjunto-tecnologico" tabindex="-1">Lecturas adicionales sobre todo el conjunto tecnológico <a class="header-anchor" href="#lecturas-adicionales-sobre-todo-el-conjunto-tecnologico" aria-label="Permalink to &quot;Lecturas adicionales sobre todo el conjunto tecnológico&quot;"></a></h2>
<p>Si buscas una única fuente que reúna todo esto, el archivo «Advances in Real-Time Rendering in Games» de SIGGRAPH (<a href="https://advances.realtimerendering.com/" target="_blank" rel="noreferrer">advances.realtimerendering.com</a>) contiene las charlas de referencia sobre follaje y renderizado controlado por la GPU desde 2014. Los <a href="http://www.adriancourreges.com/blog/" target="_blank" rel="noreferrer">artículos de análisis de GPU</a> de Adrian Courrèges incluyen desgloses fotograma a fotograma de GTA V y Horizon Zero Dawn que muestran cada pase analizado aquí en su orden de producción. Para las matemáticas de la prueba alfa en particular, la <a href="https://cwyman.org/" target="_blank" rel="noreferrer">página de investigación</a> de Chris Wyman contiene los artículos sobre alfa con hash y transparencia estocástica, además de shaders de referencia. Y los capítulos de <a href="https://www.realtimerendering.com/" target="_blank" rel="noreferrer">Real-Time Rendering, 4.ª edición</a> sobre transparencia, muestreo y gestión de la profundidad siguen siendo el punto de partida académico.</p>
]]></content:encoded>
            <enclosure url="https://app.cinevva.com/img/blog/foliage_overdraw_hero.webp" length="0" type="image/webp"/>
        </item>
        <item>
            <title><![CDATA[Construir un mundo abierto en el navegador, parte 25: Un esqueleto, todos los atuendos]]></title>
            <link>https://app.cinevva.com/es/blog/2026-05-10-open-world-browser-part-25-universal-characters</link>
            <guid>https://app.cinevva.com/es/blog/2026-05-10-open-world-browser-part-25-universal-characters</guid>
            <pubDate>Sun, 10 May 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[El Spike 50 puso a prueba si un paquete de personajes CC0 podía servir de base para un producto de personalización de avatares. Resultó que cuatro paquetes de Quaternius compartían deliberadamente un único esqueleto de 65 articulaciones, lo que convirtió el spike de un problema de canalización de animaciones en un ejercicio de revinculación del esqueleto por nombre.]]></description>
            <content:encoded><![CDATA[<h1 id="construir-un-mundo-abierto-en-el-navegador-parte-25-un-esqueleto-todos-los-atuendos" tabindex="-1">Construir un mundo abierto en el navegador, parte 25: Un esqueleto, todos los atuendos <a class="header-anchor" href="#construir-un-mundo-abierto-en-el-navegador-parte-25-un-esqueleto-todos-los-atuendos" aria-label="Permalink to &quot;Construir un mundo abierto en el navegador, parte 25: Un esqueleto, todos los atuendos&quot;"></a></h1>
<p><em>Por <a href="/es/about.html">Oleg Sidorkin</a>, CTO y cofundador de Cinevva</em></p>
<p>¿Acabas de llegar? Consulta la <a href="/es/blog/2026-02-25-open-world-browser-series-guide.html">guía de la serie</a>. Explica qué es un spike y enlaza todas las partes.</p>
<p>La <a href="/es/blog/2026-05-09-open-world-browser-part-24-persistence-and-wind.html">parte 24</a> hizo que el mundo fuera persistente y dio viento a su vegetación. Esta parte vuelve a tratar sobre las personas que lo habitan, pero desde el lado del vestuario: ¿puede un creador elegir un cuerpo base, cambiar la ropa, escoger un peinado y reproducir cualquier animación, todo con un paquete de recursos gratuito, sin rigging ni creación de animaciones? Crear un rig personalizado no es lo que conviene validar para reducir riesgos. La pregunta que merece respuesta es si un paquete CC0 puede soportar toda la carga.</p>
<h2 id="un-paquete-creado-para-encajar" tabindex="-1">Un paquete creado para encajar <a class="header-anchor" href="#un-paquete-creado-para-encajar" aria-label="Permalink to &quot;Un paquete creado para encajar&quot;"></a></h2>
<div style="position:relative;padding-bottom:56.25%;height:0;overflow:hidden;border-radius:8px;margin:1.5rem 0;border:1px solid rgba(255,255,255,0.12)">
<iframe src="/es/spikes/50-universal-characters/" title="Spike 50: personajes universales" style="position:absolute;top:0;left:0;width:100%;height:100%;border:0;background:#000" loading="lazy" allowfullscreen></iframe>
</div>
<p><a href="/es/spikes/50-universal-characters/" target="_blank">Abrir el Spike 50 en una pestaña nueva ↗</a> · <a href="/es/blog/spike-source?spike=50-universal-characters">Ver código fuente</a></p>
<p>Quaternius ofrece cuatro recursos que encajan de una forma casi sospechosamente perfecta: Universal Base Characters, con cuerpos masculinos y femeninos, además de ocho peinados y dos conjuntos de cejas; Modular Character Outfits, dividido en piezas para cuerpo, brazos, piernas y pies, con accesorios como hombreras y una capucha; y los paquetes uno y dos de Universal Animation Library, con un total de 262 clips que abarcan locomoción, combate, escalada, agricultura, pesca, poses inactivas y movimientos sociales. Al inspeccionar sus glTF se reveló por qué encajan: absolutamente todas las mallas de los cuatro paquetes están vinculadas al mismo esqueleto de estilo UE5 con 65 articulaciones, con los mismos nombres de articulaciones y las mismas poses de enlace, desde la raíz, pasando por la pelvis y la columna, hasta la cabeza, con brazos simétricos que incluyen quince articulaciones de dedos por lado y piernas simétricas. No hace falta retargeting. Esto es exactamente lo contrario del problema de retargeting entre tres esqueletos del Spike 35, donde un rig facial de 213 huesos tenía que comunicarse con un rig de Mixamo de 65 huesos. Aquí, los cuatro paquetes se crearon deliberadamente sobre el esqueleto de la biblioteca de animaciones, y la correspondencia es exacta.</p>
<p>Eso convirtió el spike en un ejercicio de vinculación en lugar de un problema de canalización de animaciones. La capa base carga el glTF de un cuerpo, clona la escena con <code>SkeletonUtils.clone</code> para que cada personaje obtenga una instancia nueva del esqueleto en vez de devolver las mutaciones de los huesos a la escena almacenada en caché por el cargador, y guarda en caché ese esqueleto de 65 huesos como referencia canónica junto con el objeto de armadura que sirve de raíz para la animación.</p>
<h2 id="revincular-un-abrigo-a-un-cuerpo" tabindex="-1">Revincular un abrigo a un cuerpo <a class="header-anchor" href="#revincular-un-abrigo-a-un-cuerpo" aria-label="Permalink to &quot;Revincular un abrigo a un cuerpo&quot;"></a></h2>
<p>El truco que hace funcionar todo esto es que no se puede simplemente cambiar la malla de un atuendo de padre dentro de la escena, porque sigue haciendo referencia a los huesos de su propio glTF, que se encuentran en un subárbol diferente. Cada pieza modular —el cuerpo de un campesino o las piernas de un explorador— llega como su propio SkinnedMesh con su propio clon de la misma armadura. La vinculación recorre los huesos del esqueleto de origen en su orden original, busca cada uno por nombre en el esqueleto canónico y crea un nuevo <code>Skeleton</code> a partir de esos huesos revinculados, reutilizando las matrices inversas de enlace del origen; después llama a <code>SkinnedMesh.bind</code> con la matriz de enlace identidad del origen. Tras la vinculación, la malla se separa de su escena de origen y pasa a depender directamente de la raíz del personaje. Como la matriz de enlace captura la transformación global en el momento de la vinculación y la raíz se encuentra en identidad, la transformación global de la propia malla nunca afecta al resultado y el skinning se realiza por completo a través de los huesos ahora compartidos.</p>
<p>El pelo y las cejas también son ranuras, y permitieron corregir una suposición errónea. La estructura de carpetas decía «vinculado al hueso de la cabeza», lo que sugería que el pelo sería una malla estática dependiente de la cabeza con un desplazamiento predefinido. No es así. Cada archivo de pelo es un SkinnedMesh ponderado entre las 65 articulaciones, y los pesos del pelo largo se extienden hasta la parte superior de la columna y el cuello para que caiga de forma natural cuando el personaje mira hacia abajo. Por tanto, el pelo sigue la misma ruta de revinculación por nombre que cualquier pieza de atuendo. El único caso especial es la ranura del cuerpo del atuendo: cuando se adjunta, la malla del cuerpo base se oculta para que no atraviese el atuendo, mientras que los brazos, las piernas, los pies y los accesorios simplemente se superponen, porque el paquete se diseñó para que coexistieran con el cuerpo base visible allí donde la ropa deja piel al descubierto.</p>
<h2 id="_262-animaciones-gratuitas" tabindex="-1">262 animaciones gratuitas <a class="header-anchor" href="#_262-animaciones-gratuitas" aria-label="Permalink to &quot;262 animaciones gratuitas&quot;"></a></h2>
<p>La animación resulta casi trivial una vez que se comparte el esqueleto. Se cargan los dos glb de las bibliotecas, sus clips se combinan en una única lista con nombres y las pistas de esos clips hacen referencia a los nombres exactos de las articulaciones mediante <code>bone.position</code>, <code>bone.quaternion</code> y <code>bone.scale</code>. Un <code>AnimationMixer</code> cuya raíz es la armadura del personaje encuentra esos huesos por nombre y los controla directamente, aplicando una transición fundida al cambiar. El panel derecho del visor contiene una lista filtrable con los 262 clips y una etiqueta de origen, de modo que buscar «fish» muestra todas las animaciones de pesca de ambas bibliotecas. Una iluminación estándar de tres puntos con sombras suaves, una cuadrícula polar bajo los pies y el mapeo tonal ACES mantienen legibles las texturas base estilizadas sin empastar las sombras del traje oscuro.</p>
<p>La reducción de riesgos para el producto es considerable. La función de personalización de avatares puede publicarse con un paquete CC0 sin ningún trabajo de rigging ni creación de animaciones: basta con incorporar los cuatro paquetes y conectar una interfaz de vestuario para obtener, desde el primer momento, aproximadamente seis atuendos por ocho peinados, por dos sexos y por 262 animaciones de variación. El esqueleto de 65 articulaciones es lo bastante pequeño como para que el coste del skinning en la GPU sea insignificante, y el trabajo de skinning por lotes del Spike 45 ya permite manejar más de 200 avatares con un rig de este tamaño. CC0 no impone restricciones de uso, por lo que puede utilizarse comercialmente en una plataforma de pago para creadores. La pregunta pendiente son los atuendos personalizados que suban los usuarios, un problema de la fase 3 que se resolverá aplicando retargeting en el momento de la subida hacia este esqueleto canónico, a la inversa del retargeting en tiempo de ejecución del Spike 35. Los recursos ocupan alrededor de 147 MB en disco como archivos PNG 2K sin procesar y glb de animación sin comprimir, una cifra que en producción se reduciría a unos 30 MB mediante compresión de texturas KTX2 y una pasada con gltf-transform.</p>
<h2 id="tecnologia-mencionada-en-este-capitulo" tabindex="-1">Tecnología mencionada en este capítulo <a class="header-anchor" href="#tecnologia-mencionada-en-este-capitulo" aria-label="Permalink to &quot;Tecnología mencionada en este capítulo&quot;"></a></h2>
<p><strong>Un único esqueleto canónico para todo el paquete.</strong> Los cuatro paquetes de Quaternius —cuerpos base, atuendos modulares y dos bibliotecas de animaciones— están vinculados a un esqueleto idéntico de estilo UE5 con 65 articulaciones, los mismos nombres de articulaciones y las mismas poses de enlace, por lo que combinarlos no requiere retargeting. Clonar la base con <code>SkeletonUtils.clone</code> proporciona a cada personaje una instancia nueva del esqueleto en lugar de mutar la escena almacenada en caché por el cargador.</p>
<p><strong>Revinculación del esqueleto por nombre.</strong> Cada pieza modular incluye su propio SkinnedMesh, que hace referencia a su propia armadura. La revinculación recorre los huesos de origen en orden, asigna cada uno por nombre al esqueleto canónico, crea un nuevo <code>Skeleton</code> reutilizando las matrices inversas de enlace del origen y llama a <code>SkinnedMesh.bind</code> con la matriz de enlace identidad. Después, hace que la malla dependa de la raíz compartida del personaje para que el skinning se ejecute por completo a través de los huesos compartidos. La ranura del cuerpo del atuendo oculta el cuerpo base para evitar intersecciones; las demás ranuras se superponen.</p>
<p><strong>El pelo como ranura con skinning.</strong> El pelo no es un elemento estático adjunto al hueso de la cabeza, sino un SkinnedMesh ponderado entre las 65 articulaciones. El pelo largo tiene pesos asignados a la parte superior de la columna y al cuello para que caiga de forma natural cuando el personaje mira hacia abajo. Sigue la misma ruta de revinculación que las piezas de los atuendos.</p>
<p><strong>Retargeting gratuito de animaciones basado en nombres.</strong> Los clips de Animation Library hacen referencia a las articulaciones por su nombre exacto, por lo que un <code>AnimationMixer</code> cuya raíz es la armadura compartida controla directamente los 262 clips con transición fundida, sin retargeting individual por clip. La licencia CC0 permite el uso comercial, y el reducido número de articulaciones mantiene el skinning en la GPU lo bastante barato como para reutilizar la ruta de skinning por lotes del Spike 45. Consulta <a href="/es/guides/landscape-generation-browser.html#gpu-driven-lod-with-webgpu">LOD controlado por la GPU</a>.</p>
<hr>
<p>Parte 25 de 29.
Anterior: <a href="/es/blog/2026-05-09-open-world-browser-part-24-persistence-and-wind.html">Parte 24 - Guardar un mundo y hacer visible el viento</a>
Siguiente: <a href="/es/blog/2026-05-12-open-world-browser-part-26-water.html">Parte 26 - Agua que funciona a cualquier escala</a>
Guía de la serie: <a href="/es/blog/2026-02-25-open-world-browser-series-guide.html">/es/blog/2026-02-25-open-world-browser-series-guide</a></p>
]]></content:encoded>
            <enclosure url="https://cdn.cinevva.com/blog/why-webgpu-engine-hero.jpg" length="0" type="image/jpg"/>
        </item>
        <item>
            <title><![CDATA[Construyendo un mundo abierto en el navegador, parte 24: Guardar un mundo y hacer visible el viento]]></title>
            <link>https://app.cinevva.com/es/blog/2026-05-09-open-world-browser-part-24-persistence-and-wind</link>
            <guid>https://app.cinevva.com/es/blog/2026-05-09-open-world-browser-part-24-persistence-and-wind</guid>
            <pubDate>Sat, 09 May 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[El Spike 47 hizo persistentes las ediciones del mundo: un Durable Object que arbitra la propiedad, guarda blobs binarios por chunk y hace converger el terreno de todos los pares mediante un protocolo de edición conmutativo. El Spike 49 trasladó fielmente a TSL los shaders de viento de Godot de Quaternius y luego persiguió una recompilación por fotograma que reducía la escena a 1 fps.]]></description>
            <content:encoded><![CDATA[<h1 id="construyendo-un-mundo-abierto-en-el-navegador-parte-24-guardar-un-mundo-y-hacer-visible-el-viento" tabindex="-1">Construyendo un mundo abierto en el navegador, parte 24: Guardar un mundo y hacer visible el viento <a class="header-anchor" href="#construyendo-un-mundo-abierto-en-el-navegador-parte-24-guardar-un-mundo-y-hacer-visible-el-viento" aria-label="Permalink to &quot;Construyendo un mundo abierto en el navegador, parte 24: Guardar un mundo y hacer visible el viento&quot;"></a></h1>
<p><em>Por <a href="/es/about.html">Oleg Sidorkin</a>, CTO y cofundador de Cinevva</em></p>
<p>¿Acabas de llegar? Consulta la <a href="/es/blog/2026-02-25-open-world-browser-series-guide.html">guía de la serie</a>. Explica qué es un spike y enlaza todas las partes.</p>
<p>La <a href="/es/blog/2026-05-08-open-world-browser-part-23-avatars-and-voice.html">parte 23</a> puso personas en el mundo y les dio voz. Esta parte trata de conseguir que el mundo recuerde lo que hicieron en él y que parezca vivo cuando nadie lo toca. El Spike 47 se centra en la persistencia: un creador esculpe el terreno y coloca elementos, y esas ediciones sobreviven a una recarga, se sincronizan con todos los demás pares y se arbitran de forma limpia cuando dos personas editan a la vez. El Spike 49 se centra en el viento: trasladar los shaders de vegetación de un paquete de naturaleza estilizada para que los árboles, arbustos y la hierba se muevan como pretendía el artista, lo que terminó convirtiéndose más en una lucha con el compilador de shaders que con las matemáticas.</p>
<h2 id="un-mundo-que-recuerda" tabindex="-1">Un mundo que recuerda <a class="header-anchor" href="#un-mundo-que-recuerda" aria-label="Permalink to &quot;Un mundo que recuerda&quot;"></a></h2>
<div style="position:relative;padding-bottom:56.25%;height:0;overflow:hidden;border-radius:8px;margin:1.5rem 0;border:1px solid rgba(255,255,255,0.12)">
<iframe src="/es/spikes/47-world-persistence/" title="Spike 47: Persistencia del mundo" style="position:absolute;top:0;left:0;width:100%;height:100%;border:0;background:#000" loading="lazy" allowfullscreen></iframe>
</div>
<p><a href="/es/spikes/47-world-persistence/" target="_blank">Abrir el Spike 47 en una pestaña nueva ↗</a> · <a href="/es/blog/spike-source?spike=47-world-persistence">Ver código fuente</a></p>
<p>El escenario es una sesión de creación compartida. Los jugadores recorren un mundo, colocan elementos con un clic, los eliminan con un clic derecho y esculpen el suelo arrastrando un pincel, elevando y reduciendo el mapa de alturas o excavando cuevas volumétricas en el terreno SDF, lo que hace que un chunk pase a usar marching cubes. Todo lo que hacen persiste en un <code>WorldChunkDO</code> de Cloudflare, un Durable Object con autoridad del servidor respaldado por su propio almacenamiento SQLite. Los clientes no escriben el estado directamente. Envían su intención, el DO arbitra y difunde el resultado, y el DO es la única fuente de verdad, por lo que quien acaba de unirse recibe una instantánea y aparece exactamente en el mismo mundo que ven los demás.</p>
<p>Dos detalles de la persistencia demostraron su valor. El terreno no se almacena como un registro de eventos que haya que reproducir al unirse; se guarda como blobs binarios por chunk que constituyen la fuente de verdad y se suben al finalizar cada trazo, de modo que quien se une carga directamente los bytes confirmados en lugar de volver a ejecutar miles de muestras del pincel. Además, esos blobs usan una clave de almacenamiento por chunk en lugar de una única fila grande, porque un solo chunk SDF ocupa 168 KB y el DO tiene un límite de 2 MB por fila. Un índice de chunks registra qué claves existen para que el DO pueda rehidratar el mapa completo al reactivarse. La identidad se gestiona mediante dos almacenamientos en el cliente: el id del jugador se guarda en <code>sessionStorage</code>, por lo que dos pestañas son dos pares distintos en lugar de un mismo par que se sobrescribe a sí mismo en el mapa de jugadores del DO, mientras que el nombre visible se guarda en <code>localStorage</code>, de modo que un cambio de nombre en una pestaña se propaga a todas las demás.</p>
<h2 id="hacer-converger-las-ediciones-simultaneas" tabindex="-1">Hacer converger las ediciones simultáneas <a class="header-anchor" href="#hacer-converger-las-ediciones-simultaneas" aria-label="Permalink to &quot;Hacer converger las ediciones simultáneas&quot;"></a></h2>
<p>La parte realmente difícil de la creación multijugador es qué ocurre cuando dos personas editan una zona de terreno superpuesta en el mismo instante. El spike divide las ediciones según su álgebra. Las operaciones aditivas —elevar y bajar en el mapa de alturas, y sumar y restar en el SDF— son conmutativas: aplicarlas en cualquier orden produce el mismo resultado, por lo que siguen una ruta optimista basada en sellos donde cada cliente aplica localmente el cambio y envía el sello, y el DO lo difunde a todos sin coordinación. El orden realmente no importa, así que no hay nada que coordinar.</p>
<p>Las operaciones dependientes del orden, suavizar y aplanar, fueron el caso interesante. El primer diseño les asignaba un bloqueo de región: un cliente solicita un bloqueo al pulsar el puntero, el DO lo concede o lo deniega, el cliente almacena temporalmente las muestras mientras se mantiene la pulsación y, al soltar el puntero, el DO aplica todo el trazo de forma atómica. Funciona, pero es un protocolo independiente, con su propio TTL de bloqueo y su viaje de ida y vuelta para concederlo o denegarlo. La solución más limpia que lo sustituyó es un delta precalculado: el cliente de origen ejecuta localmente el pincel de suavizado o aplanado, después envía la lista resultante de deltas por celda y cada par se limita a sumar esos deltas a sus propias celdas sin volver a derivar nada. Esto convierte una operación dependiente del orden en una operación conmutativa al fijar su resultado en el origen, por lo que todo el sistema de edición funciona con un único protocolo conmutativo uniforme, con una convergencia idéntica y sin ningún bloqueo. Los bloqueos de elementos se mantienen por un motivo distinto: el bloqueo por registro sustituyó a la eliminación exclusiva del propietario, de modo que cualquier par puede eliminar cualquier elemento salvo que alguien lo haya bloqueado, y solo quien lo bloqueó puede desbloquearlo. Deshacer y rehacer funcionan permitiendo que el cliente asigne un id al elemento antes de colocarlo, de modo que conoce el id antes de recibir el eco del servidor y puede revertir sus propias acciones de forma determinista. Los WebSockets en hibernación mantienen gratuita una sala inactiva en todo momento, la misma propiedad que abarató el relé de avatares de la parte anterior.</p>
<h2 id="un-viento-trasladado-fielmente-y-luego-combatido" tabindex="-1">Un viento trasladado fielmente y luego combatido <a class="header-anchor" href="#un-viento-trasladado-fielmente-y-luego-combatido" aria-label="Permalink to &quot;Un viento trasladado fielmente y luego combatido&quot;"></a></h2>
<div style="position:relative;padding-bottom:56.25%;height:0;overflow:hidden;border-radius:8px;margin:1.5rem 0;border:1px solid rgba(255,255,255,0.12)">
<iframe src="/es/spikes/49-gpu-wind-props/" title="Spike 49: Viento para elementos mediante GPU" style="position:absolute;top:0;left:0;width:100%;height:100%;border:0;background:#000" loading="lazy" allowfullscreen></iframe>
</div>
<p><a href="/es/spikes/49-gpu-wind-props/" target="_blank">Abrir el Spike 49 en una pestaña nueva ↗</a> · <a href="/es/blog/spike-source?spike=49-gpu-wind-props">Ver código fuente</a></p>
<p>El Spike 49 toma el Stylized Nature MegaKit de Quaternius y traslada su viento a nuestra pila tecnológica. El paquete incluye sus shaders originales de Godot, cuatro en total, y lo acertado era traducirlos fielmente en lugar de reinventarlos. La corteza tiene una función de vértices vacía, así que los troncos son rígidos; un intento anterior basado en una máscara procedural hacía que los troncos se balancearan, y la solución fue simplemente dejar de aplicar viento a la corteza. Las hojas reciben un balanceo caótico por vértice a partir de un hash de pulsos triangulares, enmascarado según la altura para que las copas se muevan mientras la base permanece plantada. El follaje básico recibe en el espacio del mundo un balanceo seno/coseno modulado por ruido. La hierba es follaje básico más una oscilación de líneas de viento que muestrea una textura de ruido en desplazamiento mediante una curva de potencia, de modo que solo contribuyen las bandas claras de la textura, lo que produce las ondas visibles que recorren una pradera. La selección sigue la propia convención de nombres de materiales del paquete, por lo que un material llamado <code>Leaves_Birch</code> se dirige a la ruta de hojas y <code>Grass_Common</code> a la ruta de hierba, sin conjeturas.</p>
<p>Una sorpresa del traslado es que el color de las hojas no está en la textura. Quaternius define por completo el aspecto de las hojas mediante un degradado vertical y un borde Fresnel: el albedo es una mezcla desde un color adicional en la parte inferior de la copa hasta el color de la hoja en la parte superior, determinada por la altura, con un tinte de dispersión subsuperficial añadido como emisión escalada mediante un término Fresnel <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.566ex;" xmlns="http://www.w3.org/2000/svg" width="12.282ex" height="2.451ex" role="img" focusable="false" viewBox="0 -833.2 5428.4 1083.2" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mo"><path data-c="28" d="M94 250Q94 319 104 381T127 488T164 576T202 643T244 695T277 729T302 750H315H319Q333 750 333 741Q333 738 316 720T275 667T226 581T184 443T167 250T184 58T225 -81T274 -167T316 -220T333 -241Q333 -250 318 -250H315H302L274 -226Q180 -141 137 -14T94 250Z" style="stroke-width: 3;"/></g><g data-mml-node="mn" transform="translate(389,0)"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(1111.2,0)"><path data-c="2212" d="M84 237T84 250T98 270H679Q694 262 694 250T679 230H98Q84 237 84 250Z" style="stroke-width: 3;"/></g><g data-mml-node="TeXAtom" data-mjx-texclass="ORD" transform="translate(2111.4,0)"><g data-mml-node="mi"><path data-c="1D40D" d="M314 0Q296 3 181 3T48 0H39V62H147V624H39V686H171H265Q288 686 297 686T309 684T315 679Q317 676 500 455T684 233V624H576V686H585Q603 683 718 683T851 686H860V624H752V319Q752 15 750 11Q747 4 742 2T718 0H712Q708 0 706 0T700 0T696 1T693 2T690 4T687 7T684 11T679 16T674 23Q671 27 437 311L215 579V62H323V0H314Z" style="stroke-width: 3;"/></g></g><g data-mml-node="mo" transform="translate(3233.7,0)"><path data-c="22C5" d="M78 250Q78 274 95 292T138 310Q162 310 180 294T199 251Q199 226 182 208T139 190T96 207T78 250Z" style="stroke-width: 3;"/></g><g data-mml-node="TeXAtom" data-mjx-texclass="ORD" transform="translate(3733.9,0)"><g data-mml-node="mi"><path data-c="1D415" d="M592 686H604Q615 685 631 685T666 684T700 684T724 683Q829 683 835 686H843V624H744L611 315Q584 254 546 165Q492 40 482 19T461 -6L460 -7H409Q398 -4 391 9Q385 20 257 315L124 624H25V686H36Q57 683 190 683Q340 683 364 686H377V624H289L384 403L480 185L492 212Q504 240 529 298T575 405L670 624H582V686H592Z" style="stroke-width: 3;"/></g></g><g data-mml-node="msup" transform="translate(4602.9,0)"><g data-mml-node="mo"><path data-c="29" d="M60 749L64 750Q69 750 74 750H86L114 726Q208 641 251 514T294 250Q294 182 284 119T261 12T224 -76T186 -143T145 -194T113 -227T90 -246Q87 -249 86 -250H74Q66 -250 63 -250T58 -247T55 -238Q56 -237 66 -225Q221 -64 221 250T66 725Q56 737 55 738Q55 746 60 749Z" style="stroke-width: 3;"/></g><g data-mml-node="mn" transform="translate(422,363) scale(0.707)"><path data-c="33" d="M127 463Q100 463 85 480T69 524Q69 579 117 622T233 665Q268 665 277 664Q351 652 390 611T430 522Q430 470 396 421T302 350L299 348Q299 347 308 345T337 336T375 315Q457 262 457 175Q457 96 395 37T238 -22Q158 -22 100 21T42 130Q42 158 60 175T105 193Q133 193 151 175T169 130Q169 119 166 110T159 94T148 82T136 74T126 70T118 67L114 66Q165 21 238 21Q293 21 321 74Q338 107 338 175V195Q338 290 274 322Q259 328 213 329L171 330L168 332Q166 335 166 348Q166 366 174 366Q202 366 232 371Q266 376 294 413T322 525V533Q322 590 287 612Q265 626 240 626Q208 626 181 615T143 592T132 580H135Q138 579 143 578T153 573T165 566T175 555T183 540T186 520Q186 498 172 481T127 463Z" style="stroke-width: 3;"/></g></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mo stretchy="false">(</mo><mn>1</mn><mo>−</mo><mrow data-mjx-texclass="ORD"><mi mathvariant="bold">N</mi></mrow><mo>⋅</mo><mrow data-mjx-texclass="ORD"><mi mathvariant="bold">V</mi></mrow><msup><mo stretchy="false">)</mo><mn>3</mn></msup></math></mjx-assistive-mml></mjx-container>. Por eso una pasada sencilla con textura se veía plana. Los colores proceden del degradado y del borde, no del mapa pintado. El port lee un atributo de vértice <code>heightFactor</code> precalculado en lugar de la Y local sin procesar, normalizado por grupo de hojas durante la carga a partir de la Y en el espacio del mundo, para que tanto el degradado como la máscara de viento se comporten correctamente sin importar cómo haya rotado la importación FBX los ejes locales de cada malla. Las constantes de color de Godot están etiquetadas como sRGB y se convierten a lineal antes de llegar al shader, así que el port realiza la misma conversión en lugar de introducir los valores sRGB brillantes como si fueran lineales y desteñir el follaje.</p>
<h2 id="la-recompilacion-que-devoro-la-tasa-de-fotogramas" tabindex="-1">La recompilación que devoró la tasa de fotogramas <a class="header-anchor" href="#la-recompilacion-que-devoro-la-tasa-de-fotogramas" aria-label="Permalink to &quot;La recompilación que devoró la tasa de fotogramas&quot;"></a></h2>
<p>El motivo por el que esto se publicó primero con una base FBX, dejando a un lado el conjunto completo de materiales de viento en un archivo <code>.bak</code>, es un error de recompilación por fotograma que reducía la escena a aproximadamente 1 fps. Superponer TSL personalizado sobre materiales cargados desde FBX hacía que Three.js reconstruyera los programas de shaders en cada fotograma, con <code>needsUpdate</code> prácticamente atascado en el estado activo. El método de diagnóstico consistió en reducir cada material de follaje a una pasada sencilla con textura, sin nodos personalizados, y observar si el bucle de recompilación persistía. Si se detenía, el culpable era el grafo personalizado; si continuaba, la causa estaba en una fase anterior, en la configuración de materiales FBX o en el propio Three.js. La solución que permitió recuperar los shaders reales fue vincular como uniforms todas las diferencias entre materiales —color de las hojas, color SSS, intensidad y mezcla— para que todos los recursos de hojas compartieran un único programa compilado, en lugar de que el compilador emitiera un shader nuevo para cada combinación de colores única y saturara la cola de compilación.</p>
<p>Merece la pena conservar otros dos elementos. La hierba se renderiza como un <code>InstancedMesh</code> por archivo de origen, y su viento se calcula en el espacio del mundo porque las fases sinusoidales dependen de la posición global. Sin embargo, el desplazamiento debe aplicarse en el espacio local antes de que se ejecute la matriz de instancia, y WGSL no dispone de <code>inverse()</code>. Para una matriz de instancia compuesta por una traslación, una rotación Y y una escala uniforme, la inversa del bloque superior de 3×3 es simplemente su transpuesta dividida por la escala al cuadrado, por lo que el shader multiplica el desplazamiento global por la matriz de modelo transpuesta y lo divide por el cuadrado de la longitud de la primera columna de la matriz, recuperando la escala sin una raíz cuadrada. Cuando la transformación de vértices vuelve a aplicar la matriz, el movimiento termina en el espacio del mundo exactamente como se diseñó, con independencia de la rotación o escala de cada mata. Además, cada mata realiza un descarte de frustum por vértice en la GPU: proyecta el centro de la instancia al espacio de recorte y, si queda fuera del frustum con un margen, colapsa todos los vértices en el origen local para que los tres vértices de cada triángulo coincidan; el rasterizador descarta el triángulo degenerado y no se realiza ningún trabajo de fragmentos, prueba alfa ni sombras para la hierba fuera de pantalla. Esto se suma al descarte aproximado por esfera envolvente de chunk que Three.js ya realiza, construido con <code>step</code> de tipo float en lugar de booleanos para que pueda multiplicarse directamente en la mezcla de posiciones.</p>
<h2 id="tecnologia-mencionada-en-este-capitulo" tabindex="-1">Tecnología mencionada en este capítulo <a class="header-anchor" href="#tecnologia-mencionada-en-este-capitulo" aria-label="Permalink to &quot;Tecnología mencionada en este capítulo&quot;"></a></h2>
<p><strong>Persistencia del mundo con autoridad del servidor.</strong> Un Durable Object <code>WorldChunkDO</code> arbitra la colocación de elementos y las ediciones del terreno, conserva blobs binarios por chunk como fuente de verdad —para que quienes se unen carguen los bytes confirmados en lugar de reproducir un registro de eventos— y almacena una clave por chunk para mantenerse por debajo del límite de 2 MB por fila del DO. El id del jugador se guarda en <code>sessionStorage</code> para que las pestañas sean pares distintos; el nombre visible se guarda en <code>localStorage</code> para que los cambios de nombre se propaguen entre pestañas.</p>
<p><strong>Convergencia conmutativa de las ediciones.</strong> Las operaciones aditivas sobre el terreno —elevar/bajar y sumar/restar en el SDF— son conmutativas y siguen una ruta optimista basada en sellos sin coordinación. Las operaciones dependientes del orden —suavizar y aplanar— se vuelven conmutativas enviando deltas precalculados por celda en lugar de adquirir un bloqueo de región, por lo que todo el sistema converge mediante un único protocolo uniforme sin bloqueos. Los bloqueos de elementos por registro sustituyen a la eliminación exclusiva del propietario, y los ids de objetos asignados por el cliente permiten deshacer y rehacer de forma determinista antes de que llegue el eco del servidor. Consulta <a href="/es/guides/landscape-generation-browser.html#gpu-driven-lod-with-webgpu">LOD controlado por GPU</a>.</p>
<p><strong>Traslado fiel de shaders de Godot a TSL.</strong> Los cuatro shaders de viento originales de Quaternius se traducen línea por línea: corteza rígida, balanceo de hojas enmascarado por altura, balanceo del follaje en el espacio del mundo y hierba con una oscilación de líneas de viento en desplazamiento, seleccionados mediante la convención de nombres de materiales del paquete. El color de las hojas procede de un degradado de altura más un borde SSS controlado por Fresnel, en lugar de la textura, y las constantes creadas en sRGB se convierten a lineal para que el aspecto coincida con los renders de referencia.</p>
<p><strong>Evitar recompilaciones de shaders por fotograma.</strong> Superponer TSL personalizado sobre materiales FBX puede dejar <code>needsUpdate</code> activado y reconstruir los programas en cada fotograma, reduciendo el rendimiento a unos 1 fps. Vincular como uniform todas las diferencias entre materiales permite que todas las variantes compartan un único programa compilado, en lugar de emitir un shader nuevo por cada conjunto único de parámetros. Una pasada de diagnóstico sencilla con textura permite aislar si la causa es el grafo personalizado o la configuración anterior.</p>
<p><strong>Viento en el espacio del mundo para follaje instanciado.</strong> El viento de la hierba se calcula en el espacio del mundo y se transforma de vuelta al espacio local mediante una inversa derivada manualmente —transpuesta dividida por la escala al cuadrado— porque WGSL no dispone de <code>inverse()</code>. Un descarte de frustum por vértice en la GPU colapsa las matas fuera de pantalla en un triángulo degenerado para evitar cualquier trabajo de fragmentos o sombras, sumándose al descarte por esfera envolvente de chunk de Three.js.</p>
<hr>
<p>Parte 24 de 29.
Anterior: <a href="/es/blog/2026-05-08-open-world-browser-part-23-avatars-and-voice.html">Parte 23 - Cincuenta avatares y una voz en la sala</a>
Siguiente: <a href="/es/blog/2026-05-10-open-world-browser-part-25-universal-characters.html">Parte 25 - Un esqueleto, cualquier atuendo</a>
Guía de la serie: <a href="/es/blog/2026-02-25-open-world-browser-series-guide.html">/es/blog/2026-02-25-open-world-browser-series-guide</a></p>
]]></content:encoded>
            <enclosure url="https://cdn.cinevva.com/blog/why-webgpu-engine-hero.jpg" length="0" type="image/jpg"/>
        </item>
        <item>
            <title><![CDATA[Construyendo un mundo abierto en el navegador, parte 23: Cincuenta avatares y una voz en la sala]]></title>
            <link>https://app.cinevva.com/es/blog/2026-05-08-open-world-browser-part-23-avatars-and-voice</link>
            <guid>https://app.cinevva.com/es/blog/2026-05-08-open-world-browser-part-23-avatars-and-voice</guid>
            <pubDate>Fri, 08 May 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[El spike 45 redujo 50 personajes de 13 ms de JavaScript por fotograma a una sola llamada de dibujo mediante skinning por lotes en la GPU, y dedicó dos horas a perseguir un error de WGSL que resultó ser un morph target. El spike 46 implementó voz de proximidad con audio espacial HRTF y después eliminó la mitad de la cadena de audio para igualar lo que realmente ofrecen Meet y Teams.]]></description>
            <content:encoded><![CDATA[<h1 id="construyendo-un-mundo-abierto-en-el-navegador-parte-23-cincuenta-avatares-y-una-voz-en-la-sala" tabindex="-1">Construyendo un mundo abierto en el navegador, parte 23: Cincuenta avatares y una voz en la sala <a class="header-anchor" href="#construyendo-un-mundo-abierto-en-el-navegador-parte-23-cincuenta-avatares-y-una-voz-en-la-sala" aria-label="Permalink to &quot;Construyendo un mundo abierto en el navegador, parte 23: Cincuenta avatares y una voz en la sala&quot;"></a></h1>
<p><em>Por <a href="/es/about.html">Oleg Sidorkin</a>, CTO y cofundador de Cinevva</em></p>
<p>¿Acabas de llegar? Consulta la <a href="/es/blog/2026-02-25-open-world-browser-series-guide.html">guía de la serie</a>. Explica qué es un spike y enlaza todas las partes.</p>
<p>La <a href="/es/blog/2026-05-07-open-world-browser-part-22-clouds-and-meshlets.html">parte 22</a> puso un cielo sobre el mundo. Esta parte pone personas en él. Un mundo abierto en tercera persona necesita más de 50 personajes visibles en todo momento y oír a quienes están a tu lado. El spike 45 aborda el renderizado: llevar esa cantidad de avatares animados a la GPU sin colapsar el hilo principal. El spike 46 aborda el audio: voz entre pares que se panoramiza y atenúa según la posición, ajustada para sonar como una videollamada normal en lugar de como una demostración técnica.</p>
<h2 id="una-llamada-de-dibujo-para-cincuenta-bailarines" tabindex="-1">Una llamada de dibujo para cincuenta bailarines <a class="header-anchor" href="#una-llamada-de-dibujo-para-cincuenta-bailarines" aria-label="Permalink to &quot;Una llamada de dibujo para cincuenta bailarines&quot;"></a></h2>
<div style="position:relative;padding-bottom:56.25%;height:0;overflow:hidden;border-radius:8px;margin:1.5rem 0;border:1px solid rgba(255,255,255,0.12)">
<iframe src="/es/spikes/45-avatar-network-sync/" title="Spike 45: sincronización de avatares en red" style="position:absolute;top:0;left:0;width:100%;height:100%;border:0;background:#000" loading="lazy" allowfullscreen></iframe>
</div>
<p><a href="/es/spikes/45-avatar-network-sync/" target="_blank">Abrir el spike 45 en una pestaña nueva ↗</a> · <a href="/es/blog/spike-source?spike=45-avatar-network-sync">Ver el código fuente</a></p>
<p>La ruta predeterminada de Three.js asigna a cada personaje su propio <code>SkinnedMesh</code>, su propio <code>AnimationMixer</code>, su propia carga de matrices de huesos y su propia llamada de dibujo. Con 50 avatares en el Mac local, eso suponía unos 13 ms de sobrecarga de JavaScript puro por fotograma antes de que la GPU hiciera una sola cosa. La pregunta de reducción de riesgos para toda la línea de trabajo multijugador era si una arquitectura única de skinning por lotes podía controlar ese coste y escalar linealmente con la cantidad de personajes.</p>
<p>La respuesta consiste en separar dónde se calcula la animación de dónde se dibuja. Tres clases de personajes comparten una plantilla FBX. El jugador local es un <code>Avatar</code> normal, un clon completo del esqueleto con su propio mezclador y la ruta estándar de Three.js, porque nunca hay más de uno. Cada par remoto es un <code>VirtualSkeleton</code>: también un clon completo con su propio mezclador ejecutando los mismos clips, pero todos los nodos <code>SkinnedMesh</code> se eliminan inmediatamente después de la clonación para conservar solo los huesos. Nunca se añade a la escena. En cada fotograma, después de que el mezclador se actualice y las matrices se estabilicen, empaqueta <code>(bone.matrixWorld × boneInverse)</code> para los 100 huesos en una posición de un <code>Float32Array</code> compartido. A continuación, <code>BatchSkinnedRenderer</code> posee un <code>InstancedMesh</code> por cada pieza de geometría; todos leen de un único <code>StorageBufferAttribute</code> de matrices de huesos con un tamaño de <code>maxInstances × numBones × mat4</code>, es decir, 60 × 100 × 64 = 384 KB. Un <code>MeshStandardNodeMaterial</code> con <code>positionNode</code> y <code>normalNode</code> personalizados lee cuatro influencias de huesos por vértice directamente desde ese búfer de almacenamiento. El resultado es una carga al almacenamiento y una llamada de dibujo por pieza de geometría para toda la multitud, independientemente de cuántas personas haya. El skinning se ejecuta en el shader de vértices y el coste de JavaScript por avatar se reduce a ejecutar un mezclador y copiar 100 matrices.</p>
<p>El HUD que mide esto también tuvo que rehacerse. La versión anterior marcaba «presupuesto excedido» cuando el tiempo total de GPU del fotograma superaba los 3 ms, pero el fotograma siempre incluye el mapa de sombras, el suelo y la malla completa con skinning del jugador local, que juntos consumen entre 3 y 5 ms en hardware real sin importar cuántos pares sintéticos existan. La solución es un presupuesto que se calibra por sí solo: mientras no haya avatares procesados por lotes, captura el tiempo de GPU en vivo como referencia mediante una EMA rápida; después congela esa referencia y aumenta el presupuesto linealmente en 0,06 ms por cada avatar añadido cuando aparecen los sintéticos. En reposo muestra PASS en todas las máquinas y se ajusta proporcionalmente a medida que crece la multitud.</p>
<h2 id="el-fallo-era-una-cara-que-no-podias-ver" tabindex="-1">El fallo era una cara que no podías ver <a class="header-anchor" href="#el-fallo-era-una-cara-que-no-podias-ver" aria-label="Permalink to &quot;El fallo era una cara que no podías ver&quot;"></a></h2>
<p>Las primeras ejecuciones en Chrome mostraron sombras plateadas sobre el suelo y ningún avatar, junto con un error de análisis de WGSL: <code>cannot index type 'f32'</code> en una línea que intentaba indexar <code>object.nodeUniform2[i]</code> cuando el uniforme estaba declarado como un escalar. La parte sincera de esta historia es que la primera solución era incorrecta y aun así funcionó. La suposición fue que la ruta de matrices de instancias de <code>InstancedMesh</code> estaba generando el código erróneo, y sustituirla por un <code>StorageInstancedBufferAttribute</code> hizo que el error desapareciera en Chrome. Pero desapareció porque la nueva ruta emitía un código de shader diferente, no porque solucionara la causa, que es el tipo de arreglo más peligroso.</p>
<p>El verdadero culpable eran los morph targets. 3MIKE.fbx incluye expresiones faciales mediante blend shapes, la geometría clonada hereda los <code>morphAttributes</code> y <code>MorphNode.setup()</code> de Three.js declara <code>morphTargetInfluences</code> como un <code>float</code> escalar y después intenta aplicarle <code>.element(i)</code> dentro de un bucle sintetizado, que es exactamente la indexación de un escalar que el compilador rechazó. La solución es una sola línea: borrar <code>geometry.morphAttributes = {}</code> en la geometría que no utiliza morphs, para que Three.js nunca inyecte el <code>MorphNode</code>. La solución accidental para Chrome se mantuvo durante un tiempo y después se volvió en contra: en Safari, la ruta de instancias en almacenamiento produjo <code>Vertex buffer is not big enough</code> 256 veces, porque el backend WebGPU de Safari no la traduce correctamente. Revertirla fue la decisión adecuada, y el búfer de almacenamiento simple de matrices de huesos, que forma parte del núcleo de WebGPU en vez de ser una ruta de instancias generada, funciona bien en todas partes. La lección que merece conservarse es esta: cuando una solución funciona en un navegador y no puedes explicar el mecanismo, has parcheado un síntoma, así que lee el WGSL generado. Un shim de <code>getCompilationInfo()</code> añadido más adelante en el spike convirtió el genérico «module is not valid» de Three.js en el error real de Tint y amortizó con creces el tiempo invertido.</p>
<p>Junto a esto hay otro truco para esquivar el framework. Three.js detecta los nombres estándar de atributos <code>skinIndex</code> y <code>skinWeight</code> e intenta inyectar su propio <code>SkinningNode</code>, incluso en un <code>InstancedMesh</code> cuyo <code>positionNode</code> personalizado ya realiza el skinning. Renombrar esos atributos como <code>boneIndex</code> y <code>boneWeight</code> los oculta al framework, y el TSL personalizado los lee con sus nuevos nombres.</p>
<h2 id="un-rele-que-te-olvida-entre-palabras" tabindex="-1">Un relé que te olvida entre palabras <a class="header-anchor" href="#un-rele-que-te-olvida-entre-palabras" aria-label="Permalink to &quot;Un relé que te olvida entre palabras&quot;"></a></h2>
<p>La primera versión sincronizaba los pares mediante <code>BroadcastChannel</code>, un sustituto dentro del mismo navegador con el formato y la cadencia reales de la comunicación, y el comentario del protocolo prometía que cambiarlo por un transporte real requeriría una sola línea. Cumplir esa promesa dio lugar a <code>AvatarRoomDO</code>, un Durable Object de Cloudflare de 74 líneas que ni siquiera decodifica la trama binaria de 36 bytes. Reenvía cada mensaje tal cual a todos los demás pares de la sala, porque el id del remitente está integrado en la trama y cada receptor filtra su propio eco en el cliente. El relé no sabe nada sobre identidades. Los WebSockets en hibernación hacen que una sala inactiva sea gratuita: el DO desaparece de la memoria entre mensajes y el entorno de ejecución restaura los sockets etiquetados cuando llega el siguiente paquete. Con 10 eventos por segundo y por par, eso supone 36 000 solicitudes al DO por hora de conexión de cada par, aproximadamente medio centavo, con salida de datos gratuita en Cloudflare y un coste entre 6 y 10 veces menor que una configuración WebSocket equivalente en AWS.</p>
<p>El cambio sacó a la luz un fallo de la máquina de estados que merece recordarse. Un jugador remoto seguía caminando después de haberse detenido. La solicitud de animación comprobaba <code>this._state</code>, el clip que se estaba reproduciendo, en lugar del último nombre puesto en cola. Por eso, cuando dos mensajes de red llegaban en el mismo tick, primero <code>walk</code> y después <code>idle</code>, <code>idle</code> se comparaba con un estado que todavía no había avanzado y se descartaba silenciosamente. El par quedaba caminando para siempre, porque los futuros paquetes <code>idle</code> se eliminaban antes por deduplicación al no haber cambiado. La solución es sobrescribir siempre el nombre pendiente y dejar que el asistente de transición descarte las solicitudes genuinas del mismo estado, algo que ya hacía. Esta clase de fallo es general: una comprobación de deduplicación contra el valor de referencia equivocado se traga silenciosamente la entrada que importa.</p>
<p>Safari necesitó dos protecciones adicionales. Abre el WebSocket más rápido que Chrome, por lo que el primer mensaje entrante de un par podía llegar antes de que terminara de construirse el renderizador por lotes y desreferenciar un valor nulo; descartar mensajes mientras no exista el renderizador es seguro porque los pares vuelven a emitir cada 100 ms. Además, <code>'gpu' in navigator</code> devolvía true mientras <code>requestAdapter()</code> devolvía null, de modo que Three.js recurría silenciosamente a WebGL2, donde la cadena de skinning mediante búfer de almacenamiento no tiene una traducción válida y generaba errores sin parar. Comprobar que existe un adaptador real y verificar que el backend sea efectivamente WebGPU convierte un renderizado degradado en un mensaje claro en la pantalla de carga. Incluso había una diferencia de dialecto WGSL: Three.js emite la forma moderna de dos argumentos <code>@interpolate(flat, either)</code>, que el compilador de WebKit aún no admite. Se solucionó reescribiendo el código fuente del shader al entrar en <code>createShaderModule</code> para eliminar el segundo argumento, lo cual no tiene coste porque la interpolación plana transporta el mismo valor en cada vértice independientemente de él.</p>
<h2 id="una-voz-que-se-panoramiza-con-la-sala" tabindex="-1">Una voz que se panoramiza con la sala <a class="header-anchor" href="#una-voz-que-se-panoramiza-con-la-sala" aria-label="Permalink to &quot;Una voz que se panoramiza con la sala&quot;"></a></h2>
<div style="position:relative;padding-bottom:56.25%;height:0;overflow:hidden;border-radius:8px;margin:1.5rem 0;border:1px solid rgba(255,255,255,0.12)">
<iframe src="/es/spikes/46-proximity-voice/" title="Spike 46: voz de proximidad" style="position:absolute;top:0;left:0;width:100%;height:100%;border:0;background:#000" loading="lazy" allowfullscreen></iframe>
</div>
<p><a href="/es/spikes/46-proximity-voice/" target="_blank">Abrir el spike 46 en una pestaña nueva ↗</a> · <a href="/es/blog/spike-source?spike=46-proximity-voice">Ver el código fuente</a></p>
<p>El spike 46 implementa voz de proximidad: WebRTC entre pares con audio espacial HRTF, cuyo alcance se definió expresamente para igualar la calidad de Google Meet y Microsoft Teams en una sala silenciosa o moderadamente ruidosa. Un <code>VoiceRoomDO</code> gestiona la señalización como un relé JSON: envía a cada par nuevo una lista de participantes, anuncia entradas y salidas, enruta SDP e ICE a un par específico mediante la etiqueta del socket y difunde actualizaciones de posición que controlan los panoramizadores espaciales. Añade el id del remitente a cada mensaje para que los pares no puedan suplantarse entre sí, y el audio nunca pasa por el DO. Hay una <code>RTCPeerConnection</code> por cada par remoto, y el id de par lexicográficamente menor siempre crea la oferta para que ambos lados coincidan en quién inicia la conexión sin tener que implementar por completo el patrón de negociación perfecta.</p>
<p>En el lado receptor, el audio de cada par pasa por un <code>PannerNode</code> configurado como HRTF con atenuación de distancia inversa, y el <code>AudioListener</code> se actualiza en cada fotograma a partir de la posición y la orientación del jugador local mediante <code>forwardX = sin(facing)</code>, <code>forwardZ = cos(facing)</code>, lo que coincide con la convención de orientación <code>atan2(wx, wz)</code> de la escena. Una peculiaridad de Chrome costó una hora: un <code>MediaStream</code> consumido únicamente por Web Audio a veces no recibe paquetes, por lo que cada flujo también se conecta a un elemento <code>&lt;audio&gt;</code> oculto y silenciado para obligar al decodificador a programar el procesamiento. En cuanto a la calidad, los navegadores usan de forma predeterminada Opus mono a unos 32 kbps, así que el spike modifica la línea <code>fmtp</code> de cada oferta y respuesta para elevarla a 128 kbps, con FEC en banda activado y DTX desactivado, y después llama a <code>setParameters</code> con una tasa de bits máxima elevada para garantizar que el codificador utilice realmente lo que anuncia el SDP. FEC es la segunda mejora audible más importante después del aumento de la tasa de bits, ya que permite recuperarse de la pérdida de paquetes sin renegociar.</p>
<h2 id="eliminar-hasta-conseguir-un-audio-limpio" tabindex="-1">Eliminar hasta conseguir un audio limpio <a class="header-anchor" href="#eliminar-hasta-conseguir-un-audio-limpio" aria-label="Permalink to &quot;Eliminar hasta conseguir un audio limpio&quot;"></a></h2>
<p>La cadena de audio publicada es mucho más pequeña que aquella con la que empecé, y reducirla fue la verdadera lección. La primera versión tenía un filtro de paso alto, un limitador de chasquidos ajustado para capturar el ruido del teclado, un compresor, una puerta de ruido y una mezcla con fundido entre señal procesada y seca, todo ello controlado desde un panel flotante con más de doce deslizadores. Cuando el usuario informó de que se oían las pulsaciones del teclado, el primer impulso fue ajustar el limitador de forma más agresiva y reducir la mezcla seca: una pila de parches. La respuesta estructural era que, una vez que hay un eliminador de ruido basado en aprendizaje automático en la cadena, el limitador de chasquidos, la puerta y la mayor parte del filtro de paso alto resultan redundantes, porque RNNoise está entrenado precisamente con ruido de teclado, ratón y escritura, y el recorte de amplitud es una versión claramente peor de la misma tarea. Los clientes de producción incluyen eliminación de ruido mediante aprendizaje automático, cancelación de eco, ganancia automática y un compresor suave para nivelar, y nada más. Así que se eliminaron cuatro etapas, el panel de deslizadores y los controles para «elegir la reducción de ruido», dejando una única cadena fija.</p>
<p>Cada etapa que sobrevivió justifica su presencia. La cancelación de eco del navegador se mantiene porque RNNoise no elimina el eco, y sin ella la realimentación del altavoz al micrófono no tiene límite. La supresión de ruido del navegador se desactiva porque combinarla con RNNoise produce artefactos en las fricativas, así que hay que elegir un solo eliminador de ruido. La ganancia automática del navegador se mantiene porque desactivarla hacía que la señal fuera demasiado baja para que el compresor pudiera trabajar, y el <code>DynamicsCompressorNode</code> de Web Audio no tiene ningún parámetro de ganancia de compensación; la nivelación amplia del navegador y el compresor rápido del spike operan en escalas temporales diferentes y pueden coexistir. RNNoise funciona con un 92 por ciento de señal procesada mezclada con un 8 por ciento de señal seca, porque puede suprimir en exceso consonantes sordas como s, sh y f cuando disminuye su probabilidad de voz, y la pequeña ruta seca las conserva a cambio de dejar pasar ligeramente el ruido de las teclas.
Dos funciones completan el sistema. Pulsar para hablar no cambia <code>track.enabled</code>, porque eso descarta todo lo que aún queda en los búferes de la canalización y corta la última sílaba al soltar la tecla. En su lugar, un <code>GainNode</code> situado cerca del final aplica una rampa con <code>setTargetAtTime</code>: un ataque rápido para conservar la primera sílaba y una liberación lenta para dejar salir la última consonante, mientras la pista permanece habilitada en todo momento. Además, un retardo de emisión de cinco segundos, solicitado como función al estilo de la radio, utiliza una ruta de derivación y otra con un <code>DelayNode</code>, mezcladas mediante fundido cruzado, junto con un botón de corte que silencia de inmediato la salida retardada y muestra una cuenta atrás en el HUD antes de reanudar el audio. Empaquetar el eliminador de ruido fue una pequeña odisea: el worklet de RNNoise publicado utiliza importaciones con especificadores simples que ningún CDN puede resolver, así que la solución fue crear un paquete local con esbuild que produce un único archivo autocontenido de 1,9 MB, con el WASM incrustado en base64, guardado en el repositorio y referenciado mediante una URL relativa al módulo para que funcione por igual en el servidor de desarrollo, la compilación de VitePress y el dominio personalizado. Si el worklet no llega a cargarse, la cadena sigue generando audio mediante un filtro paso alto básico y un compresor, y el HUD muestra el fallo en rojo.</p>
<h2 id="tecnologia-mencionada-en-este-capitulo" tabindex="-1">Tecnología mencionada en este capítulo <a class="header-anchor" href="#tecnologia-mencionada-en-este-capitulo" aria-label="Permalink to &quot;Tecnología mencionada en este capítulo&quot;"></a></h2>
<p><strong>Skinning por lotes en la GPU para multitudes.</strong> Los avatares remotos ejecutan un <code>VirtualSkeleton</code> sin renderizado (un clon completo al que se le han retirado las mallas con skinning, conservando los huesos y su propio mezclador) que empaqueta <code>bone.matrixWorld × boneInverse</code> para cada hueso en un <code>StorageBufferAttribute</code> compartido. Un <code>InstancedMesh</code> por cada pieza geométrica lee esas matrices en un <code>positionNode</code>/<code>normalNode</code> de TSL personalizado, de modo que toda la multitud solo requiere una transferencia al almacenamiento y una llamada de dibujo por pieza, mientras que el trabajo de CPU por avatar se limita a actualizar el mezclador y copiar una matriz. Consulta <a href="/es/guides/landscape-generation-browser.html#gpu-driven-lod-with-webgpu">LOD controlado por la GPU</a>.</p>
<p><strong>Leer el WGSL generado, no el síntoma.</strong> Un error de compilación <code>cannot index type 'f32'</code> se rastreó hasta el <code>MorphNode</code> de Three.js, que declaraba <code>morphTargetInfluences</code> como escalar y después intentaba indexarlo; se corrigió vaciando <code>morphAttributes</code> en las geometrías que no utilizan morphs. Una primera solución que solo cambiaba la ruta de shaders generada ocultó la causa y más tarde provocó fallos en Safari. Cambiar el nombre de <code>skinIndex</code>/<code>skinWeight</code> a <code>boneIndex</code>/<code>boneWeight</code> oculta los atributos frente a la inyección automática de <code>SkinningNode</code> de Three.js, de modo que un material de skinning personalizado controle los cálculos.</p>
<p><strong>Relés de Durable Objects en hibernación.</strong> Un <code>AvatarRoomDO</code> exclusivamente binario reenvía tramas de 36 bytes a todos los demás pares sin decodificarlas, con la identidad del remitente incrustada en la trama y el eco propio filtrado en el cliente. Los WebSockets en hibernación hacen que una sala inactiva no tenga coste, y esta configuración cuesta aproximadamente medio centavo por hora y por par a 10 Hz, muy por debajo del precio equivalente de WebSockets gestionados. Una protección contra duplicados que comparaba con el estado de la animación en reproducción, en lugar de con el último estado puesto en cola, descartaba silenciosamente los mensajes de detención y dejaba a los jugadores remotos atrapados en un bucle de caminata.</p>
<p><strong>Voz por proximidad mediante WebRTC con HRTF.</strong> Una <code>RTCPeerConnection</code> por cada par, con los roles de oferta y respuesta decididos según el orden de los identificadores de los pares; el audio se enruta a través de un <code>PannerNode</code> HRTF con un <code>AudioListener</code> que se actualiza en cada fotograma según la orientación del jugador, y Opus se modifica a 128 kbps con FEC integrada para mejorar la resiliencia. Un elemento <code>&lt;audio&gt;</code> oculto y silenciado obliga a Chrome a extraer paquetes de un flujo utilizado exclusivamente por Web Audio.</p>
<p><strong>Ingeniería de audio sustractiva.</strong> Igualar la calidad de Meet y Teams exigió eliminar etapas, no añadirlas: eliminación de ruido mediante ML, más cancelación de eco, ganancia automática y un compresor suave, sin puerta de ruido ni limitador de clics, porque un eliminador de ruido basado en ML y entrenado con ruido de teclado vuelve redundante el recorte de amplitud. Pulsar para hablar aplica una rampa a un <code>GainNode</code> situado al final mediante una envolvente asimétrica, en vez de activar y desactivar la pista, para no cortar las sílabas; además, el worklet del eliminador de ruido se distribuye como un único paquete autocontenido de esbuild para evitar los problemas de resolución de importaciones con especificadores simples.</p>
<hr>
<p>Parte 23 de 29.
Anterior: <a href="/es/blog/2026-05-07-open-world-browser-part-22-clouds-and-meshlets.html">Parte 22 - Nubes que puedes iluminar y un descarte que necesita datos</a>
Siguiente: <a href="/es/blog/2026-05-09-open-world-browser-part-24-persistence-and-wind.html">Parte 24 - Guardar un mundo y un viento que puedes ver</a>
Guía de la serie: <a href="/es/blog/2026-02-25-open-world-browser-series-guide.html">/es/blog/2026-02-25-open-world-browser-series-guide</a></p>
]]></content:encoded>
            <enclosure url="https://cdn.cinevva.com/blog/why-webgpu-engine-hero.jpg" length="0" type="image/jpg"/>
        </item>
        <item>
            <title><![CDATA[Construir un mundo abierto en el navegador, parte 22: Nubes que puedes iluminar y un culling que hay que alimentar]]></title>
            <link>https://app.cinevva.com/es/blog/2026-05-07-open-world-browser-part-22-clouds-and-meshlets</link>
            <guid>https://app.cinevva.com/es/blog/2026-05-07-open-world-browser-part-22-clouds-and-meshlets</guid>
            <pubDate>Thu, 07 May 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[El Spike 43 puso en pantalla un cielo basado en la física y nubes volumétricas en menos de 2 ms, con atardeceres que no requieren ajustes específicos para cada hora del día. El Spike 44 implementó culling de meshlets en la GPU y demostró que la oclusión Hi-Z solo funciona si los oclusores son lo bastante grandes para sobrevivir a una reducción por máximos.]]></description>
            <content:encoded><![CDATA[<h1 id="construir-un-mundo-abierto-en-el-navegador-parte-22-nubes-que-puedes-iluminar-y-un-culling-que-hay-que-alimentar" tabindex="-1">Construir un mundo abierto en el navegador, parte 22: Nubes que puedes iluminar y un culling que hay que alimentar <a class="header-anchor" href="#construir-un-mundo-abierto-en-el-navegador-parte-22-nubes-que-puedes-iluminar-y-un-culling-que-hay-que-alimentar" aria-label="Permalink to &quot;Construir un mundo abierto en el navegador, parte 22: Nubes que puedes iluminar y un culling que hay que alimentar&quot;"></a></h1>
<p><em>Por <a href="/es/about.html">Oleg Sidorkin</a>, director de tecnología y cofundador de Cinevva</em></p>
<p>¿Acabas de llegar? Consulta la <a href="/es/blog/2026-02-25-open-world-browser-series-guide.html">guía de la serie</a>. Explica qué es un spike y enlaza todas las partes.</p>
<p>La <a href="/es/blog/2026-05-06-open-world-browser-part-21-visibility-buffer.html">parte 21</a> trataba sobre una técnica de renderizado que no dio resultado. Esta parte presenta una que sí lo dio y otra que necesitó una corrección cuidadosa para funcionar. El Spike 43 es el cielo: una atmósfera basada en la física y nubes volumétricas, la base que hace que una escena parezca un lugar en vez de una demostración técnica. El Spike 44 es culling de estilo meshlet en la GPU, cuya lección fue que la prueba de oclusión solo es tan buena como los oclusores que se le proporcionan.</p>
<h2 id="un-cielo-creado-mediante-fisica-no-con-un-gradiente" tabindex="-1">Un cielo creado mediante física, no con un gradiente <a class="header-anchor" href="#un-cielo-creado-mediante-fisica-no-con-un-gradiente" aria-label="Permalink to &quot;Un cielo creado mediante física, no con un gradiente&quot;"></a></h2>
<div style="position:relative;padding-bottom:56.25%;height:0;overflow:hidden;border-radius:8px;margin:1.5rem 0;border:1px solid rgba(255,255,255,0.12)">
<iframe src="/es/spikes/43-clouds-atmosphere/" title="Spike 43: Nubes y atmósfera" style="position:absolute;top:0;left:0;width:100%;height:100%;border:0;background:#000" loading="lazy" allowfullscreen></iframe>
</div>
<p><a href="/es/spikes/43-clouds-atmosphere/" target="_blank">Abrir el Spike 43 en una pestaña nueva ↗</a> · <a href="/es/blog/spike-source?spike=43-clouds-atmosphere">Ver código fuente</a></p>
<p>Casi todos los efectos meteorológicos cinematográficos dependen de dos componentes de infraestructura: una atmósfera basada en la física, para que el color del cielo y el del sol sigan la hora del día mediante la física en lugar de un gradiente ajustado a mano, y un volumen de nubes volumétricas, para que el cielo tenga estructura 3D en vez de un cubemap precalculado. El Spike 43 construye exactamente ese par sobre la pila existente de WebGPU y TSL, y nada más, porque una vez que ambos existen, el resto de la pila meteorológica —niebla, rayos crepusculares, superficies mojadas y nieve— se convierte en una serie de ampliaciones más pequeñas y conocidas.</p>
<p>La atmósfera utiliza el modelo de Hillaire de 2020, un conjunto de tablas de consulta calculadas en shaders de cómputo WGSL. Una tabla de transmitancia integra la luz solar a través del perfil de densidad de Rayleigh, Mie y ozono, y solo se recalcula cuando se mueve el sol. Una tabla de vista del cielo se vuelve a generar en cada fotograma porque es lo bastante barata como para que no merezca la pena añadir código para condicionarla, y usa una parametrización no lineal alrededor del horizonte para evitar el banding. Por ahora, la dispersión múltiple usa un ajuste analítico en lugar de la tabla correcta, y los atardeceres se ven bien, así que el atajo queda bien disimulado. Las nubes emplean un ray marching al estilo Schneider Nubis a través de una capa horizontal, con formas generadas mediante una textura Perlin-Worley de 128³ erosionada por una textura Worley de 32³. Ambas se precalculan al arrancar mediante cómputo, sin ninguna descarga de red. La iluminación utiliza extinción según la ley de Beer, una función de fase de doble lóbulo y una aproximación de polvo. El acoplamiento clave es que el color solar de las nubes muestrea la misma tabla de transmitancia en cada paso, por lo que la iluminación de las nubes sigue el atardecer sin una segunda fase de ajuste.</p>
<p>En un M1, todo el sistema tarda entre 1,1 y 2,0 ms con las nubes a media resolución, muy por debajo del presupuesto de 6 ms, usa unos 14 MB de memoria de la GPU y funciona a más de 100 FPS. Las dos hipótesis principales se confirmaron en la práctica. El atardecer es la toma estrella, el momento que hace que el renderizador resulte cinematográfico, y surge de la física sin ajustes específicos para cada hora del día. Y hubo un accidente afortunado: al parametrizar la capa de nubes entre los 800 m y los 4000 m, desde una cámara baja las nubes lejanas del horizonte parecen crestas montañosas oscuras, lo que proporciona relieve de fondo al mundo sin que nadie tenga que modelarlo.</p>
<p>Conviene conservar una nota sobre la arquitectura. La estructura natural consiste en pintar primero el cielo en la cadena de intercambio y dejar después que three.js dibuje la geometría encima con <code>autoClear = false</code>. Esto no funciona con el renderizador WebGPU de r184, porque la opción no controla la operación de carga del color como lo hace en WebGL, por lo que three.js sobrescribe el cielo en cada fotograma. La solución es renderizar three.js en un destino fuera de pantalla y realizar la composición final (<code>mix(skyCloud, scene, scene.alpha)</code>, seguida de ACES y luego sRGB) en un pase propio que controle la cadena de intercambio.</p>
<h2 id="un-culling-que-solo-es-tan-bueno-como-sus-oclusores" tabindex="-1">Un culling que solo es tan bueno como sus oclusores <a class="header-anchor" href="#un-culling-que-solo-es-tan-bueno-como-sus-oclusores" aria-label="Permalink to &quot;Un culling que solo es tan bueno como sus oclusores&quot;"></a></h2>
<div style="position:relative;padding-bottom:56.25%;height:0;overflow:hidden;border-radius:8px;margin:1.5rem 0;border:1px solid rgba(255,255,255,0.12)">
<iframe src="/es/spikes/44-meshlet-clusters/" title="Spike 44: Clústeres de meshlets" style="position:absolute;top:0;left:0;width:100%;height:100%;border:0;background:#000" loading="lazy" allowfullscreen></iframe>
</div>
<p><a href="/es/spikes/44-meshlet-clusters/" target="_blank">Abrir el Spike 44 en una pestaña nueva ↗</a> · <a href="/es/blog/spike-source?spike=44-meshlet-clusters">Ver código fuente</a></p>
<p>El Spike 44 compara el rendimiento de cuatro modos de renderizado: forward sencillo, culling de clústeres en la CPU, culling mediante cómputo en la GPU y un búfer de visibilidad con culling por oclusión Hi-Z. La ruta Hi-Z es la interesante y tenía un error discreto: su HUD indicaba que la oclusión estaba activada, pero el contador «Eliminados por Hi-Z» permanecía exactamente en el 0,0 % para siempre. El culling del frustum funcionaba, así que la fase previa del shader de culling estaba bien. La parte de oclusión no hacía nada, aunque se pagaba todo su coste.</p>
<p>Una prueba de oclusión Hi-Z proyecta en pantalla el cuadro delimitador de un clúster, elige un nivel mip de la pirámide de profundidad para que el rectángulo en pantalla ocupe unos 2×2 téxeles, muestrea la profundidad del oclusor más lejano dentro de ese rectángulo y descarta el clúster si su punto más cercano sigue estando más lejos que ese oclusor. La pirámide de profundidad se construye en cada fotograma inicializando el mip 0 a partir de un prepase de profundidad opaca y aplicando reducciones por máximos en los niveles sucesivos. El prepase opaco incluye deliberadamente solo oclusores sólidos —el suelo y proxies individuales para los troncos de los árboles—, porque el follaje con prueba alfa dejaría huecos que engañarían a una reducción por máximos.</p>
<p>El error era geométrico, no lógico. El proxy del tronco era una caja de 0,5 m por 4 m por 0,5 m. A 30 m se proyecta en unos 17 píxeles de pantalla. Sin embargo, un clúster de hierba típico situado a 50 m selecciona el mip 5, donde cada téxel abarca 32 píxeles de origen. Un tronco de 17 píxeles no cubre por completo ni un solo téxel del mip 5, así que cada téxel que toca el tronco también toca el suelo circundante. La primera reducción por máximos de 2×2 selecciona el valor de profundidad mayor, correspondiente al suelo más lejano situado detrás del tronco, y la profundidad del tronco se borra en la primera reducción. Al llegar al mip 5, la pirámide contiene la profundidad del suelo casi en todas partes, el clúster nunca está más lejos que el suelo y nunca se ocluye nada.</p>
<p>La solución consiste en hacer el proxy lo bastante grande como para dominar los téxeles que ocupa, dimensionándolo según la silueta del árbol y no según su madera. Un proxy de aproximadamente 2 m por 6 m por 2 m sigue siendo más pequeño que la copa real, por lo que las hojas visibles a través de los huecos nunca se eliminan en exceso, pero es lo bastante grande como para sobrevivir a la reducción por máximos hasta las distancias relevantes, y el contador de oclusión deja inmediatamente de estar a cero. La conclusión se puede generalizar como una regla para el motor de producción: todo aquello en lo que se confíe como oclusor Hi-Z debe dimensionarse de acuerdo con su silueta en pantalla, porque la eficacia de Hi-Z en escenas abiertas con follaje depende de la cobertura del oclusor en el mip correspondiente, no de la elegancia de las matemáticas de la prueba de profundidad. La oclusión de hierba contra hierba tampoco puede activarse, porque una brizna se encuentra a la misma profundidad que el suelo bajo ella, así que las mejoras reales proceden de los árboles que ocluyen follaje lejano y de los árboles que ocluyen otros árboles.</p>
<h2 id="tecnologia-mencionada-en-este-capitulo" tabindex="-1">Tecnología mencionada en este capítulo <a class="header-anchor" href="#tecnologia-mencionada-en-este-capitulo" aria-label="Permalink to &quot;Tecnología mencionada en este capítulo&quot;"></a></h2>
<p><strong>LUT de atmósfera de Hillaire 2020.</strong> Una tabla de transmitancia —la luz solar a través del perfil de Rayleigh, Mie y ozono— que solo se recalcula cuando se mueve el sol, junto con una tabla de vista del cielo por fotograma con parametrización no lineal del horizonte, proporciona colores del cielo y del sol basados en la física que siguen la hora del día sin ningún gradiente ajustado a mano. Un ajuste analítico para la dispersión múltiple sustituye a la tabla completa hasta que algún artefacto obligue a calcularla correctamente. El atardecer surge de la física sin ajustes específicos para cada hora del día.</p>
<p><strong>Nubes volumétricas Schneider Nubis.</strong> Un ray marching a través de una capa horizontal, modelada mediante una textura Perlin-Worley de 128³ precalculada al arrancar y erosionada por una textura Worley de 32³, con iluminación basada en la extinción de la ley de Beer, una fase de doble lóbulo y un término de polvo. Muestrear en cada paso el color solar de las nubes a partir de la misma tabla de transmitancia hace que su iluminación siga el amanecer y el atardecer sin coste adicional. El ray marching a media resolución cuesta aproximadamente cuatro veces menos que a resolución completa, sin una pérdida visible de calidad a distancias habituales: el compromiso estándar en producción.</p>
<p><strong>Composición de WebGPU sin procesar con three.js en r184.</strong> Pintar el cielo en la cadena de intercambio y dibujar encima la geometría de three.js con <code>autoClear = false</code> falla porque la opción no controla la operación de carga del color en el backend WebGPU. Hay que renderizar three.js en un destino RGBA16F fuera de pantalla y efectuar el <code>mix</code> final, el mapeo de tonos y la conversión a sRGB en un pase que controle la cadena de intercambio.</p>
<p><strong>Culling por oclusión Hi-Z y dimensionamiento de oclusores.</strong> Una pirámide de profundidad construida mediante reducciones por máximos permite que un pase de culling en la GPU descarte los clústeres cuyo punto más cercano está detrás del oclusor más lejano de su rectángulo en pantalla. La prueba no hace nada, sin avisar, si los oclusores son demasiado pequeños para dominar un téxel en el mip seleccionado, porque la primera reducción por máximos sustituye la profundidad del oclusor por la del fondo más lejano situado detrás. Los oclusores deben dimensionarse según su silueta en pantalla, no según su núcleo físico. Consulta <a href="/es/guides/landscape-generation-browser.html#gpu-driven-lod-with-webgpu">LOD controlado por la GPU</a>.</p>
<hr>
<p>Parte 22 de 29.
Anterior: <a href="/es/blog/2026-05-06-open-world-browser-part-21-visibility-buffer.html">Parte 21: Un renderizador más rápido que no era más rápido</a>
Siguiente: <a href="/es/blog/2026-05-08-open-world-browser-part-23-avatars-and-voice.html">Parte 23: Cincuenta avatares y una voz en la sala</a>
Guía de la serie: <a href="/es/blog/2026-02-25-open-world-browser-series-guide.html">/es/blog/2026-02-25-open-world-browser-series-guide</a></p>
]]></content:encoded>
            <enclosure url="https://cdn.cinevva.com/blog/why-webgpu-engine-hero.jpg" length="0" type="image/jpg"/>
        </item>
        <item>
            <title><![CDATA[Creando un mundo abierto en el navegador, parte 21: un renderizador más rápido que no lo era]]></title>
            <link>https://app.cinevva.com/es/blog/2026-05-06-open-world-browser-part-21-visibility-buffer</link>
            <guid>https://app.cinevva.com/es/blog/2026-05-06-open-world-browser-part-21-visibility-buffer</guid>
            <pubDate>Wed, 06 May 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[El experimento 40 implementó un búfer de visibilidad para hierba densa, la técnica que, según todos, reduce el sobredibujado, y comprobó que en Apple Silicon era un 44 % más lento que el renderizado forward convencional a alta densidad. Aquí explicamos por qué y cuándo conviene usarlo de verdad.]]></description>
            <content:encoded><![CDATA[<h1 id="creando-un-mundo-abierto-en-el-navegador-parte-21-un-renderizador-mas-rapido-que-no-lo-era" tabindex="-1">Creando un mundo abierto en el navegador, parte 21: un renderizador más rápido que no lo era <a class="header-anchor" href="#creando-un-mundo-abierto-en-el-navegador-parte-21-un-renderizador-mas-rapido-que-no-lo-era" aria-label="Permalink to &quot;Creando un mundo abierto en el navegador, parte 21: un renderizador más rápido que no lo era&quot;"></a></h1>
<p><em>Por <a href="/es/about.html">Oleg Sidorkin</a>, CTO y cofundador de Cinevva</em></p>
<p>¿Acabas de llegar? Consulta la <a href="/es/blog/2026-02-25-open-world-browser-series-guide.html">guía de la serie</a>. Explica qué es un experimento y enlaza todas las partes.</p>
<p>La <a href="/es/blog/2026-05-05-open-world-browser-part-20-parallax-occlusion.html">parte 20</a> simuló profundidad superficial sobre un quad plano. Esta parte trata sobre una decisión de arquitectura de renderizado, y es el experimento en el que la respuesta de manual resultó ser incorrecta para nuestro hardware. La pregunta: para renderizar hierba con prueba alfa y densidad cinematográfica bajo una cámara en tercera persona, ¿necesitamos un búfer de visibilidad antes de escalar hasta la densidad necesaria para 200 jugadores? La recomendación habitual es un sí rotundo. Lo implementamos, lo medimos y la respuesta fue no.</p>
<h2 id="la-tecnica-que-todo-el-mundo-recomienda" tabindex="-1">La técnica que todo el mundo recomienda <a class="header-anchor" href="#la-tecnica-que-todo-el-mundo-recomienda" aria-label="Permalink to &quot;La técnica que todo el mundo recomienda&quot;"></a></h2>
<div style="position:relative;padding-bottom:56.25%;height:0;overflow:hidden;border-radius:8px;margin:1.5rem 0;border:1px solid rgba(255,255,255,0.12)">
<iframe src="/es/spikes/40-visibility-buffer/" title="Experimento 40: búfer de visibilidad" style="position:absolute;top:0;left:0;width:100%;height:100%;border:0;background:#000" loading="lazy" allowfullscreen></iframe>
</div>
<p><a href="/es/spikes/40-visibility-buffer/" target="_blank">Abrir el experimento 40 en una pestaña nueva ↗</a> · <a href="/es/blog/spike-source?spike=40-visibility-buffer">Ver código fuente</a></p>
<p>Un búfer de visibilidad divide el renderizado en dos pasadas. La pasada 1 rasteriza la geometría y escribe únicamente los identificadores de triángulo e instancia en un destino entero compacto, además de la profundidad, sin realizar ningún sombreado. La pasada 2 es una pasada a pantalla completa que lee los identificadores de cada píxel cubierto, vuelve a obtener los vértices de ese triángulo, reconstruye los atributos interpolados y sombrea cada píxel visible exactamente una vez. La propuesta es una eliminación perfecta del sobredibujado: la prueba de profundidad se ejecuta sobre fragmentos que no han realizado ningún trabajo de sombreado, por lo que el material costoso solo se ejecuta sobre aquello que realmente se ve.</p>
<p>El experimento ejecuta dos rutas en un mismo lienzo y dispositivo, de modo que la única variable sea dónde se realiza el sombreado. La ruta forward usa un <code>MeshStandardNodeMaterial</code> normal mediante three.js. La ruta del búfer de visibilidad es un pipeline WebGPU de dos pasadas sin abstracciones que se ejecuta fuera de three.js, lee la textura de hierba de three.js directamente desde el backend, escribe <code>(instanceId, triId)</code> en un destino <code>RG32Uint</code> durante la pasada 1 y resuelve la iluminación en la pasada 2. Ambas comparten una única configuración de iluminación de referencia.</p>
<p>Hay dos notas de implementación que merece la pena conservar. WebGPU todavía no dispone de una variable integrada <code>primitive_index</code> portable en los shaders de fragmentos, así que el truco consiste en incorporar un identificador de triángulo por vértice en una geometría no indexada y leerlo con interpolación <code>flat</code>. Esto triplica el número de vértices, pero resulta insignificante en una tarjeta de hierba de 12 vértices. Además, compartir el lienzo con el renderizador de three.js apenas causa problemas siempre que nunca se reconfigure el contexto ni se modifiquen las dimensiones del lienzo, pues three.js controla ambas cosas. Medir los tiempos de la ruta forward fue la parte más delicada, ya que three.js no ofrece ningún punto de extensión para inyectar consultas de marcas de tiempo de la GPU dentro de su pasada de renderizado. La solución alternativa consiste en delimitar su trabajo con dos pasadas de marcas de tiempo sin operaciones, enviadas antes y después, que la GPU ejecuta en el orden de envío.</p>
<h2 id="los-numeros-van-en-la-direccion-equivocada" tabindex="-1">Los números van en la dirección equivocada <a class="header-anchor" href="#los-numeros-van-en-la-direccion-equivocada" aria-label="Permalink to &quot;Los números van en la dirección equivocada&quot;"></a></h2>
<p>En un Mac de la serie M a unos 1080p, con briznas de hierba formadas por tarjetas cruzadas sobre un campo de 80 m:</p>
<p>Con 50.000 instancias, la ruta del búfer de visibilidad ganó por un 25 %: 4,13 ms frente a los 5,51 ms de la ruta forward. Con 100.000 quedaron empatadas. Con 200.000 instancias, la ruta forward ganó por un 44 %: 5,44 ms frente a los 7,80 ms del búfer de visibilidad. La ruta del búfer de visibilidad se vuelve <em>relativamente peor</em> a medida que aumenta la densidad, justo lo contrario de la creencia popular según la cual destaca precisamente cuando el sobredibujado es intenso.</p>
<h2 id="por-que-la-ruta-forward-mantiene-el-rendimiento" tabindex="-1">Por qué la ruta forward mantiene el rendimiento <a class="header-anchor" href="#por-que-la-ruta-forward-mantiene-el-rendimiento" aria-label="Permalink to &quot;Por qué la ruta forward mantiene el rendimiento&quot;"></a></h2>
<p>Las GPU Apple Silicon son renderizadores diferidos basados en mosaicos, y eso cambia todo el cálculo. El sombreado forward en un TBDR cuenta con una etapa de eliminación de superficies ocultas que se ejecuta antes del shader de fragmentos: el rasterizador reúne todos los fragmentos que corresponden a un mosaico, los ordena por profundidad y solo los supervivientes —después de la prueba alfa— llegan al shader de fragmentos. Por tanto, la ruta forward ya obtiene gratis, dentro del propio hardware, la mayor parte de la promesa del búfer de visibilidad de «sombrear una vez por píxel». A medida que las briznas llenan la pantalla, la eliminación de superficies ocultas descarta más fragmentos antes de ejecutar cualquier sombreado, y el coste efectivo por píxel de la ruta forward se mantiene aproximadamente constante en lugar de crecer con el sobredibujado.</p>
<p>La pasada 1 de la ruta del búfer de visibilidad obtiene esa misma ventaja del TBDR. El problema está por completo en la pasada 2. Esta lee la matriz de instancia de cada píxel desde un búfer que, con 200.000 instancias, ocupa 12,8 MB, mucho más que cualquier caché de GPU. Los píxeles adyacentes en pantalla suelen pertenecer a instancias de hierba diferentes —la distribución usa una cuadrícula con desplazamientos aleatorios, por lo que las briznas vecinas tienen identificadores de instancia arbitrarios—, así que cada wave que accede a ese búfer provoca fallos de caché divergentes. Ese acceso aleatorio e incoherente consume por sí solo unos 4 ms por fotograma. La ruta forward lo evita por completo porque la matriz de instancia llega junto con el vértice mediante la ruta de atributos por instancia. Por ello, cuando se ejecuta el shader de fragmentos, los datos de vértices transformados ya están en registros locales del mosaico y no es necesaria ninguna lectura aleatoria a escala de megabytes.</p>
<p>Este es exactamente el coste que la pasada de clasificación de materiales de Nanite pretende amortizar: agrupa los píxeles por instancia y lanza waves de cómputo ordenadas para que las lecturas de cada wave sean coherentes. Nosotros no contamos con eso. Un cálculo aproximado indica que ordenar los píxeles por instancia reduciría esos 4 ms quizá hasta 1,5 o 2 ms y desplazaría el punto de cruce hasta las 400.000 o 500.000 instancias. Pero eso supone apilar optimizaciones sobre una arquitectura que, para empezar, aquí no está ganando.</p>
<h2 id="la-conclusion-sincera-y-la-auditoria-que-la-respalda" tabindex="-1">La conclusión sincera y la auditoría que la respalda <a class="header-anchor" href="#la-conclusion-sincera-y-la-auditoria-que-la-respalda" aria-label="Permalink to &quot;La conclusión sincera y la auditoría que la respalda&quot;"></a></h2>
<p>Para follaje de tarjetas cruzadas con prueba alfa en WebGPU sobre Apple Silicon, la ruta forward con el pipeline TSL de three.js ya iguala o mejora el coste del búfer de visibilidad. Toda la infraestructura de este búfer no aporta ninguna ventaja visible hasta superar ampliamente las 200.000 instancias, y solo si además se añade una pasada de ordenación o agrupamiento. La decisión práctica para el motor de producción es mantener la combinación de renderizado forward, LOD e impostores de los experimentos anteriores y no invertir en infraestructura de búfer de visibilidad hasta que las GPU discretas de NVIDIA o AMD sean nuestro objetivo de despliegue dominante —donde el coste del sobredibujado es más lineal— o adoptemos una arquitectura de meshlets, en la que el búfer de visibilidad ya constituye la salida natural.</p>
<p>Como el resultado es contrario a la intuición, la conclusión solo tiene valor si la comparación es justa, así que sometimos el experimento a una auditoría completa. Aparecieron y se corrigieron varios errores reales: un control deslizante de escala de las briznas que desincronizaba silenciosamente ambas rutas; la mitad de las briznas forward, que se renderizaban casi negras debido a normales antiparalelas —corregido con el truco habitual de orientar hacia arriba las normales del follaje—; y el búfer de visibilidad, que se veía aproximadamente el doble de brillante por usar un factor Lambert elegido manualmente en lugar del <code>1/π</code> que conserva la energía, un término de iluminación ambiental fijo y la ausencia de mapeo de tonos. La corrección copió en WGSL la curva fílmica ACES exacta de three.js y lee en cada fotograma los colores e intensidades de las luces reales de la escena. La única diferencia conocida que permanece, la falta de especular directo en la pasada 2, sesga la comparación <em>a favor</em> del búfer de visibilidad. Es decir, la ruta forward realiza estrictamente más trabajo por píxel y aun así gana a alta densidad. Esto hace que la conclusión principal sea conservadora, no optimista. La única salvedad sigue vigente: todo esto es específico de la serie M, y el punto de cruce bien podría invertirse en una GPU discreta, por lo que conviene repetir las pruebas antes de adoptar esta combinación para objetivos que no sean de Apple.</p>
<h2 id="tecnologia-mencionada-en-este-capitulo" tabindex="-1">Tecnología mencionada en este capítulo <a class="header-anchor" href="#tecnologia-mencionada-en-este-capitulo" aria-label="Permalink to &quot;Tecnología mencionada en este capítulo&quot;"></a></h2>
<p><strong>Renderizado mediante búfer de visibilidad.</strong> La pasada 1 rasteriza la geometría y escribe únicamente los identificadores de triángulo e instancia, además de la profundidad, sin realizar ningún sombreado. La pasada 2 es una resolución a pantalla completa que lee los identificadores de cada píxel cubierto, vuelve a obtener el triángulo de origen, reconstruye los atributos baricéntricos con corrección de perspectiva y sombrea cada píxel visible una vez. Como WebGPU carece de un <code>primitive_index</code> de fragmento portable, el identificador del triángulo se incorpora como atributo por vértice con interpolación <code>flat</code> en una geometría no indexada.</p>
<p><strong>Eliminación de superficies ocultas en TBDR frente a resolución diferida.</strong> En una GPU diferida basada en mosaicos —como Apple Silicon—, el sombreado forward ya descarta los fragmentos ocluidos antes de ejecutar el shader de fragmentos. Por ello, obtiene gratis la mayor parte de la ventaja del búfer de visibilidad de sombrear una sola vez, y su coste por píxel se mantiene aproximadamente constante a medida que aumenta el sobredibujado. En cambio, una pasada de resolución del búfer de visibilidad paga el coste del acceso aleatorio incoherente a un gran búfer por instancia —12,8 MB con 200.000 instancias—, que domina a alta densidad a menos que primero se ordenen o agrupen los píxeles por instancia, como hace la clasificación de materiales de Nanite.</p>
<p><strong>Compartir un lienzo con el WebGPURenderer de three.js.</strong> Los búferes de comandos WebGPU sin abstracciones se intercalan correctamente con los envíos de three.js en la cola compartida, siempre que nunca se vuelva a llamar a <code>context.configure()</code> ni se escriba en <code>canvas.width/height</code>, pues el renderizador controla ambas cosas. Los tiempos de GPU de la ruta forward, para los que three.js no ofrece ningún punto de extensión, pueden delimitarse mediante dos pasadas de renderizado de marcas de tiempo sin operaciones enviadas alrededor de su llamada de renderizado, ya que la GPU ejecuta los búferes de comandos en el orden de envío.</p>
<p><strong>Validación de un benchmark contrario a la intuición.</strong> Un resultado de rendimiento sorprendente solo es tan fiable como la equidad de la comparación. Auditar ambas rutas para garantizar contenido y sombreado de escena idénticos —el mismo mapeo de tonos ACES, Lambert con conservación de energía, luces leídas de los mismos objetos y escala idéntica de las briznas— fue lo que convirtió «el búfer de visibilidad es más lento» de un probable artefacto de medición en una conclusión defendible, con la única asimetría restante sesgada en la dirección conservadora.</p>
<hr>
<p>Parte 21 de 29.
Anterior: <a href="/es/blog/2026-05-05-open-world-browser-part-20-parallax-occlusion.html">Parte 20 - Simular profundidad en un plano</a>
Siguiente: <a href="/es/blog/2026-05-07-open-world-browser-part-22-clouds-and-meshlets.html">Parte 22 - Nubes que puedes atravesar volando y un culling que merece la pena</a>
Guía de la serie: <a href="/es/blog/2026-02-25-open-world-browser-series-guide.html">/es/blog/2026-02-25-open-world-browser-series-guide</a></p>
]]></content:encoded>
            <enclosure url="https://cdn.cinevva.com/blog/why-webgpu-engine-hero.jpg" length="0" type="image/jpg"/>
        </item>
        <item>
            <title><![CDATA[Construir un mundo abierto en el navegador, parte 20: Simular profundidad en un plano]]></title>
            <link>https://app.cinevva.com/es/blog/2026-05-05-open-world-browser-part-20-parallax-occlusion</link>
            <guid>https://app.cinevva.com/es/blog/2026-05-05-open-world-browser-part-20-parallax-occlusion</guid>
            <pubDate>Tue, 05 May 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[El experimento 39 portó el mapeado de oclusión por paralaje a TSL, chocó con dos obstáculos del flujo de control de shaders de WebGPU, descubrió que el error se debía a no respetar la disciplina de un portado literal y creó un plano de referencia con geometría real para validar el resultado.]]></description>
            <content:encoded><![CDATA[<h1 id="construir-un-mundo-abierto-en-el-navegador-parte-20-simular-profundidad-en-un-plano" tabindex="-1">Construir un mundo abierto en el navegador, parte 20: Simular profundidad en un plano <a class="header-anchor" href="#construir-un-mundo-abierto-en-el-navegador-parte-20-simular-profundidad-en-un-plano" aria-label="Permalink to &quot;Construir un mundo abierto en el navegador, parte 20: Simular profundidad en un plano&quot;"></a></h1>
<p><em>Por <a href="/es/about.html">Oleg Sidorkin</a>, CTO y cofundador de Cinevva</em></p>
<p>¿Acabas de llegar? Consulta la <a href="/es/blog/2026-02-25-open-world-browser-series-guide.html">guía de la serie</a>. Explica qué es un experimento y enlaza todas las partes.</p>
<p>La <a href="/es/blog/2026-05-04-open-world-browser-part-19-imposters.html">parte 19</a> usó un quad plano para simular un árbol entero a distancia. Esta parte usa un quad plano para simular profundidad de cerca: mapeado de oclusión por paralaje, la técnica que hace que una calzada de adoquines parezca tener juntas hundidas 5 cm sin emplear ni un solo vértice adicional. El objetivo era llevarla a la pila de producción (Three.js r184, WebGPU y TSL), para que los materiales de detalle del terreno puedan ofrecer esa ilusión de profundidad donde importa y pagar el coste de una textura plana en el resto.</p>
<h2 id="tres-formas-de-simular-profundidad-una-junto-a-otra" tabindex="-1">Tres formas de simular profundidad, una junto a otra <a class="header-anchor" href="#tres-formas-de-simular-profundidad-una-junto-a-otra" aria-label="Permalink to &quot;Tres formas de simular profundidad, una junto a otra&quot;"></a></h2>
<div style="position:relative;padding-bottom:56.25%;height:0;overflow:hidden;border-radius:8px;margin:1.5rem 0;border:1px solid rgba(255,255,255,0.12)">
<iframe src="/es/spikes/39-parallax-pom/" title="Experimento 39: Mapeado de oclusión por paralaje" style="position:absolute;top:0;left:0;width:100%;height:100%;border:0;background:#000" loading="lazy" allowfullscreen></iframe>
</div>
<p><a href="/es/spikes/39-parallax-pom/" target="_blank">Abrir el experimento 39 en una pestaña nueva ↗</a> · <a href="/es/blog/spike-source?spike=39-parallax-pom">Ver el código fuente</a></p>
<p>El experimento coloca tres planos de 5×5 m uno junto a otro, todos con la misma estructura de material y diferenciados únicamente por las UV que alimentan los muestreadores. El modo plano muestrea la textura directamente y sirve como referencia de base. El paralaje de una sola muestra desplaza las UV una vez a lo largo de la dirección de visión según la altura de ese punto; es barato y aceptable con amplitudes bajas, pero se desliza en ángulos rasantes. POM hace avanzar un rayo por pasos en el espacio tangente: recorre el rayo de visión, encuentra la primera capa donde el rayo pasa por debajo del campo de alturas y refina la intersección. El espacio tangente sigue siendo sencillo porque todos los planos de prueba están alineados con los ejes, de modo que la dirección de visión puede transformarse al espacio tangente con un par de inversiones de signo en lugar de una matriz TBN completa por vértice. El conjunto de texturas se obtiene en directo desde la API de archivos de Polyhaven, la misma vía que usó la búsqueda de modelos de la parte 17.</p>
<h2 id="dos-obstaculos-de-webgpu-y-un-trazado-de-rayos-sin-bifurcaciones" tabindex="-1">Dos obstáculos de WebGPU y un trazado de rayos sin bifurcaciones <a class="header-anchor" href="#dos-obstaculos-de-webgpu-y-un-trazado-de-rayos-sin-bifurcaciones" aria-label="Permalink to &quot;Dos obstáculos de WebGPU y un trazado de rayos sin bifurcaciones&quot;"></a></h2>
<p>El bucle POM de manual abandona la búsqueda al encontrar la primera intersección. En r184 eso no funciona, por dos motivos distintos. <code>If(...).and(...)</code> compilaba sin errores, pero producía WGSL en el que el cuerpo del bucle nunca se ejecutaba, por lo que el refinamiento posterior al bucle operaba sobre basura y el plano se renderizaba casi blanco. Además, <code>Break()</code> como nodo independiente aún no estaba incluido en la compilación r184, así que ni siquiera con un <code>If</code> funcional había forma de expresar «detenerse en la primera intersección». Ambos problemas se remontan a incidencias conocidas de three.js relacionadas con una optimización excesiva del flujo de control de TSL a través de los límites de <code>If</code> y <code>Loop</code> en esta serie de versiones.</p>
<p>La reescritura no usa bifurcaciones. Cada iteración muestrea la textura de forma incondicional, lo que mantiene el acceso a texturas dentro del flujo de control uniforme exigido por la especificación de WGSL, y después incorpora el nuevo estado mediante una bandera <code>done</code> almacenada como un valor flotante. Una vez que <code>done</code> cambia a 1, las llamadas a <code>mix</code> de cada iteración se reducen a «mantener el estado sin cambios», el equivalente sin bifurcaciones de una interrupción. La bandera <code>done</code> se construye con una función auxiliar <code>step</code> implementada como <code>0.5 + 0.5 × sign(x + ε)</code>, porque la conversión de booleanos a valores flotantes ha sido irregular en la serie r18x y <code>sign()</code> resulta fiable en todas partes. El coste es que cada fragmento ejecuta las 64 iteraciones, independientemente de dónde se produzca realmente la intersección, pero es la compensación adecuada a escala de fragmento: el tiempo de ejecución ya limita el número máximo de pasos y una GPU real también ejecutaría especulativamente más allá de un <code>break</code> «real». Aquí es importante contar con una alternativa limpia: un <code>mix(baseUV, refined, done)</code> final, de modo que, con amplitud cero —el extremo lejano de la transición por distancia—, ningún fragmento interseque, <code>done</code> permanezca en 0 y el material POM sea idéntico bit a bit al plano. Ese es precisamente el objetivo del truco de LOD por distancia: reducirse al coste del modo plano cuando el efecto ya es menor que un píxel.</p>
<h2 id="el-error-fue-un-fallo-de-disciplina-no-de-matematicas" tabindex="-1">El error fue un fallo de disciplina, no de matemáticas <a class="header-anchor" href="#el-error-fue-un-fallo-de-disciplina-no-de-matematicas" aria-label="Permalink to &quot;El error fue un fallo de disciplina, no de matemáticas&quot;"></a></h2>
<p>La versión sin bifurcaciones funcionaba, pero se veía distorsionada: presentaba artefactos horizontales alargados con una amplitud moderada y un resultado sutilmente incorrecto y poco nítido con amplitudes bajas. La solución surgió de una instrucción de una sola línea: ve a leer la referencia canónica. El tutorial de LlamAcademy que inspiró esto no es más que un nodo de ShaderGraph de Unity, así que la implementación real se encuentra en <code>PerPixelDisplacement.hlsl</code> de Unity. Leerlo línea por línea reveló tres diferencias semánticas que había introducido sin darme cuenta: un desfase de uno en la referencia inicial de altura del rayo —Unity realiza un avance inicial antes del bucle, por lo que mi marco de referencia estaba desfasado un paso entero y situaba las intersecciones en la capa equivocada aproximadamente la mitad de las veces—, una convención de signo para el desplazamiento máximo de la que depende el paso de refinamiento y una elección entre contabilizar el desplazamiento acumulado o las UV acumuladas que complicaba mis cálculos de refinamiento y enredaba el signo.</p>
<p>La causa fundamental no fue un único error, sino mezclar dos referencias. Había tomado como guía el tutorial de POM de LearnOpenGL, que usa convenciones de signo parecidas pero diferentes y una fórmula de refinamiento distinta, y acabé en un estado híbrido donde dos tercios de las matemáticas coincidían con una fuente y el tercio restante con la otra. La reescritura es un portado casi literal del HLSL de Unity a TSL: mismos nombres de variables, mismo avance inicial y mismo refinamiento, conservando por encima la bandera <code>done</code> sin bifurcaciones. Merece la pena recordar la lección: al portar un shader conocido y fiable desde otra pila, pórtalo primero línea por línea y con los mismos nombres; después, refactorízalo según el estilo local. No vuelvas a deducirlo usando una segunda referencia a mitad del portado.</p>
<h2 id="un-plano-de-referencia-que-no-puede-mentir" tabindex="-1">Un plano de referencia que no puede mentir <a class="header-anchor" href="#un-plano-de-referencia-que-no-puede-mentir" aria-label="Permalink to &quot;Un plano de referencia que no puede mentir&quot;"></a></h2>
<p>A la comparación en paralelo le faltaba lo más evidente: un plano con geometría real. Sin él, afirmar que «POM se ve bastante bien» no se puede refutar. ¿Bastante bien comparado con qué? Por eso el experimento añadió un cuarto plano con el mismo mapa de alturas aplicado a las posiciones reales de los vértices. WebGPU no dispone de teselación por hardware —sencillamente no forma parte de la especificación, pues se eliminó por compatibilidad con Metal—, así que el sustituto es un plano densamente subdividido (256×256 segmentos, 131.072 triángulos) con desplazamiento de vértices en la etapa de vértices. El mismo uniforme de amplitud controla tanto POM como el plano geométrico, por lo que ambos se desvanecen a la vez y la comparación sigue siendo equivalente a cualquier distancia.</p>
<p>Con la referencia real en pantalla, las afirmaciones cualitativas pasaron a ser medibles. En una órbita de 16° mirando hacia abajo, POM y el plano teselado coinciden en el sombreado interno. En ángulos rasantes divergen exactamente donde deben hacerlo: POM queda limitado por el borde rectangular perfectamente recto de la geometría, mientras que la malla real muestra un perfil irregular en el horizonte, con picos y valles auténticos que reciben la luz. Así, el «deslizamiento» de los bordes de POM queda demostrado como algo intrínseco al algoritmo, no como un artefacto de la textura o la iluminación. Los dos perfiles de coste también quedan claros: POM está limitado por los fragmentos —el coste crece con los píxeles cubiertos—, mientras que el plano teselado está limitado por los vértices —el coste crece con la densidad de la malla sin importar la cobertura—. Para un bloque de terreno, que ya paga el coste de vértices de un plano controlado por un mapa de alturas, POM es la solución adecuada para el detalle por debajo de la escala de la malla.</p>
<p>El plano de referencia también detectó un error sutil de experiencia de usuario. El usuario observó que la superficie parecía hundirse al aumentar la amplitud. La causa era la convención de Unity, que trata el plano geométrico como la parte superior del campo de alturas, de modo que los picos permanecen anclados al mismo nivel y todo lo demás se desplaza hacia abajo por paralaje, arrastrando la superficie media por debajo de la referencia plana en <code>(1 − mean_h) × amplitude</code>. La solución vuelve a centrar la convención para que <code>h = 0.5</code> corresponda al plano: los picos ascienden hacia la cámara y los valles se hunden. El algoritmo se ejecuta exactamente como prescribe Unity; el experimento simplemente posprocesa el resultado con medio desplazamiento para ajustarlo a lo que «amplitud» debería significar para una persona que mueve un control deslizante.</p>
<p>El plano de referencia aclaró una cuestión más. Un control deslizante de «Pasos» parecía no hacer nada, lo que daba la impresión de ser un error de conexión, pero no lo era. El refinamiento por secante de tres iteraciones posterior a la búsqueda lineal es tan bueno —el artículo de Tatarchuk de 2006 sobre POM señala que una búsqueda de 4 pasos más 3 pasos de secante resulta visualmente indistinguible de una búsqueda de 64 pasos— que, en un mapa de alturas suave, cualquier cantidad de pasos entre 4 y 64 converge a las mismas UV con precisión inferior a un téxel. La solución fue añadir un interruptor, no rehacer las conexiones: al desactivar la secante, el control de pasos se convierte en el único ajuste de la precisión de la intersección, por lo que reducirlo a 4 produce escalones visibles en los adoquines y aumentarlo a 64 vuelve a suavizarlos. El interruptor es un uniforme 0/1 que usa <code>mix</code> para convertir cada actualización de estado de la secante en una operación nula cuando está desactivado, por lo que alternarlo nunca reconstruye el material ni provoca tirones.</p>
<h2 id="tecnologia-mencionada-en-este-capitulo" tabindex="-1">Tecnología mencionada en este capítulo <a class="header-anchor" href="#tecnologia-mencionada-en-este-capitulo" aria-label="Permalink to &quot;Tecnología mencionada en este capítulo&quot;"></a></h2>
<p><strong>Mapeado de oclusión por paralaje en TSL.</strong> POM hace avanzar un rayo por la dirección de visión a través de un campo de alturas en el espacio tangente, encuentra la primera capa donde el rayo pasa por debajo de la superficie y refina la intersección, produciendo la profundidad de unas juntas hundidas sobre un quad plano sin geometría adicional. Un <code>mix(baseUV, refined, done)</code> final hace que el material sea idéntico bit a bit al modo plano cuando ningún fragmento interseca, lo que permite que la atenuación de amplitud del LOD por distancia reduzca el coste al de una textura plana en la lejanía. Consulta <a href="/es/guides/landscape-generation-browser.html#terrain-materials">materiales de terreno</a>.</p>
<p><strong>Bucles sin bifurcaciones para el flujo de control de WebGPU.</strong> En Three.js r184, <code>If(...).and(...)</code> de TSL puede compilarse a WGSL con un cuerpo de bucle que nunca se ejecuta, y <code>Break()</code> como nodo independiente no está disponible. El patrón portable consiste en realizar una muestra de textura incondicional por iteración —manteniendo el acceso a texturas dentro de un flujo de control uniforme, conforme a la especificación de WGSL— y usar una bandera <code>done</code> almacenada como valor flotante que, mediante <code>mix</code>, convierte cada actualización de estado en una operación nula una vez activada. Una función auxiliar <code>step</code> construida a partir de <code>sign(x + ε)</code> evita la conversión poco fiable de booleanos a valores flotantes. El coste mantiene constante el número máximo de iteraciones, independientemente del punto de salida anticipada, la compensación correcta a escala de fragmento.</p>
<p><strong>Portado literal de shaders.</strong> El portado de un shader conocido y fiable desde otro motor debe hacerse primero línea por línea y con los nombres de variables originales; la adaptación al estilo local viene después. Mezclar dos referencias —<code>PerPixelDisplacement.hlsl</code> de Unity y el tutorial de LearnOpenGL— produjo un híbrido con un desfase de uno en la referencia inicial del rayo, un signo de desplazamiento invertido y una fórmula de refinamiento cuyo límite ocultaba los pesos fuera de rango en forma de discontinuidades espaciales. Una única referencia canónica, no una nueva deducción.</p>
<p><strong>Referencia real con vértices desplazados.</strong> Como WebGPU no dispone de teselación por hardware, un plano densamente subdividido —256² segmentos— y desplazado en la etapa de vértices sirve como geometría real para validar una simulación ejecutada en la etapa de fragmentos. Controlar ambos mediante el mismo uniforme de amplitud mantiene una comparación rigurosa a cualquier distancia. POM está limitado por los fragmentos —escala con los píxeles cubiertos— y el plano geométrico está limitado por los vértices —escala con la densidad de la malla—, por lo que divergen precisamente en los bordes de la silueta, demostrando que el deslizamiento de los bordes de POM es intrínseco y no un artefacto.</p>
<hr>
<p>Parte 20 de 29.
Anterior: <a href="/es/blog/2026-05-04-open-world-browser-part-19-imposters.html">Parte 19 - El impostor que debe sobrevivir a un bosque</a>
Siguiente: <a href="/es/blog/2026-05-06-open-world-browser-part-21-visibility-buffer.html">Parte 21 - Un renderizador más rápido que no era más rápido</a>
Guía de la serie: <a href="/es/blog/2026-02-25-open-world-browser-series-guide.html">/es/blog/2026-02-25-open-world-browser-series-guide</a></p>
]]></content:encoded>
            <enclosure url="https://cdn.cinevva.com/blog/why-webgpu-engine-hero.jpg" length="0" type="image/jpg"/>
        </item>
        <item>
            <title><![CDATA[Construir un mundo abierto en el navegador, parte 19: El impostor que tiene que sobrevivir a un bosque]]></title>
            <link>https://app.cinevva.com/es/blog/2026-05-04-open-world-browser-part-19-imposters</link>
            <guid>https://app.cinevva.com/es/blog/2026-05-04-open-world-browser-part-19-imposters</guid>
            <pubDate>Mon, 04 May 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[El Spike 38 redujo un árbol a dos texturas sobre una valla publicitaria; después, una reescritura KISS y una corrección para valores impares de N consiguieron que coincidiera. Los Spikes 41-42 eliminaron el salto con mezcla hemioctaédrica y llevaron un millón de árboles a la GPU.]]></description>
            <content:encoded><![CDATA[<h1 id="construir-un-mundo-abierto-en-el-navegador-parte-19-el-impostor-que-tiene-que-sobrevivir-a-un-bosque" tabindex="-1">Construir un mundo abierto en el navegador, parte 19: El impostor que tiene que sobrevivir a un bosque <a class="header-anchor" href="#construir-un-mundo-abierto-en-el-navegador-parte-19-el-impostor-que-tiene-que-sobrevivir-a-un-bosque" aria-label="Permalink to &quot;Construir un mundo abierto en el navegador, parte 19: El impostor que tiene que sobrevivir a un bosque&quot;"></a></h1>
<p><em>Por <a href="/es/about.html">Oleg Sidorkin</a>, CTO y cofundador de Cinevva</em></p>
<p>¿Acabas de llegar? Consulta la <a href="/es/blog/2026-02-25-open-world-browser-series-guide.html">guía de la serie</a>. Explica qué es un spike y enlaza todas las partes.</p>
<p>La <a href="/es/blog/2026-05-02-open-world-browser-part-18-ai-scattering.html">parte 18</a> ofreció a los creadores un pincel que llena de árboles la ladera de una colina. El problema es cuánto cuestan esos árboles cuando hay decenas de miles en pantalla. Un árbol distante no necesita 2000 triángulos para aportar cuatro píxeles. Esta parte trata del LOD más profundo: el impostor, un quad plano que lleva una imagen del árbol, y el camino desde «un árbol que se ve bien» hasta un millón de ellos en la GPU.</p>
<h2 id="un-arbol-son-dos-texturas-sobre-una-valla-publicitaria" tabindex="-1">Un árbol son dos texturas sobre una valla publicitaria <a class="header-anchor" href="#un-arbol-son-dos-texturas-sobre-una-valla-publicitaria" aria-label="Permalink to &quot;Un árbol son dos texturas sobre una valla publicitaria&quot;"></a></h2>
<div style="position:relative;padding-bottom:56.25%;height:0;overflow:hidden;border-radius:8px;margin:1.5rem 0;border:1px solid rgba(255,255,255,0.12)">
<iframe src="/es/spikes/38-imposters/" title="Spike 38: impostores octaédricos" style="position:absolute;top:0;left:0;width:100%;height:100%;border:0;background:#000" loading="lazy" allowfullscreen></iframe>
</div>
<p><a href="/es/spikes/38-imposters/" target="_blank">Abrir el Spike 38 en una pestaña nueva ↗</a> · <a href="/es/blog/spike-source?spike=38-imposters">Ver código fuente</a></p>
<p>Un impostor prerenderiza un elemento desde una cuadrícula de ángulos de visión en dos atlas de texturas, uno para el color y otro para las normales en espacio de mundo, y después, en tiempo de ejecución, muestra un único quad orientado hacia la cámara que muestrea la celda correspondiente a la vista actual. El horneado consta de dos pasadas por celda: una difusa con un material sin iluminación para que esta no quede horneada en la textura, y otra de normales codificadas como <code>normalWorld × 0.5 + 0.5</code>, con el alfa transferido desde el original para que la silueta coincida píxel por píxel. El material en tiempo de ejecución es un <code>MeshStandardNodeMaterial</code> completo, así que el impostor sigue recibiendo el sol y la IBL de la escena como cualquier otra superficie. La ventaja está en la geometría: un quad en lugar de miles de triángulos, con el detalle almacenado en una textura de 1 MB.</p>
<p>Separar esto en su propio spike fue en sí mismo una lección. El impostor comenzó como el LOD más profundo dentro del sistema de dispersión del Spike 37, y cada iteración del horneado tenía que probarse a través de todo el flujo de dispersión, con la corrección del horneado entremezclada con la migración de matrices de instancias y los cambios de LOD. Separarlo para tener un elemento y un quad, uno junto al otro con el original, redujo el tiempo de iteración de minutos a segundos.</p>
<h2 id="cuando-la-solucion-de-manual-es-la-solucion-equivocada" tabindex="-1">Cuando la solución de manual es la solución equivocada <a class="header-anchor" href="#cuando-la-solucion-de-manual-es-la-solucion-equivocada" aria-label="Permalink to &quot;Cuando la solución de manual es la solución equivocada&quot;"></a></h2>
<p>La primera implementación utilizaba codificación octaédrica, el método de manual para empaquetar las direcciones de una esfera en un cuadrado. Superaba las pruebas numéricas de ida y vuelta, pero el usuario seguía enviando capturas en las que el impostor saltaba a una celda que parecía mostrar el árbol ligeramente desde arriba en vez de de frente. Le siguieron seis rondas de correcciones —un uniforme de dirección de vista por quad, un horneado con relación de aspecto cuadrada, materiales de depuración y orientación estática de las vallas— y todas eran realmente necesarias, pero ninguna resolvía el error real. La solución solo llegó al «replantearlo desde cero, KISS, sin parches».</p>
<p>La reescritura descartó el plegado octaédrico y usó azimut por elevación sin más: <code>az = atan2(dir.x, dir.z)</code>, <code>el = asin(dir.y)</code>, <code>uv = (az/2π, el/π + ½)</code>. Esa es toda la codificación, sin normalización L1 ni casos límite relacionados con el signo del cero. La razón por la que aquí es mejor no es que sea más precisa —muestrea una esfera de forma menos uniforme—, sino que el selector de celdas de la CPU y el shader de la GPU utilizan las mismas primitivas, así que no pueden discrepar en una dirección limítrofe como hacía silenciosamente el par octaédrico. El atlas se lee como una hoja de contactos: la columna representa el ángulo alrededor del elemento y la fila, la elevación; resulta evidente de un vistazo en la superposición.</p>
<p>Incluso después de eso, persistía la queja de que «parece visto ligeramente desde arriba», y la causa era una elección de cuantización, no la codificación. Con una cuadrícula de 4×4, los centros de las filas caen en ±22,5° y ±67,5°, por lo que no hay ninguna fila exactamente a 0° de elevación. Un espectador que mira horizontalmente, el caso más habitual con mucha diferencia, siempre cae en una fila horneada con inclinación. La solución es usar un N impar: una cuadrícula de 5×5 sitúa los centros de las filas en 0°, ±36° y ±72°, de modo que el espectador horizontal obtiene una celda horneada exactamente en horizontal. El mismo tipo de error de «desfase de media celda» vuelve a aparecer en el trabajo de paralaje de la siguiente parte, y la solución es plantearse la misma pregunta: ¿mi punto de muestreo discreto cae realmente donde creo para la entrada canónica?</p>
<p>Importaban otras dos cosas. La valla debe permanecer estática por tramos, no orientarse continuamente hacia la cámara. El impostor es una imagen plana tomada desde una dirección de horneado concreta, por lo que el plano de imagen del quad en tiempo de ejecución debe coincidir con el plano de esa cámara de horneado. Esto significa que conserva su orientación a lo largo del arco en el que permanece seleccionada una misma celda y después salta en el límite. Además, el presupuesto debe seguir las zonas hacia las que realmente miran los jugadores: una pasada posterior eliminó por completo las filas inclinadas en vista cenital para favorecer 24 posiciones en un anillo horizontal, separadas por 15°, más una celda completamente cenital, porque los árboles se ven desde la altura de los ojos prácticamente todo el tiempo.</p>
<h2 id="el-salto-y-como-lo-elimino-la-mezcla" tabindex="-1">El salto y cómo lo eliminó la mezcla <a class="header-anchor" href="#el-salto-y-como-lo-elimino-la-mezcla" aria-label="Permalink to &quot;El salto y cómo lo eliminó la mezcla&quot;"></a></h2>
<div style="position:relative;padding-bottom:56.25%;height:0;overflow:hidden;border-radius:8px;margin:1.5rem 0;border:1px solid rgba(255,255,255,0.12)">
<iframe src="/es/spikes/42-imposter-flicker/" title="Spike 42: comparación del parpadeo de los impostores" style="position:absolute;top:0;left:0;width:100%;height:100%;border:0;background:#000" loading="lazy" allowfullscreen></iframe>
</div>
<p><a href="/es/spikes/42-imposter-flicker/" target="_blank">Abrir el Spike 42 en una pestaña nueva ↗</a> · <a href="/es/blog/spike-source?spike=42-imposter-flicker">Ver código fuente</a></p>
<p>La valla estática por tramos resulta imperceptible a distancia y salta a corta distancia, lo cual no supone un problema hasta que se orbita alrededor. El Spike 42 colocó cuatro variantes una al lado de la otra —el elemento original, la base az/el de 5×5 y dos cuadrículas hemioctaédricas— para aislar el parpadeo y eliminarlo. Hay dos artefactos que provocan el salto. El cambio de celda se produce porque el shader de fragmentos cuantiza la dirección de vista en una de 25 celdas, así que cruzar un límite cambia la celda muestreada y reorienta el quad en el mismo fotograma. La degeneración del polo se da en la vista cenital, donde todos los azimuts convergen en un único punto y la transición entre el anillo y la celda superior es la peor del atlas.</p>
<p>El mapeado hemioctaédrico resuelve ambos problemas. Mapea continuamente el hemisferio superior sobre el cuadrado unitario, por lo que las direcciones 3D adyacentes caen en UV adyacentes, sin singularidad en el polo ni necesidad de una celda cenital especial. La solución al parpadeo es la mezcla bilineal de celdas: en lugar de saltar a la celda más cercana, se encuentra el grupo de 2×2 celdas que encierra la dirección codificada y se mezclan las cuatro, con un total de 8 lecturas de textura —4 difusas y 4 de normales—. Ahora las vistas adyacentes se funden entre sí en vez de saltar. La mezcla de dos vectores normales unitarios no tiene por qué conservar la longitud unitaria, así que se vuelve a normalizar, lo que se comporta como un slerp para los pequeños ángulos entre celdas vecinas. El coste es real —un atlas de 12×12 ocupa unos 9 MB frente a los 1,6 MB del az/el, y el horneado tarda aproximadamente cinco veces más con 288 pasadas sobre destinos de renderizado—, pero el horneado solo se realiza una vez durante la carga y la mezcla ofrece un resultado sin saltos, que es lo que permite utilizar impostores mientras la cámara está realmente en movimiento.</p>
<h2 id="un-millon-de-arboles-una-copia-de-la-posicion-de-la-camara-por-fotograma" tabindex="-1">Un millón de árboles, una copia de la posición de la cámara por fotograma <a class="header-anchor" href="#un-millon-de-arboles-una-copia-de-la-posicion-de-la-camara-por-fotograma" aria-label="Permalink to &quot;Un millón de árboles, una copia de la posición de la cámara por fotograma&quot;"></a></h2>
<div style="position:relative;padding-bottom:56.25%;height:0;overflow:hidden;border-radius:8px;margin:1.5rem 0;border:1px solid rgba(255,255,255,0.12)">
<iframe src="/es/spikes/41-imposter-forest/" title="Spike 41: bosque de impostores" style="position:absolute;top:0;left:0;width:100%;height:100%;border:0;background:#000" loading="lazy" allowfullscreen></iframe>
</div>
<p><a href="/es/spikes/41-imposter-forest/" target="_blank">Abrir el Spike 41 en una pestaña nueva ↗</a> · <a href="/es/blog/spike-source?spike=41-imposter-forest">Ver código fuente</a></p>
<p>El sistema en tiempo de ejecución del Spike 38 ejecuta un <code>lookAt</code> en la CPU por quad y por fotograma, algo que funciona bien con un árbol pero resulta fatal para un bosque. Con un millón de árboles, las actualizaciones de matrices y la carga del búfer de instancias en cada fotograma dominarían todo el procesamiento. El Spike 41 traslada a la GPU todo el flujo por fotograma. El centro, la rotación sobre el eje vertical y la escala de cada instancia se cargan una sola vez durante la construcción como atributos de instancia y nunca cambian. El shader de vértices construye la base de la valla a partir de la dirección de vista en espacio de mundo <code>camPos − center</code> y expande un quad unitario compartido en el espacio de mundo. El shader de fragmentos realiza por píxel la codificación hemioctaédrica y la mezcla bilineal. El único trabajo que la CPU realiza por fotograma para todo el bosque es un <code>Vector3.copy</code> que actualiza el uniforme de posición de la cámara, cuyo coste no aumenta en absoluto con el número de árboles.</p>
<p>Un aspecto elegante de las matemáticas es que la rotación sobre el eje vertical de cada instancia se cancela durante la decodificación de normales. El horneado almacena las normales en el sistema de referencia de la cámara de horneado y, como una rotación alrededor del eje vertical del mundo conserva +Y y el producto vectorial es equivariante bajo rotaciones, la base en tiempo de ejecución construida con la vertical del mundo como referencia ya equivale a la base de horneado rotada. Así, el shader decodifica las normales directamente mediante los varyings de la base en tiempo de ejecución sin utilizar en ningún momento la rotación vertical de cada instancia. La colocación utiliza una cuadrícula con variación aleatoria en vez de una dispersión puramente aleatoria: se divide el área en celdas y se coloca un árbol por celda en el centro más un desplazamiento acotado, lo que garantiza una separación mínima —no hay dos árboles uno encima del otro— sin dejar de parecer un bosque natural. Un detalle fácil de pasar por alto es la esfera envolvente. La plantilla geométrica es solo un quad unitario, así que three.js descartaría por frustum todo el bosque en cuanto la cámara dejara de mirar al origen. Establecer una esfera envolvente explícita que cubra toda el área más el margen de un quad evita que los árboles de las esquinas queden recortados en ángulos rasantes.</p>
<h2 id="tecnologia-mencionada-en-este-capitulo" tabindex="-1">Tecnología mencionada en este capítulo <a class="header-anchor" href="#tecnologia-mencionada-en-este-capitulo" aria-label="Permalink to &quot;Tecnología mencionada en este capítulo&quot;"></a></h2>
<p><strong>Atlas de impostores octaédricos y de azimut-elevación.</strong> Un impostor hornea un elemento desde una cuadrícula de direcciones de vista en un atlas difuso y otro de normales en espacio de mundo, y después renderiza una única valla que muestrea la celda correspondiente, sustituyendo miles de triángulos por dos texturas. El mapeado octaédrico de manual ofrece una cobertura uniforme de la esfera, pero es propenso a divergencias entre CPU y GPU en los límites de los pliegues; una cuadrícula sencilla de azimut por elevación muestrea la esfera de manera menos uniforme, pero garantiza por construcción que el selector de celdas y el shader coincidan. Utiliza un N impar para que una fila caiga exactamente a 0° de elevación y dedica el presupuesto de celdas al anillo horizontal, ya que los elementos suelen verse desde la altura de los ojos.</p>
<p><strong>Orientación estática por tramos de las vallas.</strong> Un impostor es una imagen tomada desde una dirección de horneado concreta, por lo que el plano de imagen del quad en tiempo de ejecución debe coincidir con el plano de la cámara de horneado, no orientarse continuamente hacia la cámara en tiempo de ejecución. El quad mantiene su orientación a lo largo del arco en el que permanece seleccionada una misma celda y después salta en el límite, algo imperceptible a la distancia de uso de los impostores y que solo se nota de cerca, donde los impostores no se utilizan.</p>
<p><strong>Atlas hemioctaédrico con mezcla bilineal de celdas.</strong> Mapear continuamente el hemisferio superior sobre el cuadrado unitario elimina la singularidad del polo y la celda cenital especial. El salto se elimina muestreando el grupo de 2×2 celdas que encierra la dirección de vista codificada y mezclando bilinealmente las cuatro celdas —8 lecturas—, de modo que las vistas adyacentes se funden entre sí. Las normales mezcladas se vuelven a normalizar, aproximando un slerp en el pequeño ángulo entre celdas. El coste es un atlas más grande —unos 9 MB con 12×12— y un horneado único más largo, a cambio de un sombreado sin saltos cuando la cámara se mueve.</p>
<p><strong>Impostores instanciados controlados por la GPU.</strong> El centro, la rotación sobre el eje vertical y la escala de cada instancia se cargan una sola vez como atributos de instancia; el shader de vértices construye la base de la valla y expande un quad unitario compartido, mientras que el shader de fragmentos realiza por píxel la codificación y la mezcla. El coste de CPU por fotograma para todo el bosque se limita a una única copia del uniforme de posición de la cámara, independientemente del número de instancias. La rotación vertical de cada instancia se cancela durante la decodificación de normales porque la construcción de la base mediante productos vectoriales conserva la rotación alrededor del eje vertical del mundo. Una esfera envolvente explícita para todo el bosque evita que three.js descarte por frustum toda la malla instanciada cuando la cámara deja de mirar al origen de la plantilla del quad unitario. Consulta <a href="/es/guides/landscape-generation-browser.html#gpu-driven-lod-with-webgpu">LOD controlado por la GPU</a>.</p>
<hr>
<p>Parte 19 de 29.
Anterior: <a href="/es/blog/2026-05-02-open-world-browser-part-18-ai-scattering.html">Parte 18 - Un pincel de dispersión que parece colocar elementos mediante IA</a>
Siguiente: <a href="/es/blog/2026-05-05-open-world-browser-part-20-parallax-occlusion.html">Parte 20 - Simular profundidad en un plano</a>
Guía de la serie: <a href="/es/blog/2026-02-25-open-world-browser-series-guide.html">/es/blog/2026-02-25-open-world-browser-series-guide</a></p>
]]></content:encoded>
            <enclosure url="https://cdn.cinevva.com/blog/why-webgpu-engine-hero.jpg" length="0" type="image/jpg"/>
        </item>
        <item>
            <title><![CDATA[Nubes volumétricas y efectos meteorológicos en los juegos modernos]]></title>
            <link>https://app.cinevva.com/es/blog/2026-05-04-volumetric-clouds-and-weather</link>
            <guid>https://app.cinevva.com/es/blog/2026-05-04-volumetric-clouds-and-weather</guid>
            <pubDate>Mon, 04 May 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Cómo renderizan los juegos modernos las nubes volumétricas, la dispersión atmosférica, la niebla, la lluvia, la nieve y el clima dinámico, junto con los artículos y las ponencias sobre motores que sentaron las bases de cada técnica.]]></description>
            <content:encoded><![CDATA[<h1 id="nubes-volumetricas-y-efectos-meteorologicos-en-los-juegos-modernos" tabindex="-1">Nubes volumétricas y efectos meteorológicos en los juegos modernos <a class="header-anchor" href="#nubes-volumetricas-y-efectos-meteorologicos-en-los-juegos-modernos" aria-label="Permalink to &quot;Nubes volumétricas y efectos meteorológicos en los juegos modernos&quot;"></a></h1>
<p><em>Por <a href="/es/about.html">Oleg Sidorkin</a>, CTO y cofundador de Cinevva</em></p>
<img src="/img/blog/clouds_weather_hero.webp" alt="Escena AAA estilizada con imponentes nubes volumétricas de tormenta, relámpagos, cortinas de lluvia y un camino de piedra mojado que refleja el cielo" style="width:100%;border-radius:8px;margin:1.5rem 0" />
<p>Hace unas semanas escribí sobre <a href="/es/blog/2026-05-03-aaa-rendering-techniques.html">las técnicas de renderizado que realmente incluyen los juegos AAA modernos</a>. Un aspecto que traté por encima fue el cielo y el clima, porque merece su propia lista. Las nubes, la niebla, la lluvia y la nieve son los sistemas que convierten una demo de terreno en un lugar. También comparten más código de lo que parece. Las nubes volumétricas, la niebla a ras de suelo y los rayos crepusculares recurren al mismo trazado de rayos por pasos. Las carreteras mojadas, la acumulación de nieve y los rastros de pisadas utilizan el mismo truco de desplazamiento más PBR. El viento es un único vector de dirección que leen todos los elementos de la escena.</p>
<p>Este es un recorrido breve y subjetivo por la forma en que los grandes estudios construyen estos sistemas en 2026, junto con los artículos y las ponencias sobre motores que respaldan cada parte.</p>
<h2 id="_1-cielo-y-atmosfera-basados-en-principios-fisicos" tabindex="-1">1. Cielo y atmósfera basados en principios físicos <a class="header-anchor" href="#_1-cielo-y-atmosfera-basados-en-principios-fisicos" aria-label="Permalink to &quot;1. Cielo y atmósfera basados en principios físicos&quot;"></a></h2>
<p>La dispersión atmosférica es la base. El color del cielo, la bruma del horizonte, la forma en que las montañas lejanas adquieren un tono azul y el naranja del atardecer proceden de la dispersión de la luz al atravesar el aire. Los motores modernos calculan este fenómeno a partir de la física: dispersión de Rayleigh para el azul, dispersión de Mie para la bruma alrededor del sol y absorción del ozono para el violeta intenso del cenit.</p>
<p>El método original de Bruneton de 2008 precalculaba todos los datos en tablas de consulta 4D, lo que limitaba los cambios dinámicos de la hora del día y añadía artefactos de LUT cuando el sol estaba bajo. La actualización de Sébastien Hillaire de 2020, que es la que incluye el componente Sky Atmosphere de UE5, sustituye la LUT de alta dimensionalidad por unas pocas texturas 2D y una aproximación de dispersión múltiple que se actualiza en cada fotograma. Funciona tanto en un teléfono como en un PC de gama alta.</p>
<img src="/img/blog/clouds_weather_atmosphere.webp" alt="Cielo basado en principios físicos durante la hora dorada, con un suave gradiente de naranja a azul sobre la silueta de unas montañas lejanas" style="width:100%;border-radius:8px;margin:1.5rem 0" />
<p>Para profundizar:</p>
<ul>
<li>Hillaire, <a href="https://sebh.github.io/publications/egsr2020.pdf" target="_blank" rel="noreferrer">Una técnica escalable y lista para producción para renderizar el cielo y la atmósfera</a> (EGSR 2020, el estándar moderno, utilizado en UE5).</li>
<li>Bruneton y Neyret, <a href="https://hal.inria.fr/inria-00288758/document" target="_blank" rel="noreferrer">Dispersión atmosférica precalculada</a> (EGSR 2008, el enfoque original basado en LUT).</li>
<li>Bruneton, <a href="https://ebruneton.github.io/precomputed_atmospheric_scattering/" target="_blank" rel="noreferrer">Dispersión atmosférica precalculada: una nueva implementación</a> (implementación de referencia de código abierto, con soporte para ozono y múltiples planetas).</li>
<li>Epic Games, <a href="https://dev.epicgames.com/documentation/en-us/unreal-engine/sky-atmosphere-component-in-unreal-engine" target="_blank" rel="noreferrer">Componente Sky Atmosphere</a> (documentación de UE5).</li>
</ul>
<h2 id="_2-nubes-volumetricas-con-ruido-perlin-worley" tabindex="-1">2. Nubes volumétricas con ruido Perlin-Worley <a class="header-anchor" href="#_2-nubes-volumetricas-con-ruido-perlin-worley" aria-label="Permalink to &quot;2. Nubes volumétricas con ruido Perlin-Worley&quot;"></a></h2>
<p>La técnica fundamental para crear nubes en los juegos modernos surgió de la charla de Andrew Schneider sobre Horizon Zero Dawn en 2015. Las nubes no son mallas. Son una función de densidad 3D definida mediante capas de ruido: una mezcla Perlin-Worley de baja frecuencia proporciona la forma general de la nube, mientras que un ruido Worley de mayor frecuencia erosiona la silueta para producir bordes vaporosos. Un mapa meteorológico —una textura 2D muestreada según las coordenadas XZ del mundo— controla la cobertura, el tipo de nube y la precipitación de cada región. Un gradiente basado en la altura mezcla perfiles de cúmulos, estratos y cirros según la altitud.</p>
<p>El renderizador hace avanzar un rayo desde la cámara a través del volumen de nubes, acumulando densidad y dispersión. La iteración «Nubis» de 2017 añadió herramientas de creación y animación a escala regional, y la implementación original para PS4 renderizaba todo el cielo en unos 2 ms. La mayoría de los estudios que publican hoy juegos con nubes volumétricas siguen remontándose a este artículo.</p>
<img src="/img/blog/clouds_weather_noise.webp" alt="Una forma de nube 3D descompuesta en patrones superpuestos de ruido Perlin y Worley que muestran cómo el detalle erosiona la silueta" style="width:100%;border-radius:8px;margin:1.5rem 0" />
<p>Para profundizar:</p>
<ul>
<li>Schneider, <a href="https://www.guerrilla-games.com/read/the-real-time-volumetric-cloudscapes-of-horizon-zero-dawn" target="_blank" rel="noreferrer">Los paisajes de nubes volumétricas en tiempo real de Horizon Zero Dawn</a> (SIGGRAPH 2015, la referencia canónica).</li>
<li>Schneider, <a href="https://advances.realtimerendering.com/s2017/Nubis%20-%20Authoring%20Realtime%20Volumetric%20Cloudscapes%20with%20the%20Decima%20Engine%20-%20Final%20.pdf" target="_blank" rel="noreferrer">Nubis: creación de paisajes de nubes volumétricas en tiempo real con el motor Decima</a> (SIGGRAPH 2017, la continuación a escala regional).</li>
<li>Hillaire, <a href="https://media.contentapi.ea.com/content/dam/eacom/frostbite/files/s2016-pbs-frostbite-sky-clouds-new.pdf" target="_blank" rel="noreferrer">Renderizado de cielos, atmósferas y nubes basado en principios físicos en Frostbite</a> (SIGGRAPH 2016, la versión de Frostbite).</li>
<li>Häggström, <a href="https://www.diva-portal.org/smash/get/diva2:1223894/FULLTEXT01.pdf" target="_blank" rel="noreferrer">Renderizado en tiempo real de nubes volumétricas</a> (una tesis clara y accesible con todo el código de shaders).</li>
</ul>
<h2 id="_3-nubes-de-voxeles-y-nubis3" tabindex="-1">3. Nubes de vóxeles y Nubis³ <a class="header-anchor" href="#_3-nubes-de-voxeles-y-nubis3" aria-label="Permalink to &quot;3. Nubes de vóxeles y Nubis³&quot;"></a></h2>
<p>La evolución de Nubis de 2023 abandonó por completo la representación de formas en 2.5D en favor de vóxeles 3D reales. Cada vóxel almacena directamente la densidad de la nube, lo que permite a los artistas esculpir y animar sus formas como si modelaran terreno. El coste de pasar a una representación más densa se compensa acelerando el trazado de rayos por pasos mediante campos de distancia con signo comprimidos y técnicas ingeniosas para aumentar la resolución de datos de vóxeles dispersos.</p>
<p>El resultado es el tipo de paisaje nuboso que puedes atravesar <em>volando</em> sin que los trucos subyacentes queden al descubierto. Es excesivo para la mayoría de los estudios, pero esa es la dirección en la que avanza la gama alta.</p>
<img src="/img/blog/clouds_weather_voxel_clouds.webp" alt="Un cúmulo descompuesto en una cuadrícula de vóxeles 3D, con bordes vaporosos y suavizados que se funden con el interior de aspecto cúbico" style="width:100%;border-radius:8px;margin:1.5rem 0" />
<p>Para profundizar:</p>
<ul>
<li>Schneider, <a href="https://www.guerrilla-games.com/read/nubis-cubed" target="_blank" rel="noreferrer">Nubis³: métodos (y locuras) para modelar y renderizar nubes inmersivas basadas en vóxeles en tiempo real</a> (SIGGRAPH 2023, la charla sobre nubes de vóxeles).</li>
<li>Schneider, <a href="https://www.guerrilla-games.com/read/nubis-evolved" target="_blank" rel="noreferrer">Nubis, evolucionado</a> (SIGGRAPH 2022, el puente entre 2.5D y 3D completo).</li>
<li>Schneider, <a href="https://www.schneidervfx.com/" target="_blank" rel="noreferrer">Efectos volumétricos y VFX en tiempo real</a> (el sitio personal de Andrew, con material de cursos y análisis detallados).</li>
</ul>
<h2 id="_4-renderizado-de-nubes-por-capas-y-fondos-2d" tabindex="-1">4. Renderizado de nubes por capas y fondos 2D <a class="header-anchor" href="#_4-renderizado-de-nubes-por-capas-y-fondos-2d" aria-label="Permalink to &quot;4. Renderizado de nubes por capas y fondos 2D&quot;"></a></h2>
<p>No todos los estudios pueden permitirse nubes totalmente volumétricas, y no todos los ángulos de cámara las necesitan. Muchos juegos combinan técnicas: cirros a gran altitud renderizados como una capa 2D en desplazamiento, cúmulos a media altitud como volúmenes trazados por rayos y estratos a baja altitud como una fina lámina de medio participativo. Para el horizonte suele utilizarse un cubemap de cielo precalculado, con el que se fusiona la pasada volumétrica más allá de una distancia de desvanecimiento.</p>
<p>Este sistema de capas es lo que mantiene bajo control el presupuesto de las nubes. Un solo tipo de nube a máxima calidad puede consumir entre 4 y 6 ms; usar distintas calidades para diferentes altitudes permite mantener el mismo aspecto por la mitad del coste.</p>
<img src="/img/blog/clouds_weather_cloud_layers.webp" alt="Cielo al atardecer dividido en tres capas de nubes: finas hebras de cirros en lo alto, cúmulos a media altura y bruma de estratos cerca del horizonte" style="width:100%;border-radius:8px;margin:1.5rem 0" />
<p>Para profundizar:</p>
<ul>
<li>Vos, <a href="https://www.gdcvault.com/play/1023327/The-Real-Time-Volumetric-Cloudscapes" target="_blank" rel="noreferrer">Los paisajes de nubes volumétricas en tiempo real de Horizon Zero Dawn</a> (vídeo de GDC 2016; el análisis del sistema de capas está en la segunda mitad).</li>
<li>Bauer, <a href="https://www.youtube.com/watch?v=IYxtqlD1-Ac" target="_blank" rel="noreferrer">Creación del mundo atmosférico de Red Dead Redemption 2</a> (SIGGRAPH 2019, el pipeline combinado de cielo, nubes y efectos volumétricos de RDR2).</li>
<li>Hillaire, <a href="https://www.gdcvault.com/play/1029105/Volumetric-Clouds-and" target="_blank" rel="noreferrer">Nubes volumétricas y megapartículas en REDengine 4</a> (GDC 2025, el pipeline de nubes de Cyberpunk 2077).</li>
</ul>
<h2 id="_5-niebla-volumetrica-con-cuadriculas-de-froxeles" tabindex="-1">5. Niebla volumétrica con cuadrículas de fróxeles <a class="header-anchor" href="#_5-niebla-volumetrica-con-cuadriculas-de-froxeles" aria-label="Permalink to &quot;5. Niebla volumétrica con cuadrículas de fróxeles&quot;"></a></h2>
<p>La niebla es un campo 3D, no un efecto de pantalla 2D. El enfoque moderno estándar es la cuadrícula de fróxeles: una textura 3D alineada con el frustum de visión de la cámara, en la que cada celda («fróxel» = frustum + vóxel) almacena la densidad y el color iluminado. Un shader de cómputo inyecta en la cuadrícula la dispersión de cada fuente de luz, acumula la extinción a lo largo del rayo de visión y aplica el resultado como una pasada a pantalla completa.</p>
<p>Esto es lo que genera haces de luz a través de las ventanas, niebla coloreada alrededor de luces puntuales y volúmenes visibles en torno a las explosiones. También es el mecanismo subyacente de la «perspectiva atmosférica», que hace que los objetos lejanos se desvanezcan en el aire. Bart Wronski introdujo la técnica para Assassin's Creed 4 y Sébastien Hillaire la estandarizó en Frostbite.</p>
<img src="/img/blog/clouds_weather_froxel_fog.webp" alt="Frustum de cámara visualizado como una cuadrícula 3D de fróxeles, con celdas más pequeñas cerca de la cámara y más grandes a lo lejos, y partículas de niebla en su interior" style="width:100%;border-radius:8px;margin:1.5rem 0" />
<p>Para profundizar:</p>
<ul>
<li>Wronski, <a href="https://bartwronski.com/wp-content/uploads/2014/08/bwronski_volumetric_fog_siggraph2014.pdf" target="_blank" rel="noreferrer">Niebla volumétrica: una solución unificada para la dispersión atmosférica basada en shaders de cómputo</a> (SIGGRAPH 2014, el artículo original sobre cuadrículas de fróxeles).</li>
<li>Hillaire, <a href="http://www.frostbite.com/2015/08/physically-based-unified-volumetric-rendering-in-frostbite/" target="_blank" rel="noreferrer">Renderizado volumétrico unificado y basado en principios físicos en Frostbite</a> (SIGGRAPH 2015, la implementación lista para producción).</li>
<li>Kovalovs, <a href="https://history.siggraph.org/wp-content/uploads/2022/08/2020-Talks-Kovalovs_Volumetric-Effects-of-The-Last-of-Us-Part-Two.pdf" target="_blank" rel="noreferrer">Efectos volumétricos de The Last of Us Part Two</a> (SIGGRAPH 2020, con notas sobre jitter temporal y composición con corrección de profundidad).</li>
<li>Wright et al., <a href="https://advances.realtimerendering.com/s2022/SIGGRAPH2022-Advances-Lumen-Wright%20et%20al.pdf" target="_blank" rel="noreferrer">Lumen: iluminación global en tiempo real en Unreal Engine 5</a> (SIGGRAPH 2022, incluye la interacción de Lumen con la niebla volumétrica).</li>
</ul>
<h2 id="_6-rayos-divinos-y-haces-crepusculares" tabindex="-1">6. Rayos divinos y haces crepusculares <a class="header-anchor" href="#_6-rayos-divinos-y-haces-crepusculares" aria-label="Permalink to &quot;6. Rayos divinos y haces crepusculares&quot;"></a></h2>
<p>Los rayos de sol visibles en el aire brumoso no son un efecto independiente. Surgen del mismo sistema de niebla, siempre que tanto la densidad de la niebla como el mapa de sombras estén disponibles para el mismo shader de cómputo. Cuando el shader inyecta luz en un fróxel, muestrea el mapa de sombras en la posición de ese fróxel dentro del mundo. Las celdas en sombra permanecen oscuras y las iluminadas adoptan el color del sol. Al recorrer el resultado con el rayo de la cámara, las celdas brillantes forman haces continuos.</p>
<p>También existen variantes más baratas en espacio de pantalla —un desenfoque radial desde la posición del sol hacia el búfer de profundidad— y siguen siendo la opción adecuada para móviles o hardware de gama baja. No captan el sol cuando está fuera de pantalla, pero su coste es casi nulo.</p>
<img src="/img/blog/clouds_weather_god_rays.webp" alt="Bosque al amanecer con rayos de sol que atraviesan los troncos y la niebla a ras de suelo, formando nítidos haces de luz" style="width:100%;border-radius:8px;margin:1.5rem 0" />
<p>Para profundizar:</p>
<ul>
<li>Mitchell, <a href="https://developer.nvidia.com/gpugems/gpugems3/part-ii-light-and-shadows/chapter-13-volumetric-light-scattering-post-process" target="_blank" rel="noreferrer">Dispersión volumétrica de la luz como posproceso</a> (GPU Gems 3, el enfoque de desenfoque radial en espacio de pantalla).</li>
<li>Engelhardt y Dachsbacher, <a href="https://cg.ivd.kit.edu/publications/2010/epipolar/EpipolarSampling.pdf" target="_blank" rel="noreferrer">Muestreo epipolar para sombras y rayos crepusculares en medios participativos</a> (I3D 2010, la técnica para GPU más precisa).</li>
<li>Vos, <a href="https://www.guerrilla-games.com/read/volumetric-light-effects-in-killzone-shadow-fall" target="_blank" rel="noreferrer">Efectos de luz volumétrica en Killzone: Shadow Fall</a> (SIGGRAPH 2014, la versión de producción con integración de sombras).</li>
</ul>
<h2 id="_7-relampagos-y-fenomenos-meteorologicos-estocasticos" tabindex="-1">7. Relámpagos y fenómenos meteorológicos estocásticos <a class="header-anchor" href="#_7-relampagos-y-fenomenos-meteorologicos-estocasticos" aria-label="Permalink to &quot;7. Relámpagos y fenómenos meteorológicos estocásticos&quot;"></a></h2>
<p>Un relámpago es un efecto de un solo fotograma con dos partes: la malla del rayo y la respuesta de la iluminación y el mapeo de tonos de toda la escena. El rayo propiamente dicho suele ser una malla de billboards procedural creada mediante un algoritmo recursivo de subdivisión de segmentos, con variaciones aleatorias para darle un aspecto caótico y un estrechamiento progresivo hacia el suelo. Algunos motores lo renderizan como un destello aditivo en espacio de pantalla; otros, como geometría emisiva totalmente iluminada que proyecta luz sobre el mundo mediante la inyección de una luz puntual durante un fotograma.</p>
<p>Lo interesante es todo lo <em>demás</em>: la parte inferior de las nubes se ilumina desde abajo, el suelo resplandece durante dos fotogramas, la medición de la exposición automática tarda unos cuantos fotogramas en recuperarse y se reproduce un trueno con un retardo basado en la distancia. Bien ejecutado, esto convierte un destello de 16 ms en una secuencia de cinco segundos que transmite la sensación de que el clima ocurre dentro del mundo y no simplemente por encima de él.</p>
<img src="/img/blog/clouds_weather_lightning.webp" alt="Relámpago ramificado que cae desde una nube de tormenta al anochecer e ilumina la base de las nubes y la silueta de un pequeño pueblo" style="width:100%;border-radius:8px;margin:1.5rem 0" />
<p>Para profundizar:</p>
<ul>
<li>Reed y Wyvill, <a href="https://dl.acm.org/doi/10.1145/192161.192256" target="_blank" rel="noreferrer">Simulación visual de relámpagos</a> (SIGGRAPH 1994, el algoritmo recursivo de rayos que todavía utiliza todo el mundo).</li>
<li>Kim y Lin, <a href="https://gamma.cs.unc.edu/POWER/" target="_blank" rel="noreferrer">Animación rápida de relámpagos mediante una malla adaptativa</a> (IEEE TVCG 2007, con una base física más rigurosa).</li>
<li>Bauer, <a href="https://www.youtube.com/watch?v=IYxtqlD1-Ac" target="_blank" rel="noreferrer">Creación del mundo atmosférico de Red Dead Redemption 2</a> (SIGGRAPH 2019, el pipeline de tormentas de RDR2, incluida la temporización de los relámpagos).</li>
</ul>
<h2 id="_8-particulas-de-lluvia-mallas-de-lluvia-y-gotas-en-espacio-de-pantalla" tabindex="-1">8. Partículas de lluvia, mallas de lluvia y gotas en espacio de pantalla <a class="header-anchor" href="#_8-particulas-de-lluvia-mallas-de-lluvia-y-gotas-en-espacio-de-pantalla" aria-label="Permalink to &quot;8. Partículas de lluvia, mallas de lluvia y gotas en espacio de pantalla&quot;"></a></h2>
<p>En los juegos modernos, la lluvia rara vez se compone únicamente de partículas. La solución barata y convincente consiste en un pequeño conjunto de texturas en desplazamiento extendidas sobre quads verticales o alineados con la pantalla, iluminados por las mismas sondas de sol y cielo que el resto de la escena. Cerca de la cámara, partículas individuales con forma de estela añaden detalle. En la propia lente de la cámara, las texturas de gotas, los regueros deslizantes y las ondas de impacto refuerzan la sensación de «estar dentro de la tormenta».</p>
<p>El viento afecta a la dirección de la lluvia. El mismo vector de viento desplaza el mapa meteorológico de las nubes, dobla la hierba e inclina los quads de lluvia. Un solo vector para toda la escena y decenas de sistemas que lo utilizan.
<img src="/img/blog/clouds_weather_rain_storm.webp" alt="Fuerte tormenta nocturna con cortinas de lluvia iluminadas por faros lejanos y ondas sobre una carretera mojada" style="width:100%;border-radius:8px;margin:1.5rem 0" /></p>
<p>Para profundizar:</p>
<ul>
<li>Tatarchuk, <a href="https://gpuopen.com/wp-content/uploads/2018/04/Tatarchuk-Rain-Rendering-EGSR2006.pdf" target="_blank" rel="noreferrer">Renderizado de lluvia en tiempo real dirigible por artistas en entornos urbanos</a> (EGSR 2006, la referencia canónica sobre lluvia por capas).</li>
<li>Garg y Nayar, <a href="https://www1.cs.columbia.edu/CAVE/projects/rain_ren/rain_ren.php" target="_blank" rel="noreferrer">Renderizado fotorrealista de trazos de lluvia</a> (SIGGRAPH 2006, la física de la luz al atravesar las gotas de lluvia).</li>
<li>Wojciechowski, <a href="https://www.gdcvault.com/play/1027382/Rain-In-Cyberpunk-2077" target="_blank" rel="noreferrer">La lluvia en Cyberpunk 2077</a> (GDC 2021, un recorrido por una implementación moderna en producción).</li>
</ul>
<h2 id="_9-superficies-mojadas-charcos-y-ondas" tabindex="-1">9. Superficies mojadas, charcos y ondas <a class="header-anchor" href="#_9-superficies-mojadas-charcos-y-ondas" aria-label="Permalink to &quot;9. Superficies mojadas, charcos y ondas&quot;"></a></h2>
<p>La lluvia que no cambia el suelo parece falsa de inmediato. Las superficies mojadas responden oscureciendo su albedo (el agua absorbe la luz incidente), suavizando sus normales (la película de agua alisa la microsuperficie) y reduciendo su rugosidad (el agua es un espejo casi perfecto en ángulos rasantes). El cambio en el shader es pequeño; el cambio visual es enorme.</p>
<p>Los charcos se controlan mediante máscaras: una máscara basada en la altura o pintada sobre los vértices define las zonas bajas que se llenan de agua a medida que aumenta un parámetro de «humedad». Las ondas son texturas de mapas de normales en flipbook que se activan con los impactos de las gotas de lluvia. Las implementaciones realmente buenas acumulan el estado de humedad con el tiempo, de modo que una tormenta larga empapa lentamente el mundo, mientras que un chaparrón breve solo oscurece las zonas altas.</p>
<img src="/img/blog/clouds_weather_wet_surfaces.webp" alt="Calle adoquinada y mojada de noche, con charcos poco profundos que reflejan letreros de neón y anillos de ondas causados por las gotas de lluvia" style="width:100%;border-radius:8px;margin:1.5rem 0" />
<p>Para profundizar:</p>
<ul>
<li>Lagarde y de Rousiers, <a href="https://seblagarde.wordpress.com/2015/07/14/siggraph-2014-moving-frostbite-to-physically-based-rendering/" target="_blank" rel="noreferrer">Migración de Frostbite al renderizado basado en física 3.0, sección 5.5</a> (SIGGRAPH 2014, los ajustes PBR canónicos para superficies mojadas).</li>
<li>Lagarde, <a href="https://seblagarde.wordpress.com/2011/08/17/feeding-a-physical-based-lighting-mode/" target="_blank" rel="noreferrer">Adopción de un modelo de sombreado basado en física</a> (la serie original del blog con las matemáticas del PBR para superficies mojadas).</li>
<li>Cyanilux, <a href="https://www.cyanilux.com/tutorials/rain-effects-breakdown/" target="_blank" rel="noreferrer">Análisis de efectos de lluvia</a> (un recorrido accesible con Shader Graph sobre charcos, ondas y gotas).</li>
</ul>
<h2 id="_10-acumulacion-y-deformacion-de-nieve" tabindex="-1">10. Acumulación y deformación de nieve <a class="header-anchor" href="#_10-acumulacion-y-deformacion-de-nieve" aria-label="Permalink to &quot;10. Acumulación y deformación de nieve&quot;"></a></h2>
<p>La nieve plantea el problema simétrico al de la lluvia: el mundo debe recordarla, no solo recibirla. El enfoque habitual utiliza una textura cenital de «acumulación de nieve» que se incrementa con el tiempo allí donde el cielo es visible (calculado mediante un mapa de profundidad o de sombras cenital). El shader del terreno muestrea esta máscara y mezcla el material de nieve en las zonas sombreadas, además de aplicar desplazamiento según la profundidad de la nieve en las áreas expuestas.</p>
<p>Las huellas y las rodadas se renderizan en un mapa de deformación deslizante centrado en el jugador. A medida que la cámara se mueve, las huellas antiguas salen del mapa y la textura se repite. El shader del terreno o de la nieve muestrea este mapa de deformación y desplaza los vértices hacia abajo en las zonas donde se ha escrito. La nieve de Battlefield 5 lo hace con teselación por hardware; los enfoques más económicos utilizan una malla de terreno de alta densidad únicamente con desplazamiento de vértices.</p>
<img src="/img/blog/clouds_weather_snow_deformation.webp" alt="Paisaje nevado estilizado con huellas recientes, ventisqueros acumulados contra las rocas, copos de nieve cayendo y montañas lejanas entre la bruma" style="width:100%;border-radius:8px;margin:1.5rem 0" />
<p>Para profundizar:</p>
<ul>
<li>Barré-Brisebois, <a href="https://www.digitalfoundry.net/articles/digitalfoundry-2018-hands-on-with-battlefield-5s-closed-alpha" target="_blank" rel="noreferrer">Primer contacto con Battlefield 5: la importancia de los pequeños detalles</a> (el artículo de producción sobre la nieve de Frostbite).</li>
<li>St-Amour, <a href="https://is.muni.cz/th/m2v6i/real-time_snow_deformation.txt?lang=cs" target="_blank" rel="noreferrer">Deformación de nieve en tiempo real</a> (una tesis con todos los detalles de implementación en la GPU).</li>
<li>Andersson, <a href="https://media.contentapi.ea.com/content/dam/eacom/frostbite/files/chapter5-andersson-terrain-rendering-in-frostbite.pdf" target="_blank" rel="noreferrer">Renderizado de terreno en Frostbite mediante splatting procedural de shaders</a> (la base del sistema de splatting sobre la que funciona la acumulación de nieve).</li>
</ul>
<h2 id="_11-el-viento-como-sistema-global" tabindex="-1">11. El viento como sistema global <a class="header-anchor" href="#_11-el-viento-como-sistema-global" aria-label="Permalink to &quot;11. El viento como sistema global&quot;"></a></h2>
<p>El viento no es un efecto de partículas. En los motores de producción es un único vector global (a veces, un campo 3D de baja resolución) que <em>todos</em> los sistemas dinámicos leen desde su shader de vértices. Las briznas de hierba se doblan, las ramas de los árboles se mecen, la tela ondea, las hojas flotan, la lluvia se inclina, el humo es arrastrado y los mapas meteorológicos de nubes se desplazan. Un valor uniforme actualizado por fotograma, decenas de consumidores.</p>
<p>La versión más completa es una «cuadrícula de viento» que almacena la dirección y la intensidad muestreadas según la posición en el mundo, lo que permite crear tormentas con ráfagas localizadas, valles resguardados y estelas detrás de los edificios. Además, el follaje suele recibir un desplazamiento por vértice horneado durante la creación del recurso para que los árboles idénticos no se mezan al unísono. El resultado es un mundo que respira al mismo ritmo.</p>
<img src="/img/blog/clouds_weather_wind_foliage.webp" alt="Viento fuerte que inclina lateralmente la hierba y los árboles, con hojas arremolinándose en primer plano bajo nubes tormentosas" style="width:100%;border-radius:8px;margin:1.5rem 0" />
<p>Para profundizar:</p>
<ul>
<li>McAuley, <a href="https://www.gdcvault.com/play/1022235/Rendering-the-World-of-Far" target="_blank" rel="noreferrer">Renderizado del mundo de Far Cry 4</a> (GDC 2015, incluye la cuadrícula de viento de Far Cry 4 para la vegetación).</li>
<li>Habel y Wimmer, <a href="https://www.cg.tuwien.ac.at/research/publications/2007/HABEL-2007-IIM/" target="_blank" rel="noreferrer">Renderizado realista de paisajes en tiempo real mediante nubes de billboards</a> (antiguo, pero las matemáticas del viento aplicado a la vegetación no han cambiado).</li>
<li>Frostbite, <a href="https://www.guerrilla-games.com/read/the-vegetation-of-horizon-zero-dawn" target="_blank" rel="noreferrer">La vegetación de Horizon Zero Dawn</a> (SIGGRAPH 2017, con la arquitectura del sistema de viento).</li>
</ul>
<h2 id="_12-tormentas-de-arena-ventiscas-y-meteorologia-densa" tabindex="-1">12. Tormentas de arena, ventiscas y meteorología densa <a class="header-anchor" href="#_12-tormentas-de-arena-ventiscas-y-meteorologia-densa" aria-label="Permalink to &quot;12. Tormentas de arena, ventiscas y meteorología densa&quot;"></a></h2>
<p>La meteorología extrema constituye una categoría de renderizado propia. Una tormenta de arena es una niebla espesa y opaca, alineada con el suelo, con un marcado sesgo direccional y una niebla de distancia muy intensa. Una ventisca añade una ráfaga de partículas cerca de la cámara y reduce la visibilidad. La ceniza volcánica y el humo utilizan la misma arquitectura con colores distintos.</p>
<p>Lo que hace convincentes estos fenómenos no son las partículas, sino el <em>acoplamiento</em>: el sol se oscurece, el cielo cambia de tono, la gradación de color del posprocesado se modifica, el audio ambiental cambia, los sonidos de las pisadas se alteran y la voz del jugador se amortigua, si la tiene. El renderizador es el mensajero; la inmersión surge cuando todos los sistemas del juego responden al mismo tiempo.</p>
<img src="/img/blog/clouds_weather_sandstorm.webp" alt="Un muro de polvo y arena naranja avanzando sobre una llanura desértica, con un cielo amoratado encima y azul despejado detrás" style="width:100%;border-radius:8px;margin:1.5rem 0" />
<p>Para profundizar:</p>
<ul>
<li>Burley, <a href="https://www.gdcvault.com/play/1024954/The-Real-time-Sky-and" target="_blank" rel="noreferrer">El cielo y la atmósfera en tiempo real de Uncharted: The Lost Legacy</a> (GDC 2018, con notas sobre la composición de fenómenos meteorológicos densos).</li>
<li>Khalifa, <a href="https://www.gdcvault.com/play/1027587/Atmospheric-Weather-Effects-in-Forza" target="_blank" rel="noreferrer">Efectos meteorológicos atmosféricos en Forza Horizon 5</a> (GDC 2022, meteorología moderna para mundos abiertos).</li>
<li>Karis, <a href="https://advances.realtimerendering.com/s2021/" target="_blank" rel="noreferrer">La tecnología tras la demo «Lumen in the Land of Nanite» de Unreal Engine 5</a> (SIGGRAPH 2021, la pila volumétrica de la escena de polvo en la cueva).</li>
</ul>
<h2 id="_13-hora-del-dia-y-cielos-dinamicos" tabindex="-1">13. Hora del día y cielos dinámicos <a class="header-anchor" href="#_13-hora-del-dia-y-cielos-dinamicos" aria-label="Permalink to &quot;13. Hora del día y cielos dinámicos&quot;"></a></h2>
<p>La hora del día en tiempo real es el multiplicador que hace que merezca la pena publicar todos los demás sistemas de esta lista. La dirección y el color del sol se actualizan durante un ciclo de 24 minutos o 24 horas. La LUT de la atmósfera se actualiza con el ángulo del sol. La iluminación de las nubes se recalcula en cada fotograma. Las cascadas de sombras se reorientan. Las sondas de reflexión se actualizan. El color ambiental cambia. La exposición del posprocesado se adapta.</p>
<p>Conseguirlo sin artefactos visibles consiste, sobre todo, en gestionar la caché de texturas y la estabilidad temporal. Las técnicas rápidas precalculan el cielo para ángulos solares fijos e interpolan entre ellos; las más lentas lo recalculan en cada fotograma. El modelo atmosférico de Hillaire de 2020 es lo bastante rápido como para recalcularse, por eso UE5 lo incluye. El mapa meteorológico de nubes se desplaza con el viento, de modo que la cobertura cambia de forma natural sin que nadie tenga que crear fotogramas clave.</p>
<img src="/img/blog/clouds_weather_time_of_day.webp" alt="Tres franjas verticales sobre un mismo paisaje: amanecer rosado, mediodía azul y atardecer rojo, todas con la misma silueta de colinas" style="width:100%;border-radius:8px;margin:1.5rem 0" />
<p>Para profundizar:</p>
<ul>
<li>Hillaire, <a href="https://sebh.github.io/publications/egsr2020.pdf" target="_blank" rel="noreferrer">Una técnica escalable y preparada para producción para renderizar el cielo y la atmósfera</a> (EGSR 2020, con el análisis de la hora del día dinámica).</li>
<li>Pesce, <a href="https://www.realtimerendering.com/raytracinggems/rtg2/index.html" target="_blank" rel="noreferrer">Renderizado del cielo en tiempo real: técnicas y compromisos</a> (capítulo de Ray Tracing Gems II, una panorámica moderna).</li>
<li>Bauer, <a href="https://www.youtube.com/watch?v=IYxtqlD1-Ac" target="_blank" rel="noreferrer">Creación del mundo atmosférico de Red Dead Redemption 2</a> (SIGGRAPH 2019, con el pipeline de 24 horas).</li>
</ul>
<h2 id="_14-la-maquina-de-estados-meteorologicos" tabindex="-1">14. La máquina de estados meteorológicos <a class="header-anchor" href="#_14-la-maquina-de-estados-meteorologicos" aria-label="Permalink to &quot;14. La máquina de estados meteorológicos&quot;"></a></h2>
<p>Debajo de todo esto hay una pequeña máquina de estados. La mayoría de los juegos incluyen entre 4 y 12 estados meteorológicos (despejado, parcialmente nublado, cubierto, lluvia ligera, lluvia intensa, tormenta eléctrica, niebla, nieve, ventisca y tormenta de arena), cada uno definido por un conjunto de parámetros: cobertura y tipo de nubes, velocidad y dirección del viento, tipo e intensidad de las precipitaciones, tintes del color ambiental, perfil de audio y gradación del posprocesado.</p>
<p>Las transiciones son interpolaciones lineales entre conjuntos de parámetros durante periodos de 30 a 120 segundos. La transición no es un caso especial: son simplemente dos estados interpolados, mientras cada subsistema de renderizado lee en ese fotograma los valores actuales de los parámetros. La meteorología puede estar guionizada (una cinemática necesita una tormenta), basarse en una semilla (determinista por región y por día del juego, para que dos jugadores del mismo mundo vean el mismo tiempo) o definirse por completo sobre una cuadrícula de regiones. Los pipelines más limpios tratan los tres como planificadores diferentes que escriben en el mismo búfer de parámetros.</p>
<img src="/img/blog/clouds_weather_state_machine.webp" alt="La misma escena, lado a lado: a la izquierda bajo un sol despejado y a la derecha bajo lluvia tormentosa, con superficies mojadas y relucientes" style="width:100%;border-radius:8px;margin:1.5rem 0" />
<p>Para profundizar:</p>
<ul>
<li>Bauer, <a href="https://www.youtube.com/watch?v=IYxtqlD1-Ac" target="_blank" rel="noreferrer">Creación del mundo atmosférico de Red Dead Redemption 2</a> (SIGGRAPH 2019, con el pipeline de estados meteorológicos).</li>
<li>Khalifa, <a href="https://www.gdcvault.com/play/1027587/Atmospheric-Weather-Effects-in-Forza" target="_blank" rel="noreferrer">Efectos meteorológicos atmosféricos en Forza Horizon 5</a> (GDC 2022, con el enfoque de mezcla de parámetros).</li>
<li>Schneider, <a href="https://www.guerrilla-games.com/read/the-real-time-volumetric-cloudscapes-of-horizon-zero-dawn" target="_blank" rel="noreferrer">Los paisajes de nubes volumétricas en tiempo real de Horizon Zero Dawn</a> (SIGGRAPH 2015, con la evolución de las nubes controlada por mapas meteorológicos).</li>
</ul>
<h2 id="_15-los-momentos-cinematograficos" tabindex="-1">15. Los momentos cinematográficos <a class="header-anchor" href="#_15-los-momentos-cinematograficos" aria-label="Permalink to &quot;15. Los momentos cinematográficos&quot;"></a></h2>
<p>Toda la pila existe para crear unos pocos momentos emblemáticos. Permanecer en una cresta mientras se acerca un frente tormentoso. Ver cómo un rayo de sol atraviesa un claro entre las copas de los árboles. Salir de una cueva y adentrarse en la nieve. Volar a través de una nube cúmulo y ver la luz en su interior.</p>
<p>Estos son los momentos de los que los jugadores hacen capturas de pantalla. También son los momentos en los que todos los sistemas anteriores deben funcionar a la vez: nubes volumétricas, dispersión atmosférica, niebla con integración de sombras, PBR para superficies mojadas, viento sobre el follaje, gradación de color según la hora del día y una transición entre estados meteorológicos, todo ello compuesto en un único fotograma. Si cualquiera de ellos falla, la magia se rompe.</p>
<img src="/img/blog/clouds_weather_cloud_sea.webp" alt="Vista desde arriba de un mar de nubes del que emerge una única cima montañosa, con las partes superiores de las nubes iluminadas por el sol y valles en sombra debajo" style="width:100%;border-radius:8px;margin:1.5rem 0" />
<h2 id="que-significa-esto-para-el-navegador" tabindex="-1">Qué significa esto para el navegador <a class="header-anchor" href="#que-significa-esto-para-el-navegador" aria-label="Permalink to &quot;Qué significa esto para el navegador&quot;"></a></h2>
<p>La mayoría de estas técnicas se trasladan directamente a WebGPU. Ya hemos publicado niebla atmosférica básica, mezcla de skyboxes equirectangulares y bruma de distancia en espacio de pantalla en el <a href="/es/blog/2026-02-25-open-world-browser-series-guide.html">motor de mundo abierto para navegador</a>. Las piezas más difíciles —nubes volumétricas completas, niebla con cuadrícula de froxels, PBR para superficies mojadas con charcos dinámicos y mapas de deformación de nieve— son el siguiente paso evidente ahora que el pipeline del terreno es estable. El muestreo por fragmento del color de la niebla a partir del skybox de Spike 24 es una pieza de este rompecabezas. Lo siguiente es un raymarcher de nubes basado en shaders de cómputo que alimente la misma LUT atmosférica.</p>
<p>La buena noticia es que el mínimo de hardware de los navegadores ya es lo bastante potente. WebGPU ofrece cómputo, texturas 3D, despacho indirecto y consultas de marcas de tiempo. La atmósfera de Hillaire de 2020 se ha portado varias veces a WebGL. Nubis, de Schneider, cuenta con implementaciones de referencia de código abierto en GLSL que se traducen a WGSL mediante cambios mecánicos. Ya no hay ningún motivo relacionado con el renderizado que impida que un juego de navegador tenga el mismo cielo que uno de consola. Solo quedan motivos de ingeniería, y los motivos de ingeniería son los que nos gustan.</p>
<h2 id="lecturas-adicionales-sobre-toda-la-pila" tabindex="-1">Lecturas adicionales sobre toda la pila <a class="header-anchor" href="#lecturas-adicionales-sobre-toda-la-pila" aria-label="Permalink to &quot;Lecturas adicionales sobre toda la pila&quot;"></a></h2>
<p>Si quieres una única fuente que reúna todo esto, el archivo de SIGGRAPH «Advances in Real-Time Rendering in Games» (<a href="https://advances.realtimerendering.com/" target="_blank" rel="noreferrer">advances.realtimerendering.com</a>) contiene las ponencias canónicas sobre meteorología y atmósfera desde 2014. Para análisis de producción sobre cómo juegos concretos renderizan el cielo y la meteorología, los <a href="http://www.adriancourreges.com/blog/" target="_blank" rel="noreferrer">artículos de perfilado de GPU de Adrian Courrèges</a> incluyen desgloses detallados fotograma a fotograma de GTA V, Horizon Zero Dawn y Doom Eternal. En cuanto a las matemáticas del cielo y la atmósfera, el <a href="https://www.scratchapixel.com/lessons/3d-basic-rendering/volume-rendering-for-developers/intro-volume-rendering.html" target="_blank" rel="noreferrer">capítulo sobre renderizado volumétrico de scratchapixel.com</a> es la introducción más accesible, y el <a href="https://github.com/sebh/UnrealEngineSkyAtmosphere" target="_blank" rel="noreferrer">repositorio de la implementación</a> de código abierto de Hillaire es la referencia con calidad de producción.</p>
]]></content:encoded>
            <enclosure url="https://app.cinevva.com/img/blog/clouds_weather_hero.webp" length="0" type="image/webp"/>
        </item>
        <item>
            <title><![CDATA[Una breve lista de técnicas de renderizado utilizadas en los juegos AAA modernos]]></title>
            <link>https://app.cinevva.com/es/blog/2026-05-03-aaa-rendering-techniques</link>
            <guid>https://app.cinevva.com/es/blog/2026-05-03-aaa-rendering-techniques</guid>
            <pubDate>Sun, 03 May 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Las principales técnicas de renderizado detrás de los gráficos AAA actuales, desde la geometría virtualizada de Nanite hasta el trazado de caminos con ReSTIR y el reescalado basado en aprendizaje automático, con referencias técnicas detalladas para cada una.]]></description>
            <content:encoded><![CDATA[<h1 id="una-breve-lista-de-tecnicas-de-renderizado-utilizadas-en-los-juegos-aaa-modernos" tabindex="-1">Una breve lista de técnicas de renderizado utilizadas en los juegos AAA modernos <a class="header-anchor" href="#una-breve-lista-de-tecnicas-de-renderizado-utilizadas-en-los-juegos-aaa-modernos" aria-label="Permalink to &quot;Una breve lista de técnicas de renderizado utilizadas en los juegos AAA modernos&quot;"></a></h1>
<p><em>Por <a href="/es/about.html">Oleg Sidorkin</a>, CTO y cofundador de Cinevva</em></p>
<img src="/img/blog/aaa_rendering_hero.webp" alt="Escena compuesta que muestra materiales PBR, geometría virtualizada e iluminación con trazado de rayos en un juego AAA moderno" style="width:100%;border-radius:8px;margin:1.5rem 0" />
<p>Si analizas en detalle el pipeline de renderizado de un juego AAA de 2026, descubrirás que casi todo se basa en un pequeño conjunto de técnicas utilizadas por estudios de todo el sector. Los nombres cambian entre motores, pero las ideas son las mismas. Esta es una breve lista de las técnicas que realmente hacen el trabajo en pantalla, con una figura y varias referencias técnicas detalladas para cada una.</p>
<h2 id="_1-renderizado-basado-en-fisica-pbr" tabindex="-1">1. Renderizado basado en física (PBR) <a class="header-anchor" href="#_1-renderizado-basado-en-fisica-pbr" aria-label="Permalink to &quot;1. Renderizado basado en física (PBR)&quot;"></a></h2>
<p>Los materiales se describen mediante texturas de albedo, rugosidad, metalicidad, normales y oclusión ambiental, y se iluminan con shaders que conservan la energía (reflexión especular Cook-Torrance y reflexión difusa Lambertiana o Disney). Es la base que presupone cualquier motor AAA moderno. Si una superficie mantiene un aspecto coherente bajo la luz del sol, de una lámpara y de una linterna, se debe al PBR.</p>
<img src="/img/blog/aaa_pbr_materials.webp" alt="Casco de hierro renderizado con materiales PBR, acompañado de muestras de texturas flotantes que muestran mapas de albedo, rugosidad, metalicidad y normales" style="width:100%;border-radius:8px;margin:1.5rem 0" />
<p>Análisis en profundidad:</p>
<ul>
<li>Burley, <a href="https://media.disneyanimation.com/uploads/production/publication_asset/48/asset/s2012_pbs_disney_brdf_notes_v3.pdf" target="_blank" rel="noreferrer">Sombreado basado en física en Disney</a> (las notas originales del curso sobre el «BRDF de Disney», SIGGRAPH 2012).</li>
<li>Karis, <a href="https://cdn2.unrealengine.com/Resources/files/2013SiggraphPresentationsNotes-26915738.pdf" target="_blank" rel="noreferrer">Sombreado realista en Unreal Engine 4</a> (SIGGRAPH 2013, la charla de referencia sobre PBR en UE4).</li>
<li>Lagarde y de Rousiers, <a href="https://seblagarde.wordpress.com/2015/07/14/siggraph-2014-moving-frostbite-to-physically-based-rendering/" target="_blank" rel="noreferrer">La transición de Frostbite al renderizado basado en física 3.0</a> (SIGGRAPH 2014, el pipeline completo de Frostbite).</li>
<li><a href="https://www.realtimerendering.com/" target="_blank" rel="noreferrer">Real-Time Rendering, 4.ª edición, capítulo 9</a> (la referencia académica).</li>
</ul>
<h2 id="_2-sombreado-diferido-y-mediante-bufer-de-visibilidad" tabindex="-1">2. Sombreado diferido y mediante búfer de visibilidad <a class="header-anchor" href="#_2-sombreado-diferido-y-mediante-bufer-de-visibilidad" aria-label="Permalink to &quot;2. Sombreado diferido y mediante búfer de visibilidad&quot;"></a></h2>
<p>En primer lugar, la geometría escribe atributos (normales, identificadores de materiales y profundidad) en un G-buffer o búfer de visibilidad. Después, la iluminación se ejecuta como una pasada a pantalla completa que lee esos búferes y sombrea cada píxel una sola vez. Los búferes de visibilidad (utilizados por Nanite y sistemas similares) llevan esta idea más lejos al almacenar únicamente los identificadores de los triángulos y resolver después los parámetros del material por píxel, lo que reduce el coste del sobredibujado en geometrías densas.</p>
<img src="/img/blog/aaa_deferred_gbuffer.webp" alt="G-buffer de sombreado diferido dividido en paneles de color final, normales del mundo, profundidad e identificador de material" style="width:100%;border-radius:8px;margin:1.5rem 0" />
<p>Análisis en profundidad:</p>
<ul>
<li>Engel, <a href="https://download.nvidia.com/developer/presentations/2004/6800_Leagues/6800_Leagues_Deferred_Shading.pdf" target="_blank" rel="noreferrer">Sombreado diferido</a> (NVIDIA, la charla fundacional).</li>
<li>Burns y Hunt, <a href="http://jcgt.org/published/0002/02/04/" target="_blank" rel="noreferrer">El búfer de visibilidad: un enfoque de sombreado diferido optimizado para la caché</a> (JCGT 2013, el artículo original sobre el búfer de visibilidad).</li>
<li>Wihlidal, <a href="http://www.frostbite.com/2016/03/optimizing-the-graphics-pipeline-with-compute/" target="_blank" rel="noreferrer">«Optimización del pipeline gráfico mediante cómputo»</a> (GDC 2016, el pipeline diferido basado en cómputo de Frostbite).</li>
<li>Karis, Stubbe y Wihlidal, <a href="https://advances.realtimerendering.com/s2021/Karis_Nanite_SIGGRAPH_Advances_2021_final.pdf" target="_blank" rel="noreferrer">Análisis en profundidad de la geometría virtualizada de Nanite</a> (SIGGRAPH 2021, incluye una explicación detallada del búfer de visibilidad de Nanite).</li>
</ul>
<h2 id="_3-geometria-virtualizada-al-estilo-de-nanite" tabindex="-1">3. Geometría virtualizada (al estilo de Nanite) <a class="header-anchor" href="#_3-geometria-virtualizada-al-estilo-de-nanite" aria-label="Permalink to &quot;3. Geometría virtualizada (al estilo de Nanite)&quot;"></a></h2>
<p>Las mallas se preprocesan para formar una jerarquía de clústeres. Durante la ejecución, la GPU transmite y selecciona clústeres con la resolución adecuada para cada píxel, lo que permite obtener un nivel de detalle preciso incluso por debajo del tamaño de un píxel sin crear LOD manualmente. Nanite de Unreal es el ejemplo más conocido. Otros motores ya incluyen sus propias variantes. El resultado práctico son recursos con calidad cinematográfica en tiempo real sin tener que crear LOD.</p>
<img src="/img/blog/aaa_virtualized_geometry.webp" alt="Renderizado suave a la izquierda y clústeres de meshlets inferiores al tamaño de un píxel en colores vivos a la derecha" style="width:100%;border-radius:8px;margin:1.5rem 0" />
<p>Análisis en profundidad:</p>
<ul>
<li>Karis, Stubbe y Wihlidal, <a href="https://advances.realtimerendering.com/s2021/Karis_Nanite_SIGGRAPH_Advances_2021_final.pdf" target="_blank" rel="noreferrer">Análisis en profundidad de la geometría virtualizada de Nanite</a> (SIGGRAPH 2021).</li>
<li>Brian Karis, <a href="https://www.youtube.com/watch?v=eviSykqSUUw" target="_blank" rel="noreferrer">Charla sobre Nanite en la GDC 2021</a> (una explicación accesible en vídeo).</li>
<li>Liktor, <a href="https://research.activision.com/publications/2021/09/geometry-rendering-pipeline-architecture-at-activision" target="_blank" rel="noreferrer">Arquitectura del pipeline de renderizado de geometría en Activision</a> (renderizado basado en clústeres, 2021).</li>
<li>Schied et al., <a href="https://research.nvidia.com/publication/2017-07_spatiotemporal-variance-guided-filtering-real-time-reconstruction-path-traced" target="_blank" rel="noreferrer">Filtrado guiado por varianza espaciotemporal</a> (técnicas relacionadas de descarte de clústeres).</li>
</ul>
<h2 id="_4-trazado-de-rayos-en-tiempo-real-para-sombras-reflejos-y-ao" tabindex="-1">4. Trazado de rayos en tiempo real para sombras, reflejos y AO <a class="header-anchor" href="#_4-trazado-de-rayos-en-tiempo-real-para-sombras-reflejos-y-ao" aria-label="Permalink to &quot;4. Trazado de rayos en tiempo real para sombras, reflejos y AO&quot;"></a></h2>
<p>El trazado de rayos por hardware (DXR, Vulkan RT) proyecta rayos de sombra, rayos de reflexión especular y brillante, y rayos de oclusión ambiental contra una BVH construida en cada fotograma. Incluso unos pocos rayos por píxel superan lo que pueden conseguir las técnicas en espacio de pantalla, especialmente en reflejos de elementos situados fuera de la pantalla y sombras de contacto. La mayoría de los juegos lo utilizan de forma selectiva, no para todo.</p>
<img src="/img/blog/aaa_hardware_raytracing.webp" alt="Coche deportivo rojo y brillante en una sala de exposición de lujo, con reflejos precisos mediante trazado de rayos y sombras de contacto" style="width:100%;border-radius:8px;margin:1.5rem 0" />
<p>Análisis en profundidad:</p>
<ul>
<li>Microsoft, <a href="https://microsoft.github.io/DirectX-Specs/d3d/Raytracing.html" target="_blank" rel="noreferrer">Especificación funcional de DirectX Raytracing (DXR)</a> (la referencia de la API).</li>
<li>Wyman, <a href="http://intro-to-dxr.cwyman.org/" target="_blank" rel="noreferrer">Introducción a DirectX Raytracing</a> (las notas del curso de SIGGRAPH, muy accesibles).</li>
<li>Boksansky y Marrs, <a href="https://www.realtimerendering.com/raytracinggems/rtg2/index.html" target="_blank" rel="noreferrer">Ray Tracing Gems II, capítulos 17-19</a> (PDF gratuito sobre técnicas modernas de DXR).</li>
<li>Stachowiak, <a href="https://www.ea.com/frostbite/news/stochastic-screen-space-reflections" target="_blank" rel="noreferrer">Reflejos estocásticos en espacio de pantalla</a> (Frostbite, el puente entre SSR y RT).</li>
</ul>
<h2 id="_5-trazado-de-rayos-por-software-al-estilo-de-lumen" tabindex="-1">5. Trazado de rayos por software (al estilo de Lumen) <a class="header-anchor" href="#_5-trazado-de-rayos-por-software-al-estilo-de-lumen" aria-label="Permalink to &quot;5. Trazado de rayos por software (al estilo de Lumen)&quot;"></a></h2>
<p>No todos los jugadores tienen una tarjeta RTX, por lo que los motores también incluyen alternativas basadas en campos de distancia o cachés de superficies. Lumen de Unreal, por ejemplo, realiza el trazado contra campos de distancia con signo y cachés de superficies para obtener una iluminación global difusa de bajo coste, y solo recurre a rayos acelerados por hardware cuando es necesario. Así es como los juegos AAA consiguen un «aspecto de trazado de rayos» en consolas.</p>
<img src="/img/blog/aaa_software_rt_lumen.webp" alt="Interior de una catedral con sangrado del color de las vidrieras y una superposición de estructura alámbrica SDF que revela la geometría aproximada" style="width:100%;border-radius:8px;margin:1.5rem 0" />
<p>Análisis en profundidad:</p>
<ul>
<li>Wright et al., <a href="https://advances.realtimerendering.com/s2022/SIGGRAPH2022-Advances-Lumen-Wright%20et%20al.pdf" target="_blank" rel="noreferrer">Lumen: iluminación global en tiempo real en Unreal Engine 5</a> (SIGGRAPH 2022, el artículo sobre Lumen).</li>
<li>Epic Games, <a href="https://dev.epicgames.com/documentation/en-us/unreal-engine/lumen-technical-details-in-unreal-engine" target="_blank" rel="noreferrer">Detalles técnicos de Lumen</a> (documentación oficial del motor).</li>
<li>Wright, <a href="https://advances.realtimerendering.com/s2021/Wright%20et%20al%20-%20Radiance%20Caching%20for%20Real-Time%20Global%20Illumination%20-%20SIGGRAPH%202021.pdf" target="_blank" rel="noreferrer">Caché de radiancia para iluminación global en tiempo real</a> (SIGGRAPH 2021).</li>
<li>Wright, <a href="https://www.youtube.com/watch?v=2GYXuM10riw" target="_blank" rel="noreferrer">Charla sobre Lumen en la GDC 2022</a> (versión en vídeo).</li>
</ul>
<h2 id="_6-restir-y-muestreo-de-reservorios" tabindex="-1">6. ReSTIR y muestreo de reservorios <a class="header-anchor" href="#_6-restir-y-muestreo-de-reservorios" aria-label="Permalink to &quot;6. ReSTIR y muestreo de reservorios&quot;"></a></h2>
<p>Para calcular la iluminación directa e indirecta con miles de fuentes de luz, ReSTIR (remuestreo por importancia de reservorios espaciotemporales) reutiliza muestras de luz entre píxeles y fotogramas. Así es como juegos como Cyberpunk 2077 con trazado de caminos mantienen un nivel de ruido bajo con uno o dos rayos por píxel. Cabe esperar que aparezca en más motores a medida que el trazado de caminos se convierta en el objetivo para la gama alta.</p>
<img src="/img/blog/aaa_ray_tracing_restir.webp" alt="Calle ciberpunk con reflejos trazados por rayos sobre el pavimento mojado y trayectorias visibles de luz rebotada" style="width:100%;border-radius:8px;margin:1.5rem 0" />
<p>Análisis en profundidad:</p>
<ul>
<li>Bitterli et al., <a href="https://research.nvidia.com/sites/default/files/pubs/2020-07_Spatiotemporal-reservoir-resampling/ReSTIR.pdf" target="_blank" rel="noreferrer">Remuestreo espaciotemporal de reservorios para trazado de rayos en tiempo real con iluminación directa dinámica</a> (SIGGRAPH 2020, el artículo original sobre ReSTIR).</li>
<li>Ouyang et al., <a href="https://research.nvidia.com/publication/2021-06_restir-gi-path-resampling-real-time-path-tracing" target="_blank" rel="noreferrer">ReSTIR GI: remuestreo de caminos para trazado de caminos en tiempo real</a> (HPG 2021, ReSTIR para iluminación indirecta).</li>
<li>Lin et al., <a href="https://research.nvidia.com/publication/2022-07_generalized-resampled-importance-sampling-foundations-restir" target="_blank" rel="noreferrer">Muestreo por importancia remuestreado generalizado</a> (SIGGRAPH 2022, los fundamentos matemáticos).</li>
<li>NVIDIA, <a href="https://www.nvidia.com/en-us/geforce/news/cyberpunk-2077-ray-tracing-overdrive-technology-preview-on-rtx-4090/" target="_blank" rel="noreferrer">Análisis técnico en profundidad del trazado de caminos de Cyberpunk 2077</a> (blog de ingeniería).</li>
</ul>
<h2 id="_7-nubes-volumetricas-niebla-y-atmosfera" tabindex="-1">7. Nubes volumétricas, niebla y atmósfera <a class="header-anchor" href="#_7-nubes-volumetricas-niebla-y-atmosfera" aria-label="Permalink to &quot;7. Nubes volumétricas, niebla y atmósfera&quot;"></a></h2>
<p>Los cielos se calculan mediante marcha de rayos a través de ruido 3D y volúmenes de densidad. La atmósfera utiliza tablas de dispersión precalculadas (al estilo de Bruneton) para las transiciones del sol y la luna. La niebla utiliza una cuadrícula de froxels (imagina una textura 3D alineada con el frustum de la vista) que captura la iluminación local. Juntas, estas técnicas permiten crear un «sistema meteorológico» en lugar de limitarse a un skybox.</p>
<img src="/img/blog/aaa_volumetrics.webp" alt="Valle montañoso al atardecer con nubes volumétricas y rayos crepusculares que atraviesan el aire brumoso" style="width:100%;border-radius:8px;margin:1.5rem 0" />
<p>Análisis en profundidad:</p>
<ul>
<li>Schneider, <a href="https://www.guerrilla-games.com/read/the-real-time-volumetric-cloudscapes-of-horizon-zero-dawn" target="_blank" rel="noreferrer">Los paisajes de nubes volumétricas en tiempo real de Horizon Zero Dawn</a> (SIGGRAPH 2015, la referencia fundamental sobre nubes).</li>
<li>Hillaire, <a href="https://sebh.github.io/publications/egsr2020.pdf" target="_blank" rel="noreferrer">Una técnica escalable y lista para producción para renderizar el cielo y la atmósfera</a> (EGSR 2020, el sucesor moderno de Bruneton utilizado en UE5).</li>
<li>Wronski, <a href="https://bartwronski.com/2014/08/22/volumetric-fog-siggraph-2014/" target="_blank" rel="noreferrer">Niebla volumétrica: una solución unificada basada en shaders de cómputo para la dispersión atmosférica</a> (SIGGRAPH 2014, niebla de froxels de Assassin's Creed 4).</li>
<li>Hillaire, <a href="https://www.ea.com/frostbite/news/physically-based-unified-volumetric-rendering-in-frostbite" target="_blank" rel="noreferrer">Renderizado volumétrico unificado y basado en física en Frostbite</a> (SIGGRAPH 2015).</li>
</ul>
<h2 id="_8-mapas-de-sombras-en-cascada-y-mapas-de-sombras-virtuales" tabindex="-1">8. Mapas de sombras en cascada y mapas de sombras virtuales <a class="header-anchor" href="#_8-mapas-de-sombras-en-cascada-y-mapas-de-sombras-virtuales" aria-label="Permalink to &quot;8. Mapas de sombras en cascada y mapas de sombras virtuales&quot;"></a></h2>
<p>Para las sombras del sol, los mapas de sombras en cascada dividen el frustum en intervalos y renderizan cada uno con la resolución adecuada. Los mapas de sombras virtuales llevan la idea más lejos: un único mapa de sombras enorme se divide en páginas y solo se renderizan las páginas visibles desde la cámara. Así es como los juegos AAA mantienen sombras nítidas cerca del jugador sin consumir una cantidad descomunal de memoria.</p>
<img src="/img/blog/aaa_cascaded_shadows.webp" alt="Escena exterior con tres frustums de cascada coloreados superpuestos que muestran el detalle de las sombras cerca de la cámara" style="width:100%;border-radius:8px;margin:1.5rem 0" />
<p>Análisis en profundidad:</p>
<ul>
<li>Dimitrov, <a href="https://developer.download.nvidia.com/SDK/10.5/opengl/src/cascaded_shadow_maps/doc/cascaded_shadow_maps.pdf" target="_blank" rel="noreferrer">Mapas de sombras en cascada</a> (informe técnico de NVIDIA, la referencia estándar).</li>
<li>Microsoft, <a href="https://learn.microsoft.com/en-us/windows/win32/dxtecharts/cascaded-shadow-maps" target="_blank" rel="noreferrer">Técnicas comunes para mejorar los mapas de profundidad de sombras</a> (documentación de DirectX).</li>
<li>Wright, <a href="https://advances.realtimerendering.com/s2023/index.html#VirtualShadowMaps" target="_blank" rel="noreferrer">Mapas de sombras virtuales en el capítulo 4 de Fortnite Battle Royale</a> (SIGGRAPH 2023, la charla sobre VSM de UE5).</li>
<li>Epic Games, <a href="https://dev.epicgames.com/documentation/en-us/unreal-engine/virtual-shadow-maps-in-unreal-engine" target="_blank" rel="noreferrer">Documentación sobre mapas de sombras virtuales</a>.</li>
</ul>
<h2 id="_9-efectos-en-espacio-de-pantalla-ssao-ssr-ssgi-sssss" tabindex="-1">9. Efectos en espacio de pantalla (SSAO, SSR, SSGI, SSSSS) <a class="header-anchor" href="#_9-efectos-en-espacio-de-pantalla-ssao-ssr-ssgi-sssss" aria-label="Permalink to &quot;9. Efectos en espacio de pantalla (SSAO, SSR, SSGI, SSSSS)&quot;"></a></h2>
<p>La lectura de los búferes de profundidad y normales permite obtener con un coste reducido oclusión ambiental (SSAO), reflejos (SSR), iluminación global de un rebote (SSGI) y dispersión subsuperficial para la piel (SSSSS). No capturan los detalles situados fuera de la pantalla, razón por la que el trazado de rayos los está sustituyendo, pero siguen utilizándose en todas partes como una solución de base rápida.</p>
<img src="/img/blog/aaa_screen_space_effects.webp" alt="Comparación lado a lado de una cocina con iluminación plana a la izquierda y SSAO, SSR y SSGI a la derecha" style="width:100%;border-radius:8px;margin:1.5rem 0" />
<p>Análisis en profundidad:</p>
<ul>
<li>Mittring, <a href="https://www.crytek.com/wp-content/uploads/Finding%20Next%20Gen%20-%20CryEngine%202.pdf" target="_blank" rel="noreferrer">En busca de la nueva generación: CryENGINE 2</a> (SIGGRAPH 2007, el artículo original sobre SSAO).</li>
<li>McGuire et al., <a href="https://research.nvidia.com/publication/scalable-ambient-obscurance" target="_blank" rel="noreferrer">Oscurecimiento ambiental escalable</a> (HPG 2012, SSAO moderno).</li>
<li>Stachowiak y Uludag, <a href="https://www.ea.com/frostbite/news/stochastic-screen-space-reflections" target="_blank" rel="noreferrer">Reflejos estocásticos en espacio de pantalla</a> (Frostbite, la referencia sobre SSR).</li>
<li>Jimenez, <a href="https://www.iryoku.com/separable-sss/" target="_blank" rel="noreferrer">Dispersión subsuperficial separable</a> (la técnica utilizada para la piel en la mayoría de los motores AAA).</li>
<li>Mara et al., <a href="https://research.activision.com/publications/2016/09/deep-g-buffers-for-stable-global-illumination-approximation" target="_blank" rel="noreferrer">Espacio de pantalla profundo</a> (Activision, parte de la evolución de SSGI).</li>
</ul>
<h2 id="_10-antialiasing-temporal-y-reescalado-mediante-aprendizaje-automatico-dlss-fsr-xess" tabindex="-1">10. Antialiasing temporal y reescalado mediante aprendizaje automático (DLSS, FSR, XeSS) <a class="header-anchor" href="#_10-antialiasing-temporal-y-reescalado-mediante-aprendizaje-automatico-dlss-fsr-xess" aria-label="Permalink to &quot;10. Antialiasing temporal y reescalado mediante aprendizaje automático (DLSS, FSR, XeSS)&quot;"></a></h2>
<p>El fotograma se renderiza a una resolución interna inferior y se reconstruye mediante vectores de movimiento, profundidad y datos históricos. Los reescaladores basados en aprendizaje automático (DLSS 3/4, FSR 3, XeSS) añaden además generación de fotogramas, interpolando fotogramas intermedios a partir del flujo óptico. La mayoría de los títulos AAA se diseñan ya asumiendo que habrá un reescalador activado, lo que cambia cómo se distribuye el presupuesto de renderizado del resto del fotograma.</p>
<img src="/img/blog/aaa_ml_upscaling.webp" alt="Comparación lado a lado de una entrada de baja resolución y una salida nítida del mismo personaje reconstruida mediante aprendizaje automático" style="width:100%;border-radius:8px;margin:1.5rem 0" />
Análisis en profundidad:
- Karis, [Supermuestreo temporal de alta calidad](http://advances.realtimerendering.com/s2014/index.html#_HIGH-QUALITY_TEMPORAL_SUPERSAMPLING) (SIGGRAPH 2014, la charla de referencia sobre TAA).
- Salvi, [Una incursión en el supermuestreo temporal](https://research.nvidia.com/sites/default/files/pubs/2016-03_An-Excursion-in/dlss_DTAA-2-2.pdf) (NVIDIA, en el camino hacia DLSS).
- Edelsten, [Verdaderamente de nueva generación: incorporación del aprendizaje profundo a los juegos y los gráficos](https://www.gdcvault.com/play/1026184/) (GDC 2019, arquitectura de DLSS).
- AMD, [Detalles técnicos de FidelityFX Super Resolution 3](https://gpuopen.com/fidelityfx-super-resolution-3/) e Intel, [Documento técnico de XeSS](https://www.intel.com/content/www/us/en/developer/articles/technical/intel-xess-technical-paper.html).
<h2 id="_11-renderizado-controlado-por-la-gpu-y-sombreadores-de-malla" tabindex="-1">11. Renderizado controlado por la GPU y sombreadores de malla <a class="header-anchor" href="#_11-renderizado-controlado-por-la-gpu-y-sombreadores-de-malla" aria-label="Permalink to &quot;11. Renderizado controlado por la GPU y sombreadores de malla&quot;"></a></h2>
<p>El descarte, la selección de LOD y el envío de llamadas de dibujado se ejecutan íntegramente en la GPU. Los sombreadores de malla sustituyen la canalización de vértices, geometría y teselado por una etapa más flexible, similar a la de cómputo, que genera meshlets. En combinación con el dibujado indirecto múltiple, esto elimina por completo a la CPU del bucle crítico por objeto.</p>
<img src="/img/blog/aaa_gpu_driven_meshlets.webp" alt="Escena de un puerto espacial alienígena con una superposición de clústeres de meshlets de colores que muestra el renderizado controlado por la GPU" style="width:100%;border-radius:8px;margin:1.5rem 0" />
<p>Análisis en profundidad:</p>
<ul>
<li>Haar y Aaltonen, <a href="https://advances.realtimerendering.com/s2015/aaltonenhaar_siggraph2015_combined_final_footer_220dpi.pdf" target="_blank" rel="noreferrer">Canalizaciones de renderizado controladas por la GPU</a> (SIGGRAPH 2015, la charla fundacional sobre Assassin's Creed Unity).</li>
<li>Wihlidal, <a href="https://www.frostbite.com/2016/03/optimizing-the-graphics-pipeline-with-compute/" target="_blank" rel="noreferrer">Optimización de la canalización gráfica mediante cómputo</a> (GDC 2016, descarte controlado por la GPU en Frostbite).</li>
<li>Kubisch, <a href="https://developer.nvidia.com/blog/introduction-turing-mesh-shaders/" target="_blank" rel="noreferrer">Introducción a los sombreadores de malla de Turing</a> (NVIDIA, introducción básica a los sombreadores de malla).</li>
<li>Pesce, <a href="https://www.bartwronski.com/" target="_blank" rel="noreferrer">Un recorrido vertiginoso por los sombreadores de malla</a> (y blogs de ingeniería similares recopilados en los <a href="http://www.adriancourreges.com/blog/" target="_blank" rel="noreferrer">análisis con RenderDoc de Adrian Courrèges</a>).</li>
</ul>
<h2 id="_12-renderizado-de-cabello-tela-y-piel" tabindex="-1">12. Renderizado de cabello, tela y piel <a class="header-anchor" href="#_12-renderizado-de-cabello-tela-y-piel" aria-label="Permalink to &quot;12. Renderizado de cabello, tela y piel&quot;"></a></h2>
<p>El cabello utiliza sombreado anisotrópico al estilo Marschner con geometría basada en hebras (NVIDIA HairWorks, AMD TressFX o sistemas nativos del motor). La tela se simula en la GPU mediante dinámica basada en posiciones y se renderiza con reflejos especulares anisotrópicos. La piel utiliza dispersión subsuperficial en espacio de pantalla junto con iluminación envolvente preintegrada. Estos tres elementos suelen ser los que delatan la diferencia de presupuesto entre una producción AAA y una independiente.</p>
<img src="/img/blog/aaa_hair_cloth_skin.webp" alt="Primer plano de un guerrero con cabello basado en hebras, capa de tela y piel con dispersión subsuperficial" style="width:100%;border-radius:8px;margin:1.5rem 0" />
<p>Análisis en profundidad:</p>
<ul>
<li>Marschner et al., <a href="https://www.cs.cornell.edu/~srm/publications/SG03-hair.pdf" target="_blank" rel="noreferrer">Dispersión de la luz en las fibras del cabello humano</a> (SIGGRAPH 2003, el modelo fundacional de cabello).</li>
<li>Chiang et al., <a href="https://benedikt-bitterli.me/pchfm/pchfm.pdf" target="_blank" rel="noreferrer">Un modelo práctico y controlable de cabello y pelaje para trazado de trayectorias en producción</a> (Disney 2016, ampliamente utilizado en aproximaciones en tiempo real).</li>
<li>Müller et al., <a href="https://matthias-research.github.io/pages/publications/posBasedDyn.pdf" target="_blank" rel="noreferrer">Dinámica basada en posiciones</a> (la referencia estándar para la simulación de telas).</li>
<li>Jimenez et al., <a href="https://www.iryoku.com/separable-sss/" target="_blank" rel="noreferrer">Dispersión subsuperficial separable</a> y <a href="https://www.iryoku.com/translucency/" target="_blank" rel="noreferrer">Translucidez realista de la piel en tiempo real</a>.</li>
</ul>
<h2 id="_13-calcomanias-texturizado-virtual-y-capas-de-materiales" tabindex="-1">13. Calcomanías, texturizado virtual y capas de materiales <a class="header-anchor" href="#_13-calcomanias-texturizado-virtual-y-capas-de-materiales" aria-label="Permalink to &quot;13. Calcomanías, texturizado virtual y capas de materiales&quot;"></a></h2>
<p>La variación de las superficies proviene de calcomanías superpuestas (agujeros de bala, suciedad, sangre y mugre) proyectadas sobre el búfer de profundidad, además de texturas virtuales que transmiten detalles de alta resolución justo cuando se necesitan. Las capas de materiales combinan varios conjuntos PBR por píxel mediante máscaras y proyección triplanar, logrando así que una sola roca parezca cinco distintas.</p>
<img src="/img/blog/aaa_decals_virtual_textures.webp" alt="Pared desgastada de un búnker de hormigón con calcomanías de impactos de bala, grafitis y un recuadro con el atlas de páginas de una textura virtual" style="width:100%;border-radius:8px;margin:1.5rem 0" />
<p>Análisis en profundidad:</p>
<ul>
<li>Pranckevičius, <a href="https://aras-p.info/blog/2009/02/27/deferred-decals/" target="_blank" rel="noreferrer">Calcomanías diferidas</a> y artículos posteriores (la clásica serie del blog de Aras).</li>
<li>Mittring, <a href="http://advances.realtimerendering.com/s2012/Epic/UnrealEngine4_Mittring_SIGGRAPH2012_Final_Cleaned.pdf" target="_blank" rel="noreferrer">La tecnología detrás de la «demo Elemental de Unreal Engine 4»</a> (SIGGRAPH 2012, incluye detalles sobre el texturizado virtual).</li>
<li>van Waveren, <a href="https://www.realtimerendering.com/blog/id-tech-5-challenges-from-texture-virtualization-to-massive-parallelization/" target="_blank" rel="noreferrer">Desafíos de id Tech 5: de la virtualización de texturas al paralelismo masivo</a> (SIGGRAPH 2009, la charla sobre MegaTexture).</li>
<li>Williams, <a href="https://www.gdcvault.com/play/1022144/Crafting-the-World-of-The" target="_blank" rel="noreferrer">Capas de materiales en The Order: 1886</a> (GDC 2014, materiales PBR por capas).</li>
</ul>
<h2 id="_14-transparencia-independiente-del-orden" tabindex="-1">14. Transparencia independiente del orden <a class="header-anchor" href="#_14-transparencia-independiente-del-orden" aria-label="Permalink to &quot;14. Transparencia independiente del orden&quot;"></a></h2>
<p>El cabello, el follaje, las partículas y el cristal no se pueden ordenar de forma limpia. Los motores AAA utilizan técnicas como OIT combinada y ponderada, pelado de profundidad o listas enlazadas por píxel para renderizarlos correctamente sin una fase de ordenación en la CPU. Aunque pase desapercibida, es una de las partes más costosas del fotograma en escenas con mucho follaje.</p>
<img src="/img/blog/aaa_oit_transparency.webp" alt="Escena de bosque con follaje translúcido superpuesto, humo, gotas de cristal y cabello translúcido" style="width:100%;border-radius:8px;margin:1.5rem 0" />
<p>Análisis en profundidad:</p>
<ul>
<li>McGuire y Bavoil, <a href="http://jcgt.org/published/0002/02/09/" target="_blank" rel="noreferrer">Transparencia independiente del orden mediante combinación ponderada</a> (JCGT 2013, el artículo sobre WBOIT).</li>
<li>Bavoil y Myers, <a href="https://developer.download.nvidia.com/SDK/10/opengl/src/dual_depth_peeling/doc/DualDepthPeeling.pdf" target="_blank" rel="noreferrer">Transparencia independiente del orden mediante pelado doble de profundidad</a> (informe técnico de NVIDIA).</li>
<li>Yang et al., <a href="https://www.cse.chalmers.se/edu/year/2017/course/TDA362/Per-Pixel%20Linked%20List.pdf" target="_blank" rel="noreferrer">Construcción simultánea de listas enlazadas en tiempo real en la GPU</a> (la referencia sobre listas enlazadas por píxel).</li>
<li>Wyman, <a href="https://research.nvidia.com/publication/2016-06_exploring-and-expanding-continuum-oit-algorithms" target="_blank" rel="noreferrer">Exploración y ampliación del continuo de algoritmos OIT</a> (HPG 2016, estudio comparativo).</li>
</ul>
<h2 id="_15-cache-neuronal-de-radiancia-y-eliminacion-de-ruido-mediante-aprendizaje-automatico" tabindex="-1">15. Caché neuronal de radiancia y eliminación de ruido mediante aprendizaje automático <a class="header-anchor" href="#_15-cache-neuronal-de-radiancia-y-eliminacion-de-ruido-mediante-aprendizaje-automatico" aria-label="Permalink to &quot;15. Caché neuronal de radiancia y eliminación de ruido mediante aprendizaje automático&quot;"></a></h2>
<p>La capa más reciente. La caché neuronal de radiancia de NVIDIA aprende la iluminación indirecta de cada escena y la consulta en lugar de trazar más rayos. Los eliminadores de ruido mediante aprendizaje automático (OptiX, Intel Open Image Denoise o soluciones internas personalizadas) limpian en milisegundos las señales dispersas del trazado de rayos. Cabe esperar que esta categoría crezca rápidamente durante los próximos dos años.</p>
<img src="/img/blog/aaa_neural_radiance_denoise.webp" alt="Catedral renderizada mediante trazado de rayos a 1 muestra por píxel y con ruido a la izquierda; resultado limpio tras la eliminación de ruido mediante aprendizaje automático a la derecha" style="width:100%;border-radius:8px;margin:1.5rem 0" />
<p>Análisis en profundidad:</p>
<ul>
<li>Müller et al., <a href="https://research.nvidia.com/publication/2021-06_real-time-neural-radiance-caching-path-tracing" target="_blank" rel="noreferrer">Caché neuronal de radiancia en tiempo real para trazado de trayectorias</a> (SIGGRAPH 2021, el artículo sobre NRC).</li>
<li>Schied et al., <a href="https://research.nvidia.com/publication/2017-07_spatiotemporal-variance-guided-filtering-real-time-reconstruction-path-traced" target="_blank" rel="noreferrer">Filtrado espaciotemporal guiado por la varianza: reconstrucción en tiempo real para iluminación global mediante trazado de trayectorias</a> (HPG 2017, SVGF).</li>
<li>Chaitanya et al., <a href="https://research.nvidia.com/publication/interactive-reconstruction-monte-carlo-image-sequences-using-recurrent-denoising" target="_blank" rel="noreferrer">Reconstrucción interactiva de secuencias de imágenes de Monte Carlo mediante un autocodificador recurrente de eliminación de ruido</a> (SIGGRAPH 2017, el primer eliminador de ruido recurrente basado en aprendizaje automático).</li>
<li>Intel, <a href="https://www.openimagedenoise.org/documentation.html" target="_blank" rel="noreferrer">Documentación de Open Image Denoise</a> (eliminador de ruido de producción de código abierto).</li>
</ul>
<h2 id="que-significa-esto-para-el-navegador" tabindex="-1">Qué significa esto para el navegador <a class="header-anchor" href="#que-significa-esto-para-el-navegador" aria-label="Permalink to &quot;Qué significa esto para el navegador&quot;"></a></h2>
<p>Hemos implementado varias de estas técnicas en WebGPU para nuestro <a href="/es/blog/2026-02-25-open-world-browser-series-guide.html">motor de mundo abierto para navegadores</a>. Los mapas de sombras en cascada, la instanciación controlada por la GPU, el PBR triplanar, la niebla en espacio de pantalla y el terreno virtualizado basado en clipmaps funcionan a 120 FPS en una pestaña. El resto (trazado de rayos por hardware, sombreadores de malla y escalado mediante aprendizaje automático) llegará a la web a medida que la especificación de WebGPU se ponga al día. Para profundizar, consulta nuestras guías sobre <a href="/es/guides/browser-3d-open-world-tech.html">tecnología de mundos abiertos para navegadores</a> y <a href="/es/guides/landscape-generation-browser.html">generación de paisajes</a>.</p>
<h2 id="lecturas-adicionales-sobre-toda-la-pila-tecnologica" tabindex="-1">Lecturas adicionales sobre toda la pila tecnológica <a class="header-anchor" href="#lecturas-adicionales-sobre-toda-la-pila-tecnologica" aria-label="Permalink to &quot;Lecturas adicionales sobre toda la pila tecnológica&quot;"></a></h2>
<p>Si quieres leer un solo libro, <a href="https://www.realtimerendering.com/" target="_blank" rel="noreferrer">Renderizado en tiempo real, 4.ª edición</a> es la referencia estándar que abarca la mayoría de los temas anteriores. Para consultar investigaciones en curso, el archivo del curso de SIGGRAPH «Avances en el renderizado en tiempo real en videojuegos» (<a href="https://advances.realtimerendering.com/" target="_blank" rel="noreferrer">advances.realtimerendering.com</a>) ofrece PDF gratuitos de análisis en profundidad de motores AAA que se remontan a 2006. Para conocer en detalle cómo renderizan sus fotogramas juegos concretos, los <a href="http://www.adriancourreges.com/blog/" target="_blank" rel="noreferrer">artículos de Adrian Courrèges sobre análisis de rendimiento de GPU</a> son lectura obligatoria.</p>
]]></content:encoded>
            <enclosure url="https://app.cinevva.com/img/blog/aaa_rendering_hero.webp" length="0" type="image/webp"/>
        </item>
        <item>
            <title><![CDATA[Construir un mundo abierto en el navegador, parte 18: Un pincel de dispersión que parece usar IA]]></title>
            <link>https://app.cinevva.com/es/blog/2026-05-02-open-world-browser-part-18-ai-scattering</link>
            <guid>https://app.cinevva.com/es/blog/2026-05-02-open-world-browser-part-18-ai-scattering</guid>
            <pubDate>Sat, 02 May 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[El Spike 37 creó un pincel de dispersión heurístico que mantiene los árboles alejados de los acantilados y los guijarros en la línea de agua sin usar ningún LLM, y después lo llevó por el instanciado, el LOD por distancia y una pila de errores hasta lograr una pincelada de 4 ms.]]></description>
            <content:encoded><![CDATA[<h1 id="construir-un-mundo-abierto-en-el-navegador-parte-18-un-pincel-de-dispersion-que-parece-usar-ia" tabindex="-1">Construir un mundo abierto en el navegador, parte 18: Un pincel de dispersión que parece usar IA <a class="header-anchor" href="#construir-un-mundo-abierto-en-el-navegador-parte-18-un-pincel-de-dispersion-que-parece-usar-ia" aria-label="Permalink to &quot;Construir un mundo abierto en el navegador, parte 18: Un pincel de dispersión que parece usar IA&quot;"></a></h1>
<p><em>Por <a href="/es/about.html">Oleg Sidorkin</a>, CTO y cofundador de Cinevva</em></p>
<p>¿Acabas de llegar? Consulta la <a href="/es/blog/2026-02-25-open-world-browser-series-guide.html">guía de la serie</a>. Explica qué es un spike y enlaza todas las partes.</p>
<p>La <a href="/es/blog/2026-05-01-open-world-browser-part-17-animations-and-search.html">parte 17</a> proporcionó al jugador un conjunto de animaciones apto para el combate y una forma de incorporar al mundo cualquier modelo CC0. Esta parte vuelve al lado del creador. La paleta del Spike 34 coloca un objeto por clic, lo cual sirve para situar un objeto protagonista, pero no para crear un bosque. El Spike 37 es el pincel: arrastra sobre el terreno y los árboles llenarán los lugares donde deberían estar.</p>
<h2 id="«colocado-por-ia»-sin-una-ia" tabindex="-1">«Colocado por IA» sin una IA <a class="header-anchor" href="#«colocado-por-ia»-sin-una-ia" aria-label="Permalink to &quot;«Colocado por IA» sin una IA&quot;"></a></h2>
<div style="position:relative;padding-bottom:56.25%;height:0;overflow:hidden;border-radius:8px;margin:1.5rem 0;border:1px solid rgba(255,255,255,0.12)">
<iframe src="/es/spikes/37-ai-scattering/" title="Spike 37: dispersión de objetos asistida por IA" style="position:absolute;top:0;left:0;width:100%;height:100%;border:0;background:#000" loading="lazy" allowfullscreen></iframe>
</div>
<p><a href="/es/spikes/37-ai-scattering/" target="_blank">Abrir el Spike 37 en una pestaña nueva ↗</a> · <a href="/es/blog/spike-source?spike=37-ai-scattering">Ver el código fuente</a></p>
<p>La pregunta que responde este spike es si un pincel puramente heurístico resulta lo bastante inteligente como para prescindir del LLM. La prueba de que algo parece «colocado por IA» es concreta: los árboles se mantienen alejados de los acantilados, las rocas se inclinan siguiendo la pendiente y los guijarros de playa se detienen en la línea de agua, todo desde la primera pincelada. Lo conseguimos con predicados de pendiente y altitud, selecciones ponderadas y espaciado por familia, sin una sola llamada a un modelo.</p>
<p>El pincel funciona sobre un mapa de alturas de CPU de 257×257 con elementos ajustados a mano para que cada preajuste tenga algún lugar donde aplicarse: montañas al norte para las selecciones de pendientes mixtas, una franja de acantilados al este para los canchales, una llanura costera al sur para la playa y la pradera, y una cuenca lacustre al sudoeste. El terreno precalcula los colores de los vértices mediante un clasificador de biomas basado en <code>(altitude, slope)</code>, de modo que antes de pintar un solo árbol ya puedes ver dónde se aplicará un preajuste. Se incluyen cinco preajustes como datos planos, cada uno con una lista de selecciones como <code>{ category, weight, slopeMin, slopeMax, altMin, altMax, minSpacing, alignToSlope }</code>. Cliff and Scree establece <code>slopeMin: 0.3</code> para que las rocas solo aparezcan en pendientes reales y <code>alignToSlope: true</code> para que el vector vertical de cada roca siga la normal de la superficie.</p>
<p>En cada pincelada, el motor de dispersión muestrea <code>densityPerM2 × area</code> puntos candidatos dentro del disco del pincel, lee la altura y la pendiente de cada candidato, filtra las selecciones del preajuste para conservar aquellas cuyos predicados se cumplen, elige una mediante selección ponderada y después comprueba el espaciado mediante un hash espacial dentro del radio. Todo es determinista: un generador aleatorio Mulberry32 con semilla controla cada selección, por lo que <code>(seed, brush events)</code> reproduce cualquier sesión con exactitud. En el terreno inicial, una pincelada de Mixed Forest sobre una pradera llana colocó 139 de 158 candidatos en 5 ms, mientras que el mismo preajuste sobre un acantilado solo colocó 106 de 226 y el HUD indicó que 81 habían sido rechazados por la pendiente. Ese desglose de rechazos constituye toda la experiencia de usuario: puedes ver <em>por qué</em> el acantilado solo aceptó unos pocos árboles en lugar de tener que adivinarlo.</p>
<p>La ventaja de mantener los preajustes como datos planos es que, cuando llegue la versión con LLM, bastará con sustituir un JSON en lugar de reescribir el sistema. A <code>paint({ preset })</code> no le importa si <code>preset.picks</code> procede de una receta ajustada a mano o de un worker que convirtió «bosque caducifolio con rocas cubiertas de musgo» en ponderaciones. El motor tampoco codifica de forma fija ningún identificador de objeto, así que incorporar un catálogo distinto no requiere cambios en el motor.</p>
<h2 id="de-300-llamadas-de-dibujo-a-49" tabindex="-1">De 300 llamadas de dibujo a 49 <a class="header-anchor" href="#de-300-llamadas-de-dibujo-a-49" aria-label="Permalink to &quot;De 300 llamadas de dibujo a 49&quot;"></a></h2>
<p>La primera versión renderizaba cada elemento colocado como un <code>clone(true)</code> de un grupo con varias mallas. Esto funciona bien con unos pocos cientos de objetos, pero se convierte en un límite al alcanzar el máximo de 2.500, cuando las llamadas de dibujo suben a varios miles. Antes de llegar a ese punto cambiamos a <code>InstancedMesh</code>, con un bucket por cada <code>(propId, partIndex)</code>. Cada bucket crece duplicando su tamaño: se asigna un <code>InstancedMesh</code> mayor, se copian las matrices activas, se sustituye el padre de la escena y se libera el atributo anterior. El borrado usa intercambio con el último elemento, por lo que eliminar una instancia es O(1) independientemente del tamaño del bucket. El determinismo, el espaciado y el HUD de rechazos se mantienen sin cambios porque la sustitución ocurre por completo por debajo del registro de colocación.</p>
<p>Un diagnóstico del paquete MegaKit resolvió una cuestión arquitectónica real. Una malla glTF con varias primitivas —tronco y hojas— puede llegar a three.js como una sola malla con un array de materiales y <code>geometry.groups</code>, o como varias mallas hermanas independientes con un material cada una. Para este paquete, el cargador sigue la segunda ruta: cada parte es una malla de un solo material con los grupos vacíos. Esa estructura es mejor para la dispersión, porque tener buckets separados por primitiva permite que el bucket del tronco crezca de forma independiente al de las hojas si sus cantidades divergen. El número de llamadas de dibujo es el mismo en ambos casos, pero la separación ofrece una mejor distribución de memoria. La mejora medida se mantuvo: una pincelada de bosque que generaba unas 300 llamadas de dibujo pasó a 49, y una sesión completa con varias pinceladas alcanzó 3.221 instancias a 75 FPS con 51 llamadas de dibujo, un límite que la ruta de clonación nunca podría alcanzar antes de agotar el presupuesto por fotograma.</p>
<h2 id="lod-por-distancia-y-cuatro-errores-ocultos-en-el" tabindex="-1">LOD por distancia y cuatro errores ocultos en él <a class="header-anchor" href="#lod-por-distancia-y-cuatro-errores-ocultos-en-el" aria-label="Permalink to &quot;LOD por distancia y cuatro errores ocultos en él&quot;"></a></h2>
<p>El instanciado redujo las llamadas de dibujo, pero cada instancia seguía renderizando todos sus triángulos, incluso los árboles situados a 90 m que apenas aportaban dos píxeles de detalle en las hojas. Por eso precalculamos tres niveles de LOD por cada parte del objeto con meshoptimizer —completo, 50 % y 15 %—, ampliamos la clave del bucket a <code>(propId, partIndex, lod)</code> y añadimos un <code>move()</code> que traslada un elemento colocado entre buckets hermanos sin asignaciones. Las franjas de distancia son de 0 a 30 m, de 30 a 90 m y más allá, con ±4 m de histéresis alrededor de cada límite para que una cámara situada cerca del borde de una franja no mueva repetidamente un elemento de un lado a otro ni vuelva a subir su matriz en cada fotograma. La reevaluación está limitada a 4 Hz y solo se ejecuta si la cámara se ha movido realmente, por lo que una cámara inmóvil cuesta una sola comparación de distancia al cuadrado por fotograma.</p>
<p>En esa ruta de LOD se escondían los errores más instructivos. El primero se manifestó como elementos que desaparecían o se duplicaban al orbitar la cámara, y empeoraba a medida que se llenaba la escena. La causa era una matriz temporal compartida: <code>move()</code> leía la transformación de un elemento colocado en <code>_tmpMat</code>, definida en el ámbito del módulo, pero la eliminación mediante intercambio del bucket de origen usaba esa misma <code>_tmpMat</code> para su reorganización interna, sobrescribiendo la matriz transportada antes de que el destino pudiera escribirla. El error solo evitaba el caso en el que la posición trasladada ya era la última de su bucket, con una probabilidad aproximada de <code>1/count</code>, lo que coincide exactamente con el «parpadeo poco frecuente que empeora a medida que crece la escena» observado durante las pruebas. La solución fue reservar una <code>_carryMat</code> exclusivamente para <code>move()</code>. Tras una prueba de estrés con 1.274 movimientos acumulados, el grupo se mantuvo idéntico píxel a píxel.</p>
<p>El segundo error era más sutil: todas las transiciones de LOD parecían fluidas <em>excepto</em> la primera. Los árboles que pasaban a LOD1 mostraban un cambio visible de sombreado aunque su silueta apenas variaba, mientras que reducciones mayores de triángulos en niveles posteriores se veían bien. El simplificador con <code>LockBorder</code> nunca mueve ni crea vértices, por lo que los vértices supervivientes conservan exactamente sus normales, pero aun así llamábamos a <code>computeVertexNormals()</code> después de cada simplificación. LOD0 devuelve intactas las normales originales creadas por el artista; LOD1 y los niveles posteriores recibían el recálculo genérico por promedio de caras de three.js. El límite entre 0 y 1 era el único punto de la escala donde cambiaba el régimen de normales, y por eso el salto aparecía allí. Eliminar esa única línea defensiva corrigió el sombreado y, como ventaja adicional, redujo aproximadamente a la mitad el tiempo de precálculo por objeto, porque dejamos de recalcular normales en cuatro LOD por cada parte.</p>
<p>La auditoría del resultado del simplificador reveló una tercera mejora. Cada LOD era un <code>original.clone()</code> con un índice nuevo, y <code>BufferGeometry.clone()</code> hace una copia profunda de todos los atributos, por lo que cinco LOD almacenaban cinco copias independientes de los búferes de posición, normales, UV y color cuyos valores eran idénticos bit a bit. Refactorizamos el sistema para compartir referencias a los atributos y mantener únicamente un búfer de índices privado por cada LOD, lo que redujo una parte de árbol típica de 20 identidades de atributos distintas a 9 y permitió subir cada búfer de vértices a la GPU una sola vez. El almacenamiento compartido impone dos condiciones: no modificar los datos de atributos desde ningún LOD individual y no ejecutar <code>dispose()</code> sobre la geometría de un solo LOD, ya que ambas acciones afectarían a todos los niveles hermanos que comparten el búfer.</p>
<p>El cuarto error no tenía nada que ver con pintar. El simple hecho de mover el cursor sobre el terreno reducía la velocidad de fotogramas, sin mantener pulsado ningún botón. El controlador <code>pointermove</code> lanzaba rayos contra la malla del terreno, un plano de 131.072 triángulos sin ninguna estructura espacial, por lo que three.js recorría todo el búfer de índices en cada evento, hasta 1.000 eventos por segundo. No necesitábamos la malla para esa consulta, porque el terreno es un mapa de alturas paramétrico. Una marcha de rayos adaptativa contra <code>sampleHeight</code> —pasos grandes muy por encima de la superficie, un mínimo de 0,4 m cerca de ella y después 12 bisecciones cuando cambia el signo— cuesta aproximadamente entre 8 y 30 muestras por rayo en lugar de 131.072 pruebas de triángulos, unas tres órdenes de magnitud menos, y al pasar el cursor vuelve a mantenerse el límite de fotogramas.</p>
<h2 id="el-coste-solo-se-desplaza-asegurate-de-sacarlo-del-clic" tabindex="-1">El coste solo se desplaza; asegúrate de sacarlo del clic <a class="header-anchor" href="#el-coste-solo-se-desplaza-asegurate-de-sacarlo-del-clic" aria-label="Permalink to &quot;El coste solo se desplaza; asegúrate de sacarlo del clic&quot;"></a></h2>
<p>Después de cambiar el spike a <code>WebGPURenderer</code> en three r184 —el objetivo de producción—, un perfil de DevTools mostró que la primera pincelada bloqueaba durante 265 ms, con un 79 % del tiempo dentro del WASM de meshoptimizer. El precálculo realizaba trabajo real, unas 180 llamadas de simplificación para un preajuste en frío, pero se ejecutaba dentro del controlador del clic porque <code>preloadProps</code> solo descargaba y analizaba escenas, sin activar nunca el precálculo de LOD. La solución fue hacer que la selección del preajuste ejecutara el precálculo completo en segundo plano: ahora <code>preloadProps</code> llama a la ruta de resolución de partes, guarda en caché la promesa en curso para que un clic rápido se una a ella en lugar de iniciar un duplicado y memoriza el preprocesamiento por geometría que el simplificador repetía cuatro veces por cada parte. La primera pincelada bajó de 209 ms a 4 ms en el HUD. El tiempo del WASM no desapareció; simplemente salió de la ruta crítica del usuario y ahora se ejecuta mientras este observa el terreno y decide dónde pintar.</p>
<p>Esa es la lección recurrente de este spike. Casi ninguna de estas correcciones cambió lo que el pincel <em>hace</em>. Cambiaron <em>cuándo</em> se paga el coste: fuera del clic, fuera del movimiento del cursor y fuera del límite cerca del que se encuentra la cámara. Una herramienta de dispersión que parece instantánea no hace menos trabajo; hace el trabajo cuando el usuario no está esperándolo.</p>
<h2 id="tecnologia-mencionada-en-este-capitulo" tabindex="-1">Tecnología mencionada en este capítulo <a class="header-anchor" href="#tecnologia-mencionada-en-este-capitulo" aria-label="Permalink to &quot;Tecnología mencionada en este capítulo&quot;"></a></h2>
<p><strong>Dispersión heurística por idoneidad.</strong> Un pincel muestrea puntos candidatos dentro de un disco, lee <code>(height, slope)</code> por cada punto desde un mapa de alturas en la CPU, filtra las selecciones de un preajuste mediante predicados de pendiente y altitud, elige una de forma ponderada y la rechaza si infringe el espaciado mínimo por familia registrado en un hash espacial. Las selecciones alineadas con la pendiente giran su vector vertical para adaptarlo a la normal de la superficie. Esto genera una colocación que parece intencionada —árboles alejados de los acantilados, rocas inclinadas sobre las pendientes y guijarros que se detienen en la línea de agua— sin ponderaciones aprendidas, y mantiene el preajuste como datos planos para que una lista de selecciones generada por un LLM pueda sustituirla directamente.</p>
<p><strong>Colocación determinista con cargas asíncronas.</strong> Un generador aleatorio Mulberry32 con semilla controla cada selección, por lo que <code>(seed, brush events)</code> reproduce una sesión con exactitud. Las extracciones aleatorias se producen antes de cualquier <code>await</code>, y las reservas de espaciado se insertan en el índice espacial antes de que se resuelva el clon de glTF, de modo que los candidatos concurrentes se respetan entre sí y la carga asíncrona de recursos no puede alterar la secuencia.</p>
<p><strong>InstancedMesh organizados en buckets con ediciones O(1).</strong> Un <code>InstancedMesh</code> por cada <code>(propId, partIndex, lod)</code>, cuya capacidad se duplica bajo demanda copiando las matrices activas en un búfer mayor. El borrado y la expulsión FIFO usan intercambio con el último elemento y corrigen en un array de referencias inversas el índice de la instancia trasladada, por lo que una eliminación es O(1) independientemente del tamaño del bucket. Un diagnóstico confirmó que las partes glTF llegan como mallas de un solo material, lo que convierte un bucket por primitiva en la ruta activa y proporciona a cada primitiva un bucket capaz de crecer de forma independiente.</p>
<p><strong>LOD por distancia con histéresis y búferes de atributos compartidos.</strong> Tres niveles simplificados con meshopt por cada parte, seleccionados mediante franjas de distancia con ±4 m de histéresis para que una cámara cerca de un límite no alterne continuamente entre niveles, reevaluados a una frecuencia limitada y solo cuando existe movimiento real de la cámara. Como la simplificación con <code>LockBorder</code> nunca mueve los vértices, todos los LOD comparten un solo conjunto de búferes de posición, normales, UV y color, y solo se diferencian por su búfer de índices privado, lo que reduce aproximadamente a la mitad los búferes de vértices distintos en la GPU. Omitir un <code>computeVertexNormals</code> defensivo mantiene idénticas las normales creadas por el artista en todos los LOD y elimina la única discontinuidad de sombreado de la escala. Consulta <a href="/es/guides/landscape-generation-browser.html#gpu-driven-lod-with-webgpu">LOD y meshoptimizer</a>.</p>
<p><strong>Lanzamiento de rayos analítico sobre el mapa de alturas para consultas de alta frecuencia.</strong> Una consulta del cursor a la frecuencia de <code>pointermove</code> contra la malla de un plano de 131.000 triángulos recorre todo el búfer de índices en cada evento. Sustituirla por una marcha de rayos adaptativa contra la función de altura analítica —pasos grandes lejos de la superficie, un mínimo pequeño cerca de ella y bisección cuando cambia el signo de <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.869ex;" xmlns="http://www.w3.org/2000/svg" width="16.358ex" height="2.566ex" role="img" focusable="false" viewBox="0 -750 7230.4 1134.3" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mo"><path data-c="28" d="M94 250Q94 319 104 381T127 488T164 576T202 643T244 695T277 729T302 750H315H319Q333 750 333 741Q333 738 316 720T275 667T226 581T184 443T167 250T184 58T225 -81T274 -167T316 -220T333 -241Q333 -250 318 -250H315H302L274 -226Q180 -141 137 -14T94 250Z" style="stroke-width: 3;"/></g><g data-mml-node="msub" transform="translate(389,0)"><g data-mml-node="mtext"><path data-c="72" d="M36 46H50Q89 46 97 60V68Q97 77 97 91T98 122T98 161T98 203Q98 234 98 269T98 328L97 351Q94 370 83 376T38 385H20V408Q20 431 22 431L32 432Q42 433 60 434T96 436Q112 437 131 438T160 441T171 442H174V373Q213 441 271 441H277Q322 441 343 419T364 373Q364 352 351 337T313 322Q288 322 276 338T263 372Q263 381 265 388T270 400T273 405Q271 407 250 401Q234 393 226 386Q179 341 179 207V154Q179 141 179 127T179 101T180 81T180 66V61Q181 59 183 57T188 54T193 51T200 49T207 48T216 47T225 47T235 46T245 46H276V0H267Q249 3 140 3Q37 3 28 0H20V46H36Z" style="stroke-width: 3;"/><path data-c="61" d="M137 305T115 305T78 320T63 359Q63 394 97 421T218 448Q291 448 336 416T396 340Q401 326 401 309T402 194V124Q402 76 407 58T428 40Q443 40 448 56T453 109V145H493V106Q492 66 490 59Q481 29 455 12T400 -6T353 12T329 54V58L327 55Q325 52 322 49T314 40T302 29T287 17T269 6T247 -2T221 -8T190 -11Q130 -11 82 20T34 107Q34 128 41 147T68 188T116 225T194 253T304 268H318V290Q318 324 312 340Q290 411 215 411Q197 411 181 410T156 406T148 403Q170 388 170 359Q170 334 154 320ZM126 106Q126 75 150 51T209 26Q247 26 276 49T315 109Q317 116 318 175Q318 233 317 233Q309 233 296 232T251 223T193 203T147 166T126 106Z" transform="translate(392,0)" style="stroke-width: 3;"/><path data-c="79" d="M69 -66Q91 -66 104 -80T118 -116Q118 -134 109 -145T91 -160Q84 -163 97 -166Q104 -168 111 -168Q131 -168 148 -159T175 -138T197 -106T213 -75T225 -43L242 0L170 183Q150 233 125 297Q101 358 96 368T80 381Q79 382 78 382Q66 385 34 385H19V431H26L46 430Q65 430 88 429T122 428Q129 428 142 428T171 429T200 430T224 430L233 431H241V385H232Q183 385 185 366L286 112Q286 113 332 227L376 341V350Q376 365 366 373T348 383T334 385H331V431H337H344Q351 431 361 431T382 430T405 429T422 429Q477 429 503 431H508V385H497Q441 380 422 345Q420 343 378 235T289 9T227 -131Q180 -204 113 -204Q69 -204 44 -177T19 -116Q19 -89 35 -78T69 -66Z" transform="translate(892,0)" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(1453,-239.4) scale(0.707)"><path data-c="1D466" d="M21 287Q21 301 36 335T84 406T158 442Q199 442 224 419T250 355Q248 336 247 334Q247 331 231 288T198 191T182 105Q182 62 196 45T238 27Q261 27 281 38T312 61T339 94Q339 95 344 114T358 173T377 247Q415 397 419 404Q432 431 462 431Q475 431 483 424T494 412T496 403Q496 390 447 193T391 -23Q363 -106 294 -155T156 -205Q111 -205 77 -183T43 -117Q43 -95 50 -80T69 -58T89 -48T106 -45Q150 -45 150 -87Q150 -107 138 -122T115 -142T102 -147L99 -148Q101 -153 118 -160T152 -167H160Q177 -167 186 -165Q219 -156 247 -127T290 -65T313 -9T321 21L315 17Q309 13 296 6T270 -6Q250 -11 231 -11Q185 -11 150 11T104 82Q103 89 103 113Q103 170 138 262T173 379Q173 380 173 381Q173 390 173 393T169 400T158 404H154Q131 404 112 385T82 344T65 302T57 280Q55 278 41 278H27Q21 284 21 287Z" style="stroke-width: 3;"/></g></g><g data-mml-node="mo" transform="translate(2460.7,0)"><path data-c="2212" d="M84 237T84 250T98 270H679Q694 262 694 250T679 230H98Q84 237 84 250Z" style="stroke-width: 3;"/></g><g data-mml-node="msub" transform="translate(3460.9,0)"><g data-mml-node="mtext"><path data-c="74" d="M27 422Q80 426 109 478T141 600V615H181V431H316V385H181V241Q182 116 182 100T189 68Q203 29 238 29Q282 29 292 100Q293 108 293 146V181H333V146V134Q333 57 291 17Q264 -10 221 -10Q187 -10 162 2T124 33T105 68T98 100Q97 107 97 248V385H18V422H27Z" style="stroke-width: 3;"/><path data-c="65" d="M28 218Q28 273 48 318T98 391T163 433T229 448Q282 448 320 430T378 380T406 316T415 245Q415 238 408 231H126V216Q126 68 226 36Q246 30 270 30Q312 30 342 62Q359 79 369 104L379 128Q382 131 395 131H398Q415 131 415 121Q415 117 412 108Q393 53 349 21T250 -11Q155 -11 92 58T28 218ZM333 275Q322 403 238 411H236Q228 411 220 410T195 402T166 381T143 340T127 274V267H333V275Z" transform="translate(389,0)" style="stroke-width: 3;"/><path data-c="72" d="M36 46H50Q89 46 97 60V68Q97 77 97 91T98 122T98 161T98 203Q98 234 98 269T98 328L97 351Q94 370 83 376T38 385H20V408Q20 431 22 431L32 432Q42 433 60 434T96 436Q112 437 131 438T160 441T171 442H174V373Q213 441 271 441H277Q322 441 343 419T364 373Q364 352 351 337T313 322Q288 322 276 338T263 372Q263 381 265 388T270 400T273 405Q271 407 250 401Q234 393 226 386Q179 341 179 207V154Q179 141 179 127T179 101T180 81T180 66V61Q181 59 183 57T188 54T193 51T200 49T207 48T216 47T225 47T235 46T245 46H276V0H267Q249 3 140 3Q37 3 28 0H20V46H36Z" transform="translate(833,0)" style="stroke-width: 3;"/><path data-c="72" d="M36 46H50Q89 46 97 60V68Q97 77 97 91T98 122T98 161T98 203Q98 234 98 269T98 328L97 351Q94 370 83 376T38 385H20V408Q20 431 22 431L32 432Q42 433 60 434T96 436Q112 437 131 438T160 441T171 442H174V373Q213 441 271 441H277Q322 441 343 419T364 373Q364 352 351 337T313 322Q288 322 276 338T263 372Q263 381 265 388T270 400T273 405Q271 407 250 401Q234 393 226 386Q179 341 179 207V154Q179 141 179 127T179 101T180 81T180 66V61Q181 59 183 57T188 54T193 51T200 49T207 48T216 47T225 47T235 46T245 46H276V0H267Q249 3 140 3Q37 3 28 0H20V46H36Z" transform="translate(1225,0)" style="stroke-width: 3;"/><path data-c="61" d="M137 305T115 305T78 320T63 359Q63 394 97 421T218 448Q291 448 336 416T396 340Q401 326 401 309T402 194V124Q402 76 407 58T428 40Q443 40 448 56T453 109V145H493V106Q492 66 490 59Q481 29 455 12T400 -6T353 12T329 54V58L327 55Q325 52 322 49T314 40T302 29T287 17T269 6T247 -2T221 -8T190 -11Q130 -11 82 20T34 107Q34 128 41 147T68 188T116 225T194 253T304 268H318V290Q318 324 312 340Q290 411 215 411Q197 411 181 410T156 406T148 403Q170 388 170 359Q170 334 154 320ZM126 106Q126 75 150 51T209 26Q247 26 276 49T315 109Q317 116 318 175Q318 233 317 233Q309 233 296 232T251 223T193 203T147 166T126 106Z" transform="translate(1617,0)" style="stroke-width: 3;"/><path data-c="69" d="M69 609Q69 637 87 653T131 669Q154 667 171 652T188 609Q188 579 171 564T129 549Q104 549 87 564T69 609ZM247 0Q232 3 143 3Q132 3 106 3T56 1L34 0H26V46H42Q70 46 91 49Q100 53 102 60T104 102V205V293Q104 345 102 359T88 378Q74 385 41 385H30V408Q30 431 32 431L42 432Q52 433 70 434T106 436Q123 437 142 438T171 441T182 442H185V62Q190 52 197 50T232 46H255V0H247Z" transform="translate(2117,0)" style="stroke-width: 3;"/><path data-c="6E" d="M41 46H55Q94 46 102 60V68Q102 77 102 91T102 122T103 161T103 203Q103 234 103 269T102 328V351Q99 370 88 376T43 385H25V408Q25 431 27 431L37 432Q47 433 65 434T102 436Q119 437 138 438T167 441T178 442H181V402Q181 364 182 364T187 369T199 384T218 402T247 421T285 437Q305 442 336 442Q450 438 463 329Q464 322 464 190V104Q464 66 466 59T477 49Q498 46 526 46H542V0H534L510 1Q487 2 460 2T422 3Q319 3 310 0H302V46H318Q379 46 379 62Q380 64 380 200Q379 335 378 343Q372 371 358 385T334 402T308 404Q263 404 229 370Q202 343 195 315T187 232V168V108Q187 78 188 68T191 55T200 49Q221 46 249 46H265V0H257L234 1Q210 2 183 2T145 3Q42 3 33 0H25V46H41Z" transform="translate(2395,0)" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(2984,-150) scale(0.707)"><path data-c="1D466" d="M21 287Q21 301 36 335T84 406T158 442Q199 442 224 419T250 355Q248 336 247 334Q247 331 231 288T198 191T182 105Q182 62 196 45T238 27Q261 27 281 38T312 61T339 94Q339 95 344 114T358 173T377 247Q415 397 419 404Q432 431 462 431Q475 431 483 424T494 412T496 403Q496 390 447 193T391 -23Q363 -106 294 -155T156 -205Q111 -205 77 -183T43 -117Q43 -95 50 -80T69 -58T89 -48T106 -45Q150 -45 150 -87Q150 -107 138 -122T115 -142T102 -147L99 -148Q101 -153 118 -160T152 -167H160Q177 -167 186 -165Q219 -156 247 -127T290 -65T313 -9T321 21L315 17Q309 13 296 6T270 -6Q250 -11 231 -11Q185 -11 150 11T104 82Q103 89 103 113Q103 170 138 262T173 379Q173 380 173 381Q173 390 173 393T169 400T158 404H154Q131 404 112 385T82 344T65 302T57 280Q55 278 41 278H27Q21 284 21 287Z" style="stroke-width: 3;"/></g></g><g data-mml-node="mo" transform="translate(6841.4,0)"><path data-c="29" d="M60 749L64 750Q69 750 74 750H86L114 726Q208 641 251 514T294 250Q294 182 284 119T261 12T224 -76T186 -143T145 -194T113 -227T90 -246Q87 -249 86 -250H74Q66 -250 63 -250T58 -247T55 -238Q56 -237 66 -225Q221 -64 221 250T66 725Q56 737 55 738Q55 746 60 749Z" style="stroke-width: 3;"/></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mo stretchy="false">(</mo><msub><mtext>ray</mtext><mi>y</mi></msub><mo>−</mo><msub><mtext>terrain</mtext><mi>y</mi></msub><mo stretchy="false">)</mo></math></mjx-assistive-mml></mjx-container>— cuesta decenas de muestras en lugar de decenas de miles de pruebas de triángulos, unas tres órdenes de magnitud menos, y un vector de salida preasignado mantiene la ruta crítica libre de asignaciones.</p>
<p><strong>Sacar el trabajo de la ruta crítica de la interacción.</strong> El trabajo costoso que solo se realiza una vez —precálculos de LOD con meshopt, compilaciones de pipelines WGSL— debe ejecutarse durante los intervalos de inactividad, no dentro del controlador del clic. Precargar el cálculo completo del preajuste activo al seleccionarlo, almacenar en caché la promesa en curso para que un clic rápido se una a ella en lugar de iniciar otra y memorizar el preprocesamiento por geometría redujo la latencia de la primera pincelada de 209 ms a 4 ms sin disminuir el trabajo total realizado.</p>
<hr>
<p>Parte 18 de 29.
Anterior: <a href="/es/blog/2026-05-01-open-world-browser-part-17-animations-and-search.html">Parte 17 - Animaciones que no necesitaron retargeting y una búsqueda de recursos en tiempo real</a>
Siguiente: <a href="/es/blog/2026-05-04-open-world-browser-part-19-imposters.html">Parte 19 - El impostor que tiene que sobrevivir a un bosque</a>
Guía de la serie: <a href="/es/blog/2026-02-25-open-world-browser-series-guide.html">/es/blog/2026-02-25-open-world-browser-series-guide</a></p>
]]></content:encoded>
            <enclosure url="https://cdn.cinevva.com/blog/why-webgpu-engine-hero.jpg" length="0" type="image/jpg"/>
        </item>
        <item>
            <title><![CDATA[Creando un mundo abierto en el navegador, parte 17: Animaciones que no necesitaron retargeting y una búsqueda de recursos en tiempo real]]></title>
            <link>https://app.cinevva.com/es/blog/2026-05-01-open-world-browser-part-17-animations-and-search</link>
            <guid>https://app.cinevva.com/es/blog/2026-05-01-open-world-browser-part-17-animations-and-search</guid>
            <pubDate>Fri, 01 May 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[El Spike 35 aplicó retargeting a 262 clips de combate y locomoción para adaptarlos al rig del jugador, y creó una prueba de paridad sin conexión para verificar su fidelidad. El Spike 36 integró una búsqueda de modelos de Polyhaven en tiempo real sin ningún paso de compilación.]]></description>
            <content:encoded><![CDATA[<h1 id="creando-un-mundo-abierto-en-el-navegador-parte-17-animaciones-que-no-necesitaron-retargeting-y-una-busqueda-de-recursos-en-tiempo-real" tabindex="-1">Creando un mundo abierto en el navegador, parte 17: Animaciones que no necesitaron retargeting y una búsqueda de recursos en tiempo real <a class="header-anchor" href="#creando-un-mundo-abierto-en-el-navegador-parte-17-animaciones-que-no-necesitaron-retargeting-y-una-busqueda-de-recursos-en-tiempo-real" aria-label="Permalink to &quot;Creando un mundo abierto en el navegador, parte 17: Animaciones que no necesitaron retargeting y una búsqueda de recursos en tiempo real&quot;"></a></h1>
<p><em>Por <a href="/es/about.html">Oleg Sidorkin</a>, CTO y cofundador de Cinevva</em></p>
<p>¿Es tu primera vez aquí? Consulta la <a href="/es/blog/2026-02-25-open-world-browser-series-guide.html">guía de la serie</a>. Explica qué es un spike y enlaza todas las partes.</p>
<p>La <a href="/es/blog/2026-04-28-open-world-browser-part-16-structure-and-authoring.html">parte 16</a> nos dio un mundo en el que colocar objetos. Esta parte ofrece al jugador algo mejor que hacer en él: un conjunto de animaciones apto para el combate y una forma de incorporar al mundo cualquiera de entre mil modelos CC0 con solo escribir una búsqueda.</p>
<h2 id="_262-clips-un-esqueleto-y-tres-correcciones-de-retargeting" tabindex="-1">262 clips, un esqueleto y tres correcciones de retargeting <a class="header-anchor" href="#_262-clips-un-esqueleto-y-tres-correcciones-de-retargeting" aria-label="Permalink to &quot;262 clips, un esqueleto y tres correcciones de retargeting&quot;"></a></h2>
<div style="position:relative;padding-bottom:56.25%;height:0;overflow:hidden;border-radius:8px;margin:1.5rem 0;border:1px solid rgba(255,255,255,0.12)">
<iframe src="/es/spikes/35-combat-animations/" title="Spike 35: animaciones de combate" style="position:absolute;top:0;left:0;width:100%;height:100%;border:0;background:#000" loading="lazy" allowfullscreen></iframe>
</div>
<p><a href="/es/spikes/35-combat-animations/" target="_blank">Abrir el Spike 35 en una pestaña nueva ↗</a> · <a href="/es/blog/spike-source?spike=35-combat-animations">Ver el código fuente</a></p>
<p>El rig del jugador es un esqueleto <code>3MIKE</code> al estilo CC4 con 213 huesos, incluidos un rig facial de más de 80 huesos y todas las articulaciones de los dedos. Las fuentes de animación no coinciden con él. La primera versión aplicaba retargeting a clips de combate de Mixamo seleccionados manualmente, pero el conjunto de fuentes era escaso y la locomoción estaba dividida de forma incómoda entre Mixamo y unas pocas animaciones de reposo BVH de Kimodo. El verdadero avance llegó cuando cambiamos la biblioteca de origen por los dos paquetes Universal Animation Library de Quaternius: 262 clips en total sobre un único maniquí coherente de 65 huesos al estilo UE5, con combos de espada, tiro con arco, escalada, carreras por paredes, esquivas, reacciones a impactos, gestos y un conjunto de locomoción mucho más limpio.</p>
<p>Eso supone pasar de una fuente de 65 huesos a un destino de 213, sin nombres de huesos, orientaciones en pose T ni proporciones de extremidades compartidos. Cada clip se reasigna en tres pasos: un mapa de nombres de huesos, una alineación de la pose de enlace para que ambos rigs compartan una orientación de referencia y un escalado de las pistas de posición para que el rig de origen, más bajo, no deje al personaje hundido hasta las rodillas en el suelo. Hacerlo bien implicó perseguir una serie de errores, cada uno de los cuales nos enseñó algo concreto.</p>
<p>El personaje aparecía excesivamente retorcido, con todos los hombros y codos girados unos 30° de más. La causa era una discrepancia de poses: la fuente UAL viene con una pose T real, la pose de enlace de CC4 es una pose A y el sistema de retargeting suponía que ambos rigs estaban en poses de referencia coincidentes, por lo que la diferencia entre A y T se añadía a cada delta por fotograma. La corrección fuerza la cadena de los brazos de CC4 a adoptar una pose T real para capturar el enlace y después aplica el retargeting, de modo que los deltas se mantengan pequeños.</p>
<p>Después, el cuerpo dejó de trasladarse. Los retrocesos desplazaban la parte superior del cuerpo, pero dejaban los pies clavados. UAL coloca el desplazamiento en el hueso <code>root</code>, no en la pelvis, por lo que leer la posición de la pelvis producía un movimiento casi nulo. La corrección suma <code>root.position</code> y <code>pelvis.position</code>, escala la parte horizontal y escribe una única pista de posición de la cadera. Al hacerlo descubrimos que los desplazamientos verticales se desviaban alrededor de un 12 %, porque habíamos usado la proporción global de las extremidades para el eje Y, cuando la altura de la pelvis necesita la proporción entre la cadera y el suelo. Dos proporciones, dos ejes: <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.566ex;" xmlns="http://www.w3.org/2000/svg" width="40.854ex" height="2.262ex" role="img" focusable="false" viewBox="0 -750 18057.6 1000" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mtext"><path data-c="76" d="M338 431Q344 429 422 429Q479 429 503 431H508V385H497Q439 381 423 345Q421 341 356 172T288 -2Q283 -11 263 -11Q244 -11 239 -2Q99 359 98 364Q93 378 82 381T43 385H19V431H25L33 430Q41 430 53 430T79 430T104 429T122 428Q217 428 232 431H240V385H226Q187 384 184 370Q184 366 235 234L286 102L377 341V349Q377 363 367 372T349 383T335 385H331V431H338Z" style="stroke-width: 3;"/><path data-c="65" d="M28 218Q28 273 48 318T98 391T163 433T229 448Q282 448 320 430T378 380T406 316T415 245Q415 238 408 231H126V216Q126 68 226 36Q246 30 270 30Q312 30 342 62Q359 79 369 104L379 128Q382 131 395 131H398Q415 131 415 121Q415 117 412 108Q393 53 349 21T250 -11Q155 -11 92 58T28 218ZM333 275Q322 403 238 411H236Q228 411 220 410T195 402T166 381T143 340T127 274V267H333V275Z" transform="translate(528,0)" style="stroke-width: 3;"/><path data-c="72" d="M36 46H50Q89 46 97 60V68Q97 77 97 91T98 122T98 161T98 203Q98 234 98 269T98 328L97 351Q94 370 83 376T38 385H20V408Q20 431 22 431L32 432Q42 433 60 434T96 436Q112 437 131 438T160 441T171 442H174V373Q213 441 271 441H277Q322 441 343 419T364 373Q364 352 351 337T313 322Q288 322 276 338T263 372Q263 381 265 388T270 400T273 405Q271 407 250 401Q234 393 226 386Q179 341 179 207V154Q179 141 179 127T179 101T180 81T180 66V61Q181 59 183 57T188 54T193 51T200 49T207 48T216 47T225 47T235 46T245 46H276V0H267Q249 3 140 3Q37 3 28 0H20V46H36Z" transform="translate(972,0)" style="stroke-width: 3;"/><path data-c="74" d="M27 422Q80 426 109 478T141 600V615H181V431H316V385H181V241Q182 116 182 100T189 68Q203 29 238 29Q282 29 292 100Q293 108 293 146V181H333V146V134Q333 57 291 17Q264 -10 221 -10Q187 -10 162 2T124 33T105 68T98 100Q97 107 97 248V385H18V422H27Z" transform="translate(1364,0)" style="stroke-width: 3;"/><path data-c="69" d="M69 609Q69 637 87 653T131 669Q154 667 171 652T188 609Q188 579 171 564T129 549Q104 549 87 564T69 609ZM247 0Q232 3 143 3Q132 3 106 3T56 1L34 0H26V46H42Q70 46 91 49Q100 53 102 60T104 102V205V293Q104 345 102 359T88 378Q74 385 41 385H30V408Q30 431 32 431L42 432Q52 433 70 434T106 436Q123 437 142 438T171 441T182 442H185V62Q190 52 197 50T232 46H255V0H247Z" transform="translate(1753,0)" style="stroke-width: 3;"/><path data-c="63" d="M370 305T349 305T313 320T297 358Q297 381 312 396Q317 401 317 402T307 404Q281 408 258 408Q209 408 178 376Q131 329 131 219Q131 137 162 90Q203 29 272 29Q313 29 338 55T374 117Q376 125 379 127T395 129H409Q415 123 415 120Q415 116 411 104T395 71T366 33T318 2T249 -11Q163 -11 99 53T34 214Q34 318 99 383T250 448T370 421T404 357Q404 334 387 320Z" transform="translate(2031,0)" style="stroke-width: 3;"/><path data-c="61" d="M137 305T115 305T78 320T63 359Q63 394 97 421T218 448Q291 448 336 416T396 340Q401 326 401 309T402 194V124Q402 76 407 58T428 40Q443 40 448 56T453 109V145H493V106Q492 66 490 59Q481 29 455 12T400 -6T353 12T329 54V58L327 55Q325 52 322 49T314 40T302 29T287 17T269 6T247 -2T221 -8T190 -11Q130 -11 82 20T34 107Q34 128 41 147T68 188T116 225T194 253T304 268H318V290Q318 324 312 340Q290 411 215 411Q197 411 181 410T156 406T148 403Q170 388 170 359Q170 334 154 320ZM126 106Q126 75 150 51T209 26Q247 26 276 49T315 109Q317 116 318 175Q318 233 317 233Q309 233 296 232T251 223T193 203T147 166T126 106Z" transform="translate(2475,0)" style="stroke-width: 3;"/><path data-c="6C" d="M42 46H56Q95 46 103 60V68Q103 77 103 91T103 124T104 167T104 217T104 272T104 329Q104 366 104 407T104 482T104 542T103 586T103 603Q100 622 89 628T44 637H26V660Q26 683 28 683L38 684Q48 685 67 686T104 688Q121 689 141 690T171 693T182 694H185V379Q185 62 186 60Q190 52 198 49Q219 46 247 46H263V0H255L232 1Q209 2 183 2T145 3T107 3T57 1L34 0H26V46H42Z" transform="translate(2975,0)" style="stroke-width: 3;"/><path data-c="52" d="M130 622Q123 629 119 631T103 634T60 637H27V683H202H236H300Q376 683 417 677T500 648Q595 600 609 517Q610 512 610 501Q610 468 594 439T556 392T511 361T472 343L456 338Q459 335 467 332Q497 316 516 298T545 254T559 211T568 155T578 94Q588 46 602 31T640 16H645Q660 16 674 32T692 87Q692 98 696 101T712 105T728 103T732 90Q732 59 716 27T672 -16Q656 -22 630 -22Q481 -16 458 90Q456 101 456 163T449 246Q430 304 373 320L363 322L297 323H231V192L232 61Q238 51 249 49T301 46H334V0H323Q302 3 181 3Q59 3 38 0H27V46H60Q102 47 111 49T130 61V622ZM491 499V509Q491 527 490 539T481 570T462 601T424 623T362 636Q360 636 340 636T304 637H283Q238 637 234 628Q231 624 231 492V360H289Q390 360 434 378T489 456Q491 467 491 499Z" transform="translate(3253,0)" style="stroke-width: 3;"/><path data-c="61" d="M137 305T115 305T78 320T63 359Q63 394 97 421T218 448Q291 448 336 416T396 340Q401 326 401 309T402 194V124Q402 76 407 58T428 40Q443 40 448 56T453 109V145H493V106Q492 66 490 59Q481 29 455 12T400 -6T353 12T329 54V58L327 55Q325 52 322 49T314 40T302 29T287 17T269 6T247 -2T221 -8T190 -11Q130 -11 82 20T34 107Q34 128 41 147T68 188T116 225T194 253T304 268H318V290Q318 324 312 340Q290 411 215 411Q197 411 181 410T156 406T148 403Q170 388 170 359Q170 334 154 320ZM126 106Q126 75 150 51T209 26Q247 26 276 49T315 109Q317 116 318 175Q318 233 317 233Q309 233 296 232T251 223T193 203T147 166T126 106Z" transform="translate(3989,0)" style="stroke-width: 3;"/><path data-c="74" d="M27 422Q80 426 109 478T141 600V615H181V431H316V385H181V241Q182 116 182 100T189 68Q203 29 238 29Q282 29 292 100Q293 108 293 146V181H333V146V134Q333 57 291 17Q264 -10 221 -10Q187 -10 162 2T124 33T105 68T98 100Q97 107 97 248V385H18V422H27Z" transform="translate(4489,0)" style="stroke-width: 3;"/><path data-c="69" d="M69 609Q69 637 87 653T131 669Q154 667 171 652T188 609Q188 579 171 564T129 549Q104 549 87 564T69 609ZM247 0Q232 3 143 3Q132 3 106 3T56 1L34 0H26V46H42Q70 46 91 49Q100 53 102 60T104 102V205V293Q104 345 102 359T88 378Q74 385 41 385H30V408Q30 431 32 431L42 432Q52 433 70 434T106 436Q123 437 142 438T171 441T182 442H185V62Q190 52 197 50T232 46H255V0H247Z" transform="translate(4878,0)" style="stroke-width: 3;"/><path data-c="6F" d="M28 214Q28 309 93 378T250 448Q340 448 405 380T471 215Q471 120 407 55T250 -10Q153 -10 91 57T28 214ZM250 30Q372 30 372 193V225V250Q372 272 371 288T364 326T348 362T317 390T268 410Q263 411 252 411Q222 411 195 399Q152 377 139 338T126 246V226Q126 130 145 91Q177 30 250 30Z" transform="translate(5156,0)" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(5933.8,0)"><path data-c="3D" d="M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(6989.6,0) translate(0 -0.5)"><path data-c="7C" d="M139 -249H137Q125 -249 119 -235V251L120 737Q130 750 139 750Q152 750 159 735V-235Q151 -249 141 -249H139Z" style="stroke-width: 3;"/></g><g data-mml-node="TeXAtom" data-mjx-texclass="ORD" transform="translate(7267.6,0)"><g data-mml-node="mtext"><path data-c="74" d="M27 422Q80 426 109 478T141 600V615H181V431H316V385H181V241Q182 116 182 100T189 68Q203 29 238 29Q282 29 292 100Q293 108 293 146V181H333V146V134Q333 57 291 17Q264 -10 221 -10Q187 -10 162 2T124 33T105 68T98 100Q97 107 97 248V385H18V422H27Z" style="stroke-width: 3;"/><path data-c="61" d="M137 305T115 305T78 320T63 359Q63 394 97 421T218 448Q291 448 336 416T396 340Q401 326 401 309T402 194V124Q402 76 407 58T428 40Q443 40 448 56T453 109V145H493V106Q492 66 490 59Q481 29 455 12T400 -6T353 12T329 54V58L327 55Q325 52 322 49T314 40T302 29T287 17T269 6T247 -2T221 -8T190 -11Q130 -11 82 20T34 107Q34 128 41 147T68 188T116 225T194 253T304 268H318V290Q318 324 312 340Q290 411 215 411Q197 411 181 410T156 406T148 403Q170 388 170 359Q170 334 154 320ZM126 106Q126 75 150 51T209 26Q247 26 276 49T315 109Q317 116 318 175Q318 233 317 233Q309 233 296 232T251 223T193 203T147 166T126 106Z" transform="translate(389,0)" style="stroke-width: 3;"/><path data-c="72" d="M36 46H50Q89 46 97 60V68Q97 77 97 91T98 122T98 161T98 203Q98 234 98 269T98 328L97 351Q94 370 83 376T38 385H20V408Q20 431 22 431L32 432Q42 433 60 434T96 436Q112 437 131 438T160 441T171 442H174V373Q213 441 271 441H277Q322 441 343 419T364 373Q364 352 351 337T313 322Q288 322 276 338T263 372Q263 381 265 388T270 400T273 405Q271 407 250 401Q234 393 226 386Q179 341 179 207V154Q179 141 179 127T179 101T180 81T180 66V61Q181 59 183 57T188 54T193 51T200 49T207 48T216 47T225 47T235 46T245 46H276V0H267Q249 3 140 3Q37 3 28 0H20V46H36Z" transform="translate(889,0)" style="stroke-width: 3;"/><path data-c="67" d="M329 409Q373 453 429 453Q459 453 472 434T485 396Q485 382 476 371T449 360Q416 360 412 390Q410 404 415 411Q415 412 416 414V415Q388 412 363 393Q355 388 355 386Q355 385 359 381T368 369T379 351T388 325T392 292Q392 230 343 187T222 143Q172 143 123 171Q112 153 112 133Q112 98 138 81Q147 75 155 75T227 73Q311 72 335 67Q396 58 431 26Q470 -13 470 -72Q470 -139 392 -175Q332 -206 250 -206Q167 -206 107 -175Q29 -140 29 -75Q29 -39 50 -15T92 18L103 24Q67 55 67 108Q67 155 96 193Q52 237 52 292Q52 355 102 398T223 442Q274 442 318 416L329 409ZM299 343Q294 371 273 387T221 404Q192 404 171 388T145 343Q142 326 142 292Q142 248 149 227T179 192Q196 182 222 182Q244 182 260 189T283 207T294 227T299 242Q302 258 302 292T299 343ZM403 -75Q403 -50 389 -34T348 -11T299 -2T245 0H218Q151 0 138 -6Q118 -15 107 -34T95 -74Q95 -84 101 -97T122 -127T170 -155T250 -167Q319 -167 361 -139T403 -75Z" transform="translate(1281,0)" style="stroke-width: 3;"/><path data-c="65" d="M28 218Q28 273 48 318T98 391T163 433T229 448Q282 448 320 430T378 380T406 316T415 245Q415 238 408 231H126V216Q126 68 226 36Q246 30 270 30Q312 30 342 62Q359 79 369 104L379 128Q382 131 395 131H398Q415 131 415 121Q415 117 412 108Q393 53 349 21T250 -11Q155 -11 92 58T28 218ZM333 275Q322 403 238 411H236Q228 411 220 410T195 402T166 381T143 340T127 274V267H333V275Z" transform="translate(1781,0)" style="stroke-width: 3;"/><path data-c="74" d="M27 422Q80 426 109 478T141 600V615H181V431H316V385H181V241Q182 116 182 100T189 68Q203 29 238 29Q282 29 292 100Q293 108 293 146V181H333V146V134Q333 57 291 17Q264 -10 221 -10Q187 -10 162 2T124 33T105 68T98 100Q97 107 97 248V385H18V422H27Z" transform="translate(2225,0)" style="stroke-width: 3;"/><path data-c="48" d="M128 622Q121 629 117 631T101 634T58 637H25V683H36Q57 680 180 680Q315 680 324 683H335V637H302Q262 636 251 634T233 622L232 500V378H517V622Q510 629 506 631T490 634T447 637H414V683H425Q446 680 569 680Q704 680 713 683H724V637H691Q651 636 640 634T622 622V61Q628 51 639 49T691 46H724V0H713Q692 3 569 3Q434 3 425 0H414V46H447Q489 47 498 49T517 61V332H232V197L233 61Q239 51 250 49T302 46H335V0H324Q303 3 180 3Q45 3 36 0H25V46H58Q100 47 109 49T128 61V622Z" transform="translate(2614,0)" style="stroke-width: 3;"/><path data-c="69" d="M69 609Q69 637 87 653T131 669Q154 667 171 652T188 609Q188 579 171 564T129 549Q104 549 87 564T69 609ZM247 0Q232 3 143 3Q132 3 106 3T56 1L34 0H26V46H42Q70 46 91 49Q100 53 102 60T104 102V205V293Q104 345 102 359T88 378Q74 385 41 385H30V408Q30 431 32 431L42 432Q52 433 70 434T106 436Q123 437 142 438T171 441T182 442H185V62Q190 52 197 50T232 46H255V0H247Z" transform="translate(3364,0)" style="stroke-width: 3;"/><path data-c="70" d="M36 -148H50Q89 -148 97 -134V-126Q97 -119 97 -107T97 -77T98 -38T98 6T98 55T98 106Q98 140 98 177T98 243T98 296T97 335T97 351Q94 370 83 376T38 385H20V408Q20 431 22 431L32 432Q42 433 61 434T98 436Q115 437 135 438T165 441T176 442H179V416L180 390L188 397Q247 441 326 441Q407 441 464 377T522 216Q522 115 457 52T310 -11Q242 -11 190 33L182 40V-45V-101Q182 -128 184 -134T195 -145Q216 -148 244 -148H260V-194H252L228 -193Q205 -192 178 -192T140 -191Q37 -191 28 -194H20V-148H36ZM424 218Q424 292 390 347T305 402Q234 402 182 337V98Q222 26 294 26Q345 26 384 80T424 218Z" transform="translate(3642,0)" style="stroke-width: 3;"/><path data-c="59" d="M518 0Q497 3 374 3Q253 3 232 0H221V46H254Q313 47 321 58Q324 62 324 167V273L221 446Q117 620 114 623Q106 631 91 634T31 637H11V683H20Q29 680 148 680Q273 680 294 683H305V637H287Q239 636 236 621Q236 619 321 475L407 332L483 460Q502 492 527 534Q563 594 563 604Q563 632 517 637H508V683H517H525Q533 683 545 683T571 682T600 681T626 681Q695 681 731 683H738V637H723Q640 633 613 588Q612 587 517 427L425 273V169V95Q425 66 428 59T444 49Q459 46 506 46H528V0H518Z" transform="translate(4198,0)" style="stroke-width: 3;"/></g></g><g data-mml-node="TeXAtom" data-mjx-texclass="ORD" transform="translate(12215.6,0)"><g data-mml-node="mo"><path data-c="2F" d="M423 750Q432 750 438 744T444 730Q444 725 271 248T92 -240Q85 -250 75 -250Q68 -250 62 -245T56 -231Q56 -221 230 257T407 740Q411 750 423 750Z" style="stroke-width: 3;"/></g></g><g data-mml-node="TeXAtom" data-mjx-texclass="ORD" transform="translate(12715.6,0)"><g data-mml-node="mtext"><path data-c="73" d="M295 316Q295 356 268 385T190 414Q154 414 128 401Q98 382 98 349Q97 344 98 336T114 312T157 287Q175 282 201 278T245 269T277 256Q294 248 310 236T342 195T359 133Q359 71 321 31T198 -10H190Q138 -10 94 26L86 19L77 10Q71 4 65 -1L54 -11H46H42Q39 -11 33 -5V74V132Q33 153 35 157T45 162H54Q66 162 70 158T75 146T82 119T101 77Q136 26 198 26Q295 26 295 104Q295 133 277 151Q257 175 194 187T111 210Q75 227 54 256T33 318Q33 357 50 384T93 424T143 442T187 447H198Q238 447 268 432L283 424L292 431Q302 440 314 448H322H326Q329 448 335 442V310L329 304H301Q295 310 295 316Z" style="stroke-width: 3;"/><path data-c="6F" d="M28 214Q28 309 93 378T250 448Q340 448 405 380T471 215Q471 120 407 55T250 -10Q153 -10 91 57T28 214ZM250 30Q372 30 372 193V225V250Q372 272 371 288T364 326T348 362T317 390T268 410Q263 411 252 411Q222 411 195 399Q152 377 139 338T126 246V226Q126 130 145 91Q177 30 250 30Z" transform="translate(394,0)" style="stroke-width: 3;"/><path data-c="75" d="M383 58Q327 -10 256 -10H249Q124 -10 105 89Q104 96 103 226Q102 335 102 348T96 369Q86 385 36 385H25V408Q25 431 27 431L38 432Q48 433 67 434T105 436Q122 437 142 438T172 441T184 442H187V261Q188 77 190 64Q193 49 204 40Q224 26 264 26Q290 26 311 35T343 58T363 90T375 120T379 144Q379 145 379 161T380 201T380 248V315Q380 361 370 372T320 385H302V431Q304 431 378 436T457 442H464V264Q464 84 465 81Q468 61 479 55T524 46H542V0Q540 0 467 -5T390 -11H383V58Z" transform="translate(894,0)" style="stroke-width: 3;"/><path data-c="72" d="M36 46H50Q89 46 97 60V68Q97 77 97 91T98 122T98 161T98 203Q98 234 98 269T98 328L97 351Q94 370 83 376T38 385H20V408Q20 431 22 431L32 432Q42 433 60 434T96 436Q112 437 131 438T160 441T171 442H174V373Q213 441 271 441H277Q322 441 343 419T364 373Q364 352 351 337T313 322Q288 322 276 338T263 372Q263 381 265 388T270 400T273 405Q271 407 250 401Q234 393 226 386Q179 341 179 207V154Q179 141 179 127T179 101T180 81T180 66V61Q181 59 183 57T188 54T193 51T200 49T207 48T216 47T225 47T235 46T245 46H276V0H267Q249 3 140 3Q37 3 28 0H20V46H36Z" transform="translate(1450,0)" style="stroke-width: 3;"/><path data-c="63" d="M370 305T349 305T313 320T297 358Q297 381 312 396Q317 401 317 402T307 404Q281 408 258 408Q209 408 178 376Q131 329 131 219Q131 137 162 90Q203 29 272 29Q313 29 338 55T374 117Q376 125 379 127T395 129H409Q415 123 415 120Q415 116 411 104T395 71T366 33T318 2T249 -11Q163 -11 99 53T34 214Q34 318 99 383T250 448T370 421T404 357Q404 334 387 320Z" transform="translate(1842,0)" style="stroke-width: 3;"/><path data-c="65" d="M28 218Q28 273 48 318T98 391T163 433T229 448Q282 448 320 430T378 380T406 316T415 245Q415 238 408 231H126V216Q126 68 226 36Q246 30 270 30Q312 30 342 62Q359 79 369 104L379 128Q382 131 395 131H398Q415 131 415 121Q415 117 412 108Q393 53 349 21T250 -11Q155 -11 92 58T28 218ZM333 275Q322 403 238 411H236Q228 411 220 410T195 402T166 381T143 340T127 274V267H333V275Z" transform="translate(2286,0)" style="stroke-width: 3;"/><path data-c="48" d="M128 622Q121 629 117 631T101 634T58 637H25V683H36Q57 680 180 680Q315 680 324 683H335V637H302Q262 636 251 634T233 622L232 500V378H517V622Q510 629 506 631T490 634T447 637H414V683H425Q446 680 569 680Q704 680 713 683H724V637H691Q651 636 640 634T622 622V61Q628 51 639 49T691 46H724V0H713Q692 3 569 3Q434 3 425 0H414V46H447Q489 47 498 49T517 61V332H232V197L233 61Q239 51 250 49T302 46H335V0H324Q303 3 180 3Q45 3 36 0H25V46H58Q100 47 109 49T128 61V622Z" transform="translate(2730,0)" style="stroke-width: 3;"/><path data-c="69" d="M69 609Q69 637 87 653T131 669Q154 667 171 652T188 609Q188 579 171 564T129 549Q104 549 87 564T69 609ZM247 0Q232 3 143 3Q132 3 106 3T56 1L34 0H26V46H42Q70 46 91 49Q100 53 102 60T104 102V205V293Q104 345 102 359T88 378Q74 385 41 385H30V408Q30 431 32 431L42 432Q52 433 70 434T106 436Q123 437 142 438T171 441T182 442H185V62Q190 52 197 50T232 46H255V0H247Z" transform="translate(3480,0)" style="stroke-width: 3;"/><path data-c="70" d="M36 -148H50Q89 -148 97 -134V-126Q97 -119 97 -107T97 -77T98 -38T98 6T98 55T98 106Q98 140 98 177T98 243T98 296T97 335T97 351Q94 370 83 376T38 385H20V408Q20 431 22 431L32 432Q42 433 61 434T98 436Q115 437 135 438T165 441T176 442H179V416L180 390L188 397Q247 441 326 441Q407 441 464 377T522 216Q522 115 457 52T310 -11Q242 -11 190 33L182 40V-45V-101Q182 -128 184 -134T195 -145Q216 -148 244 -148H260V-194H252L228 -193Q205 -192 178 -192T140 -191Q37 -191 28 -194H20V-148H36ZM424 218Q424 292 390 347T305 402Q234 402 182 337V98Q222 26 294 26Q345 26 384 80T424 218Z" transform="translate(3758,0)" style="stroke-width: 3;"/><path data-c="59" d="M518 0Q497 3 374 3Q253 3 232 0H221V46H254Q313 47 321 58Q324 62 324 167V273L221 446Q117 620 114 623Q106 631 91 634T31 637H11V683H20Q29 680 148 680Q273 680 294 683H305V637H287Q239 636 236 621Q236 619 321 475L407 332L483 460Q502 492 527 534Q563 594 563 604Q563 632 517 637H508V683H517H525Q533 683 545 683T571 682T600 681T626 681Q695 681 731 683H738V637H723Q640 633 613 588Q612 587 517 427L425 273V169V95Q425 66 428 59T444 49Q459 46 506 46H528V0H518Z" transform="translate(4314,0)" style="stroke-width: 3;"/></g></g><g data-mml-node="mo" transform="translate(17779.6,0) translate(0 -0.5)"><path data-c="7C" d="M139 -249H137Q125 -249 119 -235V251L120 737Q130 750 139 750Q152 750 159 735V-235Q151 -249 141 -249H139Z" style="stroke-width: 3;"/></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mtext>verticalRatio</mtext><mo>=</mo><mo data-mjx-texclass="ORD" stretchy="false">|</mo><mrow data-mjx-texclass="ORD"><mtext>targetHipY</mtext></mrow><mrow data-mjx-texclass="ORD"><mo>/</mo></mrow><mrow data-mjx-texclass="ORD"><mtext>sourceHipY</mtext></mrow><mo data-mjx-texclass="ORD" stretchy="false">|</mo></math></mjx-assistive-mml></mjx-container> para Y y la proporción general para el plano horizontal. Se acabó el exceso de desplazamiento. Además, una sucesión de advertencias NaN de <code>RL_BoneRoot.position</code> resultó deberse a que asignábamos el <code>root</code> de UAL, situado en <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.186ex;" xmlns="http://www.w3.org/2000/svg" width="5.875ex" height="1.731ex" role="img" focusable="false" viewBox="0 -683 2596.6 765" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mi"><path data-c="1D44C" d="M66 637Q54 637 49 637T39 638T32 641T30 647T33 664T42 682Q44 683 56 683Q104 680 165 680Q288 680 306 683H316Q322 677 322 674T320 656Q316 643 310 637H298Q242 637 242 624Q242 619 292 477T343 333L346 336Q350 340 358 349T379 373T411 410T454 461Q546 568 561 587T577 618Q577 634 545 637Q528 637 528 647Q528 649 530 661Q533 676 535 679T549 683Q551 683 578 682T657 680Q684 680 713 681T746 682Q763 682 763 673Q763 669 760 657T755 643Q753 637 734 637Q662 632 617 587Q608 578 477 424L348 273L322 169Q295 62 295 57Q295 46 363 46Q379 46 384 45T390 35Q390 33 388 23Q384 6 382 4T366 1Q361 1 324 1T232 2Q170 2 138 2T102 1Q84 1 84 9Q84 14 87 24Q88 27 89 30T90 35T91 39T93 42T96 44T101 45T107 45T116 46T129 46Q168 47 180 50T198 63Q201 68 227 171L252 274L129 623Q128 624 127 625T125 627T122 629T118 631T113 633T105 634T96 635T83 636T66 637Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(1040.8,0)"><path data-c="3D" d="M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z" style="stroke-width: 3;"/></g><g data-mml-node="mn" transform="translate(2096.6,0)"><path data-c="30" d="M96 585Q152 666 249 666Q297 666 345 640T423 548Q460 465 460 320Q460 165 417 83Q397 41 362 16T301 -15T250 -22Q224 -22 198 -16T137 16T82 83Q39 165 39 320Q39 494 96 585ZM321 597Q291 629 250 629Q208 629 178 597Q153 571 145 525T137 333Q137 175 145 125T181 46Q209 16 250 16Q290 16 318 46Q347 76 354 130T362 333Q362 478 354 524T321 597Z" style="stroke-width: 3;"/></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mi>Y</mi><mo>=</mo><mn>0</mn></math></mjx-assistive-mml></mjx-container>, a un hueso de destino cuya pista de posición se normaliza dividiéndola entre su Y de enlace. División por cero, NaN y pista descartada silenciosamente. La solución fue eliminar por completo la asignación de la raíz, ya que su traslación ya está incluida en la pista de la cadera.</p>
<p>La corrección más pequeña fue la más satisfactoria de ver. El personaje sujetaba la espada con los dedos flácidos de la pose de enlace porque el mapa de huesos no incluía entradas para los dedos, y el sistema de retargeting solo escribe pistas para los huesos asignados. Añadir 30 huesos de los dedos —cinco dedos, tres segmentos, dos manos, omitiendo el cuarto hueso auxiliar de la punta de UAL, que no deforma— hizo que la mano se cerrara sobre la empuñadura y se abriera al soltarla.</p>
<h2 id="verificar-262-clips-sin-tener-que-ver-262-clips" tabindex="-1">Verificar 262 clips sin tener que ver 262 clips <a class="header-anchor" href="#verificar-262-clips-sin-tener-que-ver-262-clips" aria-label="Permalink to &quot;Verificar 262 clips sin tener que ver 262 clips&quot;"></a></h2>
<p>No se puede verificar visualmente una biblioteca de 262 clips, así que creamos una prueba de paridad de trayectorias sin conexión: un script de Node sin interfaz que carga cada paquete, muestrea el esqueleto de origen a 60 Hz, ejecuta el pipeline de retargeting y compara las posiciones y rotaciones globales de cada hueso con las de la fuente después del escalado. La deriva máxima de la pelvis en Y fue de 0,003 m. Las manos mostraban un desplazamiento constante de 2,5° que al principio interpretamos como «los dedos no siguen la animación», pero un desplazamiento constante es el delta de enlace entre la mano plana de UAL y la pose de enlace ligeramente curvada de CC4, y permanece invariable durante todo el clip. Los errores reales de animación se manifiestan como una deriva que varía de un fotograma a otro. Una vez aclarado esto, la prueba se convirtió en una comprobación de regresión de una sola pasada: si la deriva de un clip deja de mantener esa referencia constante, un cambio reciente ha roto el retargeting.</p>
<p>Un maniquí de referencia mostrado en paralelo hizo decisiva la parte visual de la depuración. Al pulsar la barra invertida aparece junto al jugador el rig de origen al que pertenece el clip actual, de modo que la pregunta «¿por qué está retorcido el hombro?» se convierte en «¿el giro está en la fuente o lo ha añadido el retargeting?». Las pruebas numéricas detectan regresiones, la referencia visual detecta errores de la pose de enlace que los números no revelan y, juntas, eliminaron las conjeturas.</p>
<p>Con el pipeline consolidado, cambiar la base de WASD, salto y natación de Mixamo a UAL solo requirió un pequeño mapa de alias: la máquina de estados finitos sigue usando nombres de estado genéricos como <code>idle</code> y <code>walk</code>, que se resuelven a nombres de clips de UAL durante la reproducción. La natación necesitaba desplazamientos de rig específicos para cada clip porque las poses de estilo libre y de mantenerse a flote anclan la pelvis a distintas alturas anatómicas, así que sumergimos el rig medio metro para la natación activa y algo más para mantenerse a flote, interpolando suavemente entre ambas a 5 Hz.</p>
<h2 id="escribe-una-palabra-y-obten-un-modelo" tabindex="-1">Escribe una palabra y obtén un modelo <a class="header-anchor" href="#escribe-una-palabra-y-obten-un-modelo" aria-label="Permalink to &quot;Escribe una palabra y obtén un modelo&quot;"></a></h2>
<div style="position:relative;padding-bottom:56.25%;height:0;overflow:hidden;border-radius:8px;margin:1.5rem 0;border:1px solid rgba(255,255,255,0.12)">
<iframe src="/es/spikes/36-polyhaven-models/" title="Spike 36: modelos de Polyhaven" style="position:absolute;top:0;left:0;width:100%;height:100%;border:0;background:#000" loading="lazy" allowfullscreen></iframe>
</div>
<p><a href="/es/spikes/36-polyhaven-models/" target="_blank">Abrir el Spike 36 en una pestaña nueva ↗</a> · <a href="/es/blog/spike-source?spike=36-polyhaven-models">Ver el código fuente</a></p>
<p>El Spike 34 consumió un día entero seleccionando manualmente un paquete CC0. La solución a largo plazo es un cuadro de búsqueda. Polyhaven publica unos 1.100 modelos CC0 mediante una API JSON permisiva y una CDN determinista, y este spike conecta todo el recorrido —consulta, miniaturas, carga y renderizado— desde una página estática sin ningún paso de compilación, en unas 300 líneas de JavaScript puro más three.js.</p>
<p>Al iniciarse, descarga una vez el catálogo completo, de unos 600 KB. La búsqueda usa un sistema de puntuación puramente del lado del cliente —el nombre tiene prioridad sobre el identificador, este sobre la categoría y esta sobre la etiqueta— con un retardo de 120 ms, y muestra las 60 tarjetas principales. Las miniaturas se cargan de forma diferida mediante un <code>IntersectionObserver</code>, para que escribir no dispare 60 solicitudes a la vez. La parte interesante es la carga. El endpoint de archivos de Polyhaven expone glTF de varios archivos, no GLB, con texturas compartidas entre resoluciones y divididas en archivos separados, y devuelve un mapa <code>include</code> que relaciona cada ruta relativa con una URL absoluta de la CDN. En lugar de descargar y modificar nosotros mismos el JSON, pasamos ese mapa por <code>LoadingManager.setURLModifier</code>, que se ejecuta para cada dependencia que necesita el cargador —el <code>.bin</code> y cada textura— y la resuelve mediante la CDN. Un clic, un único archivo en apariencia. Tanto la API como la CDN establecen CORS permisivo, algo que verificamos con <code>curl</code> antes de escribir código de cliente, así que no hace falta ningún proxy. Los materiales PBR se renderizan correctamente con <code>RoomEnvironment</code> y los valores predeterminados del mapeo de tonos ACES, sin ajustes específicos por recurso, y las texturas de 1k mantienen un modelo típico entre 2 y 5 MB en lugar de los 20 a 40 MB de las texturas 4k.</p>
<p>Una pasada WASM de meshoptimizer completa el sistema con un reductor no destructivo: cada malla guarda un clon de su geometría original y, al cambiar la proporción, reconstruye un búfer de índices a partir de ese clon en lugar de simplificar de forma acumulativa. La geometría con varios materiales se simplifica por grupo y reconstruye <code>geometry.groups</code> para que las ranuras de materiales no colapsen. Un sillón pasa de 5.626 triángulos en calidad completa a 2.812 a la mitad.</p>
<h2 id="tecnologia-mencionada-en-este-capitulo" tabindex="-1">Tecnología mencionada en este capítulo <a class="header-anchor" href="#tecnologia-mencionada-en-este-capitulo" aria-label="Permalink to &quot;Tecnología mencionada en este capítulo&quot;"></a></h2>
<p><strong>Retargeting de esqueletos con alineación de la pose de enlace.</strong> Transferir una animación de un esqueleto a otro con distintos nombres de huesos, proporciones y poses de referencia requiere tres correcciones: un mapa de nombres de huesos, una alineación de la pose de enlace para que ambos rigs compartan una orientación de referencia —forzando la cadena de brazos en pose A del destino a adoptar la pose T de la fuente— y el escalado de las pistas de posición. Una discrepancia de poses añade la rotación de A a T a cada delta por fotograma, duplicando la rotación de las articulaciones. Los huesos auxiliares sin asignar deben descartarse, ya que un hueso raíz en <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.186ex;" xmlns="http://www.w3.org/2000/svg" width="5.875ex" height="1.731ex" role="img" focusable="false" viewBox="0 -683 2596.6 765" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mi"><path data-c="1D44C" d="M66 637Q54 637 49 637T39 638T32 641T30 647T33 664T42 682Q44 683 56 683Q104 680 165 680Q288 680 306 683H316Q322 677 322 674T320 656Q316 643 310 637H298Q242 637 242 624Q242 619 292 477T343 333L346 336Q350 340 358 349T379 373T411 410T454 461Q546 568 561 587T577 618Q577 634 545 637Q528 637 528 647Q528 649 530 661Q533 676 535 679T549 683Q551 683 578 682T657 680Q684 680 713 681T746 682Q763 682 763 673Q763 669 760 657T755 643Q753 637 734 637Q662 632 617 587Q608 578 477 424L348 273L322 169Q295 62 295 57Q295 46 363 46Q379 46 384 45T390 35Q390 33 388 23Q384 6 382 4T366 1Q361 1 324 1T232 2Q170 2 138 2T102 1Q84 1 84 9Q84 14 87 24Q88 27 89 30T90 35T91 39T93 42T96 44T101 45T107 45T116 46T129 46Q168 47 180 50T198 63Q201 68 227 171L252 274L129 623Q128 624 127 625T125 627T122 629T118 631T113 633T105 634T96 635T83 636T66 637Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(1040.8,0)"><path data-c="3D" d="M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z" style="stroke-width: 3;"/></g><g data-mml-node="mn" transform="translate(2096.6,0)"><path data-c="30" d="M96 585Q152 666 249 666Q297 666 345 640T423 548Q460 465 460 320Q460 165 417 83Q397 41 362 16T301 -15T250 -22Q224 -22 198 -16T137 16T82 83Q39 165 39 320Q39 494 96 585ZM321 597Q291 629 250 629Q208 629 178 597Q153 571 145 525T137 333Q137 175 145 125T181 46Q209 16 250 16Q290 16 318 46Q347 76 354 130T362 333Q362 478 354 524T321 597Z" style="stroke-width: 3;"/></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mi>Y</mi><mo>=</mo><mn>0</mn></math></mjx-assistive-mml></mjx-container> provoca una división silenciosa por cero al normalizar la pista de posición.</p>
<p><strong>Dos proporciones de escala para un solo rig.</strong> El desplazamiento horizontal usa la proporción global de las extremidades —el tamaño total del esqueleto—, pero el desplazamiento vertical de la pelvis usa la proporción entre la cadera y el suelo <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.566ex;" xmlns="http://www.w3.org/2000/svg" width="25.041ex" height="2.262ex" role="img" focusable="false" viewBox="0 -750 11068 1000" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mo" transform="translate(0 -0.5)"><path data-c="7C" d="M139 -249H137Q125 -249 119 -235V251L120 737Q130 750 139 750Q152 750 159 735V-235Q151 -249 141 -249H139Z" style="stroke-width: 3;"/></g><g data-mml-node="TeXAtom" data-mjx-texclass="ORD" transform="translate(278,0)"><g data-mml-node="mtext"><path data-c="74" d="M27 422Q80 426 109 478T141 600V615H181V431H316V385H181V241Q182 116 182 100T189 68Q203 29 238 29Q282 29 292 100Q293 108 293 146V181H333V146V134Q333 57 291 17Q264 -10 221 -10Q187 -10 162 2T124 33T105 68T98 100Q97 107 97 248V385H18V422H27Z" style="stroke-width: 3;"/><path data-c="61" d="M137 305T115 305T78 320T63 359Q63 394 97 421T218 448Q291 448 336 416T396 340Q401 326 401 309T402 194V124Q402 76 407 58T428 40Q443 40 448 56T453 109V145H493V106Q492 66 490 59Q481 29 455 12T400 -6T353 12T329 54V58L327 55Q325 52 322 49T314 40T302 29T287 17T269 6T247 -2T221 -8T190 -11Q130 -11 82 20T34 107Q34 128 41 147T68 188T116 225T194 253T304 268H318V290Q318 324 312 340Q290 411 215 411Q197 411 181 410T156 406T148 403Q170 388 170 359Q170 334 154 320ZM126 106Q126 75 150 51T209 26Q247 26 276 49T315 109Q317 116 318 175Q318 233 317 233Q309 233 296 232T251 223T193 203T147 166T126 106Z" transform="translate(389,0)" style="stroke-width: 3;"/><path data-c="72" d="M36 46H50Q89 46 97 60V68Q97 77 97 91T98 122T98 161T98 203Q98 234 98 269T98 328L97 351Q94 370 83 376T38 385H20V408Q20 431 22 431L32 432Q42 433 60 434T96 436Q112 437 131 438T160 441T171 442H174V373Q213 441 271 441H277Q322 441 343 419T364 373Q364 352 351 337T313 322Q288 322 276 338T263 372Q263 381 265 388T270 400T273 405Q271 407 250 401Q234 393 226 386Q179 341 179 207V154Q179 141 179 127T179 101T180 81T180 66V61Q181 59 183 57T188 54T193 51T200 49T207 48T216 47T225 47T235 46T245 46H276V0H267Q249 3 140 3Q37 3 28 0H20V46H36Z" transform="translate(889,0)" style="stroke-width: 3;"/><path data-c="67" d="M329 409Q373 453 429 453Q459 453 472 434T485 396Q485 382 476 371T449 360Q416 360 412 390Q410 404 415 411Q415 412 416 414V415Q388 412 363 393Q355 388 355 386Q355 385 359 381T368 369T379 351T388 325T392 292Q392 230 343 187T222 143Q172 143 123 171Q112 153 112 133Q112 98 138 81Q147 75 155 75T227 73Q311 72 335 67Q396 58 431 26Q470 -13 470 -72Q470 -139 392 -175Q332 -206 250 -206Q167 -206 107 -175Q29 -140 29 -75Q29 -39 50 -15T92 18L103 24Q67 55 67 108Q67 155 96 193Q52 237 52 292Q52 355 102 398T223 442Q274 442 318 416L329 409ZM299 343Q294 371 273 387T221 404Q192 404 171 388T145 343Q142 326 142 292Q142 248 149 227T179 192Q196 182 222 182Q244 182 260 189T283 207T294 227T299 242Q302 258 302 292T299 343ZM403 -75Q403 -50 389 -34T348 -11T299 -2T245 0H218Q151 0 138 -6Q118 -15 107 -34T95 -74Q95 -84 101 -97T122 -127T170 -155T250 -167Q319 -167 361 -139T403 -75Z" transform="translate(1281,0)" style="stroke-width: 3;"/><path data-c="65" d="M28 218Q28 273 48 318T98 391T163 433T229 448Q282 448 320 430T378 380T406 316T415 245Q415 238 408 231H126V216Q126 68 226 36Q246 30 270 30Q312 30 342 62Q359 79 369 104L379 128Q382 131 395 131H398Q415 131 415 121Q415 117 412 108Q393 53 349 21T250 -11Q155 -11 92 58T28 218ZM333 275Q322 403 238 411H236Q228 411 220 410T195 402T166 381T143 340T127 274V267H333V275Z" transform="translate(1781,0)" style="stroke-width: 3;"/><path data-c="74" d="M27 422Q80 426 109 478T141 600V615H181V431H316V385H181V241Q182 116 182 100T189 68Q203 29 238 29Q282 29 292 100Q293 108 293 146V181H333V146V134Q333 57 291 17Q264 -10 221 -10Q187 -10 162 2T124 33T105 68T98 100Q97 107 97 248V385H18V422H27Z" transform="translate(2225,0)" style="stroke-width: 3;"/><path data-c="48" d="M128 622Q121 629 117 631T101 634T58 637H25V683H36Q57 680 180 680Q315 680 324 683H335V637H302Q262 636 251 634T233 622L232 500V378H517V622Q510 629 506 631T490 634T447 637H414V683H425Q446 680 569 680Q704 680 713 683H724V637H691Q651 636 640 634T622 622V61Q628 51 639 49T691 46H724V0H713Q692 3 569 3Q434 3 425 0H414V46H447Q489 47 498 49T517 61V332H232V197L233 61Q239 51 250 49T302 46H335V0H324Q303 3 180 3Q45 3 36 0H25V46H58Q100 47 109 49T128 61V622Z" transform="translate(2614,0)" style="stroke-width: 3;"/><path data-c="69" d="M69 609Q69 637 87 653T131 669Q154 667 171 652T188 609Q188 579 171 564T129 549Q104 549 87 564T69 609ZM247 0Q232 3 143 3Q132 3 106 3T56 1L34 0H26V46H42Q70 46 91 49Q100 53 102 60T104 102V205V293Q104 345 102 359T88 378Q74 385 41 385H30V408Q30 431 32 431L42 432Q52 433 70 434T106 436Q123 437 142 438T171 441T182 442H185V62Q190 52 197 50T232 46H255V0H247Z" transform="translate(3364,0)" style="stroke-width: 3;"/><path data-c="70" d="M36 -148H50Q89 -148 97 -134V-126Q97 -119 97 -107T97 -77T98 -38T98 6T98 55T98 106Q98 140 98 177T98 243T98 296T97 335T97 351Q94 370 83 376T38 385H20V408Q20 431 22 431L32 432Q42 433 61 434T98 436Q115 437 135 438T165 441T176 442H179V416L180 390L188 397Q247 441 326 441Q407 441 464 377T522 216Q522 115 457 52T310 -11Q242 -11 190 33L182 40V-45V-101Q182 -128 184 -134T195 -145Q216 -148 244 -148H260V-194H252L228 -193Q205 -192 178 -192T140 -191Q37 -191 28 -194H20V-148H36ZM424 218Q424 292 390 347T305 402Q234 402 182 337V98Q222 26 294 26Q345 26 384 80T424 218Z" transform="translate(3642,0)" style="stroke-width: 3;"/><path data-c="59" d="M518 0Q497 3 374 3Q253 3 232 0H221V46H254Q313 47 321 58Q324 62 324 167V273L221 446Q117 620 114 623Q106 631 91 634T31 637H11V683H20Q29 680 148 680Q273 680 294 683H305V637H287Q239 636 236 621Q236 619 321 475L407 332L483 460Q502 492 527 534Q563 594 563 604Q563 632 517 637H508V683H517H525Q533 683 545 683T571 682T600 681T626 681Q695 681 731 683H738V637H723Q640 633 613 588Q612 587 517 427L425 273V169V95Q425 66 428 59T444 49Q459 46 506 46H528V0H518Z" transform="translate(4198,0)" style="stroke-width: 3;"/></g></g><g data-mml-node="TeXAtom" data-mjx-texclass="ORD" transform="translate(5226,0)"><g data-mml-node="mo"><path data-c="2F" d="M423 750Q432 750 438 744T444 730Q444 725 271 248T92 -240Q85 -250 75 -250Q68 -250 62 -245T56 -231Q56 -221 230 257T407 740Q411 750 423 750Z" style="stroke-width: 3;"/></g></g><g data-mml-node="TeXAtom" data-mjx-texclass="ORD" transform="translate(5726,0)"><g data-mml-node="mtext"><path data-c="73" d="M295 316Q295 356 268 385T190 414Q154 414 128 401Q98 382 98 349Q97 344 98 336T114 312T157 287Q175 282 201 278T245 269T277 256Q294 248 310 236T342 195T359 133Q359 71 321 31T198 -10H190Q138 -10 94 26L86 19L77 10Q71 4 65 -1L54 -11H46H42Q39 -11 33 -5V74V132Q33 153 35 157T45 162H54Q66 162 70 158T75 146T82 119T101 77Q136 26 198 26Q295 26 295 104Q295 133 277 151Q257 175 194 187T111 210Q75 227 54 256T33 318Q33 357 50 384T93 424T143 442T187 447H198Q238 447 268 432L283 424L292 431Q302 440 314 448H322H326Q329 448 335 442V310L329 304H301Q295 310 295 316Z" style="stroke-width: 3;"/><path data-c="6F" d="M28 214Q28 309 93 378T250 448Q340 448 405 380T471 215Q471 120 407 55T250 -10Q153 -10 91 57T28 214ZM250 30Q372 30 372 193V225V250Q372 272 371 288T364 326T348 362T317 390T268 410Q263 411 252 411Q222 411 195 399Q152 377 139 338T126 246V226Q126 130 145 91Q177 30 250 30Z" transform="translate(394,0)" style="stroke-width: 3;"/><path data-c="75" d="M383 58Q327 -10 256 -10H249Q124 -10 105 89Q104 96 103 226Q102 335 102 348T96 369Q86 385 36 385H25V408Q25 431 27 431L38 432Q48 433 67 434T105 436Q122 437 142 438T172 441T184 442H187V261Q188 77 190 64Q193 49 204 40Q224 26 264 26Q290 26 311 35T343 58T363 90T375 120T379 144Q379 145 379 161T380 201T380 248V315Q380 361 370 372T320 385H302V431Q304 431 378 436T457 442H464V264Q464 84 465 81Q468 61 479 55T524 46H542V0Q540 0 467 -5T390 -11H383V58Z" transform="translate(894,0)" style="stroke-width: 3;"/><path data-c="72" d="M36 46H50Q89 46 97 60V68Q97 77 97 91T98 122T98 161T98 203Q98 234 98 269T98 328L97 351Q94 370 83 376T38 385H20V408Q20 431 22 431L32 432Q42 433 60 434T96 436Q112 437 131 438T160 441T171 442H174V373Q213 441 271 441H277Q322 441 343 419T364 373Q364 352 351 337T313 322Q288 322 276 338T263 372Q263 381 265 388T270 400T273 405Q271 407 250 401Q234 393 226 386Q179 341 179 207V154Q179 141 179 127T179 101T180 81T180 66V61Q181 59 183 57T188 54T193 51T200 49T207 48T216 47T225 47T235 46T245 46H276V0H267Q249 3 140 3Q37 3 28 0H20V46H36Z" transform="translate(1450,0)" style="stroke-width: 3;"/><path data-c="63" d="M370 305T349 305T313 320T297 358Q297 381 312 396Q317 401 317 402T307 404Q281 408 258 408Q209 408 178 376Q131 329 131 219Q131 137 162 90Q203 29 272 29Q313 29 338 55T374 117Q376 125 379 127T395 129H409Q415 123 415 120Q415 116 411 104T395 71T366 33T318 2T249 -11Q163 -11 99 53T34 214Q34 318 99 383T250 448T370 421T404 357Q404 334 387 320Z" transform="translate(1842,0)" style="stroke-width: 3;"/><path data-c="65" d="M28 218Q28 273 48 318T98 391T163 433T229 448Q282 448 320 430T378 380T406 316T415 245Q415 238 408 231H126V216Q126 68 226 36Q246 30 270 30Q312 30 342 62Q359 79 369 104L379 128Q382 131 395 131H398Q415 131 415 121Q415 117 412 108Q393 53 349 21T250 -11Q155 -11 92 58T28 218ZM333 275Q322 403 238 411H236Q228 411 220 410T195 402T166 381T143 340T127 274V267H333V275Z" transform="translate(2286,0)" style="stroke-width: 3;"/><path data-c="48" d="M128 622Q121 629 117 631T101 634T58 637H25V683H36Q57 680 180 680Q315 680 324 683H335V637H302Q262 636 251 634T233 622L232 500V378H517V622Q510 629 506 631T490 634T447 637H414V683H425Q446 680 569 680Q704 680 713 683H724V637H691Q651 636 640 634T622 622V61Q628 51 639 49T691 46H724V0H713Q692 3 569 3Q434 3 425 0H414V46H447Q489 47 498 49T517 61V332H232V197L233 61Q239 51 250 49T302 46H335V0H324Q303 3 180 3Q45 3 36 0H25V46H58Q100 47 109 49T128 61V622Z" transform="translate(2730,0)" style="stroke-width: 3;"/><path data-c="69" d="M69 609Q69 637 87 653T131 669Q154 667 171 652T188 609Q188 579 171 564T129 549Q104 549 87 564T69 609ZM247 0Q232 3 143 3Q132 3 106 3T56 1L34 0H26V46H42Q70 46 91 49Q100 53 102 60T104 102V205V293Q104 345 102 359T88 378Q74 385 41 385H30V408Q30 431 32 431L42 432Q52 433 70 434T106 436Q123 437 142 438T171 441T182 442H185V62Q190 52 197 50T232 46H255V0H247Z" transform="translate(3480,0)" style="stroke-width: 3;"/><path data-c="70" d="M36 -148H50Q89 -148 97 -134V-126Q97 -119 97 -107T97 -77T98 -38T98 6T98 55T98 106Q98 140 98 177T98 243T98 296T97 335T97 351Q94 370 83 376T38 385H20V408Q20 431 22 431L32 432Q42 433 61 434T98 436Q115 437 135 438T165 441T176 442H179V416L180 390L188 397Q247 441 326 441Q407 441 464 377T522 216Q522 115 457 52T310 -11Q242 -11 190 33L182 40V-45V-101Q182 -128 184 -134T195 -145Q216 -148 244 -148H260V-194H252L228 -193Q205 -192 178 -192T140 -191Q37 -191 28 -194H20V-148H36ZM424 218Q424 292 390 347T305 402Q234 402 182 337V98Q222 26 294 26Q345 26 384 80T424 218Z" transform="translate(3758,0)" style="stroke-width: 3;"/><path data-c="59" d="M518 0Q497 3 374 3Q253 3 232 0H221V46H254Q313 47 321 58Q324 62 324 167V273L221 446Q117 620 114 623Q106 631 91 634T31 637H11V683H20Q29 680 148 680Q273 680 294 683H305V637H287Q239 636 236 621Q236 619 321 475L407 332L483 460Q502 492 527 534Q563 594 563 604Q563 632 517 637H508V683H517H525Q533 683 545 683T571 682T600 681T626 681Q695 681 731 683H738V637H723Q640 633 613 588Q612 587 517 427L425 273V169V95Q425 66 428 59T444 49Q459 46 506 46H528V0H518Z" transform="translate(4314,0)" style="stroke-width: 3;"/></g></g><g data-mml-node="mo" transform="translate(10790,0) translate(0 -0.5)"><path data-c="7C" d="M139 -249H137Q125 -249 119 -235V251L120 737Q130 750 139 750Q152 750 159 735V-235Q151 -249 141 -249H139Z" style="stroke-width: 3;"/></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mo data-mjx-texclass="ORD" stretchy="false">|</mo><mrow data-mjx-texclass="ORD"><mtext>targetHipY</mtext></mrow><mrow data-mjx-texclass="ORD"><mo>/</mo></mrow><mrow data-mjx-texclass="ORD"><mtext>sourceHipY</mtext></mrow><mo data-mjx-texclass="ORD" stretchy="false">|</mo></math></mjx-assistive-mml></mjx-container>, porque la proporción entre las piernas y el torso difiere entre rigs. Usar una sola proporción para ambos ejes hace que las escaladas se excedan y que las recuperaciones se hundan bajo el suelo. El desplazamiento de UAL también reside en el hueso <code>root</code>, no en la pelvis, así que ambos deben sumarse en una única pista de posición de la cadera para conservar el movimiento en clips de retroceso, escalada y locomoción.</p>
<p><strong>Pruebas sin conexión de paridad de trayectorias.</strong> Un script sin interfaz muestrea el esqueleto de origen a 60 Hz, ejecuta el pipeline de retargeting y compara las transformaciones globales de cada hueso con la fuente. Un desplazamiento constante por fotograma es el delta de enlace inofensivo, mientras que una deriva que varía de un fotograma a otro es un error real; por eso, la prueba se convierte en una comprobación de regresión que se activa cuando un cambio elimina o distorsiona una pista. El aislamiento de los GLB por paquete —carga nueva y liberación antes del siguiente— evita la contención de caché durante el recorrido completo.</p>
<p><strong>LoadingManager.setURLModifier para grafos glTF alojados en una CDN.</strong> Cuando una CDN distribuye glTF como un grafo de URI relativas acompañado de un mapa de inclusiones —ruta relativa a URL absoluta—, <code>setURLModifier</code> resuelve mediante la CDN cada dependencia solicitada por el cargador sin reescribir el JSON. Esto convierte una distribución de varios archivos y resoluciones en una carga con un solo clic. Liberar la geometría, los materiales y los mapas de texturas de cada modelo anterior antes de cargar el siguiente evita que se acumulen cientos de MB de memoria de GPU durante una sesión de exploración.</p>
<p><strong>Simplificación no destructiva de mallas.</strong> Guardar un clon de la geometría original de cada malla y reconstruir solo el búfer de índices para cada proporción de simplificación mantiene los cambios rápidos y evita los daños acumulativos de simplificaciones repetidas. Ejecutar el proceso por cada sección de <code>geometry.groups</code> y reconstruir los grupos conserva las asignaciones de varios materiales. Consulta <a href="/es/guides/landscape-generation-browser.html#gpu-driven-lod-with-webgpu">LOD y meshoptimizer</a> para ver cómo se integra esto en el LOD basado en la distancia.</p>
<hr>
<p>Parte 17 de 29.
Anterior: <a href="/es/blog/2026-04-28-open-world-browser-part-16-structure-and-authoring.html">Parte 16 - Estructura para un mundo que no deja de crecer</a>
Siguiente: <a href="/es/blog/2026-05-02-open-world-browser-part-18-ai-scattering.html">Parte 18 - Un pincel de dispersión que parece guiado por IA</a>
Guía de la serie: <a href="/es/blog/2026-02-25-open-world-browser-series-guide.html">/es/blog/2026-02-25-open-world-browser-series-guide</a></p>
]]></content:encoded>
            <enclosure url="https://cdn.cinevva.com/blog/why-webgpu-engine-hero.jpg" length="0" type="image/jpg"/>
        </item>
        <item>
            <title><![CDATA[Anatomía de un motor de juegos con IA: qué hay realmente dentro del prompt]]></title>
            <link>https://app.cinevva.com/es/blog/2026-04-30-anatomy-of-an-ai-game-engine</link>
            <guid>https://app.cinevva.com/es/blog/2026-04-30-anatomy-of-an-ai-game-engine</guid>
            <pubDate>Thu, 30 Apr 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Cinevva parece un único cuadro de texto. Detrás hay un orquestador, 26 herramientas tipadas, once proveedores de recursos, un iframe con el juego en vivo que el agente puede jugar y un escaparate conectado a vídeos de gameplay. Aquí está la máquina completa, pieza por pieza.]]></description>
            <content:encoded><![CDATA[<h1 id="anatomia-de-un-motor-de-juegos-con-ia-que-hay-realmente-dentro-del-prompt" tabindex="-1">Anatomía de un motor de juegos con IA: qué hay realmente dentro del prompt <a class="header-anchor" href="#anatomia-de-un-motor-de-juegos-con-ia-que-hay-realmente-dentro-del-prompt" aria-label="Permalink to &quot;Anatomía de un motor de juegos con IA: qué hay realmente dentro del prompt&quot;"></a></h1>
<p><em>Por <a href="/es/about.html">Mariana Muntean</a>, CEO de Cinevva</em></p>
<p>Lo que más suelen decir quienes descubren Cinevva es que se trata de una capa sobre una IA. Llegan a la página de inicio, ven un único cuadro de texto que dice «Describe tu juego» y creen que ya han entendido el producto. Han entendido la puerta de entrada. El producto es todo lo que no ves cuando escribes esa frase y, desde esta semana, también un mundo abierto en el que tus jugadores entran para encontrar tu juego.</p>
<p>Detrás de ese cuadro hay un motor de juegos completo, un orquestador con 26 herramientas tipadas, una flota de modelos generativos, una búsqueda agregada de recursos entre once proveedores, un iframe con el juego en vivo que el agente puede leer y modificar, y un escaparate donde ese mismo agente publica tu juego terminado como un vídeo de gameplay que se puede deslizar. Nada de eso es exótico. Todo es infraestructura. El trabajo interesante consistió en decidir qué conectar con qué.</p>
<p>Este artículo recorre la máquina de arriba abajo. Es la explicación que damos a los inversores técnicos y también a los desarrolladores que están pensando en contribuir. Ambos quieren la misma respuesta.</p>
<h2 id="_1-el-prompt-es-la-superficie-no-el-sistema" tabindex="-1">1. El prompt es la superficie, no el sistema <a class="header-anchor" href="#_1-el-prompt-es-la-superficie-no-el-sistema" aria-label="Permalink to &quot;1. El prompt es la superficie, no el sistema&quot;"></a></h2>
<img src="/img/blog/engine-anatomy/cinevva-engine-prompt.png" alt="El campo del prompt de Cinevva en la página de inicio. Un único campo de texto dice «Crea un shooter espacial de neón con asteroides, potenciadores y una banda sonora de sintetizadores». Debajo aparecen tres sugerencias y el logotipo de Cinevva." style="width:100%;border-radius:8px;margin:1.5rem 0" />
<p>La primera decisión de diseño fue ocultarlo todo hasta que el usuario ya tuviera algo en juego. La página de inicio tiene una sola función: tomar una frase y convertirla en un proyecto. Dividimos la experiencia en una parte pública (el prompt, las muestras y el feed del escaparate) y otra para creadores (el IDE, las herramientas de recursos y el flujo de publicación), para que quienes solo quieren jugar no tengan que mirar la cabina de mando.</p>
<p>Por eso el texto de ejemplo va alternando entre frases como «Crea un juego de la serpiente con gráficos de neón» y «Shooter de zombis con vista cenital». No son tutoriales. Son una invitación. El usuario entiende que una «idea extraña para un arcade» es una entrada válida.</p>
<p>En cuanto lo envías, ocurren tres cosas. El sistema crea un proyecto de juego nuevo con un ID estable. Inicializa un árbol de archivos vacío (<code>index.html</code>, <code>game.js</code>, <code>style.css</code>, <code>assets/</code>, <code>GDD.md</code>). Y dirige tu frase al orquestador junto con una ventana de contexto del proyecto que apunta a esos archivos vacíos. A partir de ahí, hablas con un agente que tiene manos.</p>
<h2 id="_2-detras-del-campo-de-texto-un-ide-completo-en-el-navegador" tabindex="-1">2. Detrás del campo de texto, un IDE completo en el navegador <a class="header-anchor" href="#_2-detras-del-campo-de-texto-un-ide-completo-en-el-navegador" aria-label="Permalink to &quot;2. Detrás del campo de texto, un IDE completo en el navegador&quot;"></a></h2>
<img src="/img/blog/engine-anatomy/cinevva-engine-ide.png" alt="El IDE para creadores de Cinevva en modo oscuro. Tres paneles: un árbol de archivos a la izquierda con GDD.md, index.html, game.js, style.css y una carpeta de recursos; un editor de código con resaltado de sintaxis en el centro que muestra la configuración de un renderizador de Three.js; y una vista previa del juego en vivo a la derecha que muestra un shooter espacial de neón con vista cenital y una interfaz con PUNTUACIÓN y VIDAS." style="width:100%;border-radius:8px;margin:1.5rem 0" />
<p>El espacio de trabajo para creadores es un IDE de tres paneles que se ejecuta por completo en el navegador. El árbol de archivos está a la izquierda, el editor de código en el centro, el iframe con el juego en vivo a la derecha y, en la parte inferior, un campo de chat. Elegimos esta disposición deliberadamente. Quienes ya programan la reconocen al instante. Quienes no, pueden ignorar el panel central y comunicarse únicamente mediante el chat.</p>
<p>El árbol de archivos no es una metáfora. Cada proyecto es realmente un pequeño sitio estático compuesto por HTML, JS, CSS, imágenes generadas, modelos GLB y archivos de audio, servido directamente desde R2 mediante un Cloudflare Worker. No hay ningún paso de compilación. La razón es importante. Significa que el agente puede leer y modificar los archivos que publicarías realmente, y que el mismo artefacto funciona en el iframe, en un teléfono envuelto con Capacitor, en Steam envuelto con Tauri y dentro de Discord como Embedded Activity. Un sistema de archivos, seis destinos de distribución.</p>
<p>Todos los juegos que generamos deben exponer dos funciones en <code>window</code>. <code>getGameState()</code> devuelve un objeto sencillo que describe el juego en ejecución (posición del jugador, puntuación, vidas, enemigos y temporizadores). <code>setGameState(patch)</code> aplica una actualización parcial al juego en vivo. Esa pequeña API es el contrato que permite al agente inspeccionar y modificar un juego en ejecución sin recargarlo. Volveremos al motivo en la sección 6.</p>
<h2 id="_3-el-orquestador-donde-reside-el-motor-propiamente-dicho" tabindex="-1">3. El orquestador, donde reside el motor propiamente dicho <a class="header-anchor" href="#_3-el-orquestador-donde-reside-el-motor-propiamente-dicho" aria-label="Permalink to &quot;3. El orquestador, donde reside el motor propiamente dicho&quot;"></a></h2>
<img src="/img/blog/engine-anatomy/cinevva-engine-orchestrator.png" alt="Un diagrama del orquestador de Cinevva. Un nodo central con la etiqueta «Orquestador (LLM)» está conectado a ocho nodos de herramientas dispuestos a su alrededor: list_game_files, read_files, edit_files, write_files, generate_image (Flux), generate_skybox (Blockade), generate_music (ElevenLabs) y rig_model (Tripo). Una línea de puntos conecta el orquestador con un nodo «Iframe del juego» etiquetado como «capturas de pantalla + consola»." style="width:100%;border-radius:8px;margin:1.5rem 0" />
<p>Lo que no entienden quienes llaman a esto «una capa sobre una IA» es que la IA no escribe código tanto como dirige una pequeña orquesta. El orquestador es un bucle de llamadas a herramientas que se ejecuta sobre un modelo de vanguardia, con un prompt de sistema de unas mil líneas y una interfaz tipada de 26 funciones. Las definiciones de las herramientas son el motor. El modelo es el director.</p>
<p>Las 26 herramientas se dividen en cinco familias. Las herramientas del sistema de archivos (<code>list_game_files</code>, <code>read_files</code>, <code>search_game_file</code>, <code>edit_files</code>, <code>write_files</code>, <code>delete_files</code>, <code>rename_files</code>) permiten al agente tratar tu juego como cualquier otro repositorio de código. Las herramientas de proyecto (<code>create_new_game</code>, <code>list_games</code>, <code>open_game</code>, <code>ask_user</code>, <code>game_ready</code>) gestionan el ciclo de vida de un proyecto y la devolución del control a la persona. Las herramientas generativas (<code>generate_image</code>, <code>generate_skybox</code>, <code>generate_music</code>, <code>generate_sfx</code>, <code>rig_model</code>, <code>apply_animation</code>, <code>list_animations</code>, <code>list_skybox_styles</code>) llaman a modelos especializados que veremos a continuación. Las herramientas de conocimiento (<code>search_fonts</code>, <code>list_library_docs</code>, <code>search_library_docs</code>, <code>list_generations</code>) proporcionan al agente fuentes fiables e indexadas, en lugar de API alucinadas. Y las herramientas de ejecución (<code>read_console_logs</code>, <code>execute_js</code>) permiten al agente ver y manipular el juego en vivo.</p>
<p>Un primer turno típico es más o menos así. El usuario escribe «Crea un shooter espacial de neón». El modelo emite una llamada a <code>write_files</code> con un <code>GDD.md</code> que describe el diseño y después vuelve a llamar a <code>write_files</code> con <code>index.html</code>, <code>game.js</code> y <code>style.css</code>. Llama a <code>generate_music</code> con <code>prompt=&quot;shooter espacial synthwave, 120 BPM, línea de bajo enérgica&quot;</code>, lo que inicia un trabajo en ElevenLabs Music y devuelve una URL de MP3 dentro de R2. Llama a <code>generate_skybox</code> con un estilo del modelo 3 de Blockade Labs para crear el campo estelar. Llama a <code>game_ready(title, message)</code> para cambiar el iframe a la nueva versión y, por último, a <code>read_console_logs</code> para confirmar que el juego se inició sin errores. Si detecta una traza de pila, vuelve a <code>edit_files</code> y la corrige antes de que el usuario tenga que informar de nada.</p>
<p>La propiedad interesante de este diseño es que el prompt del sistema y los esquemas de las herramientas son lo único específico del producto. Si cambias el modelo, todo sigue funcionando. Durante el último año hemos migrado entre tres modelos de vanguardia sin modificar la interfaz, porque la interfaz es nuestra.</p>
<h2 id="_4-la-parte-de-los-recursos-distribucion-entre-modelos" tabindex="-1">4. La parte de los recursos: distribución entre modelos <a class="header-anchor" href="#_4-la-parte-de-los-recursos-distribucion-entre-modelos" aria-label="Permalink to &quot;4. La parte de los recursos: distribución entre modelos&quot;"></a></h2>
<img src="/img/blog/engine-anatomy/cinevva-engine-assets.png" alt="Un panel de generación de recursos dividido en tres secciones. El panel izquierdo es un generador de música con el prompt «shooter espacial synthwave, 120 BPM, línea de bajo enérgica», un control de duración de 60 segundos y un botón Generar, además de una tarjeta con una forma de onda en reproducción titulada «Tema de deriva entre asteroides». El panel central es un generador de skyboxes con el prompt «espacio profundo, nebulosa distante, dos lunas» y una cuadrícula de cuatro miniaturas de entornos de 360 grados. El panel derecho muestra una vista previa giratoria de un modelo 3D de una nave espacial morada low poly, con un botón «Crear rig + caminar» y un indicador de estado que dice «Creando rig... quedan 1 min 42 s»." style="width:100%;border-radius:8px;margin:1.5rem 0" />
<p>El agente no genera imágenes, música, sonido ni modelos 3D. Recurre a especialistas. La parte de recursos de Cinevva distribuye el trabajo entre los mejores modelos de su clase, conectados de modo que la salida de uno sea una entrada válida para el siguiente.</p>
<p>Para imágenes y sprites, <code>generate_image</code> llama a Flux Pro 1.1 con una anchura y una altura que siempre son múltiplos de 32, y un formato de salida que cambia a PNG cuando el prompt solicita transparencia. Para canciones completas, el agente llama a ElevenLabs Music con un prompt estilístico y una duración en segundos. Para efectos puntuales, ElevenLabs SFX produce en entre cinco y quince segundos un clip a partir de texto como «disparo de pistola láser, bláster de ciencia ficción». Para entornos de 360 grados, <code>generate_skybox</code> llama a Blockade Labs con uno de unos noventa estilos y utiliza de forma predeterminada Digital Painting del modelo 3. Para personajes 3D, <code>rig_model</code> envía un GLB a Tripo para añadirle esqueleto y rig como criatura bípeda, cuadrúpeda, hexápoda, octópoda, serpentina o acuática; después, <code>apply_animation</code> reproduce cualquiera de los quince preajustes (reposo, caminar, correr, saltar, escalar, bucear, atacar con arma blanca, disparar, recibir daño, caer y girar, además de las marchas para criaturas no bípedas).</p>
<p>Cada una de estas operaciones es un trabajo, no una llamada síncrona. Tardan desde segundos hasta minutos. El orquestador las inicia, devuelve inmediatamente un <code>jobId</code> y un canal independiente incorpora el resultado a la conversación cuando el recurso está listo. Esto cambia por completo la experiencia. El agente puede seguir creando la lógica del juego mientras un modelo 3D termina de prepararse en segundo plano. El usuario nunca tiene que esperar por una única ruta crítica.</p>
<p>Todos los artefactos terminan en el mismo lugar: R2, detrás de <code>cdn.cinevva.com</code>, accesibles mediante URL normales. Esto significa que la siguiente llamada del agente a <code>write_files</code> puede limitarse a insertar <code>&lt;audio src=&quot;https://cdn.cinevva.com/audio/abc.mp3&quot;&gt;</code> y el juego funciona sin más. Sin SDK, sin empaquetador de recursos y sin manifiesto.</p>
<h2 id="_5-busqueda-de-recursos-entre-once-proveedores" tabindex="-1">5. Búsqueda de recursos entre once proveedores <a class="header-anchor" href="#_5-busqueda-de-recursos-entre-once-proveedores" aria-label="Permalink to &quot;5. Búsqueda de recursos entre once proveedores&quot;"></a></h2>
<img src="/img/blog/engine-anatomy/cinevva-engine-asset-search.png" alt="La página de búsqueda de recursos de Cinevva en modo oscuro. Una barra de búsqueda en la parte superior contiene la consulta «roca de asteroide» y una fila de filtros por proveedor muestra Todos, PolyHaven, Sketchfab, Kenney, Quaternius, AmbientCG, OpenGameArt, Freesound, Smithsonian, Synty y Jamendo, con Sketchfab resaltado. Debajo aparece una cuadrícula de cuatro columnas con miniaturas de modelos de asteroides; cada tarjeta muestra la insignia de su proveedor, una etiqueta de licencia CC0 o CC-BY y un botón «Usar en el juego». Un pequeño texto en la esquina superior derecha muestra una burbuja de chat que dice «ChatGPT: una de las mejores herramientas gratuitas de recursos para desarrolladores de juegos»." style="width:100%;border-radius:8px;margin:1.5rem 0" />
<p>La generación es excelente cuando necesitas algo específico. La búsqueda es más rápida cuando ya existe lo que necesitas. La <a href="/es/assets.html">Biblioteca de recursos</a> es una búsqueda federada entre once proveedores de recursos gratuitos y con licencia, cuyos resultados se presentan en un único feed ordenado por relevancia.</p>
<p>El registro de proveedores reside en el worker y ejecuta cada consulta en paralelo en PolyHaven, Sketchfab, Freesound, Kenney, AmbientCG, Quaternius, OpenGameArt, la colección 3D del Smithsonian, TurboSquid, Synty y Jamendo. Cada proveedor implementa una interfaz común (<code>search</code>, <code>getMetadata</code>, <code>isBrowsable</code>, <code>getSupportedTypes</code>), por lo que añadir uno nuevo solo requiere un archivo TypeScript. La capa de agregación gestiona la paginación mediante cursores entre proveedores que paginan de forma distinta, elimina licencias duplicadas, normaliza los tipos de recursos en una taxonomía común (modelo, textura, audio, HDRI y sprite) y etiqueta cada recurso con su licencia para que el agente nunca elija algo que no pueda redistribuir.</p>
<p>Cuando ChatGPT recomendó esta herramienta el trimestre pasado como uno de los mejores buscadores gratuitos de recursos para desarrolladores de juegos, fuimos a leer la recomendación. Acertaba en lo importante. La cuestión no es que tengamos una barra de búsqueda para una única biblioteca. La cuestión es que un desarrollador independiente que busca «textura de muro de piedra» obtiene, con una sola consulta y metadatos de licencia coherentes, resultados de PolyHaven y AmbientCG junto a la versión estilizada de Kenney y una opción de fotogrametría del Smithsonian. El agente puede consultar el mismo endpoint y elegir recursos del mismo modo que lo haría una persona.</p>
<p>Esta es la parte del motor que suele infravalorarse. La mayoría de las demostraciones de IA para juegos lo generan todo desde cero y terminan con un aspecto uniforme, brillante y ligeramente inquietante. Los juegos interesantes de Cinevva combinan recursos generados con fotogrametría CC0 real del Smithsonian y un árbol low poly hecho a mano por Quaternius. El orquestador puede hacerlo en un solo turno.</p>
<h2 id="_6-el-agente-juega-al-juego" tabindex="-1">6. El agente juega al juego <a class="header-anchor" href="#_6-el-agente-juega-al-juego" aria-label="Permalink to &quot;6. El agente juega al juego&quot;"></a></h2>
<img src="/img/blog/engine-anatomy/cinevva-engine-debug.png" alt="Una vista de depuración en vivo. A la izquierda, un shooter espacial de neón en ejecución que muestra la nave del jugador esquivando asteroides, con una PUNTUACIÓN de 4820 y 2 vidas restantes. A la derecha, dos paneles apilados: un panel execute_js que muestra la llamada JSON.stringify(getGameState()) y un objeto JSON devuelto con la posición, velocidad, salud, puntuación y vidas del jugador, además del número de asteroides; y un panel read_console_logs que muestra las líneas de registro más recientes, entre ellas la aparición de un asteroide, la recogida de un potenciador, una advertencia de carga de textura y una lectura de 58 FPS." style="width:100%;border-radius:8px;margin:1.5rem 0" />
<p>Esta es la parte que más sorprende a la mayoría de los ingenieros cuando se la mostramos. El agente no se limita a escribir código en archivos. Ejecuta el juego en un iframe aislado, lee su consola, toma capturas de pantalla por capas para distinguir la interfaz de usuario de la escena 3D y ejecuta JavaScript dentro del entorno en vivo para inspeccionar o modificar el estado.
<code>read_console_logs</code> devuelve las últimas cincuenta líneas de <code>console.log</code>, <code>console.warn</code>, <code>console.error</code> y las excepciones no capturadas del iframe. Después de cada llamada a <code>game_ready</code>, el prompt del sistema exige que el agente llame a <code>read_console_logs</code> y corrija cualquier error antes de entregar el resultado al usuario. Esa única regla elimina la mayoría de los fallos del tipo «la IA dijo que había terminado, pero la pantalla está en negro» que sufren otras herramientas.</p>
<p><code>execute_js</code> es la herramienta más potente. Ejecuta JavaScript arbitrario dentro del ámbito global del juego. Como todos los juegos deben implementar <code>getGameState</code> y <code>setGameState</code>, el agente puede ejecutar <code>JSON.stringify(getGameState())</code> para leer el estado completo del juego en ejecución y después usar <code>setGameState({player: {x: 500, y: 100}})</code> para teletransportar al jugador, <code>setGameState({lives: 99})</code> para concederle invencibilidad o <code>setGameState({level: 3})</code> para saltar a un nivel posterior. También puede inspeccionar capas de más bajo nivel, por ejemplo con <code>scene.children.map(c =&gt; c.type)</code> para examinar el grafo de escena de Three.js o con <code>document.querySelectorAll('canvas').length</code> para confirmar que el renderizador se ha montado.</p>
<p>Es fácil ver por qué esto importa. Cuando un usuario dice «el jugador se queda atascado en la pared del segundo nivel», el agente no tiene que adivinar. Abre el segundo nivel, ejecuta <code>getGameState()</code>, examina los datos de colisión, aplica un parche con <code>execute_js</code> para probar una solución y solo entonces escribe la corrección en el disco. Depura como lo harías tú. Tratamos el iframe como un igual, no como un objetivo.</p>
<h2 id="_7-documentacion-de-bibliotecas-la-aburrida-fuente-de-la-verdad" tabindex="-1">7. Documentación de bibliotecas: la aburrida fuente de la verdad <a class="header-anchor" href="#_7-documentacion-de-bibliotecas-la-aburrida-fuente-de-la-verdad" aria-label="Permalink to &quot;7. Documentación de bibliotecas: la aburrida fuente de la verdad&quot;"></a></h2>
<p>Indexamos la documentación oficial de las bibliotecas que realmente usan los juegos (Three.js, Tone.js, Cannon y cada vez más) en un repositorio JSON estructurado y con función de búsqueda. El agente recurre a <code>search_library_docs(&quot;threejs&quot;, &quot;Mesh&quot;)</code> antes de acudir a la web abierta. Es más rápido, está versionado y nunca se inventa un método cuyo nombre cambió hace dos versiones menores.</p>
<p>No es algo espectacular. Es la diferencia entre una IA que produce código funcional y una IA que produce código de apariencia convincente que falla en la línea cuarenta. Gran parte de la calidad visible de los juegos creados con Cinevva procede de esta única decisión.</p>
<h2 id="_8-de-jugable-a-descubrible-reels-y-escaparate" tabindex="-1">8. De jugable a descubrible: reels y escaparate <a class="header-anchor" href="#_8-de-jugable-a-descubrible-reels-y-escaparate" aria-label="Permalink to &quot;8. De jugable a descubrible: reels y escaparate&quot;"></a></h2>
<img src="/img/blog/engine-anatomy/cinevva-engine-reels.png" alt="Un escaparate de reels breves de partidas. En el centro, una tarjeta con forma de teléfono reproduce un vídeo vertical de un shooter espacial de neón en pleno combate, con iconos de interfaz social apilados a la derecha (un corazón con 14 mil, un globo de chat con 3,2 mil, una flecha para compartir con 1,8 mil y un botón «Jugar ahora»). La etiqueta del reel en la parte inferior dice «Asteroid Drift • de @indiedev • 3,1 M de visualizaciones». A la izquierda, un pequeño fragmento de chat titulado «Del chat del creador» muestra el mensaje del asistente «El juego ya está disponible. El reel se ha publicado automáticamente en tu escaparate». A la derecha, un panel del escaparate enumera tres juegos en tendencia: Asteroid Drift, Roadhawk Runner y Birb Clicker, cada uno con un número de visualizaciones y una insignia «En tendencia»." style="width:100%;border-radius:8px;margin:1.5rem 0" />
<p>Un juego al que nadie juega es un pasatiempo privado. El problema más difícil aún sin resolver del desarrollo independiente ya no es crear juegos. Es distribuirlos. Por eso el motor no se detiene en «jugable». Se detiene en «delante de los jugadores».</p>
<p>Cada proyecto de Cinevva tiene una URL estable para compartir, como <code>play.cinevva.com/{game-id}</code>, que abre la última versión del juego en un iframe a página completa con una pequeña superposición para indicar «Me gusta» y compartir. Cuando el agente llama a <code>game_ready</code>, no se limita a activar la vista previa del IDE. También ofrece publicar un reel de 15 segundos de la partida en el <a href="/es/play.html">escaparate de Cinevva</a>. El reel es una grabación real del juego en acción, capturada directamente desde el iframe (incluimos un pequeño script de grabación que el agente inyecta en el entorno de ejecución del juego), de modo que lo que el espectador ve al desplazarse es una partida real, no un montaje de marketing.</p>
<p>Eso cambia el ciclo en el que vive un desarrollador. El ciclo anterior era programar, compilar, empaquetar, subir, escribir una página de Steam, pelearse con un algoritmo y mirar un contador de listas de deseos. El nuevo ciclo consiste en escribir una frase, ver cómo el agente construye el juego, pulsar «Publicar» y ver cómo aparece en el mismo feed vertical junto a todos los demás. El descubrimiento ocurre en el mismo producto en el que ocurre la creación, con la misma URL y el mismo inicio de sesión.</p>
<p>Para quienes forman parte de la comunidad de desarrollo, esta es la parte que conviene examinar. La distribución siempre ha sido la ventaja competitiva que los motores de juego no incluían. Unity proporciona un editor; tú publicas el juego en Steam. Unreal proporciona un editor; tú publicas en Epic Store. Cinevva ofrece ambas mitades. El motor y el escaparate se comunican mediante el mismo orquestador que creó el juego.</p>
<h2 id="_9-mejores-juegos-el-volante-de-inercia-del-descubrimiento" tabindex="-1">9. Mejores juegos: el volante de inercia del descubrimiento <a class="header-anchor" href="#_9-mejores-juegos-el-volante-de-inercia-del-descubrimiento" aria-label="Permalink to &quot;9. Mejores juegos: el volante de inercia del descubrimiento&quot;"></a></h2>
<img src="/img/blog/engine-anatomy/cinevva-engine-charts.png" alt="La clasificación de mejores juegos de Cinevva. En la parte superior hay tres pestañas: En tendencia, Recientes y Mejores, con Mejores seleccionada. Debajo aparece un podio con tres juegos destacados: en el número uno, The Breaker Belt con 42,1 mil partidas; en el número dos, Roadhawk Runner con 27,7 mil partidas; y en el número tres, Asteroid Drift con 37,1 mil partidas. Bajo el podio hay una cuadrícula más densa de seis tarjetas de juegos más pequeñas, entre ellas Pixel Platformer, Zombie Shooter, Fruit Ninja Clone, Tower Defense, Card Battler y Zombie Builder, cada una con miniatura, identificador del creador y número de partidas." style="width:100%;border-radius:8px;margin:1.5rem 0" />
<p>El feed de reels es una mitad del volante de inercia. La <a href="/es/charts.html">clasificación de mejores juegos</a> es la otra. Clasifica los juegos por tendencias, novedades y mejores de todos los tiempos, ponderados según la tasa de finalización (si el jugador terminó una sesión) en lugar de por los clics brutos. La finalización es más difícil de manipular que las instalaciones. Un juego que mantiene la atención durante sesenta segundos supera a uno que se abre y se cierra de inmediato.</p>
<p>Cada señal vuelve a alimentar el siguiente turno del orquestador. Cuando el agente dice «añadamos un potenciador», no está recurriendo a una biblioteca fija de patrones. Recurre a un modelo que ha observado qué mecánicas están consiguiendo retener jugadores en Cinevva este mes. El volante de inercia no es una gráfica al final de la página. Es la señal de entrenamiento de todo el motor.</p>
<p>Para los inversores, este es el foso de datos. No solo tenemos juegos generados. Tenemos juegos generados con métricas reales de interacción en cada sesión, vinculadas a los prompts que los produjeron, a los recursos que eligió el agente y a los jugadores a quienes les gustaron. Cada ciclo refuerza el siguiente.</p>
<h2 id="_10-el-motor-se-convierte-en-un-juego" tabindex="-1">10. El motor se convierte en un juego <a class="header-anchor" href="#_10-el-motor-se-convierte-en-un-juego" aria-label="Permalink to &quot;10. El motor se convierte en un juego&quot;"></a></h2>
<p>Esta es la parte que llevo meses insinuando en redes sociales. Todo lo descrito en las secciones 1 a 9 corresponde a un sistema que crea juegos. Lo más difícil de explicar, hasta que se ve, es lo que ocurre cuando el propio sistema se convierte en un lugar.</p>
<p>Crear juegos es un trabajo difícil, incluso con todo lo que hemos desarrollado. Si nunca has creado uno, de repente eres responsable de la trama, los personajes, el mundo, las mecánicas, quién hace qué y cuándo, el comportamiento de la luz, la superposición de los efectos especiales, la música, los efectos de sonido y los movimientos de cámara. Es mucho. Y, además, quieres que el resultado parezca tuyo, no una plantilla escupida por la herramienta de otra persona. El prompt y el orquestador se encargan de la mayor parte del trabajo mecánico. Lo que no pueden hacer por sí solos es ofrecer a tu creación terminada un escenario en el que mostrarse mientras otras personas la contemplan.</p>
<p>Así que construimos el escenario. Durante la mayor parte de este año, <a href="/es/about.html">Oleg</a> y el equipo del motor han ido publicando su trabajo en una <a href="/es/blog/2026-02-25-open-world-browser-series-guide.html">serie de 14 partes</a> sobre cómo llevar un mundo abierto al navegador. Terreno esculpido que puedes modificar en tiempo real. Biomas que se pintan automáticamente con roca o hierba según la pendiente y la altitud. 80 000 briznas de hierba que se mecen con el viento sobre terreno generado mediante cómputo. Un personaje que camina, corre, salta y planea tanto sobre terreno de mapas de altura como sobre terreno volumétrico con el mismo sistema de movimiento. Nada de esto era una demostración técnica hecha porque sí. Era la base de todo esto.</p>
<p>Hoy, el mundo abierto ya está disponible en una versión preliminar. Eliges un avatar y entras. Tus juegos publicados aparecen a tu alrededor como espacios que puedes visitar, igual que ahora aparecen en los <a href="/es/play.html">reels del escaparate</a> y en la <a href="/es/charts.html">clasificación de mejores juegos</a>, salvo que llegas caminando en vez de deslizando el dedo. Puedes entrar en el juego de un desconocido desde el mundo sin salir de él. Puedes colocarte junto a la persona que creó lo que acabas de jugar y contarle qué añadirías a continuación. Puedes esculpir un fragmento de terreno con alguien a quien acabas de conocer y convertirlo en la semilla de un nuevo proyecto. El descubrimiento deja de ser un feed. Se convierte en un paseo.</p>
<p>Nuestro motor siempre ha sido un motor de juego en el sentido técnico. Hoy también se convierte en uno en el sentido literal. Lo que crea tu juego ahora es un juego en sí mismo, y el mismo orquestador de la sección 3, los mismos canales de recursos de la sección 4, el mismo contrato <code>getGameState</code> de la sección 6, los mismos reels de la sección 8 y la misma clasificación de la sección 9 se integran en el único lugar por el que caminan tus jugadores. La frontera entre crear y jugar siempre fue artificial. Ahora ha desaparecido.</p>
<h2 id="lo-que-creemos-haber-hecho-bien" tabindex="-1">Lo que creemos haber hecho bien <a class="header-anchor" href="#lo-que-creemos-haber-hecho-bien" aria-label="Permalink to &quot;Lo que creemos haber hecho bien&quot;"></a></h2>
<p>Lo primero que hicimos bien fue tratar el prompt como un recurso de interfaz en lugar de como un producto. El producto es el orquestador, el conjunto de herramientas, los canales de recursos y el escaparate. El prompt es la forma más sencilla posible de introducir a un usuario en el sistema.</p>
<p>Lo segundo fue insistir en un sistema de archivos plano y nativo del navegador, sin ningún paso de compilación. Por eso un juego de Cinevva puede distribuirse en móviles, ordenadores, Steam y Discord desde una única fuente de verdad. Por eso el agente puede leer lo que ha escrito.</p>
<p>Lo tercero fue el contrato por el que todos los juegos generados implementan <code>getGameState</code> y <code>setGameState</code>. Esa única línea del prompt del sistema es lo que hace que el agente parezca un colaborador en lugar de un generador de código. El agente puede jugar, y un sistema que puede jugar también puede depurar.</p>
<p>Lo cuarto fue integrar el escaparate en el mismo ciclo que el motor. No vamos a ganar por la calidad bruta del modelo. Llevar dos meses de ventaja a un generador de pesos abiertos no constituye ninguna ventaja defendible. Ganamos cuando el mismo agente que crea tu juego también lo publica, lo mide y aprende de cómo lo jugaron desconocidos.</p>
<p>Si quieres ver toda la máquina en movimiento, el prompt de la página de inicio sigue siendo la puerta de entrada. Escribe una frase. Observa lo que ocurre detrás. Después vuelve aquí y dinos sobre qué parte del motor deberíamos escribir a continuación.</p>
]]></content:encoded>
            <enclosure url="https://app.cinevva.com/img/blog/engine-anatomy/cinevva-engine-prompt.png" length="0" type="image/png"/>
        </item>
        <item>
            <title><![CDATA[Construir un mundo abierto en el navegador, parte 16: Una estructura para un mundo que no deja de crecer]]></title>
            <link>https://app.cinevva.com/es/blog/2026-04-28-open-world-browser-part-16-structure-and-authoring</link>
            <guid>https://app.cinevva.com/es/blog/2026-04-28-open-world-browser-part-16-structure-and-authoring</guid>
            <pubDate>Tue, 28 Apr 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[El spike 33 dividió un monolito de 6285 líneas en módulos y reveló tres errores ocultos relacionados con el orden de inicialización. El spike 34 aprovechó esa estructura para añadir más de 100 objetos colocables sin inflar nada.]]></description>
            <content:encoded><![CDATA[<h1 id="construir-un-mundo-abierto-en-el-navegador-parte-16-una-estructura-para-un-mundo-que-no-deja-de-crecer" tabindex="-1">Construir un mundo abierto en el navegador, parte 16: Una estructura para un mundo que no deja de crecer <a class="header-anchor" href="#construir-un-mundo-abierto-en-el-navegador-parte-16-una-estructura-para-un-mundo-que-no-deja-de-crecer" aria-label="Permalink to &quot;Construir un mundo abierto en el navegador, parte 16: Una estructura para un mundo que no deja de crecer&quot;"></a></h1>
<p><em>Por <a href="/es/about.html">Oleg Sidorkin</a>, CTO y cofundador de Cinevva</em></p>
<p>¿Acabas de llegar? Consulta la <a href="/es/blog/2026-02-25-open-world-browser-series-guide.html">guía de la serie</a>. Explica qué es un spike y enlaza todas las partes.</p>
<p>Todos los spikes desde la <a href="/es/blog/2026-04-13-open-world-browser-part-13-terrain-sculpting.html">parte 13</a> habían seguido la misma receta: copiar el monolito anterior y añadir una función. Al terminar el <a href="/es/blog/2026-04-13-open-world-browser-part-15-multiplayer-and-water.html">spike 32</a>, ese monolito era un <code>index.html</code> de 6285 líneas dentro de un único <code>&lt;script type=&quot;module&quot;&gt;</code>. Las búsquedas de código producían demasiado ruido, encontrar dónde añadir una función llevaba más tiempo que escribirla y cualquier cambio arquitectónico afectaba a un archivo demasiado grande para abarcar mentalmente el diff. Antes de añadir otra función, pusimos la estructura en orden.</p>
<h2 id="dividir-el-monolito-sin-cambiar-el-comportamiento" tabindex="-1">Dividir el monolito sin cambiar el comportamiento <a class="header-anchor" href="#dividir-el-monolito-sin-cambiar-el-comportamiento" aria-label="Permalink to &quot;Dividir el monolito sin cambiar el comportamiento&quot;"></a></h2>
<div style="position:relative;padding-bottom:56.25%;height:0;overflow:hidden;border-radius:8px;margin:1.5rem 0;border:1px solid rgba(255,255,255,0.12)">
<iframe src="/es/spikes/33-code-structure/" title="Refactorización de la estructura del código del spike 33" style="position:absolute;top:0;left:0;width:100%;height:100%;border:0;background:#000" loading="lazy" allowfullscreen></iframe>
</div>
<p><a href="/es/spikes/33-code-structure/" target="_blank">Abrir el spike 33 en una pestaña nueva ↗</a> · <a href="/es/blog/spike-source?spike=33-code-structure">Ver el código fuente</a></p>
<p>La restricción era estricta: cada división debía ser una refactorización pura, no un rediseño. El monolito se convirtió en 19 archivos <code>.mjs</code> más un shell principal de 151 líneas. Módulos de nivel superior para la escena, el agua, la hierba, el personaje, la física, el multijugador y la interfaz; un <code>wgsl.mjs</code> que contiene todas las cadenas de código fuente WGSL como única fuente de verdad para la GPU; y un subárbol <code>terrain/</code> para el mapa de alturas, el SDF, los chunks, los wrappers de búferes de GPU, el pincel, el LOD y la persistencia. El total quedó en 6555 líneas, básicamente el monolito más el código repetitivo de las importaciones. Ningún cambio neto de volumen y un gran cambio en facilidad de navegación.</p>
<p>Entonces la página cargó con la pantalla en negro. Dos mensajes de error, dos causas raíz sin relación entre sí. El primero era una queja de WebGPU sobre un binding de búfer de cero bytes. En el monolito, el búfer del pincel SDF se asignaba de forma diferida cuando aparecía el primer chunk de marching cubes, y la fábrica de grupos de bindings se ejecutaba después, una vez que el búfer ya existía. Separar <code>terrain/gpu.mjs</code> de <code>terrain/brush.mjs</code> cambió el orden de evaluación de los módulos, así que la fábrica pasó a ejecutarse primero e intentó enlazar un marcador <code>null</code>. La solución fue posponer la creación del grupo de bindings hasta el primer dispatch mediante un helper <code>getOrCreateBindGroup(chunk)</code>. El patrón de «crearlo todo por adelantado» era un artefacto de la ruta de inicialización única del monolito.</p>
<p>El segundo mensaje era una alarmante advertencia sobre un esqueleto FBX que resultó ser una pista falsa. Se mostraba desde el spike 25 y era inofensiva. El personaje solo faltaba porque el primer error se propagaba: cada dispatch de cómputo lanzaba una excepción, el mapa de alturas nunca se escribía, las muestras de altura devolvían 0 y el personaje aparecía en el origen y caía a través del mundo. Al arreglar el búfer, el personaje se animaba correctamente, con advertencia incluida.</p>
<p>Esa es la verdadera lección de la refactorización. El monolito ocultaba todas las relaciones del tipo «X debe existir antes de construir Y» dentro del orden de arriba abajo del script. La modularización alteró ese orden y sacó a la luz otros tres errores latentes de ordenación: la dispersión de hierba antes de subir el mapa de alturas, la adición del plano de agua antes de que terminara de decodificarse el mapa de entorno y la carga de la persistencia después del primer fotograma. Los tres se arreglaron con una sola línea y ninguno se habría detectado sin la división.</p>
<h2 id="cien-objetos-sin-hacer-crecer-nada" tabindex="-1">Cien objetos sin hacer crecer nada <a class="header-anchor" href="#cien-objetos-sin-hacer-crecer-nada" aria-label="Permalink to &quot;Cien objetos sin hacer crecer nada&quot;"></a></h2>
<div style="position:relative;padding-bottom:56.25%;height:0;overflow:hidden;border-radius:8px;margin:1.5rem 0;border:1px solid rgba(255,255,255,0.12)">
<iframe src="/es/spikes/34-world-authoring/" title="Creación del mundo del spike 34" style="position:absolute;top:0;left:0;width:100%;height:100%;border:0;background:#000" loading="lazy" allowfullscreen></iframe>
</div>
<p><a href="/es/spikes/34-world-authoring/" target="_blank">Abrir el spike 34 en una pestaña nueva ↗</a> · <a href="/es/blog/spike-source?spike=34-world-authoring">Ver el código fuente</a></p>
<p>El spike 34 fue la prueba para comprobar si la estructura había valido la pena. El objetivo era crear una paleta en primera persona para colocar árboles, rocas, arbustos, setas y caminos procedentes de un paquete de modelos CC0, con alineación adaptada al terreno, persistencia, sincronización multijugador y colliders físicos, todo ello sin soltar los controles. Cada línea de código nueva se añadió en cinco archivos nuevos dentro de <code>src/props/</code>, y ningún módulo existente creció más de diez líneas de conexión.</p>
<p>El recorrido de los recursos dio un rodeo que merece la pena documentar, porque es el tipo de cosa que consume un día entero. Empezamos con el paquete Ultimate Nature de Quaternius, una biblioteca FBX sin texturas incrustadas. Los materiales FBX venían como <code>MeshPhong</code> sin mapa, así que conectamos una tabla manual de nombres de materiales a archivos PNG, convertimos Phong a Standard y configuramos los espacios de color a mano. Alrededor del 30 % de los materiales no tenía un PNG correspondiente y varios nombres eran ambiguos entre árboles similares. Un segundo paquete FBX presentaba el mismo problema. La solución no era crear más tablas de correspondencias, sino usar un paquete mejor preparado: Stylized Nature MegaKit de Quaternius incluye 116 glTF completos con materiales PBR incrustados y normales precalculadas. Cambiar <code>FBXLoader</code> por <code>GLTFLoader</code> eliminó el escalado de centímetros a metros, la tabla de texturas y la conversión de Phong, y redujo <code>library.mjs</code> en unas 80 líneas. La conclusión: glTF con PBR es el pipeline adecuado para los paquetes CC0 que lo ofrecen, mientras que FBX con asignación manual de texturas requería el doble de código para obtener la mitad de calidad.</p>
<p>La ruta de glTF también trajo algunos problemas delicados. La paleta renderiza 116 miniaturas, y <code>canvas.toDataURL()</code> de WebGPU devuelve una imagen vacía para una superficie <code>GPUCanvasContext</code>, por lo que las miniaturas se renderizan en un <code>RenderTarget</code>, se leen con <code>readRenderTargetPixelsAsync</code> y se copian en un canvas 2D, teniendo en cuenta la alineación de filas de 256 bytes de WebGPU. Las previsualizaciones fantasma clonan cada material para teñirlo de verde, lo que fallaba en las mallas cuyo <code>material</code> era un array; se corrigió con una rama <code>Array.isArray</code>. Además, los mapas de normales de 16 bits, que ocupaban unos 200 MB, se redujeron una sola vez con <code>mogrify -depth 8</code> hasta unos 32 MB, sin diferencias visuales, ya que los navegadores reducen su resolución durante la carga de todos modos.</p>
<h2 id="cuando-la-geometria-renderizada-solo-existe-en-la-gpu" tabindex="-1">Cuando la geometría renderizada solo existe en la GPU <a class="header-anchor" href="#cuando-la-geometria-renderizada-solo-existe-en-la-gpu" aria-label="Permalink to &quot;Cuando la geometría renderizada solo existe en la GPU&quot;"></a></h2>
<p>El error más instructivo hacía que la previsualización fantasma saltara en incrementos de entre 1 y 2 metros al mover el cursor. Las mallas del terreno almacenan las posiciones de los vértices en un <code>StorageBufferAttribute</code> porque el pipeline de cómputo las escribe directamente en la GPU, de modo que el <code>Raycaster</code> de CPU de three.js no puede verlas y no devuelve nada. La alternativa era un ray marching aproximado con pasos de 1,5 m contra el mapa de alturas analítico, y ese intervalo fijo era la cuadrícula que veía el usuario. Lo sustituimos por un recorrido adaptativo: pasos de 2,5 m cuando el rayo está muy por encima de la superficie, reducción a 0,4 m al encontrarse a menos de 5 m y, después, 14 bisecciones cuando cambia el signo de <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.869ex;" xmlns="http://www.w3.org/2000/svg" width="16.358ex" height="2.566ex" role="img" focusable="false" viewBox="0 -750 7230.4 1134.3" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mo"><path data-c="28" d="M94 250Q94 319 104 381T127 488T164 576T202 643T244 695T277 729T302 750H315H319Q333 750 333 741Q333 738 316 720T275 667T226 581T184 443T167 250T184 58T225 -81T274 -167T316 -220T333 -241Q333 -250 318 -250H315H302L274 -226Q180 -141 137 -14T94 250Z" style="stroke-width: 3;"/></g><g data-mml-node="msub" transform="translate(389,0)"><g data-mml-node="mtext"><path data-c="72" d="M36 46H50Q89 46 97 60V68Q97 77 97 91T98 122T98 161T98 203Q98 234 98 269T98 328L97 351Q94 370 83 376T38 385H20V408Q20 431 22 431L32 432Q42 433 60 434T96 436Q112 437 131 438T160 441T171 442H174V373Q213 441 271 441H277Q322 441 343 419T364 373Q364 352 351 337T313 322Q288 322 276 338T263 372Q263 381 265 388T270 400T273 405Q271 407 250 401Q234 393 226 386Q179 341 179 207V154Q179 141 179 127T179 101T180 81T180 66V61Q181 59 183 57T188 54T193 51T200 49T207 48T216 47T225 47T235 46T245 46H276V0H267Q249 3 140 3Q37 3 28 0H20V46H36Z" style="stroke-width: 3;"/><path data-c="61" d="M137 305T115 305T78 320T63 359Q63 394 97 421T218 448Q291 448 336 416T396 340Q401 326 401 309T402 194V124Q402 76 407 58T428 40Q443 40 448 56T453 109V145H493V106Q492 66 490 59Q481 29 455 12T400 -6T353 12T329 54V58L327 55Q325 52 322 49T314 40T302 29T287 17T269 6T247 -2T221 -8T190 -11Q130 -11 82 20T34 107Q34 128 41 147T68 188T116 225T194 253T304 268H318V290Q318 324 312 340Q290 411 215 411Q197 411 181 410T156 406T148 403Q170 388 170 359Q170 334 154 320ZM126 106Q126 75 150 51T209 26Q247 26 276 49T315 109Q317 116 318 175Q318 233 317 233Q309 233 296 232T251 223T193 203T147 166T126 106Z" transform="translate(392,0)" style="stroke-width: 3;"/><path data-c="79" d="M69 -66Q91 -66 104 -80T118 -116Q118 -134 109 -145T91 -160Q84 -163 97 -166Q104 -168 111 -168Q131 -168 148 -159T175 -138T197 -106T213 -75T225 -43L242 0L170 183Q150 233 125 297Q101 358 96 368T80 381Q79 382 78 382Q66 385 34 385H19V431H26L46 430Q65 430 88 429T122 428Q129 428 142 428T171 429T200 430T224 430L233 431H241V385H232Q183 385 185 366L286 112Q286 113 332 227L376 341V350Q376 365 366 373T348 383T334 385H331V431H337H344Q351 431 361 431T382 430T405 429T422 429Q477 429 503 431H508V385H497Q441 380 422 345Q420 343 378 235T289 9T227 -131Q180 -204 113 -204Q69 -204 44 -177T19 -116Q19 -89 35 -78T69 -66Z" transform="translate(892,0)" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(1453,-239.4) scale(0.707)"><path data-c="1D466" d="M21 287Q21 301 36 335T84 406T158 442Q199 442 224 419T250 355Q248 336 247 334Q247 331 231 288T198 191T182 105Q182 62 196 45T238 27Q261 27 281 38T312 61T339 94Q339 95 344 114T358 173T377 247Q415 397 419 404Q432 431 462 431Q475 431 483 424T494 412T496 403Q496 390 447 193T391 -23Q363 -106 294 -155T156 -205Q111 -205 77 -183T43 -117Q43 -95 50 -80T69 -58T89 -48T106 -45Q150 -45 150 -87Q150 -107 138 -122T115 -142T102 -147L99 -148Q101 -153 118 -160T152 -167H160Q177 -167 186 -165Q219 -156 247 -127T290 -65T313 -9T321 21L315 17Q309 13 296 6T270 -6Q250 -11 231 -11Q185 -11 150 11T104 82Q103 89 103 113Q103 170 138 262T173 379Q173 380 173 381Q173 390 173 393T169 400T158 404H154Q131 404 112 385T82 344T65 302T57 280Q55 278 41 278H27Q21 284 21 287Z" style="stroke-width: 3;"/></g></g><g data-mml-node="mo" transform="translate(2460.7,0)"><path data-c="2212" d="M84 237T84 250T98 270H679Q694 262 694 250T679 230H98Q84 237 84 250Z" style="stroke-width: 3;"/></g><g data-mml-node="msub" transform="translate(3460.9,0)"><g data-mml-node="mtext"><path data-c="74" d="M27 422Q80 426 109 478T141 600V615H181V431H316V385H181V241Q182 116 182 100T189 68Q203 29 238 29Q282 29 292 100Q293 108 293 146V181H333V146V134Q333 57 291 17Q264 -10 221 -10Q187 -10 162 2T124 33T105 68T98 100Q97 107 97 248V385H18V422H27Z" style="stroke-width: 3;"/><path data-c="65" d="M28 218Q28 273 48 318T98 391T163 433T229 448Q282 448 320 430T378 380T406 316T415 245Q415 238 408 231H126V216Q126 68 226 36Q246 30 270 30Q312 30 342 62Q359 79 369 104L379 128Q382 131 395 131H398Q415 131 415 121Q415 117 412 108Q393 53 349 21T250 -11Q155 -11 92 58T28 218ZM333 275Q322 403 238 411H236Q228 411 220 410T195 402T166 381T143 340T127 274V267H333V275Z" transform="translate(389,0)" style="stroke-width: 3;"/><path data-c="72" d="M36 46H50Q89 46 97 60V68Q97 77 97 91T98 122T98 161T98 203Q98 234 98 269T98 328L97 351Q94 370 83 376T38 385H20V408Q20 431 22 431L32 432Q42 433 60 434T96 436Q112 437 131 438T160 441T171 442H174V373Q213 441 271 441H277Q322 441 343 419T364 373Q364 352 351 337T313 322Q288 322 276 338T263 372Q263 381 265 388T270 400T273 405Q271 407 250 401Q234 393 226 386Q179 341 179 207V154Q179 141 179 127T179 101T180 81T180 66V61Q181 59 183 57T188 54T193 51T200 49T207 48T216 47T225 47T235 46T245 46H276V0H267Q249 3 140 3Q37 3 28 0H20V46H36Z" transform="translate(833,0)" style="stroke-width: 3;"/><path data-c="72" d="M36 46H50Q89 46 97 60V68Q97 77 97 91T98 122T98 161T98 203Q98 234 98 269T98 328L97 351Q94 370 83 376T38 385H20V408Q20 431 22 431L32 432Q42 433 60 434T96 436Q112 437 131 438T160 441T171 442H174V373Q213 441 271 441H277Q322 441 343 419T364 373Q364 352 351 337T313 322Q288 322 276 338T263 372Q263 381 265 388T270 400T273 405Q271 407 250 401Q234 393 226 386Q179 341 179 207V154Q179 141 179 127T179 101T180 81T180 66V61Q181 59 183 57T188 54T193 51T200 49T207 48T216 47T225 47T235 46T245 46H276V0H267Q249 3 140 3Q37 3 28 0H20V46H36Z" transform="translate(1225,0)" style="stroke-width: 3;"/><path data-c="61" d="M137 305T115 305T78 320T63 359Q63 394 97 421T218 448Q291 448 336 416T396 340Q401 326 401 309T402 194V124Q402 76 407 58T428 40Q443 40 448 56T453 109V145H493V106Q492 66 490 59Q481 29 455 12T400 -6T353 12T329 54V58L327 55Q325 52 322 49T314 40T302 29T287 17T269 6T247 -2T221 -8T190 -11Q130 -11 82 20T34 107Q34 128 41 147T68 188T116 225T194 253T304 268H318V290Q318 324 312 340Q290 411 215 411Q197 411 181 410T156 406T148 403Q170 388 170 359Q170 334 154 320ZM126 106Q126 75 150 51T209 26Q247 26 276 49T315 109Q317 116 318 175Q318 233 317 233Q309 233 296 232T251 223T193 203T147 166T126 106Z" transform="translate(1617,0)" style="stroke-width: 3;"/><path data-c="69" d="M69 609Q69 637 87 653T131 669Q154 667 171 652T188 609Q188 579 171 564T129 549Q104 549 87 564T69 609ZM247 0Q232 3 143 3Q132 3 106 3T56 1L34 0H26V46H42Q70 46 91 49Q100 53 102 60T104 102V205V293Q104 345 102 359T88 378Q74 385 41 385H30V408Q30 431 32 431L42 432Q52 433 70 434T106 436Q123 437 142 438T171 441T182 442H185V62Q190 52 197 50T232 46H255V0H247Z" transform="translate(2117,0)" style="stroke-width: 3;"/><path data-c="6E" d="M41 46H55Q94 46 102 60V68Q102 77 102 91T102 122T103 161T103 203Q103 234 103 269T102 328V351Q99 370 88 376T43 385H25V408Q25 431 27 431L37 432Q47 433 65 434T102 436Q119 437 138 438T167 441T178 442H181V402Q181 364 182 364T187 369T199 384T218 402T247 421T285 437Q305 442 336 442Q450 438 463 329Q464 322 464 190V104Q464 66 466 59T477 49Q498 46 526 46H542V0H534L510 1Q487 2 460 2T422 3Q319 3 310 0H302V46H318Q379 46 379 62Q380 64 380 200Q379 335 378 343Q372 371 358 385T334 402T308 404Q263 404 229 370Q202 343 195 315T187 232V168V108Q187 78 188 68T191 55T200 49Q221 46 249 46H265V0H257L234 1Q210 2 183 2T145 3Q42 3 33 0H25V46H41Z" transform="translate(2395,0)" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(2984,-150) scale(0.707)"><path data-c="1D466" d="M21 287Q21 301 36 335T84 406T158 442Q199 442 224 419T250 355Q248 336 247 334Q247 331 231 288T198 191T182 105Q182 62 196 45T238 27Q261 27 281 38T312 61T339 94Q339 95 344 114T358 173T377 247Q415 397 419 404Q432 431 462 431Q475 431 483 424T494 412T496 403Q496 390 447 193T391 -23Q363 -106 294 -155T156 -205Q111 -205 77 -183T43 -117Q43 -95 50 -80T69 -58T89 -48T106 -45Q150 -45 150 -87Q150 -107 138 -122T115 -142T102 -147L99 -148Q101 -153 118 -160T152 -167H160Q177 -167 186 -165Q219 -156 247 -127T290 -65T313 -9T321 21L315 17Q309 13 296 6T270 -6Q250 -11 231 -11Q185 -11 150 11T104 82Q103 89 103 113Q103 170 138 262T173 379Q173 380 173 381Q173 390 173 393T169 400T158 404H154Q131 404 112 385T82 344T65 302T57 280Q55 278 41 278H27Q21 284 21 287Z" style="stroke-width: 3;"/></g></g><g data-mml-node="mo" transform="translate(6841.4,0)"><path data-c="29" d="M60 749L64 750Q69 750 74 750H86L114 726Q208 641 251 514T294 250Q294 182 284 119T261 12T224 -76T186 -143T145 -194T113 -227T90 -246Q87 -249 86 -250H74Q66 -250 63 -250T58 -247T55 -238Q56 -237 66 -225Q221 -64 221 250T66 725Q56 737 55 738Q55 746 60 749Z" style="stroke-width: 3;"/></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mo stretchy="false">(</mo><msub><mtext>ray</mtext><mi>y</mi></msub><mo>−</mo><msub><mtext>terrain</mtext><mi>y</mi></msub><mo stretchy="false">)</mo></math></mjx-assistive-mml></mjx-container>. Así se obtiene una precisión inferior al milímetro con unos 30 pasos amplios más 14 bisecciones por lanzamiento. Cuando la geometría renderizada solo existe en la GPU, no luches contra el raycaster: recorre la fuente analítica.</p>
<h2 id="colliders-que-siguen-siendo-fieles-tras-las-ediciones" tabindex="-1">Colliders que siguen siendo fieles tras las ediciones <a class="header-anchor" href="#colliders-que-siguen-siendo-fieles-tras-las-ediciones" aria-label="Permalink to &quot;Colliders que siguen siendo fieles tras las ediciones&quot;"></a></h2>
<p>Elegimos proxies primitivos en lugar de envolventes convexas o colliders de malla. Los objetos de Quaternius son redondeados y de bajo número de polígonos, sin concavidades relevantes, por lo que las envolventes requerirían aproximadamente 50 veces más código y multiplicarían por 10 el coste en tiempo de ejecución para ofrecer la misma experiencia de juego. Cada objeto se reduce a una forma derivada de su caja delimitadora: árboles y cactus se convierten en una cápsula vertical, rocas en una esfera, troncos en una cápsula horizontal a lo largo de su eje mayor, y los arbustos y flores decorativos no tienen collider. Se puede caminar sobre las rocas y los troncos —empuje solo vertical para poder ponerse encima—, mientras que los árboles y cactus bloquean el paso —empuje 3D completo para impedir trepar por un tronco—. Un hash espacial de 8 m limita la comprobación por fotograma al vecindario de 3×3 del jugador, normalmente entre cero y seis objetos.</p>
<p>Dos decisiones de diseño mantuvieron la coherencia del sistema. La alineación con el terreno es un indicador del manifiesto, no un enum de categorías fijado en el código, por lo que tanto la previsualización fantasma como la colocación confirmada leen el mismo valor <code>placement.alignToTerrain</code> y no pueden discrepar. Además, los objetos colocados reaccionan a las ediciones del terreno mediante un único helper: después de una pincelada —local o reproducida desde otro par—, <code>refreshPlacementsInRadius</code> vuelve a muestrear el suelo bajo cada objeto dentro del disco afectado, reaplica la alineación y vuelve a derivar los extremos del collider. Esculpe una colina debajo de un árbol y el árbol ascenderá con ella. La persistencia y el multijugador reutilizan exactamente el patrón del spike 31: almacenan una lista plana de <code>{uid, propId, x, y, z, rotY, scale}</code> y replican los eventos de colocación, eliminación y ajuste mediante BroadcastChannel.</p>
<h2 id="tecnologia-mencionada-en-este-capitulo" tabindex="-1">Tecnología mencionada en este capítulo <a class="header-anchor" href="#tecnologia-mencionada-en-este-capitulo" aria-label="Permalink to &quot;Tecnología mencionada en este capítulo&quot;"></a></h2>
<p><strong>Descomposición en módulos ES con WebGPU.</strong> Dividir un <code>&lt;script type=&quot;module&quot;&gt;</code> monolítico en importaciones <code>.mjs</code> con rutas directas no requiere un empaquetador cuando los módulos se sirven como recursos estáticos, y TSL de three.js funciona sin problemas entre módulos. El coste oculto es el orden de inicialización: un monolito codifica «construir X antes que Y» mediante el orden de arriba abajo del script, mientras que los módulos se evalúan según el orden de importación, lo que puede ejecutar una fábrica de grupos de bindings de GPU antes de que exista su búfer. El patrón de solución es la inicialización diferida (<code>getOrCreate...</code> en el primer uso) y esperar la promesa adecuada en lugar de depender del orden de declaración.</p>
<p><strong>glTF con PBR incrustado frente a FBX con asignación manual.</strong> glTF utiliza metros, referencia sus propias texturas y proporciona directamente <code>MeshStandardMaterial</code>, por lo que un paquete CC0 creado como glTF se integra directamente en un pipeline PBR. Los paquetes FBX sin metadatos de vinculación de texturas requieren una tabla manual de nombres de materiales a archivos PNG que queda desactualizada con cada actualización del paquete, además de una conversión de Phong a Standard y el etiquetado manual del espacio de color. Como red de seguridad para el follaje, los materiales <code>transparent</code> sin <code>alphaTest</code> se convierten en tarjetas recortadas con <code>alphaTest: 0.5</code>, para que se ordenen correctamente detrás de la geometría opaca.</p>
<p><strong>Miniaturas fuera de pantalla con WebGPU.</strong> <code>canvas.toDataURL()</code> devuelve una imagen vacía para un canvas respaldado por <code>GPUCanvasContext</code> porque no existe una ruta desde una superficie de presentación hasta un contexto 2D. Renderizar en un <code>RenderTarget</code>, leer los píxeles con <code>readRenderTargetPixelsAsync</code> y copiarlos en un canvas 2D funciona, siempre que la copia avance según el stride de lectura alineado a 256 bytes de WebGPU. Los resultados se almacenan en caché en <code>localStorage</code> bajo una clave cuya versión se incrementa para que los cambios en el paquete invaliden los renderizados obsoletos.</p>
<p><strong>Ray marching adaptativo contra un mapa de alturas analítico.</strong> Cuando los vértices del terreno viven en un <code>StorageBufferAttribute</code> de la GPU, el raycaster de CPU no puede verlos. Recorrer la función de altura analítica con pasos grandes lejos de la superficie, pasos pequeños cerca de ella y un refinamiento mediante búsqueda binaria cuando cambia el signo de <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.869ex;" xmlns="http://www.w3.org/2000/svg" width="16.358ex" height="2.566ex" role="img" focusable="false" viewBox="0 -750 7230.4 1134.3" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mo"><path data-c="28" d="M94 250Q94 319 104 381T127 488T164 576T202 643T244 695T277 729T302 750H315H319Q333 750 333 741Q333 738 316 720T275 667T226 581T184 443T167 250T184 58T225 -81T274 -167T316 -220T333 -241Q333 -250 318 -250H315H302L274 -226Q180 -141 137 -14T94 250Z" style="stroke-width: 3;"/></g><g data-mml-node="msub" transform="translate(389,0)"><g data-mml-node="mtext"><path data-c="72" d="M36 46H50Q89 46 97 60V68Q97 77 97 91T98 122T98 161T98 203Q98 234 98 269T98 328L97 351Q94 370 83 376T38 385H20V408Q20 431 22 431L32 432Q42 433 60 434T96 436Q112 437 131 438T160 441T171 442H174V373Q213 441 271 441H277Q322 441 343 419T364 373Q364 352 351 337T313 322Q288 322 276 338T263 372Q263 381 265 388T270 400T273 405Q271 407 250 401Q234 393 226 386Q179 341 179 207V154Q179 141 179 127T179 101T180 81T180 66V61Q181 59 183 57T188 54T193 51T200 49T207 48T216 47T225 47T235 46T245 46H276V0H267Q249 3 140 3Q37 3 28 0H20V46H36Z" style="stroke-width: 3;"/><path data-c="61" d="M137 305T115 305T78 320T63 359Q63 394 97 421T218 448Q291 448 336 416T396 340Q401 326 401 309T402 194V124Q402 76 407 58T428 40Q443 40 448 56T453 109V145H493V106Q492 66 490 59Q481 29 455 12T400 -6T353 12T329 54V58L327 55Q325 52 322 49T314 40T302 29T287 17T269 6T247 -2T221 -8T190 -11Q130 -11 82 20T34 107Q34 128 41 147T68 188T116 225T194 253T304 268H318V290Q318 324 312 340Q290 411 215 411Q197 411 181 410T156 406T148 403Q170 388 170 359Q170 334 154 320ZM126 106Q126 75 150 51T209 26Q247 26 276 49T315 109Q317 116 318 175Q318 233 317 233Q309 233 296 232T251 223T193 203T147 166T126 106Z" transform="translate(392,0)" style="stroke-width: 3;"/><path data-c="79" d="M69 -66Q91 -66 104 -80T118 -116Q118 -134 109 -145T91 -160Q84 -163 97 -166Q104 -168 111 -168Q131 -168 148 -159T175 -138T197 -106T213 -75T225 -43L242 0L170 183Q150 233 125 297Q101 358 96 368T80 381Q79 382 78 382Q66 385 34 385H19V431H26L46 430Q65 430 88 429T122 428Q129 428 142 428T171 429T200 430T224 430L233 431H241V385H232Q183 385 185 366L286 112Q286 113 332 227L376 341V350Q376 365 366 373T348 383T334 385H331V431H337H344Q351 431 361 431T382 430T405 429T422 429Q477 429 503 431H508V385H497Q441 380 422 345Q420 343 378 235T289 9T227 -131Q180 -204 113 -204Q69 -204 44 -177T19 -116Q19 -89 35 -78T69 -66Z" transform="translate(892,0)" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(1453,-239.4) scale(0.707)"><path data-c="1D466" d="M21 287Q21 301 36 335T84 406T158 442Q199 442 224 419T250 355Q248 336 247 334Q247 331 231 288T198 191T182 105Q182 62 196 45T238 27Q261 27 281 38T312 61T339 94Q339 95 344 114T358 173T377 247Q415 397 419 404Q432 431 462 431Q475 431 483 424T494 412T496 403Q496 390 447 193T391 -23Q363 -106 294 -155T156 -205Q111 -205 77 -183T43 -117Q43 -95 50 -80T69 -58T89 -48T106 -45Q150 -45 150 -87Q150 -107 138 -122T115 -142T102 -147L99 -148Q101 -153 118 -160T152 -167H160Q177 -167 186 -165Q219 -156 247 -127T290 -65T313 -9T321 21L315 17Q309 13 296 6T270 -6Q250 -11 231 -11Q185 -11 150 11T104 82Q103 89 103 113Q103 170 138 262T173 379Q173 380 173 381Q173 390 173 393T169 400T158 404H154Q131 404 112 385T82 344T65 302T57 280Q55 278 41 278H27Q21 284 21 287Z" style="stroke-width: 3;"/></g></g><g data-mml-node="mo" transform="translate(2460.7,0)"><path data-c="2212" d="M84 237T84 250T98 270H679Q694 262 694 250T679 230H98Q84 237 84 250Z" style="stroke-width: 3;"/></g><g data-mml-node="msub" transform="translate(3460.9,0)"><g data-mml-node="mtext"><path data-c="74" d="M27 422Q80 426 109 478T141 600V615H181V431H316V385H181V241Q182 116 182 100T189 68Q203 29 238 29Q282 29 292 100Q293 108 293 146V181H333V146V134Q333 57 291 17Q264 -10 221 -10Q187 -10 162 2T124 33T105 68T98 100Q97 107 97 248V385H18V422H27Z" style="stroke-width: 3;"/><path data-c="65" d="M28 218Q28 273 48 318T98 391T163 433T229 448Q282 448 320 430T378 380T406 316T415 245Q415 238 408 231H126V216Q126 68 226 36Q246 30 270 30Q312 30 342 62Q359 79 369 104L379 128Q382 131 395 131H398Q415 131 415 121Q415 117 412 108Q393 53 349 21T250 -11Q155 -11 92 58T28 218ZM333 275Q322 403 238 411H236Q228 411 220 410T195 402T166 381T143 340T127 274V267H333V275Z" transform="translate(389,0)" style="stroke-width: 3;"/><path data-c="72" d="M36 46H50Q89 46 97 60V68Q97 77 97 91T98 122T98 161T98 203Q98 234 98 269T98 328L97 351Q94 370 83 376T38 385H20V408Q20 431 22 431L32 432Q42 433 60 434T96 436Q112 437 131 438T160 441T171 442H174V373Q213 441 271 441H277Q322 441 343 419T364 373Q364 352 351 337T313 322Q288 322 276 338T263 372Q263 381 265 388T270 400T273 405Q271 407 250 401Q234 393 226 386Q179 341 179 207V154Q179 141 179 127T179 101T180 81T180 66V61Q181 59 183 57T188 54T193 51T200 49T207 48T216 47T225 47T235 46T245 46H276V0H267Q249 3 140 3Q37 3 28 0H20V46H36Z" transform="translate(833,0)" style="stroke-width: 3;"/><path data-c="72" d="M36 46H50Q89 46 97 60V68Q97 77 97 91T98 122T98 161T98 203Q98 234 98 269T98 328L97 351Q94 370 83 376T38 385H20V408Q20 431 22 431L32 432Q42 433 60 434T96 436Q112 437 131 438T160 441T171 442H174V373Q213 441 271 441H277Q322 441 343 419T364 373Q364 352 351 337T313 322Q288 322 276 338T263 372Q263 381 265 388T270 400T273 405Q271 407 250 401Q234 393 226 386Q179 341 179 207V154Q179 141 179 127T179 101T180 81T180 66V61Q181 59 183 57T188 54T193 51T200 49T207 48T216 47T225 47T235 46T245 46H276V0H267Q249 3 140 3Q37 3 28 0H20V46H36Z" transform="translate(1225,0)" style="stroke-width: 3;"/><path data-c="61" d="M137 305T115 305T78 320T63 359Q63 394 97 421T218 448Q291 448 336 416T396 340Q401 326 401 309T402 194V124Q402 76 407 58T428 40Q443 40 448 56T453 109V145H493V106Q492 66 490 59Q481 29 455 12T400 -6T353 12T329 54V58L327 55Q325 52 322 49T314 40T302 29T287 17T269 6T247 -2T221 -8T190 -11Q130 -11 82 20T34 107Q34 128 41 147T68 188T116 225T194 253T304 268H318V290Q318 324 312 340Q290 411 215 411Q197 411 181 410T156 406T148 403Q170 388 170 359Q170 334 154 320ZM126 106Q126 75 150 51T209 26Q247 26 276 49T315 109Q317 116 318 175Q318 233 317 233Q309 233 296 232T251 223T193 203T147 166T126 106Z" transform="translate(1617,0)" style="stroke-width: 3;"/><path data-c="69" d="M69 609Q69 637 87 653T131 669Q154 667 171 652T188 609Q188 579 171 564T129 549Q104 549 87 564T69 609ZM247 0Q232 3 143 3Q132 3 106 3T56 1L34 0H26V46H42Q70 46 91 49Q100 53 102 60T104 102V205V293Q104 345 102 359T88 378Q74 385 41 385H30V408Q30 431 32 431L42 432Q52 433 70 434T106 436Q123 437 142 438T171 441T182 442H185V62Q190 52 197 50T232 46H255V0H247Z" transform="translate(2117,0)" style="stroke-width: 3;"/><path data-c="6E" d="M41 46H55Q94 46 102 60V68Q102 77 102 91T102 122T103 161T103 203Q103 234 103 269T102 328V351Q99 370 88 376T43 385H25V408Q25 431 27 431L37 432Q47 433 65 434T102 436Q119 437 138 438T167 441T178 442H181V402Q181 364 182 364T187 369T199 384T218 402T247 421T285 437Q305 442 336 442Q450 438 463 329Q464 322 464 190V104Q464 66 466 59T477 49Q498 46 526 46H542V0H534L510 1Q487 2 460 2T422 3Q319 3 310 0H302V46H318Q379 46 379 62Q380 64 380 200Q379 335 378 343Q372 371 358 385T334 402T308 404Q263 404 229 370Q202 343 195 315T187 232V168V108Q187 78 188 68T191 55T200 49Q221 46 249 46H265V0H257L234 1Q210 2 183 2T145 3Q42 3 33 0H25V46H41Z" transform="translate(2395,0)" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(2984,-150) scale(0.707)"><path data-c="1D466" d="M21 287Q21 301 36 335T84 406T158 442Q199 442 224 419T250 355Q248 336 247 334Q247 331 231 288T198 191T182 105Q182 62 196 45T238 27Q261 27 281 38T312 61T339 94Q339 95 344 114T358 173T377 247Q415 397 419 404Q432 431 462 431Q475 431 483 424T494 412T496 403Q496 390 447 193T391 -23Q363 -106 294 -155T156 -205Q111 -205 77 -183T43 -117Q43 -95 50 -80T69 -58T89 -48T106 -45Q150 -45 150 -87Q150 -107 138 -122T115 -142T102 -147L99 -148Q101 -153 118 -160T152 -167H160Q177 -167 186 -165Q219 -156 247 -127T290 -65T313 -9T321 21L315 17Q309 13 296 6T270 -6Q250 -11 231 -11Q185 -11 150 11T104 82Q103 89 103 113Q103 170 138 262T173 379Q173 380 173 381Q173 390 173 393T169 400T158 404H154Q131 404 112 385T82 344T65 302T57 280Q55 278 41 278H27Q21 284 21 287Z" style="stroke-width: 3;"/></g></g><g data-mml-node="mo" transform="translate(6841.4,0)"><path data-c="29" d="M60 749L64 750Q69 750 74 750H86L114 726Q208 641 251 514T294 250Q294 182 284 119T261 12T224 -76T186 -143T145 -194T113 -227T90 -246Q87 -249 86 -250H74Q66 -250 63 -250T58 -247T55 -238Q56 -237 66 -225Q221 -64 221 250T66 725Q56 737 55 738Q55 746 60 749Z" style="stroke-width: 3;"/></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mo stretchy="false">(</mo><msub><mtext>ray</mtext><mi>y</mi></msub><mo>−</mo><msub><mtext>terrain</mtext><mi>y</mi></msub><mo stretchy="false">)</mo></math></mjx-assistive-mml></mjx-container> proporciona al cursor una precisión inferior al milímetro con un número acotado de muestras. La misma primitiva se utiliza para el cursor del pincel y el objeto fantasma.</p>
<p><strong>Colliders de cápsula primitivos con un hash espacial.</strong> Cada objeto se reduce a una cápsula o esfera derivada de su categoría a partir de su caja delimitadora, se registra como <code>{kind, walkable, radius, p1, p2}</code> y se añade a cada bucket de 8 m del hash con el que se solapa. En cada fotograma, el jugador solo comprueba los objetos del vecindario de 3×3 buckets, con una resolución cápsula contra cápsula para cada uno. Los proxies transitables —rocas y troncos— reciben un empuje solo vertical; los proxies que bloquean —árboles— reciben el empuje 3D completo. Consulta <a href="/es/guides/landscape-generation-browser.html#physics-on-sdf-terrain">Colisiones con terreno SDF</a> para ver las matemáticas de cápsulas en las que se basa este sistema.</p>
<hr>
<p>Parte 16 de 29.
Anterior: <a href="/es/blog/2026-04-13-open-world-browser-part-15-multiplayer-and-water.html">Parte 15 - Sustituir la base y después sincronizarla</a>
Siguiente: <a href="/es/blog/2026-05-01-open-world-browser-part-17-animations-and-search.html">Parte 17 - Animaciones que no necesitaron retargeting y una búsqueda de recursos en vivo</a>
Guía de la serie: <a href="/es/blog/2026-02-25-open-world-browser-series-guide.html">/es/blog/2026-02-25-open-world-browser-series-guide</a></p>
]]></content:encoded>
            <enclosure url="https://cdn.cinevva.com/blog/why-webgpu-engine-hero.jpg" length="0" type="image/jpg"/>
        </item>
        <item>
            <title><![CDATA[Cuatro apuestas que hice sobre los videojuegos en 2022. Cómo han envejecido.]]></title>
            <link>https://app.cinevva.com/es/blog/2026-04-24-2022-predictions-aging-well</link>
            <guid>https://app.cinevva.com/es/blog/2026-04-24-2022-predictions-aging-well</guid>
            <pubDate>Fri, 24 Apr 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[En una entrevista de 2022 aposté por los motores de juegos WebGL, GPT-3 para diálogos, la colaboración creativa en tiempo real y el auge de los indies. Cuatro años después, esto es lo que ocurrió con cada predicción.]]></description>
            <content:encoded><![CDATA[<h1 id="cuatro-apuestas-que-hice-sobre-los-videojuegos-en-2022-como-han-envejecido" tabindex="-1">Cuatro apuestas que hice sobre los videojuegos en 2022. Cómo han envejecido. <a class="header-anchor" href="#cuatro-apuestas-que-hice-sobre-los-videojuegos-en-2022-como-han-envejecido" aria-label="Permalink to &quot;Cuatro apuestas que hice sobre los videojuegos en 2022. Cómo han envejecido.&quot;"></a></h1>
<p><em>Por <a href="/es/about.html">Mariana Muntean</a>, CEO de Cinevva</em></p>
<img src="/img/blog/tech-done-different.jpg" alt="Entrevista en el pódcast Tech Done Different, mayo de 2022" style="width:100%;border-radius:8px;margin:1.5rem 0" />
<p>En mayo de 2022, me senté para una entrevista en el pódcast <em>Tech Done Different</em> de Ted Harrington. El artículo original <a href="https://medium.com/@vio-202020/interview-with-tech-done-different-3b9bf74d99c2" target="_blank" rel="noreferrer">sigue disponible en Medium</a>. Llevaba unos dos años al frente de Cinevva. Éramos cinco personas, habíamos recaudado 200.000 dólares, teníamos un premio de Mozilla Builders en la pared y muchas opiniones sobre el rumbo que estaba tomando el desarrollo de videojuegos.</p>
<p>La mayoría de esas opiniones no estaban de moda en 2022. La Web3 hacía mucho ruido, los estudios AAA dominaban la conversación, GPT-3 era un juguete de investigación y WebGL era algo que los aficionados usaban para crear juegos en jams. Decir en voz alta que «cualquier persona creativa podrá desarrollar videojuegos» recibía asentimientos corteses y cero cheques.</p>
<p>La semana pasada volví a leer aquella entrevista. Algunas de las cosas que dije parecen ilusiones. Otras hacen pensar que tenía una máquina del tiempo. Estas son las cuatro apuestas que mejor han envejecido, junto con la realidad de cada una en 2026.</p>
<h2 id="apuesta-1-los-motores-de-juegos-deben-estar-en-el-navegador" tabindex="-1">Apuesta 1: Los motores de juegos deben estar en el navegador <a class="header-anchor" href="#apuesta-1-los-motores-de-juegos-deben-estar-en-el-navegador" aria-label="Permalink to &quot;Apuesta 1: Los motores de juegos deben estar en el navegador&quot;"></a></h2>
<p>Lo que dije en 2022:</p>
<blockquote>
<p>La tecnología WebGL puede utilizarse en múltiples plataformas, incluidos los dispositivos móviles, a diferencia de otras API que pueden estar restringidas únicamente a PC. Así que, tanto si estás en la comodidad de tu hogar como si estás fuera, puedes seguir creando y publicando. Los juegos WebGL solo utilizan una fracción de la potencia de CPU y GPU que requeriría un juego tradicional de PC.</p>
</blockquote>
<p>En 2022, esta era una apuesta contraria a la corriente dominante. Todos los grandes motores daban por sentados las descargas, las instalaciones y los ciclos de parches. Los juegos de navegador evocaban nostalgia por Flash y Friv.</p>
<p>En 2026, nuestro <a href="/es/blog/2026-02-25-open-world-browser-series-guide.html">motor de mundo abierto funciona a 120 FPS en una pestaña del navegador</a>. Terreno, árboles, físicas y sincronización multijugador, todo en una sola URL. Sin descargas, sin tienda de aplicaciones y sin instalación.</p>
<img src="/img/blog/open-world-browser-120fps.png" alt="El mundo abierto de Cinevva funcionando a 120 FPS en una pestaña del navegador, con terreno, árboles, físicas y una cápsula de jugador renderizados en una sola pestaña" style="width:100%;border-radius:8px;margin:1.5rem 0" />
<p>El navegador se puso al día porque tres cosas llegaron al mismo tiempo. WebGPU se incorporó a todos los navegadores principales. SharedArrayBuffer y el aislamiento entre orígenes se volvieron fiables. WebAssembly alcanzó la velocidad necesaria para ejecutar auténticos motores de físicas compilados desde Rust. Nuestro equipo <a href="/es/blog/2026-02-25-open-world-browser-series-guide.html">publicó un diario de campo de 12 entregas</a> sobre el coste real de cada uno de esos pasos. En resumen, el navegador ya es un verdadero entorno de ejecución para juegos, no un lugar donde alojar la demo del juego de verdad.</p>
<p>La apuesta dentro de la apuesta que no acerté: subestimé cuánto trabajo tendría que hacerse en el ámbito de la cultura de ingeniería. Los motores de juegos para navegador ya no están limitados por los navegadores. Están limitados por la idea de que un juego de verdad debe tener un launcher.</p>
<h2 id="apuesta-2-la-ia-forma-parte-del-flujo-de-trabajo-no-es-una-funcion-secundaria" tabindex="-1">Apuesta 2: La IA forma parte del flujo de trabajo, no es una función secundaria <a class="header-anchor" href="#apuesta-2-la-ia-forma-parte-del-flujo-de-trabajo-no-es-una-funcion-secundaria" aria-label="Permalink to &quot;Apuesta 2: La IA forma parte del flujo de trabajo, no es una función secundaria&quot;"></a></h2>
<p>Lo que dije en 2022:</p>
<blockquote>
<p>Para que nuestra plataforma funcione a la perfección, utilizamos herramientas de código abierto para videojuegos, pero también desarrollamos nuestra propia tecnología mediante procesamiento del lenguaje natural, visión artificial y soluciones de OpenAI, como GPT3 para los diálogos y DALL:E para generar imágenes a partir de texto.</p>
</blockquote>
<p>En mayo de 2022, GPT-3 era una API de pago que la mayoría de la gente nunca había utilizado. DALL·E apenas tenía un año y contaba con una lista de espera. Decir que íbamos a utilizarlos como herramientas de producción para desarrollar videojuegos era, en el mejor de los casos, una interpretación ambiciosa.</p>
<p>En 2026, todos los flujos creativos serios incorporan modelos de lenguaje y generación de imágenes, incluido el nuestro. Actualmente, dentro de Cinevva usamos ElevenLabs Music para bandas sonoras, ElevenLabs SFX para efectos, Hunyuan3D y SAM3D para recursos, Flux para elementos visuales, Mubert para audio adaptativo y AceStep para instrumentación. Se introducen prompts, salen recursos utilizables y todo sucede dentro del editor.</p>
<img src="/img/blog/prompting-3d-games.png" alt="Generación de recursos 3D mediante prompts dentro del editor de Cinevva" style="width:100%;border-radius:8px;margin:1.5rem 0" />
<p>Las pruebas están en el informe <em>State of the Game Industry</em> de la GDC 2026. <a href="/es/signals/2026-03-28-the-52-52-split.html">El 52 % de las empresas de videojuegos afirma utilizar IA generativa en producción</a>. Ese mismo 52 % de desarrolladores afirma que el uso de la IA está teniendo un impacto negativo en la industria. Ambas cifras son ciertas. La cuestión es que la tecnología subyacente se convirtió en un requisito básico más rápido de lo que nadie quería admitir.</p>
<p>En qué me equivoqué: pensé que la resistencia vendría de ingenieros preocupados por la calidad. La mayor parte vino de artistas preocupados por sus empleos. Esa conversación es <a href="/es/signals/2026-03-16-when-ai-overrides-the-artist.html">mucho más compleja de lo que esperaba</a>, y quienes la presentan como una victoria rotunda no están prestando atención.</p>
<h2 id="apuesta-3-el-desarrollo-de-videojuegos-necesita-una-colaboracion-al-estilo-de-google-docs" tabindex="-1">Apuesta 3: El desarrollo de videojuegos necesita una colaboración al estilo de Google Docs <a class="header-anchor" href="#apuesta-3-el-desarrollo-de-videojuegos-necesita-una-colaboracion-al-estilo-de-google-docs" aria-label="Permalink to &quot;Apuesta 3: El desarrollo de videojuegos necesita una colaboración al estilo de Google Docs&quot;"></a></h2>
<p>Lo que dije en 2022:</p>
<blockquote>
<p>El control de código fuente y el trabajo con distintas versiones de las aplicaciones suelen estar vinculados a la colaboración remota. Hoy, para hacerlo, tienes que saber adónde ir, qué versión de la aplicación debes descargar y estar sincronizado con todo el mundo. Dios no quiera que un miembro del equipo utilice una versión incorrecta de la aplicación, porque se convierte en un problema. Aspiramos a ofrecer una experiencia casi en tiempo real como la de un documento de Google: sencilla, sin complicaciones y divertida.</p>
</blockquote>
<p>La colaboración en tiempo real dentro de las herramientas de programación era una idea marginal en 2022. Replit la ofrecía. VS Code Live Share existía. La mayoría de los motores profesionales exigían Perforce, una VPN y un ingeniero sénior vigilando tu rama.</p>
<p>En 2026, la colaboración en tiempo real es la opción predeterminada para cualquier herramienta creativa que quiera ser tomada en serio. Figma la normalizó para el diseño. Cursor y Bolt la normalizaron para el código. Lovable la normalizó para el prototipado de aplicaciones. Los motores de juegos se quedaron rezagados en lugar de liderar el cambio.</p>
<img src="/img/blog/open-world-chunk-streaming.png" alt="Transmisión en tiempo real de fragmentos de un juego de mundo abierto entre jugadores" style="width:100%;border-radius:8px;margin:1.5rem 0" />
<p>En nuestro propio motor ya tenemos sincronización multijugador funcionando como un <a href="/es/blog/2026-02-25-open-world-browser-part-04-streaming-before-fancy.html">experimento de primera clase</a>, con transmisión de fragmentos, presencia y estado compartido en el navegador. La experiencia se parece más a «abre el enlace y entra» que a «configura Perforce, pregunta en Slack por la versión correcta e instala el launcher».</p>
<p>La parte que subestimé: lo más difícil de la colaboración en tiempo real en videojuegos no son las redes. Es resolver los conflictos de intención creativa. Que dos personas editen el mismo nivel al mismo tiempo es un problema de UX antes que un problema de sincronización, y la mayoría de las herramientas aún no lo han resuelto.</p>
<h2 id="apuesta-4-el-futuro-es-indie" tabindex="-1">Apuesta 4: El futuro es indie <a class="header-anchor" href="#apuesta-4-el-futuro-es-indie" aria-label="Permalink to &quot;Apuesta 4: El futuro es indie&quot;"></a></h2>
<p>Lo que dije en 2022:</p>
<blockquote>
<p>Las personas creativas que antes no podían crear contenido para videojuegos podrán hacerlo. Descubriremos abundantes formas nuevas de percibir y expresar la creatividad. Esta vez, el proceso no estará controlado únicamente por corporaciones o grandes estudios AAA. El futuro es indie.</p>
</blockquote>
<p>Esta fue la frase más romántica de la entrevista y la más fácil de descartar en 2022. Los presupuestos AAA nunca habían sido tan altos. Los proyectos indie nunca lo habían tenido tan difícil para conseguir visibilidad. Las cifras parecían avanzar en la dirección contraria.</p>
<p>En 2026, las cifras dieron la vuelta. Creamos <a href="/es/blog/2026-02-18-a-breaker-belt.html">A Breaker Belt</a> en tres días, entre dos personas y para web, móviles y PC desde una única base de código. Antes, eso le habría llevado un trimestre a un equipo pequeño. <a href="/es/signals/2026-03-23-solo-devs-shipping-not-vibing.html">Los desarrolladores en solitario están publicando juegos, no solo programando por sensaciones</a>, y Steam Next Fest 2026 batió el récord de participantes con equipos de una sola persona.</p>
<img src="/img/social/industry-solo-dev-shipping.png" alt="Desarrolladores en solitario publicando juegos con calidad de producción mediante herramientas de IA y motores para navegador" style="width:100%;border-radius:8px;margin:1.5rem 0" />
<p>El coste de averiguar si una idea extraña funciona se ha desplomado. Ese es el verdadero cambio, y todo lo demás —la IA en el flujo de trabajo, el navegador como entorno de ejecución y la colaboración en tiempo real— está a su servicio. Un desarrollador en solitario con las herramientas adecuadas tiene ahora la capacidad de producción que tenía un estudio de 20 personas en 2018.</p>
<p>Lo que no vi con suficiente claridad en 2022: el cuello de botella se desplaza de la producción al descubrimiento. Cuando todo el mundo puede publicar, conseguir visibilidad se convierte en el problema más difícil. Ese es el siguiente conjunto de apuestas y ahora mismo estamos en plena fase de hacerlas.</p>
<h2 id="en-que-me-equivoque-a-proposito" tabindex="-1">En qué me equivoqué a propósito <a class="header-anchor" href="#en-que-me-equivoque-a-proposito" aria-label="Permalink to &quot;En qué me equivoqué a propósito&quot;"></a></h2>
<p>Algunas de las apuestas de 2022 siguen pendientes o necesitan una revisión.</p>
<p>El enfoque Web3 tuvo más protagonismo del que debería en aquella entrevista. La parte de cifrado y pruebas de conocimiento cero sigue siendo válida como base para los derechos sobre el contenido. El planteamiento basado en tokens y marketplaces envejeció mal, y buena parte de la energía que le dediqué en 2022 habría estado mejor invertida en herramientas de IA, donde estaba el verdadero potencial.</p>
<p>También subestimé hasta qué punto «cualquiera puede crear un juego» es un problema de descubrimiento y distribución, no de herramientas. Crear ahora es fácil. Conseguir visibilidad e ingresos sigue siendo difícil, y ahí es donde se concentra actualmente la mayor parte de nuestro trabajo.</p>
<p>Esa es la apuesta que estamos haciendo ahora mismo. Acabamos de lanzar un feed de reels al estilo de TikTok en <a href="/es/play.html">cinevva.com/play</a>. Clips verticales de quince segundos con gameplay real, sin tráileres ni metraje promocional. Si algo te llama la atención, con un toque ya estás jugando en el navegador. Sin descargas, sin instalaciones y sin tutoriales que se interpongan entre el juego y tú.</p>
<p>La razón por la que esto importa para los desarrolladores indie se reduce a unas cifras brutales. Steam Next Fest 2026 registró un número récord de participantes, lo que suena genial hasta que calculas el presupuesto de atención disponible por juego. La mayoría de las demos obtuvieron menos de mil impresiones. El embudo de las páginas de la tienda ya estaba roto antes de que la IA lo empeorara. Una superficie de desplazamiento vertical en la que el propio gameplay es el anuncio reduce el ciclo de descubrimiento a un solo gesto. Pone a los desarrolladores en solitario frente a los jugadores del mismo modo que TikTok pone a músicos desconocidos frente a sus oyentes. Esa es la pieza que falta entre «cualquiera puede publicar» y «cualquiera puede triunfar».</p>
<p>Si quieres leer la entrevista original completa, <a href="https://medium.com/@vio-202020/interview-with-tech-done-different-3b9bf74d99c2" target="_blank" rel="noreferrer">está aquí</a>. Volver a leerla fue útil. La mayor parte de lo que dijimos en voz alta en 2022 resultó ser una hoja de ruta viable, solo que con plazos más rápidos de lo que imaginábamos.</p>
]]></content:encoded>
            <enclosure url="https://app.cinevva.com/img/blog/tech-done-different.jpg" length="0" type="image/jpg"/>
        </item>
        <item>
            <title><![CDATA[Construir un mundo abierto en el navegador, parte 13: Esculpido del terreno y la muerte de la función matemática]]></title>
            <link>https://app.cinevva.com/es/blog/2026-04-13-open-world-browser-part-13-terrain-sculpting</link>
            <guid>https://app.cinevva.com/es/blog/2026-04-13-open-world-browser-part-13-terrain-sculpting</guid>
            <pubDate>Mon, 13 Apr 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Tres intentos fallidos, una malla que explotó y un error en las uniones que nos obligó a replantearnos cómo funcionan los datos del terreno.]]></description>
            <content:encoded><![CDATA[<h1 id="construir-un-mundo-abierto-en-el-navegador-parte-13-esculpido-del-terreno-y-la-muerte-de-la-funcion-matematica" tabindex="-1">Construir un mundo abierto en el navegador, parte 13: Esculpido del terreno y la muerte de la función matemática <a class="header-anchor" href="#construir-un-mundo-abierto-en-el-navegador-parte-13-esculpido-del-terreno-y-la-muerte-de-la-funcion-matematica" aria-label="Permalink to &quot;Construir un mundo abierto en el navegador, parte 13: Esculpido del terreno y la muerte de la función matemática&quot;"></a></h1>
<p><em>Por <a href="/es/about.html">Oleg Sidorkin</a>, CTO y cofundador de Cinevva</em></p>
<p>¿Acabas de llegar? Consulta la <a href="/es/blog/2026-02-25-open-world-browser-series-guide.html">guía de la serie</a>. Explica qué es un spike y enlaza todas las partes.</p>
<p>Durante doce partes construimos un motor de terreno que se podía contemplar. Sobrevolarlo. Admirar cómo no se abrían las uniones. Esta vez queríamos tocarlo.</p>
<p>El objetivo parecía sencillo: permitir que un jugador esculpiera el terreno con un pincel, en tiempo real, sin romper ninguno de los sistemas que habíamos tardado 24 spikes en construir. Hicieron falta tres intentos, dos errores que parecían fallos de renderizado pero que en realidad eran fallos del modelo de datos, y un replanteamiento fundamental de cómo debían funcionar los datos del terreno.</p>
<h2 id="tres-intentos-fallidos" tabindex="-1">Tres intentos fallidos <a class="header-anchor" href="#tres-intentos-fallidos" aria-label="Permalink to &quot;Tres intentos fallidos&quot;"></a></h2>
<p>Se suponía que el Spike 25 iba a ser el fácil. La base de código de producción ya tenía un trazador de rayos que detectaba las mallas del terreno. La herramienta de colocación lo usa para soltar objetos. Una herramienta de pincel sigue el mismo patrón, solo que modifica valores del mapa de alturas en lugar de instanciar un prefab. Sencillo.</p>
<p>Primer intento: lo construí directamente en el código TypeScript de producción de <code>world/client/</code>. Un nuevo <code>terrain-brush.ts</code>, modificaciones en <code>chunk.ts</code>, cambios en el protocolo y actualizaciones de componentes Vue. Al cabo de una hora tenía un pincel que más o menos funcionaba, pero los límites entre chunks mostraban discontinuidades visibles en las normales. No podía saber si el error estaba en el código del pincel, en el cosido de chunks existente o en alguna interacción con el bucle de renderizado completo. Esa es exactamente la situación que la metodología de spikes pretende evitar. Me había saltado la regla y pagué por ello de inmediato. Revertí todos los cambios.</p>
<p>Segundo intento: un spike independiente, pero recurrí a Three.js 0.170.0 y WebGL. El código de producción usa WebGL, así que parecía lo natural. Pero los Spikes 13-24 ya habían migrado todos a WebGPU. Crear un spike de pincel con WebGL demostraría que funcionaba con el renderizador antiguo, no con aquel hacia el que estamos migrando. Dirección equivocada. Empecé de nuevo.</p>
<p>Tercer intento: WebGPU, <code>WebGPURenderer</code>, shader de cómputo para generar vértices y la misma pila tecnológica que el Spike 22. Esta vez la arquitectura era correcta. Cinco operaciones de pincel funcionando: elevar, bajar, suavizar, aplanar y añadir ruido. P95 del ciclo del pincel por debajo de 4 ms en un M1.</p>
<p>Y el error de las uniones seguía ahí.</p>
<div style="position:relative;padding-bottom:56.25%;height:0;overflow:hidden;border-radius:8px;margin:1.5rem 0;border:1px solid rgba(255,255,255,0.12)">
<iframe src="/es/spikes/25-heightmap-brush/" title="Spike 25: Pincel de mapa de alturas" style="position:absolute;top:0;left:0;width:100%;height:100%;border:0;background:#000" loading="lazy" allowfullscreen></iframe>
</div>
<p><a href="/es/spikes/25-heightmap-brush/" target="_blank">Abrir el Spike 25 en una pestaña nueva ↗</a> · <a href="/es/blog/spike-source?spike=25-heightmap-brush">Ver el código fuente</a></p>
<h2 id="el-error-de-las-uniones-que-se-negaba-a-morir" tabindex="-1">El error de las uniones que se negaba a morir <a class="header-anchor" href="#el-error-de-las-uniones-que-se-negaba-a-morir" aria-label="Permalink to &quot;El error de las uniones que se negaba a morir&quot;"></a></h2>
<p>La solución habitual para calcular normales entre chunks es solapar los bordes: cada chunk almacena un anillo adicional de datos de sus vecinos para que el cálculo de la normal en el límite pueda muestrear ambos lados. Lo implementé. Copié los datos de los bordes vecinos en un búfer ampliado. Las uniones seguían abriéndose.</p>
<p>Me sumergí en las matemáticas. En el límite entre el chunk A (cx=-1) y el chunk B (cx=0), ambos chunks deben calcular la misma normal en el vértice compartido. El shader del chunk A muestreaba <code>mix(own_col31, own_col32, 0.85)</code>. El del chunk B muestreaba <code>mix(neighbor_edge, own_col0, 0.85)</code>. Son rutas de interpolación bilineal distintas a través de datos diferentes. Incluso con datos de borde correctos, los dos chunks calculan normales distintas para el mismo punto.</p>
<p>Fue entonces cuando comprendí que copiar el borde no era el verdadero error. El verdadero error estaba en el modelo de datos.</p>
<p>Todos los spikes del 1 al 24 usaban una función matemática procedimental llamada <code>height_at()</code>. Le pasabas coordenadas del mundo y devolvía una altura. Limpia, global y sin estado. El pincel no podía modificar una función matemática, así que había añadido encima un búfer de <code>displacement</code>. El terreno era ahora <code>height_at(x,z) + displacement[i]</code>. El shader de GPU contenía 30 líneas de funciones de ruido para el terreno base, además del código de interpolación bilineal para la capa de desplazamiento. El pincel de aplanado tenía que restar <code>height_at()</code> para averiguar qué valor de desplazamiento produciría la altura objetivo. Dos sistemas superpuestos, calculando cosas distintas con estrategias de muestreo diferentes.</p>
<p>Nada de esto es propio de un juego real. En producción, el terreno creado se representa mediante datos muestreados almacenados en búferes. La función procedimental era un sustituto práctico de los primeros spikes. Había cumplido su propósito. Ahora estaba provocando errores activamente.</p>
<p>La eliminé.</p>
<p>Ahora cada chunk posee un <code>heightmap</code> Float32Array con valores de altura reales. Al crearlo, se rellena con ruido procedimental. Después, la función de ruido no vuelve a llamarse. El pincel modifica directamente las alturas almacenadas. El shader de GPU lee de un único búfer mediante una única función: <code>hm_at(i,j)</code>. Las normales usan diferencias centrales alineadas con la cuadrícula sobre los mismos datos. Sin ambigüedad en la interpolación bilineal. Sin incompatibilidad entre dos sistemas. El shader pasó de 90 líneas a 40.</p>
<p>Las uniones se arreglaron solas. Ahora, en un borde compartido, ambos chunks leen los mismos valores discretos de altura de sus respectivos búferes, con los puntos interiores correctos del vecino en el solapamiento del borde. Los mismos datos de entrada producen las mismas normales.</p>
<p>Esta no fue una lección sobre pinceles. Fue una lección sobre arquitectura de datos que el pincel sacó a la luz.</p>
<h2 id="la-malla-que-exploto" tabindex="-1">La malla que explotó <a class="header-anchor" href="#la-malla-que-exploto" aria-label="Permalink to &quot;La malla que explotó&quot;"></a></h2>
<p>El Spike 26 era el equivalente volumétrico. Modificar con un pincel un volumen SDF de 64 al cubo y volver a generar la malla con marching cubes. La misma pregunta que en el Spike 25, pero en 3D.</p>
<p>La primera vez que lo ejecuté, la malla explotó. Largas púas salían disparadas en todas direcciones, como un erizo de mar teniendo un mal día.</p>
<div style="position:relative;padding-bottom:56.25%;height:0;overflow:hidden;border-radius:8px;margin:1.5rem 0;border:1px solid rgba(255,255,255,0.12)">
<iframe src="/es/spikes/26-sdf-brush/" title="Spike 26: Pincel SDF" style="position:absolute;top:0;left:0;width:100%;height:100%;border:0;background:#000" loading="lazy" allowfullscreen></iframe>
</div>
<p><a href="/es/spikes/26-sdf-brush/" target="_blank">Abrir el Spike 26 en una pestaña nueva ↗</a> · <a href="/es/blog/spike-source?spike=26-sdf-brush">Ver el código fuente</a></p>
<p>La tabla de casos de MC que había generado tenía 3840 entradas en vez de 4096. La tabla completa es de <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.439ex;" xmlns="http://www.w3.org/2000/svg" width="31.973ex" height="1.971ex" role="img" focusable="false" viewBox="0 -677 14132 871" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mn"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"/><path data-c="35" d="M164 157Q164 133 148 117T109 101H102Q148 22 224 22Q294 22 326 82Q345 115 345 210Q345 313 318 349Q292 382 260 382H254Q176 382 136 314Q132 307 129 306T114 304Q97 304 95 310Q93 314 93 485V614Q93 664 98 664Q100 666 102 666Q103 666 123 658T178 642T253 634Q324 634 389 662Q397 666 402 666Q410 666 410 648V635Q328 538 205 538Q174 538 149 544L139 546V374Q158 388 169 396T205 412T256 420Q337 420 393 355T449 201Q449 109 385 44T229 -22Q148 -22 99 32T50 154Q50 178 61 192T84 210T107 214Q132 214 148 197T164 157Z" transform="translate(500,0)" style="stroke-width: 3;"/><path data-c="36" d="M42 313Q42 476 123 571T303 666Q372 666 402 630T432 550Q432 525 418 510T379 495Q356 495 341 509T326 548Q326 592 373 601Q351 623 311 626Q240 626 194 566Q147 500 147 364L148 360Q153 366 156 373Q197 433 263 433H267Q313 433 348 414Q372 400 396 374T435 317Q456 268 456 210V192Q456 169 451 149Q440 90 387 34T253 -22Q225 -22 199 -14T143 16T92 75T56 172T42 313ZM257 397Q227 397 205 380T171 335T154 278T148 216Q148 133 160 97T198 39Q222 21 251 21Q302 21 329 59Q342 77 347 104T352 209Q352 289 347 316T329 361Q302 397 257 397Z" transform="translate(1000,0)" style="stroke-width: 3;"/></g><g data-mml-node="mtext" transform="translate(1500,0)"><path data-c="A0" d="" style="stroke-width: 3;"/></g><g data-mml-node="mtext" transform="translate(1750,0)"><path data-c="63" d="M370 305T349 305T313 320T297 358Q297 381 312 396Q317 401 317 402T307 404Q281 408 258 408Q209 408 178 376Q131 329 131 219Q131 137 162 90Q203 29 272 29Q313 29 338 55T374 117Q376 125 379 127T395 129H409Q415 123 415 120Q415 116 411 104T395 71T366 33T318 2T249 -11Q163 -11 99 53T34 214Q34 318 99 383T250 448T370 421T404 357Q404 334 387 320Z" style="stroke-width: 3;"/><path data-c="61" d="M137 305T115 305T78 320T63 359Q63 394 97 421T218 448Q291 448 336 416T396 340Q401 326 401 309T402 194V124Q402 76 407 58T428 40Q443 40 448 56T453 109V145H493V106Q492 66 490 59Q481 29 455 12T400 -6T353 12T329 54V58L327 55Q325 52 322 49T314 40T302 29T287 17T269 6T247 -2T221 -8T190 -11Q130 -11 82 20T34 107Q34 128 41 147T68 188T116 225T194 253T304 268H318V290Q318 324 312 340Q290 411 215 411Q197 411 181 410T156 406T148 403Q170 388 170 359Q170 334 154 320ZM126 106Q126 75 150 51T209 26Q247 26 276 49T315 109Q317 116 318 175Q318 233 317 233Q309 233 296 232T251 223T193 203T147 166T126 106Z" transform="translate(444,0)" style="stroke-width: 3;"/><path data-c="73" d="M295 316Q295 356 268 385T190 414Q154 414 128 401Q98 382 98 349Q97 344 98 336T114 312T157 287Q175 282 201 278T245 269T277 256Q294 248 310 236T342 195T359 133Q359 71 321 31T198 -10H190Q138 -10 94 26L86 19L77 10Q71 4 65 -1L54 -11H46H42Q39 -11 33 -5V74V132Q33 153 35 157T45 162H54Q66 162 70 158T75 146T82 119T101 77Q136 26 198 26Q295 26 295 104Q295 133 277 151Q257 175 194 187T111 210Q75 227 54 256T33 318Q33 357 50 384T93 424T143 442T187 447H198Q238 447 268 432L283 424L292 431Q302 440 314 448H322H326Q329 448 335 442V310L329 304H301Q295 310 295 316Z" transform="translate(944,0)" style="stroke-width: 3;"/><path data-c="6F" d="M28 214Q28 309 93 378T250 448Q340 448 405 380T471 215Q471 120 407 55T250 -10Q153 -10 91 57T28 214ZM250 30Q372 30 372 193V225V250Q372 272 371 288T364 326T348 362T317 390T268 410Q263 411 252 411Q222 411 195 399Q152 377 139 338T126 246V226Q126 130 145 91Q177 30 250 30Z" transform="translate(1338,0)" style="stroke-width: 3;"/><path data-c="73" d="M295 316Q295 356 268 385T190 414Q154 414 128 401Q98 382 98 349Q97 344 98 336T114 312T157 287Q175 282 201 278T245 269T277 256Q294 248 310 236T342 195T359 133Q359 71 321 31T198 -10H190Q138 -10 94 26L86 19L77 10Q71 4 65 -1L54 -11H46H42Q39 -11 33 -5V74V132Q33 153 35 157T45 162H54Q66 162 70 158T75 146T82 119T101 77Q136 26 198 26Q295 26 295 104Q295 133 277 151Q257 175 194 187T111 210Q75 227 54 256T33 318Q33 357 50 384T93 424T143 442T187 447H198Q238 447 268 432L283 424L292 431Q302 440 314 448H322H326Q329 448 335 442V310L329 304H301Q295 310 295 316Z" transform="translate(1838,0)" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(4204.2,0)"><path data-c="D7" d="M630 29Q630 9 609 9Q604 9 587 25T493 118L389 222L284 117Q178 13 175 11Q171 9 168 9Q160 9 154 15T147 29Q147 36 161 51T255 146L359 250L255 354Q174 435 161 449T147 471Q147 480 153 485T168 490Q173 490 175 489Q178 487 284 383L389 278L493 382Q570 459 587 475T609 491Q630 491 630 471Q630 464 620 453T522 355L418 250L522 145Q606 61 618 48T630 29Z" style="stroke-width: 3;"/></g><g data-mml-node="mn" transform="translate(5204.4,0)"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" style="stroke-width: 3;"/><path data-c="36" d="M42 313Q42 476 123 571T303 666Q372 666 402 630T432 550Q432 525 418 510T379 495Q356 495 341 509T326 548Q326 592 373 601Q351 623 311 626Q240 626 194 566Q147 500 147 364L148 360Q153 366 156 373Q197 433 263 433H267Q313 433 348 414Q372 400 396 374T435 317Q456 268 456 210V192Q456 169 451 149Q440 90 387 34T253 -22Q225 -22 199 -14T143 16T92 75T56 172T42 313ZM257 397Q227 397 205 380T171 335T154 278T148 216Q148 133 160 97T198 39Q222 21 251 21Q302 21 329 59Q342 77 347 104T352 209Q352 289 347 316T329 361Q302 397 257 397Z" transform="translate(500,0)" style="stroke-width: 3;"/></g><g data-mml-node="mtext" transform="translate(6204.4,0)"><path data-c="A0" d="" style="stroke-width: 3;"/></g><g data-mml-node="mtext" transform="translate(6454.4,0)"><path data-c="70" d="M36 -148H50Q89 -148 97 -134V-126Q97 -119 97 -107T97 -77T98 -38T98 6T98 55T98 106Q98 140 98 177T98 243T98 296T97 335T97 351Q94 370 83 376T38 385H20V408Q20 431 22 431L32 432Q42 433 61 434T98 436Q115 437 135 438T165 441T176 442H179V416L180 390L188 397Q247 441 326 441Q407 441 464 377T522 216Q522 115 457 52T310 -11Q242 -11 190 33L182 40V-45V-101Q182 -128 184 -134T195 -145Q216 -148 244 -148H260V-194H252L228 -193Q205 -192 178 -192T140 -191Q37 -191 28 -194H20V-148H36ZM424 218Q424 292 390 347T305 402Q234 402 182 337V98Q222 26 294 26Q345 26 384 80T424 218Z" style="stroke-width: 3;"/><path data-c="6F" d="M28 214Q28 309 93 378T250 448Q340 448 405 380T471 215Q471 120 407 55T250 -10Q153 -10 91 57T28 214ZM250 30Q372 30 372 193V225V250Q372 272 371 288T364 326T348 362T317 390T268 410Q263 411 252 411Q222 411 195 399Q152 377 139 338T126 246V226Q126 130 145 91Q177 30 250 30Z" transform="translate(556,0)" style="stroke-width: 3;"/><path data-c="73" d="M295 316Q295 356 268 385T190 414Q154 414 128 401Q98 382 98 349Q97 344 98 336T114 312T157 287Q175 282 201 278T245 269T277 256Q294 248 310 236T342 195T359 133Q359 71 321 31T198 -10H190Q138 -10 94 26L86 19L77 10Q71 4 65 -1L54 -11H46H42Q39 -11 33 -5V74V132Q33 153 35 157T45 162H54Q66 162 70 158T75 146T82 119T101 77Q136 26 198 26Q295 26 295 104Q295 133 277 151Q257 175 194 187T111 210Q75 227 54 256T33 318Q33 357 50 384T93 424T143 442T187 447H198Q238 447 268 432L283 424L292 431Q302 440 314 448H322H326Q329 448 335 442V310L329 304H301Q295 310 295 316Z" transform="translate(1056,0)" style="stroke-width: 3;"/><path data-c="69" d="M69 609Q69 637 87 653T131 669Q154 667 171 652T188 609Q188 579 171 564T129 549Q104 549 87 564T69 609ZM247 0Q232 3 143 3Q132 3 106 3T56 1L34 0H26V46H42Q70 46 91 49Q100 53 102 60T104 102V205V293Q104 345 102 359T88 378Q74 385 41 385H30V408Q30 431 32 431L42 432Q52 433 70 434T106 436Q123 437 142 438T171 441T182 442H185V62Q190 52 197 50T232 46H255V0H247Z" transform="translate(1450,0)" style="stroke-width: 3;"/><path data-c="63" d="M370 305T349 305T313 320T297 358Q297 381 312 396Q317 401 317 402T307 404Q281 408 258 408Q209 408 178 376Q131 329 131 219Q131 137 162 90Q203 29 272 29Q313 29 338 55T374 117Q376 125 379 127T395 129H409Q415 123 415 120Q415 116 411 104T395 71T366 33T318 2T249 -11Q163 -11 99 53T34 214Q34 318 99 383T250 448T370 421T404 357Q404 334 387 320Z" transform="translate(1728,0)" style="stroke-width: 3;"/><path data-c="69" d="M69 609Q69 637 87 653T131 669Q154 667 171 652T188 609Q188 579 171 564T129 549Q104 549 87 564T69 609ZM247 0Q232 3 143 3Q132 3 106 3T56 1L34 0H26V46H42Q70 46 91 49Q100 53 102 60T104 102V205V293Q104 345 102 359T88 378Q74 385 41 385H30V408Q30 431 32 431L42 432Q52 433 70 434T106 436Q123 437 142 438T171 441T182 442H185V62Q190 52 197 50T232 46H255V0H247Z" transform="translate(2172,0)" style="stroke-width: 3;"/><path data-c="6F" d="M28 214Q28 309 93 378T250 448Q340 448 405 380T471 215Q471 120 407 55T250 -10Q153 -10 91 57T28 214ZM250 30Q372 30 372 193V225V250Q372 272 371 288T364 326T348 362T317 390T268 410Q263 411 252 411Q222 411 195 399Q152 377 139 338T126 246V226Q126 130 145 91Q177 30 250 30Z" transform="translate(2450,0)" style="stroke-width: 3;"/><path data-c="6E" d="M41 46H55Q94 46 102 60V68Q102 77 102 91T102 122T103 161T103 203Q103 234 103 269T102 328V351Q99 370 88 376T43 385H25V408Q25 431 27 431L37 432Q47 433 65 434T102 436Q119 437 138 438T167 441T178 442H181V402Q181 364 182 364T187 369T199 384T218 402T247 421T285 437Q305 442 336 442Q450 438 463 329Q464 322 464 190V104Q464 66 466 59T477 49Q498 46 526 46H542V0H534L510 1Q487 2 460 2T422 3Q319 3 310 0H302V46H318Q379 46 379 62Q380 64 380 200Q379 335 378 343Q372 371 358 385T334 402T308 404Q263 404 229 370Q202 343 195 315T187 232V168V108Q187 78 188 68T191 55T200 49Q221 46 249 46H265V0H257L234 1Q210 2 183 2T145 3Q42 3 33 0H25V46H41Z" transform="translate(2950,0)" style="stroke-width: 3;"/><path data-c="65" d="M28 218Q28 273 48 318T98 391T163 433T229 448Q282 448 320 430T378 380T406 316T415 245Q415 238 408 231H126V216Q126 68 226 36Q246 30 270 30Q312 30 342 62Q359 79 369 104L379 128Q382 131 395 131H398Q415 131 415 121Q415 117 412 108Q393 53 349 21T250 -11Q155 -11 92 58T28 218ZM333 275Q322 403 238 411H236Q228 411 220 410T195 402T166 381T143 340T127 274V267H333V275Z" transform="translate(3506,0)" style="stroke-width: 3;"/><path data-c="73" d="M295 316Q295 356 268 385T190 414Q154 414 128 401Q98 382 98 349Q97 344 98 336T114 312T157 287Q175 282 201 278T245 269T277 256Q294 248 310 236T342 195T359 133Q359 71 321 31T198 -10H190Q138 -10 94 26L86 19L77 10Q71 4 65 -1L54 -11H46H42Q39 -11 33 -5V74V132Q33 153 35 157T45 162H54Q66 162 70 158T75 146T82 119T101 77Q136 26 198 26Q295 26 295 104Q295 133 277 151Q257 175 194 187T111 210Q75 227 54 256T33 318Q33 357 50 384T93 424T143 442T187 447H198Q238 447 268 432L283 424L292 431Q302 440 314 448H322H326Q329 448 335 442V310L329 304H301Q295 310 295 316Z" transform="translate(3950,0)" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(11076.2,0)"><path data-c="3D" d="M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z" style="stroke-width: 3;"/></g><g data-mml-node="mn" transform="translate(12132,0)"><path data-c="34" d="M462 0Q444 3 333 3Q217 3 199 0H190V46H221Q241 46 248 46T265 48T279 53T286 61Q287 63 287 115V165H28V211L179 442Q332 674 334 675Q336 677 355 677H373L379 671V211H471V165H379V114Q379 73 379 66T385 54Q393 47 442 46H471V0H462ZM293 211V545L74 212L183 211H293Z" style="stroke-width: 3;"/><path data-c="30" d="M96 585Q152 666 249 666Q297 666 345 640T423 548Q460 465 460 320Q460 165 417 83Q397 41 362 16T301 -15T250 -22Q224 -22 198 -16T137 16T82 83Q39 165 39 320Q39 494 96 585ZM321 597Q291 629 250 629Q208 629 178 597Q153 571 145 525T137 333Q137 175 145 125T181 46Q209 16 250 16Q290 16 318 46Q347 76 354 130T362 333Q362 478 354 524T321 597Z" transform="translate(500,0)" style="stroke-width: 3;"/><path data-c="39" d="M352 287Q304 211 232 211Q154 211 104 270T44 396Q42 412 42 436V444Q42 537 111 606Q171 666 243 666Q245 666 249 666T257 665H261Q273 665 286 663T323 651T370 619T413 560Q456 472 456 334Q456 194 396 97Q361 41 312 10T208 -22Q147 -22 108 7T68 93T121 149Q143 149 158 135T173 96Q173 78 164 65T148 49T135 44L131 43Q131 41 138 37T164 27T206 22H212Q272 22 313 86Q352 142 352 280V287ZM244 248Q292 248 321 297T351 430Q351 508 343 542Q341 552 337 562T323 588T293 615T246 625Q208 625 181 598Q160 576 154 546T147 441Q147 358 152 329T172 282Q197 248 244 248Z" transform="translate(1000,0)" style="stroke-width: 3;"/><path data-c="36" d="M42 313Q42 476 123 571T303 666Q372 666 402 630T432 550Q432 525 418 510T379 495Q356 495 341 509T326 548Q326 592 373 601Q351 623 311 626Q240 626 194 566Q147 500 147 364L148 360Q153 366 156 373Q197 433 263 433H267Q313 433 348 414Q372 400 396 374T435 317Q456 268 456 210V192Q456 169 451 149Q440 90 387 34T253 -22Q225 -22 199 -14T143 16T92 75T56 172T42 313ZM257 397Q227 397 205 380T171 335T154 278T148 216Q148 133 160 97T198 39Q222 21 251 21Q302 21 329 59Q342 77 347 104T352 209Q352 289 347 316T329 361Q302 397 257 397Z" transform="translate(1500,0)" style="stroke-width: 3;"/></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mn>256</mn><mtext> </mtext><mtext>casos</mtext><mo>×</mo><mn>16</mn><mtext> </mtext><mtext>posiciones</mtext><mo>=</mo><mn>4096</mn></math></mjx-assistive-mml></mjx-container>, pero yo tenía <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.186ex;" xmlns="http://www.w3.org/2000/svg" width="15.964ex" height="1.717ex" role="img" focusable="false" viewBox="0 -677 7056 759" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mn"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"/><path data-c="35" d="M164 157Q164 133 148 117T109 101H102Q148 22 224 22Q294 22 326 82Q345 115 345 210Q345 313 318 349Q292 382 260 382H254Q176 382 136 314Q132 307 129 306T114 304Q97 304 95 310Q93 314 93 485V614Q93 664 98 664Q100 666 102 666Q103 666 123 658T178 642T253 634Q324 634 389 662Q397 666 402 666Q410 666 410 648V635Q328 538 205 538Q174 538 149 544L139 546V374Q158 388 169 396T205 412T256 420Q337 420 393 355T449 201Q449 109 385 44T229 -22Q148 -22 99 32T50 154Q50 178 61 192T84 210T107 214Q132 214 148 197T164 157Z" transform="translate(500,0)" style="stroke-width: 3;"/><path data-c="36" d="M42 313Q42 476 123 571T303 666Q372 666 402 630T432 550Q432 525 418 510T379 495Q356 495 341 509T326 548Q326 592 373 601Q351 623 311 626Q240 626 194 566Q147 500 147 364L148 360Q153 366 156 373Q197 433 263 433H267Q313 433 348 414Q372 400 396 374T435 317Q456 268 456 210V192Q456 169 451 149Q440 90 387 34T253 -22Q225 -22 199 -14T143 16T92 75T56 172T42 313ZM257 397Q227 397 205 380T171 335T154 278T148 216Q148 133 160 97T198 39Q222 21 251 21Q302 21 329 59Q342 77 347 104T352 209Q352 289 347 316T329 361Q302 397 257 397Z" transform="translate(1000,0)" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(1722.2,0)"><path data-c="D7" d="M630 29Q630 9 609 9Q604 9 587 25T493 118L389 222L284 117Q178 13 175 11Q171 9 168 9Q160 9 154 15T147 29Q147 36 161 51T255 146L359 250L255 354Q174 435 161 449T147 471Q147 480 153 485T168 490Q173 490 175 489Q178 487 284 383L389 278L493 382Q570 459 587 475T609 491Q630 491 630 471Q630 464 620 453T522 355L418 250L522 145Q606 61 618 48T630 29Z" style="stroke-width: 3;"/></g><g data-mml-node="mn" transform="translate(2722.4,0)"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" style="stroke-width: 3;"/><path data-c="35" d="M164 157Q164 133 148 117T109 101H102Q148 22 224 22Q294 22 326 82Q345 115 345 210Q345 313 318 349Q292 382 260 382H254Q176 382 136 314Q132 307 129 306T114 304Q97 304 95 310Q93 314 93 485V614Q93 664 98 664Q100 666 102 666Q103 666 123 658T178 642T253 634Q324 634 389 662Q397 666 402 666Q410 666 410 648V635Q328 538 205 538Q174 538 149 544L139 546V374Q158 388 169 396T205 412T256 420Q337 420 393 355T449 201Q449 109 385 44T229 -22Q148 -22 99 32T50 154Q50 178 61 192T84 210T107 214Q132 214 148 197T164 157Z" transform="translate(500,0)" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(4000.2,0)"><path data-c="3D" d="M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z" style="stroke-width: 3;"/></g><g data-mml-node="mn" transform="translate(5056,0)"><path data-c="33" d="M127 463Q100 463 85 480T69 524Q69 579 117 622T233 665Q268 665 277 664Q351 652 390 611T430 522Q430 470 396 421T302 350L299 348Q299 347 308 345T337 336T375 315Q457 262 457 175Q457 96 395 37T238 -22Q158 -22 100 21T42 130Q42 158 60 175T105 193Q133 193 151 175T169 130Q169 119 166 110T159 94T148 82T136 74T126 70T118 67L114 66Q165 21 238 21Q293 21 321 74Q338 107 338 175V195Q338 290 274 322Q259 328 213 329L171 330L168 332Q166 335 166 348Q166 366 174 366Q202 366 232 371Q266 376 294 413T322 525V533Q322 590 287 612Q265 626 240 626Q208 626 181 615T143 592T132 580H135Q138 579 143 578T153 573T165 566T175 555T183 540T186 520Q186 498 172 481T127 463Z" style="stroke-width: 3;"/><path data-c="38" d="M70 417T70 494T124 618T248 666Q319 666 374 624T429 515Q429 485 418 459T392 417T361 389T335 371T324 363L338 354Q352 344 366 334T382 323Q457 264 457 174Q457 95 399 37T249 -22Q159 -22 101 29T43 155Q43 263 172 335L154 348Q133 361 127 368Q70 417 70 494ZM286 386L292 390Q298 394 301 396T311 403T323 413T334 425T345 438T355 454T364 471T369 491T371 513Q371 556 342 586T275 624Q268 625 242 625Q201 625 165 599T128 534Q128 511 141 492T167 463T217 431Q224 426 228 424L286 386ZM250 21Q308 21 350 55T392 137Q392 154 387 169T375 194T353 216T330 234T301 253T274 270Q260 279 244 289T218 306L210 311Q204 311 181 294T133 239T107 157Q107 98 150 60T250 21Z" transform="translate(500,0)" style="stroke-width: 3;"/><path data-c="34" d="M462 0Q444 3 333 3Q217 3 199 0H190V46H221Q241 46 248 46T265 48T279 53T286 61Q287 63 287 115V165H28V211L179 442Q332 674 334 675Q336 677 355 677H373L379 671V211H471V165H379V114Q379 73 379 66T385 54Q393 47 442 46H471V0H462ZM293 211V545L74 212L183 211H293Z" transform="translate(1000,0)" style="stroke-width: 3;"/><path data-c="30" d="M96 585Q152 666 249 666Q297 666 345 640T423 548Q460 465 460 320Q460 165 417 83Q397 41 362 16T301 -15T250 -22Q224 -22 198 -16T137 16T82 83Q39 165 39 320Q39 494 96 585ZM321 597Q291 629 250 629Q208 629 178 597Q153 571 145 525T137 333Q137 175 145 125T181 46Q209 16 250 16Q290 16 318 46Q347 76 354 130T362 333Q362 478 354 524T321 597Z" transform="translate(1500,0)" style="stroke-width: 3;"/></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mn>256</mn><mo>×</mo><mn>15</mn><mo>=</mo><mn>3840</mn></math></mjx-assistive-mml></mjx-container>: faltaban dieciséis filas a partir del caso 112. Todas las consultas posteriores a ese índice estaban desplazadas, por lo que el número de caso ya no coincidía con los datos de triangulación. Cuando marching cubes lee una entrada incorrecta, crea aristas cuyos dos extremos están en el mismo lado de la superficie. En una arista que realmente cruza la superficie, el parámetro de interpolación</p>
<mjx-container tabindex="0" class="MathJax" jax="SVG" display="true" style="direction: ltr; display: block; text-align: center; margin: 1em 0; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -1.909ex;" xmlns="http://www.w3.org/2000/svg" width="11.698ex" height="4.757ex" role="img" focusable="false" viewBox="0 -1259 5170.4 2102.8" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mi"><path data-c="1D461" d="M26 385Q19 392 19 395Q19 399 22 411T27 425Q29 430 36 430T87 431H140L159 511Q162 522 166 540T173 566T179 586T187 603T197 615T211 624T229 626Q247 625 254 615T261 596Q261 589 252 549T232 470L222 433Q222 431 272 431H323Q330 424 330 420Q330 398 317 385H210L174 240Q135 80 135 68Q135 26 162 26Q197 26 230 60T283 144Q285 150 288 151T303 153H307Q322 153 322 145Q322 142 319 133Q314 117 301 95T267 48T216 6T155 -11Q125 -11 98 4T59 56Q57 64 57 83V101L92 241Q127 382 128 383Q128 385 77 385H26Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(638.8,0)"><path data-c="3D" d="M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z" style="stroke-width: 3;"/></g><g data-mml-node="mfrac" transform="translate(1694.6,0)"><g data-mml-node="mrow" transform="translate(877.9,676)"><g data-mml-node="mo"><path data-c="2212" d="M84 237T84 250T98 270H679Q694 262 694 250T679 230H98Q84 237 84 250Z" style="stroke-width: 3;"/></g><g data-mml-node="msub" transform="translate(778,0)"><g data-mml-node="mi"><path data-c="1D463" d="M173 380Q173 405 154 405Q130 405 104 376T61 287Q60 286 59 284T58 281T56 279T53 278T49 278T41 278H27Q21 284 21 287Q21 294 29 316T53 368T97 419T160 441Q202 441 225 417T249 361Q249 344 246 335Q246 329 231 291T200 202T182 113Q182 86 187 69Q200 26 250 26Q287 26 319 60T369 139T398 222T409 277Q409 300 401 317T383 343T365 361T357 383Q357 405 376 424T417 443Q436 443 451 425T467 367Q467 340 455 284T418 159T347 40T241 -11Q177 -11 139 22Q102 54 102 117Q102 148 110 181T151 298Q173 362 173 380Z" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(518,-150) scale(0.707)"><path data-c="1D44E" d="M33 157Q33 258 109 349T280 441Q331 441 370 392Q386 422 416 422Q429 422 439 414T449 394Q449 381 412 234T374 68Q374 43 381 35T402 26Q411 27 422 35Q443 55 463 131Q469 151 473 152Q475 153 483 153H487Q506 153 506 144Q506 138 501 117T481 63T449 13Q436 0 417 -8Q409 -10 393 -10Q359 -10 336 5T306 36L300 51Q299 52 296 50Q294 48 292 46Q233 -10 172 -10Q117 -10 75 30T33 157ZM351 328Q351 334 346 350T323 385T277 405Q242 405 210 374T160 293Q131 214 119 129Q119 126 119 118T118 106Q118 61 136 44T179 26Q217 26 254 59T298 110Q300 114 325 217T351 328Z" style="stroke-width: 3;"/></g></g></g><g data-mml-node="mrow" transform="translate(220,-686)"><g data-mml-node="msub"><g data-mml-node="mi"><path data-c="1D463" d="M173 380Q173 405 154 405Q130 405 104 376T61 287Q60 286 59 284T58 281T56 279T53 278T49 278T41 278H27Q21 284 21 287Q21 294 29 316T53 368T97 419T160 441Q202 441 225 417T249 361Q249 344 246 335Q246 329 231 291T200 202T182 113Q182 86 187 69Q200 26 250 26Q287 26 319 60T369 139T398 222T409 277Q409 300 401 317T383 343T365 361T357 383Q357 405 376 424T417 443Q436 443 451 425T467 367Q467 340 455 284T418 159T347 40T241 -11Q177 -11 139 22Q102 54 102 117Q102 148 110 181T151 298Q173 362 173 380Z" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(518,-150) scale(0.707)"><path data-c="1D44F" d="M73 647Q73 657 77 670T89 683Q90 683 161 688T234 694Q246 694 246 685T212 542Q204 508 195 472T180 418L176 399Q176 396 182 402Q231 442 283 442Q345 442 383 396T422 280Q422 169 343 79T173 -11Q123 -11 82 27T40 150V159Q40 180 48 217T97 414Q147 611 147 623T109 637Q104 637 101 637H96Q86 637 83 637T76 640T73 647ZM336 325V331Q336 405 275 405Q258 405 240 397T207 376T181 352T163 330L157 322L136 236Q114 150 114 114Q114 66 138 42Q154 26 178 26Q211 26 245 58Q270 81 285 114T318 219Q336 291 336 325Z" style="stroke-width: 3;"/></g></g><g data-mml-node="mo" transform="translate(1093.6,0)"><path data-c="2212" d="M84 237T84 250T98 270H679Q694 262 694 250T679 230H98Q84 237 84 250Z" style="stroke-width: 3;"/></g><g data-mml-node="msub" transform="translate(2093.8,0)"><g data-mml-node="mi"><path data-c="1D463" d="M173 380Q173 405 154 405Q130 405 104 376T61 287Q60 286 59 284T58 281T56 279T53 278T49 278T41 278H27Q21 284 21 287Q21 294 29 316T53 368T97 419T160 441Q202 441 225 417T249 361Q249 344 246 335Q246 329 231 291T200 202T182 113Q182 86 187 69Q200 26 250 26Q287 26 319 60T369 139T398 222T409 277Q409 300 401 317T383 343T365 361T357 383Q357 405 376 424T417 443Q436 443 451 425T467 367Q467 340 455 284T418 159T347 40T241 -11Q177 -11 139 22Q102 54 102 117Q102 148 110 181T151 298Q173 362 173 380Z" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(518,-150) scale(0.707)"><path data-c="1D44E" d="M33 157Q33 258 109 349T280 441Q331 441 370 392Q386 422 416 422Q429 422 439 414T449 394Q449 381 412 234T374 68Q374 43 381 35T402 26Q411 27 422 35Q443 55 463 131Q469 151 473 152Q475 153 483 153H487Q506 153 506 144Q506 138 501 117T481 63T449 13Q436 0 417 -8Q409 -10 393 -10Q359 -10 336 5T306 36L300 51Q299 52 296 50Q294 48 292 46Q233 -10 172 -10Q117 -10 75 30T33 157ZM351 328Q351 334 346 350T323 385T277 405Q242 405 210 374T160 293Q131 214 119 129Q119 126 119 118T118 106Q118 61 136 44T179 26Q217 26 254 59T298 110Q300 114 325 217T351 328Z" style="stroke-width: 3;"/></g></g></g><rect width="3235.9" height="60" x="120" y="220"/></g></g></g></svg><mjx-assistive-mml unselectable="on" display="block" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; overflow: hidden; width: 100%;"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><mi>t</mi><mo>=</mo><mfrac><mrow><mo>−</mo><msub><mi>v</mi><mi>a</mi></msub></mrow><mrow><msub><mi>v</mi><mi>b</mi></msub><mo>−</mo><msub><mi>v</mi><mi>a</mi></msub></mrow></mfrac></math></mjx-assistive-mml></mjx-container><p>queda dentro de <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.566ex;" xmlns="http://www.w3.org/2000/svg" width="4.526ex" height="2.262ex" role="img" focusable="false" viewBox="0 -750 2000.7 1000" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mo"><path data-c="5B" d="M118 -250V750H255V710H158V-210H255V-250H118Z" style="stroke-width: 3;"/></g><g data-mml-node="mn" transform="translate(278,0)"><path data-c="30" d="M96 585Q152 666 249 666Q297 666 345 640T423 548Q460 465 460 320Q460 165 417 83Q397 41 362 16T301 -15T250 -22Q224 -22 198 -16T137 16T82 83Q39 165 39 320Q39 494 96 585ZM321 597Q291 629 250 629Q208 629 178 597Q153 571 145 525T137 333Q137 175 145 125T181 46Q209 16 250 16Q290 16 318 46Q347 76 354 130T362 333Q362 478 354 524T321 597Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(778,0)"><path data-c="2C" d="M78 35T78 60T94 103T137 121Q165 121 187 96T210 8Q210 -27 201 -60T180 -117T154 -158T130 -185T117 -194Q113 -194 104 -185T95 -172Q95 -168 106 -156T131 -126T157 -76T173 -3V9L172 8Q170 7 167 6T161 3T152 1T140 0Q113 0 96 17Z" style="stroke-width: 3;"/></g><g data-mml-node="mn" transform="translate(1222.7,0)"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(1722.7,0)"><path data-c="5D" d="M22 710V750H159V-250H22V-210H119V710H22Z" style="stroke-width: 3;"/></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mo stretchy="false">[</mo><mn>0</mn><mo>,</mo><mn>1</mn><mo stretchy="false">]</mo></math></mjx-assistive-mml></mjx-container> porque <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.355ex;" xmlns="http://www.w3.org/2000/svg" width="2.131ex" height="1.358ex" role="img" focusable="false" viewBox="0 -443 942.1 600.1" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="msub"><g data-mml-node="mi"><path data-c="1D463" d="M173 380Q173 405 154 405Q130 405 104 376T61 287Q60 286 59 284T58 281T56 279T53 278T49 278T41 278H27Q21 284 21 287Q21 294 29 316T53 368T97 419T160 441Q202 441 225 417T249 361Q249 344 246 335Q246 329 231 291T200 202T182 113Q182 86 187 69Q200 26 250 26Q287 26 319 60T369 139T398 222T409 277Q409 300 401 317T383 343T365 361T357 383Q357 405 376 424T417 443Q436 443 451 425T467 367Q467 340 455 284T418 159T347 40T241 -11Q177 -11 139 22Q102 54 102 117Q102 148 110 181T151 298Q173 362 173 380Z" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(518,-150) scale(0.707)"><path data-c="1D44E" d="M33 157Q33 258 109 349T280 441Q331 441 370 392Q386 422 416 422Q429 422 439 414T449 394Q449 381 412 234T374 68Q374 43 381 35T402 26Q411 27 422 35Q443 55 463 131Q469 151 473 152Q475 153 483 153H487Q506 153 506 144Q506 138 501 117T481 63T449 13Q436 0 417 -8Q409 -10 393 -10Q359 -10 336 5T306 36L300 51Q299 52 296 50Q294 48 292 46Q233 -10 172 -10Q117 -10 75 30T33 157ZM351 328Q351 334 346 350T323 385T277 405Q242 405 210 374T160 293Q131 214 119 129Q119 126 119 118T118 106Q118 61 136 44T179 26Q217 26 254 59T298 110Q300 114 325 217T351 328Z" style="stroke-width: 3;"/></g></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><msub><mi>v</mi><mi>a</mi></msub></math></mjx-assistive-mml></mjx-container> y <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.357ex;" xmlns="http://www.w3.org/2000/svg" width="1.971ex" height="1.359ex" role="img" focusable="false" viewBox="0 -443 871.3 600.8" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="msub"><g data-mml-node="mi"><path data-c="1D463" d="M173 380Q173 405 154 405Q130 405 104 376T61 287Q60 286 59 284T58 281T56 279T53 278T49 278T41 278H27Q21 284 21 287Q21 294 29 316T53 368T97 419T160 441Q202 441 225 417T249 361Q249 344 246 335Q246 329 231 291T200 202T182 113Q182 86 187 69Q200 26 250 26Q287 26 319 60T369 139T398 222T409 277Q409 300 401 317T383 343T365 361T357 383Q357 405 376 424T417 443Q436 443 451 425T467 367Q467 340 455 284T418 159T347 40T241 -11Q177 -11 139 22Q102 54 102 117Q102 148 110 181T151 298Q173 362 173 380Z" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(518,-150) scale(0.707)"><path data-c="1D44F" d="M73 647Q73 657 77 670T89 683Q90 683 161 688T234 694Q246 694 246 685T212 542Q204 508 195 472T180 418L176 399Q176 396 182 402Q231 442 283 442Q345 442 383 396T422 280Q422 169 343 79T173 -11Q123 -11 82 27T40 150V159Q40 180 48 217T97 414Q147 611 147 623T109 637Q104 637 101 637H96Q86 637 83 637T76 640T73 647ZM336 325V331Q336 405 275 405Q258 405 240 397T207 376T181 352T163 330L157 322L136 236Q114 150 114 114Q114 66 138 42Q154 26 178 26Q211 26 245 58Q270 81 285 114T318 219Q336 291 336 325Z" style="stroke-width: 3;"/></g></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><msub><mi>v</mi><mi>b</mi></msub></math></mjx-assistive-mml></mjx-container> tienen signos opuestos. En una arista falsa tienen el mismo signo, por lo que <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.357ex;" xmlns="http://www.w3.org/2000/svg" width="6.868ex" height="1.676ex" role="img" focusable="false" viewBox="0 -583 3035.9 740.8" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="msub"><g data-mml-node="mi"><path data-c="1D463" d="M173 380Q173 405 154 405Q130 405 104 376T61 287Q60 286 59 284T58 281T56 279T53 278T49 278T41 278H27Q21 284 21 287Q21 294 29 316T53 368T97 419T160 441Q202 441 225 417T249 361Q249 344 246 335Q246 329 231 291T200 202T182 113Q182 86 187 69Q200 26 250 26Q287 26 319 60T369 139T398 222T409 277Q409 300 401 317T383 343T365 361T357 383Q357 405 376 424T417 443Q436 443 451 425T467 367Q467 340 455 284T418 159T347 40T241 -11Q177 -11 139 22Q102 54 102 117Q102 148 110 181T151 298Q173 362 173 380Z" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(518,-150) scale(0.707)"><path data-c="1D44F" d="M73 647Q73 657 77 670T89 683Q90 683 161 688T234 694Q246 694 246 685T212 542Q204 508 195 472T180 418L176 399Q176 396 182 402Q231 442 283 442Q345 442 383 396T422 280Q422 169 343 79T173 -11Q123 -11 82 27T40 150V159Q40 180 48 217T97 414Q147 611 147 623T109 637Q104 637 101 637H96Q86 637 83 637T76 640T73 647ZM336 325V331Q336 405 275 405Q258 405 240 397T207 376T181 352T163 330L157 322L136 236Q114 150 114 114Q114 66 138 42Q154 26 178 26Q211 26 245 58Q270 81 285 114T318 219Q336 291 336 325Z" style="stroke-width: 3;"/></g></g><g data-mml-node="mo" transform="translate(1093.6,0)"><path data-c="2212" d="M84 237T84 250T98 270H679Q694 262 694 250T679 230H98Q84 237 84 250Z" style="stroke-width: 3;"/></g><g data-mml-node="msub" transform="translate(2093.8,0)"><g data-mml-node="mi"><path data-c="1D463" d="M173 380Q173 405 154 405Q130 405 104 376T61 287Q60 286 59 284T58 281T56 279T53 278T49 278T41 278H27Q21 284 21 287Q21 294 29 316T53 368T97 419T160 441Q202 441 225 417T249 361Q249 344 246 335Q246 329 231 291T200 202T182 113Q182 86 187 69Q200 26 250 26Q287 26 319 60T369 139T398 222T409 277Q409 300 401 317T383 343T365 361T357 383Q357 405 376 424T417 443Q436 443 451 425T467 367Q467 340 455 284T418 159T347 40T241 -11Q177 -11 139 22Q102 54 102 117Q102 148 110 181T151 298Q173 362 173 380Z" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(518,-150) scale(0.707)"><path data-c="1D44E" d="M33 157Q33 258 109 349T280 441Q331 441 370 392Q386 422 416 422Q429 422 439 414T449 394Q449 381 412 234T374 68Q374 43 381 35T402 26Q411 27 422 35Q443 55 463 131Q469 151 473 152Q475 153 483 153H487Q506 153 506 144Q506 138 501 117T481 63T449 13Q436 0 417 -8Q409 -10 393 -10Q359 -10 336 5T306 36L300 51Q299 52 296 50Q294 48 292 46Q233 -10 172 -10Q117 -10 75 30T33 157ZM351 328Q351 334 346 350T323 385T277 405Q242 405 210 374T160 293Q131 214 119 129Q119 126 119 118T118 106Q118 61 136 44T179 26Q217 26 254 59T298 110Q300 114 325 217T351 328Z" style="stroke-width: 3;"/></g></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><msub><mi>v</mi><mi>b</mi></msub><mo>−</mo><msub><mi>v</mi><mi>a</mi></msub></math></mjx-assistive-mml></mjx-container> está cerca de cero o cambia de signo y <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.025ex;" xmlns="http://www.w3.org/2000/svg" width="0.817ex" height="1.441ex" role="img" focusable="false" viewBox="0 -626 361 637" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mi"><path data-c="1D461" d="M26 385Q19 392 19 395Q19 399 22 411T27 425Q29 430 36 430T87 431H140L159 511Q162 522 166 540T173 566T179 586T187 603T197 615T211 624T229 626Q247 625 254 615T261 596Q261 589 252 549T232 470L222 433Q222 431 272 431H323Q330 424 330 420Q330 398 317 385H210L174 240Q135 80 135 68Q135 26 162 26Q197 26 230 60T283 144Q285 150 288 151T303 153H307Q322 153 322 145Q322 142 319 133Q314 117 301 95T267 48T216 6T155 -11Q125 -11 98 4T59 56Q57 64 57 83V101L92 241Q127 382 128 383Q128 385 77 385H26Z" style="stroke-width: 3;"/></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mi>t</mi></math></mjx-assistive-mml></mjx-container> sale disparado fuera de <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.566ex;" xmlns="http://www.w3.org/2000/svg" width="4.526ex" height="2.262ex" role="img" focusable="false" viewBox="0 -750 2000.7 1000" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mo"><path data-c="5B" d="M118 -250V750H255V710H158V-210H255V-250H118Z" style="stroke-width: 3;"/></g><g data-mml-node="mn" transform="translate(278,0)"><path data-c="30" d="M96 585Q152 666 249 666Q297 666 345 640T423 548Q460 465 460 320Q460 165 417 83Q397 41 362 16T301 -15T250 -22Q224 -22 198 -16T137 16T82 83Q39 165 39 320Q39 494 96 585ZM321 597Q291 629 250 629Q208 629 178 597Q153 571 145 525T137 333Q137 175 145 125T181 46Q209 16 250 16Q290 16 318 46Q347 76 354 130T362 333Q362 478 354 524T321 597Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(778,0)"><path data-c="2C" d="M78 35T78 60T94 103T137 121Q165 121 187 96T210 8Q210 -27 201 -60T180 -117T154 -158T130 -185T117 -194Q113 -194 104 -185T95 -172Q95 -168 106 -156T131 -126T157 -76T173 -3V9L172 8Q170 7 167 6T161 3T152 1T140 0Q113 0 96 17Z" style="stroke-width: 3;"/></g><g data-mml-node="mn" transform="translate(1222.7,0)"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(1722.7,0)"><path data-c="5D" d="M22 710V750H159V-250H22V-210H119V710H22Z" style="stroke-width: 3;"/></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mo stretchy="false">[</mo><mn>0</mn><mo>,</mo><mn>1</mn><mo stretchy="false">]</mo></math></mjx-assistive-mml></mjx-container>, colocando el vértice muy lejos del volumen. Multiplica eso por unos cientos de celdas incorrectas y obtendrás un erizo.</p>
<p>La solución fue absurdamente sencilla: copiar byte por byte la tabla probada del Spike 12. Lección aprendida. Nunca regeneres una tabla de consulta cuando ya existe una copia probada.</p>
<p>El segundo error era más sutil. Se suponía que el pincel de suavizado debía suavizar las formas del terreno. En cambio, creaba pliegues pronunciados. El problema era que yo atraía todos los valores SDF hacia cero, es decir, hacia la isosuperficie. Parece que eso debería suavizar las cosas, pero en realidad colapsa el campo de distancias. Los vóxeles por encima y por debajo de la superficie se precipitan hacia cero, aplanándolo todo dentro del radio del pincel. En el límite, los vóxeles suavizados se encuentran con los no suavizados formando un escalón abrupto. El pincel de «suavizado» era un generador de pliegues.</p>
<p>La solución fue aplicar un suavizado laplaciano adecuado. En lugar de atraer cada valor hacia cero, hay que llevarlo hacia el promedio de sus 6 vecinos directos:</p>
<mjx-container tabindex="0" class="MathJax" jax="SVG" display="true" style="direction: ltr; display: block; text-align: center; margin: 1em 0; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -3.222ex;" xmlns="http://www.w3.org/2000/svg" width="30.99ex" height="7.575ex" role="img" focusable="false" viewBox="0 -1924.1 13697.6 3348.2" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="msub"><g data-mml-node="mi"><path data-c="1D719" d="M409 688Q413 694 421 694H429H442Q448 688 448 686Q448 679 418 563Q411 535 404 504T392 458L388 442Q388 441 397 441T429 435T477 418Q521 397 550 357T579 260T548 151T471 65T374 11T279 -10H275L251 -105Q245 -128 238 -160Q230 -192 227 -198T215 -205H209Q189 -205 189 -198Q189 -193 211 -103L234 -11Q234 -10 226 -10Q221 -10 206 -8T161 6T107 36T62 89T43 171Q43 231 76 284T157 370T254 422T342 441Q347 441 348 445L378 567Q409 686 409 688ZM122 150Q122 116 134 91T167 53T203 35T237 27H244L337 404Q333 404 326 403T297 395T255 379T211 350T170 304Q152 276 137 237Q122 191 122 150ZM500 282Q500 320 484 347T444 385T405 400T381 404H378L332 217L284 29Q284 27 285 27Q293 27 317 33T357 47Q400 66 431 100T475 170T494 234T500 282Z" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(629,-150) scale(0.707)"><path data-c="1D456" d="M184 600Q184 624 203 642T247 661Q265 661 277 649T290 619Q290 596 270 577T226 557Q211 557 198 567T184 600ZM21 287Q21 295 30 318T54 369T98 420T158 442Q197 442 223 419T250 357Q250 340 236 301T196 196T154 83Q149 61 149 51Q149 26 166 26Q175 26 185 29T208 43T235 78T260 137Q263 149 265 151T282 153Q302 153 302 143Q302 135 293 112T268 61T223 11T161 -11Q129 -11 102 10T74 74Q74 91 79 106T122 220Q160 321 166 341T173 380Q173 404 156 404H154Q124 404 99 371T61 287Q60 286 59 284T58 281T56 279T53 278T49 278T41 278H27Q21 284 21 287Z" style="stroke-width: 3;"/></g></g><g data-mml-node="mo" transform="translate(1200.7,0)"><path data-c="2190" d="M944 261T944 250T929 230H165Q167 228 182 216T211 189T244 152T277 96T303 25Q308 7 308 0Q308 -11 288 -11Q281 -11 278 -11T272 -7T267 2T263 21Q245 94 195 151T73 236Q58 242 55 247Q55 254 59 257T73 264Q121 283 158 314T215 375T247 434T264 480L267 497Q269 503 270 505T275 509T288 511Q308 511 308 500Q308 493 303 475Q293 438 278 406T246 352T215 315T185 287T165 270H929Q944 261 944 250Z" style="stroke-width: 3;"/></g><g data-mml-node="msub" transform="translate(2478.5,0)"><g data-mml-node="mi"><path data-c="1D719" d="M409 688Q413 694 421 694H429H442Q448 688 448 686Q448 679 418 563Q411 535 404 504T392 458L388 442Q388 441 397 441T429 435T477 418Q521 397 550 357T579 260T548 151T471 65T374 11T279 -10H275L251 -105Q245 -128 238 -160Q230 -192 227 -198T215 -205H209Q189 -205 189 -198Q189 -193 211 -103L234 -11Q234 -10 226 -10Q221 -10 206 -8T161 6T107 36T62 89T43 171Q43 231 76 284T157 370T254 422T342 441Q347 441 348 445L378 567Q409 686 409 688ZM122 150Q122 116 134 91T167 53T203 35T237 27H244L337 404Q333 404 326 403T297 395T255 379T211 350T170 304Q152 276 137 237Q122 191 122 150ZM500 282Q500 320 484 347T444 385T405 400T381 404H378L332 217L284 29Q284 27 285 27Q293 27 317 33T357 47Q400 66 431 100T475 170T494 234T500 282Z" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(629,-150) scale(0.707)"><path data-c="1D456" d="M184 600Q184 624 203 642T247 661Q265 661 277 649T290 619Q290 596 270 577T226 557Q211 557 198 567T184 600ZM21 287Q21 295 30 318T54 369T98 420T158 442Q197 442 223 419T250 357Q250 340 236 301T196 196T154 83Q149 61 149 51Q149 26 166 26Q175 26 185 29T208 43T235 78T260 137Q263 149 265 151T282 153Q302 153 302 143Q302 135 293 112T268 61T223 11T161 -11Q129 -11 102 10T74 74Q74 91 79 106T122 220Q160 321 166 341T173 380Q173 404 156 404H154Q124 404 99 371T61 287Q60 286 59 284T58 281T56 279T53 278T49 278T41 278H27Q21 284 21 287Z" style="stroke-width: 3;"/></g></g><g data-mml-node="mo" transform="translate(3623.7,0)"><path data-c="2B" d="M56 237T56 250T70 270H369V420L370 570Q380 583 389 583Q402 583 409 568V270H707Q722 262 722 250T707 230H409V-68Q401 -82 391 -82H389H387Q375 -82 369 -68V230H70Q56 237 56 250Z" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(4623.9,0)"><path data-c="1D706" d="M166 673Q166 685 183 694H202Q292 691 316 644Q322 629 373 486T474 207T524 67Q531 47 537 34T546 15T551 6T555 2T556 -2T550 -11H482Q457 3 450 18T399 152L354 277L340 262Q327 246 293 207T236 141Q211 112 174 69Q123 9 111 -1T83 -12Q47 -12 47 20Q47 37 61 52T199 187Q229 216 266 252T321 306L338 322Q338 323 288 462T234 612Q214 657 183 657Q166 657 166 673Z" style="stroke-width: 3;"/></g><g data-mml-node="mrow" transform="translate(5373.6,0)"><g data-mml-node="mo"><path data-c="239B" d="M837 1154Q843 1148 843 1145Q843 1141 818 1106T753 1002T667 841T574 604T494 299Q417 -84 417 -609Q417 -641 416 -647T411 -654Q409 -655 366 -655Q299 -655 297 -654Q292 -652 292 -643T291 -583Q293 -400 304 -242T347 110T432 470T574 813T785 1136Q787 1139 790 1142T794 1147T796 1150T799 1152T802 1153T807 1154T813 1154H819H837Z" transform="translate(0,770.1)" style="stroke-width: 3;"/><path data-c="239D" d="M843 -635Q843 -638 837 -644H820Q801 -644 800 -643Q792 -635 785 -626Q684 -503 605 -363T473 -75T385 216T330 518T302 809T291 1093Q291 1144 291 1153T296 1164Q298 1165 366 1165Q409 1165 411 1164Q415 1163 416 1157T417 1119Q417 529 517 109T833 -617Q843 -631 843 -635Z" transform="translate(0,-780.1)" style="stroke-width: 3;"/></g><g data-mml-node="mfrac" transform="translate(875,0)"><g data-mml-node="mn" transform="translate(220,676)"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" style="stroke-width: 3;"/></g><g data-mml-node="mn" transform="translate(220,-686)"><path data-c="36" d="M42 313Q42 476 123 571T303 666Q372 666 402 630T432 550Q432 525 418 510T379 495Q356 495 341 509T326 548Q326 592 373 601Q351 623 311 626Q240 626 194 566Q147 500 147 364L148 360Q153 366 156 373Q197 433 263 433H267Q313 433 348 414Q372 400 396 374T435 317Q456 268 456 210V192Q456 169 451 149Q440 90 387 34T253 -22Q225 -22 199 -14T143 16T92 75T56 172T42 313ZM257 397Q227 397 205 380T171 335T154 278T148 216Q148 133 160 97T198 39Q222 21 251 21Q302 21 329 59Q342 77 347 104T352 209Q352 289 347 316T329 361Q302 397 257 397Z" style="stroke-width: 3;"/></g><rect width="700" height="60" x="120" y="220"/></g><g data-mml-node="munder" transform="translate(1981.7,0)"><g data-mml-node="mo" transform="translate(370.5,0)"><path data-c="2211" d="M60 948Q63 950 665 950H1267L1325 815Q1384 677 1388 669H1348L1341 683Q1320 724 1285 761Q1235 809 1174 838T1033 881T882 898T699 902H574H543H251L259 891Q722 258 724 252Q725 250 724 246Q721 243 460 -56L196 -356Q196 -357 407 -357Q459 -357 548 -357T676 -358Q812 -358 896 -353T1063 -332T1204 -283T1307 -196Q1328 -170 1348 -124H1388Q1388 -125 1381 -145T1356 -210T1325 -294L1267 -449L666 -450Q64 -450 61 -448Q55 -446 55 -439Q55 -437 57 -433L590 177Q590 178 557 222T452 366T322 544L56 909L55 924Q55 945 60 948Z" style="stroke-width: 3;"/></g><g data-mml-node="TeXAtom" transform="translate(0,-1147.3) scale(0.707)" data-mjx-texclass="ORD"><g data-mml-node="mi"><path data-c="1D457" d="M297 596Q297 627 318 644T361 661Q378 661 389 651T403 623Q403 595 384 576T340 557Q322 557 310 567T297 596ZM288 376Q288 405 262 405Q240 405 220 393T185 362T161 325T144 293L137 279Q135 278 121 278H107Q101 284 101 286T105 299Q126 348 164 391T252 441Q253 441 260 441T272 442Q296 441 316 432Q341 418 354 401T367 348V332L318 133Q267 -67 264 -75Q246 -125 194 -164T75 -204Q25 -204 7 -183T-12 -137Q-12 -110 7 -91T53 -71Q70 -71 82 -81T95 -112Q95 -148 63 -167Q69 -168 77 -168Q111 -168 139 -140T182 -74L193 -32Q204 11 219 72T251 197T278 308T289 365Q289 372 288 376Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(412,0)"><path data-c="2208" d="M84 250Q84 372 166 450T360 539Q361 539 377 539T419 540T469 540H568Q583 532 583 520Q583 511 570 501L466 500Q355 499 329 494Q280 482 242 458T183 409T147 354T129 306T124 272V270H568Q583 262 583 250T568 230H124V228Q124 207 134 177T167 112T231 48T328 7Q355 1 466 0H570Q583 -10 583 -20Q583 -32 568 -40H471Q464 -40 446 -40T417 -41Q262 -41 172 45Q84 127 84 250Z" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(1079,0)"><path data-c="1D441" d="M234 637Q231 637 226 637Q201 637 196 638T191 649Q191 676 202 682Q204 683 299 683Q376 683 387 683T401 677Q612 181 616 168L670 381Q723 592 723 606Q723 633 659 637Q635 637 635 648Q635 650 637 660Q641 676 643 679T653 683Q656 683 684 682T767 680Q817 680 843 681T873 682Q888 682 888 672Q888 650 880 642Q878 637 858 637Q787 633 769 597L620 7Q618 0 599 0Q585 0 582 2Q579 5 453 305L326 604L261 344Q196 88 196 79Q201 46 268 46H278Q284 41 284 38T282 19Q278 6 272 0H259Q228 2 151 2Q123 2 100 2T63 2T46 1Q31 1 31 10Q31 14 34 26T39 40Q41 46 62 46Q130 49 150 85Q154 91 221 362L289 634Q287 635 234 637Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(1967,0)"><path data-c="28" d="M94 250Q94 319 104 381T127 488T164 576T202 643T244 695T277 729T302 750H315H319Q333 750 333 741Q333 738 316 720T275 667T226 581T184 443T167 250T184 58T225 -81T274 -167T316 -220T333 -241Q333 -250 318 -250H315H302L274 -226Q180 -141 137 -14T94 250Z" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(2356,0)"><path data-c="1D456" d="M184 600Q184 624 203 642T247 661Q265 661 277 649T290 619Q290 596 270 577T226 557Q211 557 198 567T184 600ZM21 287Q21 295 30 318T54 369T98 420T158 442Q197 442 223 419T250 357Q250 340 236 301T196 196T154 83Q149 61 149 51Q149 26 166 26Q175 26 185 29T208 43T235 78T260 137Q263 149 265 151T282 153Q302 153 302 143Q302 135 293 112T268 61T223 11T161 -11Q129 -11 102 10T74 74Q74 91 79 106T122 220Q160 321 166 341T173 380Q173 404 156 404H154Q124 404 99 371T61 287Q60 286 59 284T58 281T56 279T53 278T49 278T41 278H27Q21 284 21 287Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(2701,0)"><path data-c="29" d="M60 749L64 750Q69 750 74 750H86L114 726Q208 641 251 514T294 250Q294 182 284 119T261 12T224 -76T186 -143T145 -194T113 -227T90 -246Q87 -249 86 -250H74Q66 -250 63 -250T58 -247T55 -238Q56 -237 66 -225Q221 -64 221 250T66 725Q56 737 55 738Q55 746 60 749Z" style="stroke-width: 3;"/></g></g></g><g data-mml-node="msub" transform="translate(4333.3,0)"><g data-mml-node="mi"><path data-c="1D719" d="M409 688Q413 694 421 694H429H442Q448 688 448 686Q448 679 418 563Q411 535 404 504T392 458L388 442Q388 441 397 441T429 435T477 418Q521 397 550 357T579 260T548 151T471 65T374 11T279 -10H275L251 -105Q245 -128 238 -160Q230 -192 227 -198T215 -205H209Q189 -205 189 -198Q189 -193 211 -103L234 -11Q234 -10 226 -10Q221 -10 206 -8T161 6T107 36T62 89T43 171Q43 231 76 284T157 370T254 422T342 441Q347 441 348 445L378 567Q409 686 409 688ZM122 150Q122 116 134 91T167 53T203 35T237 27H244L337 404Q333 404 326 403T297 395T255 379T211 350T170 304Q152 276 137 237Q122 191 122 150ZM500 282Q500 320 484 347T444 385T405 400T381 404H378L332 217L284 29Q284 27 285 27Q293 27 317 33T357 47Q400 66 431 100T475 170T494 234T500 282Z" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(629,-150) scale(0.707)"><path data-c="1D457" d="M297 596Q297 627 318 644T361 661Q378 661 389 651T403 623Q403 595 384 576T340 557Q322 557 310 567T297 596ZM288 376Q288 405 262 405Q240 405 220 393T185 362T161 325T144 293L137 279Q135 278 121 278H107Q101 284 101 286T105 299Q126 348 164 391T252 441Q253 441 260 441T272 442Q296 441 316 432Q341 418 354 401T367 348V332L318 133Q267 -67 264 -75Q246 -125 194 -164T75 -204Q25 -204 7 -183T-12 -137Q-12 -110 7 -91T53 -71Q70 -71 82 -81T95 -112Q95 -148 63 -167Q69 -168 77 -168Q111 -168 139 -140T182 -74L193 -32Q204 11 219 72T251 197T278 308T289 365Q289 372 288 376Z" style="stroke-width: 3;"/></g></g><g data-mml-node="mo" transform="translate(5525.8,0)"><path data-c="2212" d="M84 237T84 250T98 270H679Q694 262 694 250T679 230H98Q84 237 84 250Z" style="stroke-width: 3;"/></g><g data-mml-node="msub" transform="translate(6526.1,0)"><g data-mml-node="mi"><path data-c="1D719" d="M409 688Q413 694 421 694H429H442Q448 688 448 686Q448 679 418 563Q411 535 404 504T392 458L388 442Q388 441 397 441T429 435T477 418Q521 397 550 357T579 260T548 151T471 65T374 11T279 -10H275L251 -105Q245 -128 238 -160Q230 -192 227 -198T215 -205H209Q189 -205 189 -198Q189 -193 211 -103L234 -11Q234 -10 226 -10Q221 -10 206 -8T161 6T107 36T62 89T43 171Q43 231 76 284T157 370T254 422T342 441Q347 441 348 445L378 567Q409 686 409 688ZM122 150Q122 116 134 91T167 53T203 35T237 27H244L337 404Q333 404 326 403T297 395T255 379T211 350T170 304Q152 276 137 237Q122 191 122 150ZM500 282Q500 320 484 347T444 385T405 400T381 404H378L332 217L284 29Q284 27 285 27Q293 27 317 33T357 47Q400 66 431 100T475 170T494 234T500 282Z" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(629,-150) scale(0.707)"><path data-c="1D456" d="M184 600Q184 624 203 642T247 661Q265 661 277 649T290 619Q290 596 270 577T226 557Q211 557 198 567T184 600ZM21 287Q21 295 30 318T54 369T98 420T158 442Q197 442 223 419T250 357Q250 340 236 301T196 196T154 83Q149 61 149 51Q149 26 166 26Q175 26 185 29T208 43T235 78T260 137Q263 149 265 151T282 153Q302 153 302 143Q302 135 293 112T268 61T223 11T161 -11Q129 -11 102 10T74 74Q74 91 79 106T122 220Q160 321 166 341T173 380Q173 404 156 404H154Q124 404 99 371T61 287Q60 286 59 284T58 281T56 279T53 278T49 278T41 278H27Q21 284 21 287Z" style="stroke-width: 3;"/></g></g><g data-mml-node="mo" transform="translate(7449,0)"><path data-c="239E" d="M31 1143Q31 1154 49 1154H59Q72 1154 75 1152T89 1136Q190 1013 269 873T401 585T489 294T544 -8T572 -299T583 -583Q583 -634 583 -643T577 -654Q575 -655 508 -655Q465 -655 463 -654Q459 -653 458 -647T457 -609Q457 -58 371 340T100 1037Q87 1059 61 1098T31 1143Z" transform="translate(0,770.1)" style="stroke-width: 3;"/><path data-c="23A0" d="M56 -644H50Q31 -644 31 -635Q31 -632 37 -622Q69 -579 100 -527Q286 -228 371 170T457 1119Q457 1161 462 1164Q464 1165 520 1165Q575 1165 577 1164Q582 1162 582 1153T583 1093Q581 910 570 752T527 400T442 40T300 -303T89 -626Q78 -640 75 -642T61 -644H56Z" transform="translate(0,-780.1)" style="stroke-width: 3;"/></g></g></g></g></svg><mjx-assistive-mml unselectable="on" display="block" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; overflow: hidden; width: 100%;"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><msub><mi>ϕ</mi><mi>i</mi></msub><mo stretchy="false">←</mo><msub><mi>ϕ</mi><mi>i</mi></msub><mo>+</mo><mi>λ</mi><mrow data-mjx-texclass="INNER"><mo data-mjx-texclass="OPEN">(</mo><mfrac><mn>1</mn><mn>6</mn></mfrac><munder><mo data-mjx-texclass="OP">∑</mo><mrow data-mjx-texclass="ORD"><mi>j</mi><mo>∈</mo><mi>N</mi><mo stretchy="false">(</mo><mi>i</mi><mo stretchy="false">)</mo></mrow></munder><msub><mi>ϕ</mi><mi>j</mi></msub><mo>−</mo><msub><mi>ϕ</mi><mi>i</mi></msub><mo data-mjx-texclass="CLOSE">)</mo></mrow></math></mjx-assistive-mml></mjx-container><p>El término entre paréntesis es un laplaciano discreto y <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.566ex;" xmlns="http://www.w3.org/2000/svg" width="8.862ex" height="2.262ex" role="img" focusable="false" viewBox="0 -750 3917.2 1000" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mi"><path data-c="1D706" d="M166 673Q166 685 183 694H202Q292 691 316 644Q322 629 373 486T474 207T524 67Q531 47 537 34T546 15T551 6T555 2T556 -2T550 -11H482Q457 3 450 18T399 152L354 277L340 262Q327 246 293 207T236 141Q211 112 174 69Q123 9 111 -1T83 -12Q47 -12 47 20Q47 37 61 52T199 187Q229 216 266 252T321 306L338 322Q338 323 288 462T234 612Q214 657 183 657Q166 657 166 673Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(860.8,0)"><path data-c="2208" d="M84 250Q84 372 166 450T360 539Q361 539 377 539T419 540T469 540H568Q583 532 583 520Q583 511 570 501L466 500Q355 499 329 494Q280 482 242 458T183 409T147 354T129 306T124 272V270H568Q583 262 583 250T568 230H124V228Q124 207 134 177T167 112T231 48T328 7Q355 1 466 0H570Q583 -10 583 -20Q583 -32 568 -40H471Q464 -40 446 -40T417 -41Q262 -41 172 45Q84 127 84 250Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(1805.6,0)"><path data-c="28" d="M94 250Q94 319 104 381T127 488T164 576T202 643T244 695T277 729T302 750H315H319Q333 750 333 741Q333 738 316 720T275 667T226 581T184 443T167 250T184 58T225 -81T274 -167T316 -220T333 -241Q333 -250 318 -250H315H302L274 -226Q180 -141 137 -14T94 250Z" style="stroke-width: 3;"/></g><g data-mml-node="mn" transform="translate(2194.6,0)"><path data-c="30" d="M96 585Q152 666 249 666Q297 666 345 640T423 548Q460 465 460 320Q460 165 417 83Q397 41 362 16T301 -15T250 -22Q224 -22 198 -16T137 16T82 83Q39 165 39 320Q39 494 96 585ZM321 597Q291 629 250 629Q208 629 178 597Q153 571 145 525T137 333Q137 175 145 125T181 46Q209 16 250 16Q290 16 318 46Q347 76 354 130T362 333Q362 478 354 524T321 597Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(2694.6,0)"><path data-c="2C" d="M78 35T78 60T94 103T137 121Q165 121 187 96T210 8Q210 -27 201 -60T180 -117T154 -158T130 -185T117 -194Q113 -194 104 -185T95 -172Q95 -168 106 -156T131 -126T157 -76T173 -3V9L172 8Q170 7 167 6T161 3T152 1T140 0Q113 0 96 17Z" style="stroke-width: 3;"/></g><g data-mml-node="mn" transform="translate(3139.2,0)"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(3639.2,0)"><path data-c="5D" d="M22 710V750H159V-250H22V-210H119V710H22Z" style="stroke-width: 3;"/></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mi>λ</mi><mo>∈</mo><mo stretchy="false">(</mo><mn>0</mn><mo>,</mo><mn>1</mn><mo stretchy="false">]</mo></math></mjx-assistive-mml></mjx-container> es la intensidad del suavizado. Esto promedia la geometría cercana y suaviza la forma de la superficie, a la vez que preserva el gradiente del campo de distancias en lugar de colapsarlo.</p>
<h2 id="todo-a-la-vez" tabindex="-1">Todo a la vez <a class="header-anchor" href="#todo-a-la-vez" aria-label="Permalink to &quot;Todo a la vez&quot;"></a></h2>
<p>El Spike 27 era la prueba de integración. Había que tomar la canalización completa del Spike 24 —parches de mapa de alturas, chunks MC, uniones Transvoxel y LOD con geomorfismo— y combinarla con el modelo de datos muestreados del Spike 25 y ambos tipos de pincel.</p>
<div style="position:relative;padding-bottom:56.25%;height:0;overflow:hidden;border-radius:8px;margin:1.5rem 0;border:1px solid rgba(255,255,255,0.12)">
<iframe src="/es/spikes/27-hm-mc-brush/" title="Spike 27: Integración de HM + MC + pinceles" style="position:absolute;top:0;left:0;width:100%;height:100%;border:0;background:#000" loading="lazy" allowfullscreen></iframe>
</div>
<p><a href="/es/spikes/27-hm-mc-brush/" target="_blank">Abrir el Spike 27 en una pestaña nueva ↗</a> · <a href="/es/blog/spike-source?spike=27-hm-mc-brush">Ver el código fuente</a></p>
<p>Lo primero que hice fue arrancar <code>height_at()</code> de todos los shaders. Los tres shaders de cómputo —relleno de SDF, parche de mapa de alturas y unión Transvoxel— ahora enlazan el mismo búfer de GPU de mapa de alturas de 129x129 y usan la misma función de interpolación bilineal <code>hm_sample()</code> mediante un preámbulo WGSL compartido. Una fuente de datos, múltiples consumidores. Las funciones de ruido procedimental que habían vivido en todos los shaders desde el Spike 1 desaparecieron.</p>
<p>Entonces empezaron los problemas interesantes.</p>
<p>Cuando un pincel SDF bloquea un chunk en modo MC, la unión Transvoxel entre ese chunk y su vecino de mapa de alturas debe muestrear el volumen SDF, no el mapa de alturas. Amplié el shader de uniones con enlaces adicionales a búferes de almacenamiento e indicadores MC por chunk. Había que gestionar cuatro combinaciones de límites: HM-HM, HM-MC, MC-HM y MC-MC.</p>
<p>El LOD era otro rompecabezas. En spikes anteriores, cambiar un chunk MC a un LOD inferior implicaba volver a rellenar el SDF con una resolución más baja. Lo sustituí por un muestreo basado en el paso: los datos SDF permanecen a resolución completa, con 65 puntos de cuadrícula. El shader MC calcula un paso a partir de la relación entre el tamaño de la cuadrícula y el número de celdas. En LOD0, el paso es 1. En LOD1, el paso es 2 y se muestrea un vóxel de cada dos. Los chunks pueden cambiar libremente de LOD sin tocar sus datos SDF.</p>
<p>La solución más satisfactoria fue la creación dinámica de chunks verticales. Si esculpes hacia arriba más allá de la parte superior de un chunk, aparece encima un nuevo chunk exclusivo de MC cuyo SDF se inicializa a partir de la cara limítrofe del chunk inferior. Si esculpes hacia abajo, ocurre lo mismo. El mundo crece para adaptarse a las modificaciones.</p>
<p>El último escollo fue que el pincel de mapa de alturas no hacía absolutamente nada en los chunks bloqueados en MC. El pincel HM modifica <code>heightmapCPU</code> y vuelve a subirlo. Los chunks MC ya no leen del mapa de alturas porque su SDF se rellenó a partir de él y después divergió. Añadí <code>syncHeightmapToSdf()</code>: después de cambiar el mapa de alturas, se vuelven a derivar las columnas SDF de todos los chunks MC dentro del radio del pincel y se suben los nuevos valores. Ahora ambos tipos de pincel funcionan en ambos tipos de chunk.</p>
<h2 id="lo-que-aprendimos-realmente" tabindex="-1">Lo que aprendimos realmente <a class="header-anchor" href="#lo-que-aprendimos-realmente" aria-label="Permalink to &quot;Lo que aprendimos realmente&quot;"></a></h2>
<p>Se suponía que los spikes de pinceles debían responder a una pregunta de rendimiento: ¿puede ejecutarse el esculpido sin superar el presupuesto por fotograma? Sí puede. Esa fue la parte fácil.</p>
<p>La parte difícil fue descubrir que 24 spikes usando <code>height_at()</code> como verdad del terreno habían creado una dependencia invisible que se rompió en cuanto intentamos editar algo. La función procedimental era limpia, global y sin estado, justo hasta que dejó de representar el terreno.</p>
<p>Estas son las reglas que anotamos y que no olvidaremos:</p>
<ol>
<li>La altura del terreno procede de datos muestreados. Los chunks son propietarios de sus búferes.</li>
<li>La generación procedimental rellena los datos iniciales. No es la fuente de verdad en tiempo de ejecución.</li>
<li>El pincel modifica directamente los datos del chunk. Sin capas de desplazamiento.</li>
<li>Las normales proceden de los mismos datos mediante diferencias centrales alineadas con la cuadrícula.</li>
<li>El solapamiento de bordes —1 celda del interior del vecino— permite calcular las normales entre chunks.</li>
<li>Nunca regeneres una tabla de consulta cuando ya existe una copia probada.</li>
</ol>
<p>En la <a href="/es/blog/2026-04-13-open-world-browser-part-14-world-comes-alive.html">parte 14</a> dejamos de esculpir geometría de depuración y empezamos a hacer que parezca y se sienta como un lugar real.</p>
<h2 id="tecnologia-mencionada-en-este-capitulo" tabindex="-1">Tecnología mencionada en este capítulo <a class="header-anchor" href="#tecnologia-mencionada-en-este-capitulo" aria-label="Permalink to &quot;Tecnología mencionada en este capítulo&quot;"></a></h2>
<p><strong>Arquitectura de mapas de alturas muestreados.</strong> El terreno se almacena como datos propios de cada chunk, en lugar de evaluarse mediante una función procedimental en tiempo de ejecución. Cada chunk contiene un <code>Float32Array</code> con valores de altura reales. El ruido procedimental rellena los datos iniciales al crearlo y después la función no vuelve a llamarse. Esto elimina la incompatibilidad entre el terreno matemático y las capas de edición, simplifica las operaciones del pincel —se editan directamente los valores almacenados— y hace que el shader de GPU sea trivialmente sencillo: leer del búfer y calcular las normales mediante diferencias centrales alineadas con la cuadrícula. Para un mundo abierto con streaming, el enfoque estándar es que cada chunk sea propietario de sus datos y tenga un solapamiento de 1 celda procedente de sus vecinos. Consulta nuestra <a href="/es/guides/landscape-generation-browser.html#terrain-data-representation">guía de generación de paisajes</a>.</p>
<p><strong>Operaciones de pincel SDF.</strong> Modificación de un campo de distancias con signo para esculpir el terreno. Sumar —inflar— utiliza una atenuación smooth-step alrededor de una esfera. Restar —excavar— usa la misma forma negada. Suavizar usa un promedio laplaciano: se leen los 6 vecinos directos, se calcula su media y se lleva el valor hacia ella. El enfoque ingenuo de atraer los valores hacia cero colapsa el campo de distancias y crea bordes pronunciados. El suavizado laplaciano preserva el gradiente del campo a la vez que suaviza las formas. Consulta la <a href="/es/guides/landscape-generation-browser.html#signed-distance-fields-sdfs">representación de terreno mediante SDF</a>.</p>
<p><strong>Transvoxel con fuentes de datos mixtas.</strong> Las celdas de transición situadas en el límite entre un chunk MC y uno de mapa de alturas necesitan muestrear datos diferentes en cada lado. El shader de uniones incluye indicadores por chunk y enlaces a búferes para gestionar las cuatro combinaciones: HM-HM, HM-MC, MC-HM y MC-MC. Cuando un lado está bloqueado en MC, el shader interpola trilinealmente el búfer SDF en lugar de muestrear el mapa de alturas.
<strong>LOD basado en pasos para marching cubes.</strong> Los datos SDF se almacenan a resolución completa independientemente del nivel de LOD actual del chunk. El shader de MC calcula un paso de muestreo a partir de la proporción entre los puntos de la cuadrícula SDF y las celdas de MC. A resolución completa, el paso es 1; a media resolución, es 2. Esto desacopla los datos SDF de los cambios de LOD, por lo que los chunks pueden cambiar libremente de LOD sin tener que reconstruir el SDF.</p>
<hr>
<p>Parte 13 de 14.
Anterior: <a href="/es/blog/2026-02-25-open-world-browser-part-12-lessons.html">Parte 12 - Anillos, niebla del cielo y lo que volveríamos a hacer</a>
Siguiente: <a href="/es/blog/2026-04-13-open-world-browser-part-14-world-comes-alive.html">Parte 14 - El mundo cobra vida</a>
Guía de la serie: <a href="/es/blog/2026-02-25-open-world-browser-series-guide.html">/es/blog/2026-02-25-open-world-browser-series-guide</a></p>
]]></content:encoded>
            <enclosure url="https://cdn.cinevva.com/blog/why-webgpu-engine-hero.jpg" length="0" type="image/jpg"/>
        </item>
        <item>
            <title><![CDATA[Cómo construir un mundo abierto en el navegador, parte 14: El mundo cobra vida]]></title>
            <link>https://app.cinevva.com/es/blog/2026-04-13-open-world-browser-part-14-world-comes-alive</link>
            <guid>https://app.cinevva.com/es/blog/2026-04-13-open-world-browser-part-14-world-comes-alive</guid>
            <pubDate>Mon, 13 Apr 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Materiales que reaccionan a tus modificaciones, hierba que crece en los techos de las cuevas y un planeador que te hace olvidar que estás en una pestaña del navegador.]]></description>
            <content:encoded><![CDATA[<h1 id="como-construir-un-mundo-abierto-en-el-navegador-parte-14-el-mundo-cobra-vida" tabindex="-1">Cómo construir un mundo abierto en el navegador, parte 14: El mundo cobra vida <a class="header-anchor" href="#como-construir-un-mundo-abierto-en-el-navegador-parte-14-el-mundo-cobra-vida" aria-label="Permalink to &quot;Cómo construir un mundo abierto en el navegador, parte 14: El mundo cobra vida&quot;"></a></h1>
<p><em>Por <a href="/es/about.html">Oleg Sidorkin</a>, CTO y cofundador de Cinevva</em></p>
<p>¿Acabas de llegar? Consulta la <a href="/es/blog/2026-02-25-open-world-browser-series-guide.html">guía de la serie</a>. Explica qué es un spike y enlaza todas las partes.</p>
<p>Después de la <a href="/es/blog/2026-04-13-open-world-browser-part-13-terrain-sculpting.html">parte 13</a> ya podíamos esculpir. Elevar el terreno, excavar cuevas y suavizar acantilados, todo en tiempo real y manteniendo intactas las uniones. Pero el mundo parecía una demo técnica. Sombreado plano con colores de depuración, superposiciones de malla y geometría gris con colores de LOD para distinguir los chunks. Podías editarlo. No podías sentirlo.</p>
<p>Tres spikes cambiaron eso. No cambiamos la arquitectura. Usamos exactamente el mismo pipeline, los mismos búferes y el mismo cosido de uniones de la parte 13. Solo añadimos las capas que hacen que un terreno se sienta como un lugar: superficies que responden a su forma, vida que crece sobre ellas y un cuerpo que las recorre.</p>
<p>La diferencia entre «funciona técnicamente» y «quiero quedarme aquí» resultó ser sorprendentemente pequeña.</p>
<h2 id="esculpe-un-acantilado-y-observa-como-se-convierte-en-roca" tabindex="-1">Esculpe un acantilado y observa cómo se convierte en roca <a class="header-anchor" href="#esculpe-un-acantilado-y-observa-como-se-convierte-en-roca" aria-label="Permalink to &quot;Esculpe un acantilado y observa cómo se convierte en roca&quot;"></a></h2>
<p>El spike 28 planteaba una pregunta concreta: ¿puede ejecutarse un material de cuatro capas con mapeado triplanar sobre terreno generado mediante cómputo sin agotar el presupuesto por fotograma? La respuesta fue sí, pero lo interesante fue lo que ocurrió después.</p>
<div style="position:relative;padding-bottom:56.25%;height:0;overflow:hidden;border-radius:8px;margin:1.5rem 0;border:1px solid rgba(255,255,255,0.12)">
<iframe src="/es/spikes/28-multi-material/" title="Spike 28: texturizado multimaterial" style="position:absolute;top:0;left:0;width:100%;height:100%;border:0;background:#000" loading="lazy" allowfullscreen></iframe>
</div>
<p><a href="/es/spikes/28-multi-material/" target="_blank">Abrir el spike 28 en una pestaña nueva ↗</a> · <a href="/es/blog/spike-source?spike=28-multi-material">Ver el código fuente</a></p>
<p>Cuatro texturas procedurales —hierba, roca, arena y nieve— generadas a partir de ruido FBM al iniciar. Sin archivos externos ni pipeline de recursos, solo matemáticas y una <code>DataTexture</code>. Los pesos de los materiales proceden de la propia superficie: la pendiente y la altitud. Las zonas planas por debajo de la línea de árboles reciben hierba. Las caras empinadas reciben roca. Las zonas bajas reciben arena. Las cumbres altas reciben nieve. Cada peso bruto se obtiene mediante un <code>smoothstep</code> aplicado a la pendiente y la altitud; después, se normalizan por fragmento para que <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.663ex;" xmlns="http://www.w3.org/2000/svg" width="10.014ex" height="2.36ex" role="img" focusable="false" viewBox="0 -750 4426.1 1043.1" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="munder"><g data-mml-node="mo"><path data-c="2211" d="M61 748Q64 750 489 750H913L954 640Q965 609 976 579T993 533T999 516H979L959 517Q936 579 886 621T777 682Q724 700 655 705T436 710H319Q183 710 183 709Q186 706 348 484T511 259Q517 250 513 244L490 216Q466 188 420 134T330 27L149 -187Q149 -188 362 -188Q388 -188 436 -188T506 -189Q679 -189 778 -162T936 -43Q946 -27 959 6H999L913 -249L489 -250Q65 -250 62 -248Q56 -246 56 -239Q56 -234 118 -161Q186 -81 245 -11L428 206Q428 207 242 462L57 717L56 728Q56 744 61 748Z" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(1089,-285.4) scale(0.707)"><path data-c="1D456" d="M184 600Q184 624 203 642T247 661Q265 661 277 649T290 619Q290 596 270 577T226 557Q211 557 198 567T184 600ZM21 287Q21 295 30 318T54 369T98 420T158 442Q197 442 223 419T250 357Q250 340 236 301T196 196T154 83Q149 61 149 51Q149 26 166 26Q175 26 185 29T208 43T235 78T260 137Q263 149 265 151T282 153Q302 153 302 143Q302 135 293 112T268 61T223 11T161 -11Q129 -11 102 10T74 74Q74 91 79 106T122 220Q160 321 166 341T173 380Q173 404 156 404H154Q124 404 99 371T61 287Q60 286 59 284T58 281T56 279T53 278T49 278T41 278H27Q21 284 21 287Z" style="stroke-width: 3;"/></g></g><g data-mml-node="msub" transform="translate(1549.6,0)"><g data-mml-node="mi"><path data-c="1D464" d="M580 385Q580 406 599 424T641 443Q659 443 674 425T690 368Q690 339 671 253Q656 197 644 161T609 80T554 12T482 -11Q438 -11 404 5T355 48Q354 47 352 44Q311 -11 252 -11Q226 -11 202 -5T155 14T118 53T104 116Q104 170 138 262T173 379Q173 380 173 381Q173 390 173 393T169 400T158 404H154Q131 404 112 385T82 344T65 302T57 280Q55 278 41 278H27Q21 284 21 287Q21 293 29 315T52 366T96 418T161 441Q204 441 227 416T250 358Q250 340 217 250T184 111Q184 65 205 46T258 26Q301 26 334 87L339 96V119Q339 122 339 128T340 136T341 143T342 152T345 165T348 182T354 206T362 238T373 281Q402 395 406 404Q419 431 449 431Q468 431 475 421T483 402Q483 389 454 274T422 142Q420 131 420 107V100Q420 85 423 71T442 42T487 26Q558 26 600 148Q609 171 620 213T632 273Q632 306 619 325T593 357T580 385Z" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(749,-150) scale(0.707)"><path data-c="1D456" d="M184 600Q184 624 203 642T247 661Q265 661 277 649T290 619Q290 596 270 577T226 557Q211 557 198 567T184 600ZM21 287Q21 295 30 318T54 369T98 420T158 442Q197 442 223 419T250 357Q250 340 236 301T196 196T154 83Q149 61 149 51Q149 26 166 26Q175 26 185 29T208 43T235 78T260 137Q263 149 265 151T282 153Q302 153 302 143Q302 135 293 112T268 61T223 11T161 -11Q129 -11 102 10T74 74Q74 91 79 106T122 220Q160 321 166 341T173 380Q173 404 156 404H154Q124 404 99 371T61 287Q60 286 59 284T58 281T56 279T53 278T49 278T41 278H27Q21 284 21 287Z" style="stroke-width: 3;"/></g></g><g data-mml-node="mo" transform="translate(2870.3,0)"><path data-c="3D" d="M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z" style="stroke-width: 3;"/></g><g data-mml-node="mn" transform="translate(3926.1,0)"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" style="stroke-width: 3;"/></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><munder><mo data-mjx-texclass="OP">∑</mo><mi>i</mi></munder><msub><mi>w</mi><mi>i</mi></msub><mo>=</mo><mn>1</mn></math></mjx-assistive-mml></mjx-container> y el color final sea simplemente la mezcla ponderada <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.663ex;" xmlns="http://www.w3.org/2000/svg" width="7.963ex" height="2.36ex" role="img" focusable="false" viewBox="0 -750 3519.5 1043.1" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="munder"><g data-mml-node="mo"><path data-c="2211" d="M61 748Q64 750 489 750H913L954 640Q965 609 976 579T993 533T999 516H979L959 517Q936 579 886 621T777 682Q724 700 655 705T436 710H319Q183 710 183 709Q186 706 348 484T511 259Q517 250 513 244L490 216Q466 188 420 134T330 27L149 -187Q149 -188 362 -188Q388 -188 436 -188T506 -189Q679 -189 778 -162T936 -43Q946 -27 959 6H999L913 -249L489 -250Q65 -250 62 -248Q56 -246 56 -239Q56 -234 118 -161Q186 -81 245 -11L428 206Q428 207 242 462L57 717L56 728Q56 744 61 748Z" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(1089,-285.4) scale(0.707)"><path data-c="1D456" d="M184 600Q184 624 203 642T247 661Q265 661 277 649T290 619Q290 596 270 577T226 557Q211 557 198 567T184 600ZM21 287Q21 295 30 318T54 369T98 420T158 442Q197 442 223 419T250 357Q250 340 236 301T196 196T154 83Q149 61 149 51Q149 26 166 26Q175 26 185 29T208 43T235 78T260 137Q263 149 265 151T282 153Q302 153 302 143Q302 135 293 112T268 61T223 11T161 -11Q129 -11 102 10T74 74Q74 91 79 106T122 220Q160 321 166 341T173 380Q173 404 156 404H154Q124 404 99 371T61 287Q60 286 59 284T58 281T56 279T53 278T49 278T41 278H27Q21 284 21 287Z" style="stroke-width: 3;"/></g></g><g data-mml-node="msub" transform="translate(1549.6,0)"><g data-mml-node="mi"><path data-c="1D464" d="M580 385Q580 406 599 424T641 443Q659 443 674 425T690 368Q690 339 671 253Q656 197 644 161T609 80T554 12T482 -11Q438 -11 404 5T355 48Q354 47 352 44Q311 -11 252 -11Q226 -11 202 -5T155 14T118 53T104 116Q104 170 138 262T173 379Q173 380 173 381Q173 390 173 393T169 400T158 404H154Q131 404 112 385T82 344T65 302T57 280Q55 278 41 278H27Q21 284 21 287Q21 293 29 315T52 366T96 418T161 441Q204 441 227 416T250 358Q250 340 217 250T184 111Q184 65 205 46T258 26Q301 26 334 87L339 96V119Q339 122 339 128T340 136T341 143T342 152T345 165T348 182T354 206T362 238T373 281Q402 395 406 404Q419 431 449 431Q468 431 475 421T483 402Q483 389 454 274T422 142Q420 131 420 107V100Q420 85 423 71T442 42T487 26Q558 26 600 148Q609 171 620 213T632 273Q632 306 619 325T593 357T580 385Z" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(749,-150) scale(0.707)"><path data-c="1D456" d="M184 600Q184 624 203 642T247 661Q265 661 277 649T290 619Q290 596 270 577T226 557Q211 557 198 567T184 600ZM21 287Q21 295 30 318T54 369T98 420T158 442Q197 442 223 419T250 357Q250 340 236 301T196 196T154 83Q149 61 149 51Q149 26 166 26Q175 26 185 29T208 43T235 78T260 137Q263 149 265 151T282 153Q302 153 302 143Q302 135 293 112T268 61T223 11T161 -11Q129 -11 102 10T74 74Q74 91 79 106T122 220Q160 321 166 341T173 380Q173 404 156 404H154Q124 404 99 371T61 287Q60 286 59 284T58 281T56 279T53 278T49 278T41 278H27Q21 284 21 287Z" style="stroke-width: 3;"/></g></g><g data-mml-node="mstyle" transform="translate(2592.6,0)"><g data-mml-node="mspace"/></g><g data-mml-node="msub" transform="translate(2759.6,0)"><g data-mml-node="mi"><path data-c="1D450" d="M34 159Q34 268 120 355T306 442Q362 442 394 418T427 355Q427 326 408 306T360 285Q341 285 330 295T319 325T330 359T352 380T366 386H367Q367 388 361 392T340 400T306 404Q276 404 249 390Q228 381 206 359Q162 315 142 235T121 119Q121 73 147 50Q169 26 205 26H209Q321 26 394 111Q403 121 406 121Q410 121 419 112T429 98T420 83T391 55T346 25T282 0T202 -11Q127 -11 81 37T34 159Z" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(466,-150) scale(0.707)"><path data-c="1D456" d="M184 600Q184 624 203 642T247 661Q265 661 277 649T290 619Q290 596 270 577T226 557Q211 557 198 567T184 600ZM21 287Q21 295 30 318T54 369T98 420T158 442Q197 442 223 419T250 357Q250 340 236 301T196 196T154 83Q149 61 149 51Q149 26 166 26Q175 26 185 29T208 43T235 78T260 137Q263 149 265 151T282 153Q302 153 302 143Q302 135 293 112T268 61T223 11T161 -11Q129 -11 102 10T74 74Q74 91 79 106T122 220Q160 321 166 341T173 380Q173 404 156 404H154Q124 404 99 371T61 287Q60 286 59 284T58 281T56 279T53 278T49 278T41 278H27Q21 284 21 287Z" style="stroke-width: 3;"/></g></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><munder><mo data-mjx-texclass="OP">∑</mo><mi>i</mi></munder><msub><mi>w</mi><mi>i</mi></msub><mstyle scriptlevel="0"><mspace width="0.167em"/></mstyle><msub><mi>c</mi><mi>i</mi></msub></math></mjx-assistive-mml></mjx-container>. La normalización evita que la superficie quede demasiado oscura o sobreexpuesta donde se solapan los biomas. El mapeado triplanar se encarga de la proyección UV para los chunks de MC, cuyas caras no tienen coordenadas UV significativas.</p>
<p>El momento que nos convenció: elevas el terreno con el pincel para crear un acantilado empinado y la textura de roca aparece sobre la nueva cara en el mismo fotograma. Vuelves a aplanarlo y la hierba recupera la superficie. El material no sabe nada del pincel. Solo lee la posición en el mundo y la normal de la superficie, los mismos datos a partir de los cuales se construyó la geometría. El bucle de retroalimentación visual al esculpir es instantáneo y no depende de ningún script específico.</p>
<p>El spike 8 probó hace mes y medio el coste del material del terreno con una malla estática en WebGL. El spike 28 demuestra que funciona sobre terreno dinámico generado mediante cómputo, con todo el pipeline de esculpido ejecutándose por debajo. Lo habíamos contemplado en el presupuesto, pero verlo mantenerse a 60 fps con todo en ejecución siguió siendo un alivio.</p>
<h2 id="_80-000-matas-de-hierba-y-el-techo-de-una-cueva" tabindex="-1">80 000 matas de hierba y el techo de una cueva <a class="header-anchor" href="#_80-000-matas-de-hierba-y-el-techo-de-una-cueva" aria-label="Permalink to &quot;80 000 matas de hierba y el techo de una cueva&quot;"></a></h2>
<p>En el spike 29 fue donde nuestros instintos de desarrollo de videojuegos tomaron el control.</p>
<div style="position:relative;padding-bottom:56.25%;height:0;overflow:hidden;border-radius:8px;margin:1.5rem 0;border:1px solid rgba(255,255,255,0.12)">
<iframe src="/es/spikes/29-vegetation/" title="Spike 29: vegetación y hierba mediante shaders" style="position:absolute;top:0;left:0;width:100%;height:100%;border:0;background:#000" loading="lazy" allowfullscreen></iframe>
</div>
<p><a href="/es/spikes/29-vegetation/" target="_blank">Abrir el spike 29 en una pestaña nueva ↗</a> · <a href="/es/blog/spike-source?spike=29-vegetation">Ver el código fuente</a></p>
<p>Queríamos la hierba de Breath of the Wild. No el número de polígonos, sino la sensación. Hierba que cubriera los lugares adecuados, se moviera con el viento y te diera ganas de correr entre ella.</p>
<p>Cada mata de hierba consta de tres quads que se cruzan con ángulos de 60 grados y tienen cuatro segmentos verticales para poder doblarse. Es una forma de cruz que parece volumétrica desde cualquier ángulo sin recurrir a trucos con billboards. Un <code>InstancedMesh</code> por chunk, 80 000 matas repartidas por el mundo y unos 2,4 millones de vértices de hierba en total.</p>
<p>La colocación es la parte importante. La CPU recorre una cuadrícula con variaciones aleatorias sobre cada chunk y evalúa la misma lógica de pendiente y altitud que utiliza el shader de materiales de la GPU. Donde el sistema de materiales dice «hierba», crece hierba. Donde predominan la roca o la arena, la densidad cae a cero. La transición es suave porque los pesos <code>smoothstep</code> subyacentes producen gradientes continuos en los límites de los biomas. No percibes ninguna frontera porque no la hay.</p>
<p>Después hicimos algo que no estaba seguro de que fuera a funcionar: hierba sobre superficies SDF. La función de dispersión recorre cada columna del volumen SDF y busca cruces por cero entre vóxeles adyacentes. Donde el SDF pasa de negativo a positivo, hay una superficie. La normal de la superficie es simplemente el gradiente normalizado del campo, <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -1.238ex;" xmlns="http://www.w3.org/2000/svg" width="9.256ex" height="3.445ex" role="img" focusable="false" viewBox="0 -975.7 4091.1 1522.8" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="TeXAtom" data-mjx-texclass="ORD"><g data-mml-node="mover"><g data-mml-node="mi"><path data-c="1D45B" d="M21 287Q22 293 24 303T36 341T56 388T89 425T135 442Q171 442 195 424T225 390T231 369Q231 367 232 367L243 378Q304 442 382 442Q436 442 469 415T503 336T465 179T427 52Q427 26 444 26Q450 26 453 27Q482 32 505 65T540 145Q542 153 560 153Q580 153 580 145Q580 144 576 130Q568 101 554 73T508 17T439 -10Q392 -10 371 17T350 73Q350 92 386 193T423 345Q423 404 379 404H374Q288 404 229 303L222 291L189 157Q156 26 151 16Q138 -11 108 -11Q95 -11 87 -5T76 7T74 17Q74 30 112 180T152 343Q153 348 153 366Q153 405 129 405Q91 405 66 305Q60 285 60 284Q58 278 41 278H27Q21 284 21 287Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(300,16) translate(-250 0)"><path data-c="5E" d="M112 560L249 694L257 686Q387 562 387 560L361 531Q359 532 303 581L250 627L195 580Q182 569 169 557T148 538L140 532Q138 530 125 546L112 560Z" style="stroke-width: 3;"/></g></g></g><g data-mml-node="mo" transform="translate(877.8,0)"><path data-c="3D" d="M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z" style="stroke-width: 3;"/></g><g data-mml-node="mfrac" transform="translate(1933.6,0)"><g data-mml-node="mrow" transform="translate(573.6,485) scale(0.707)"><g data-mml-node="mi"><path data-c="2207" d="M46 676Q46 679 51 683H781Q786 679 786 676Q786 674 617 326T444 -26Q439 -33 416 -33T388 -26Q385 -22 216 326T46 676ZM697 596Q697 597 445 597T193 596Q195 591 319 336T445 80L697 596Z" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(833,0)"><path data-c="1D719" d="M409 688Q413 694 421 694H429H442Q448 688 448 686Q448 679 418 563Q411 535 404 504T392 458L388 442Q388 441 397 441T429 435T477 418Q521 397 550 357T579 260T548 151T471 65T374 11T279 -10H275L251 -105Q245 -128 238 -160Q230 -192 227 -198T215 -205H209Q189 -205 189 -198Q189 -193 211 -103L234 -11Q234 -10 226 -10Q221 -10 206 -8T161 6T107 36T62 89T43 171Q43 231 76 284T157 370T254 422T342 441Q347 441 348 445L378 567Q409 686 409 688ZM122 150Q122 116 134 91T167 53T203 35T237 27H244L337 404Q333 404 326 403T297 395T255 379T211 350T170 304Q152 276 137 237Q122 191 122 150ZM500 282Q500 320 484 347T444 385T405 400T381 404H378L332 217L284 29Q284 27 285 27Q293 27 317 33T357 47Q400 66 431 100T475 170T494 234T500 282Z" style="stroke-width: 3;"/></g></g><g data-mml-node="mrow" transform="translate(220,-370.3) scale(0.707)"><g data-mml-node="mo"><path data-c="2016" d="M133 736Q138 750 153 750Q164 750 170 739Q172 735 172 250T170 -239Q164 -250 152 -250Q144 -250 138 -244L137 -243Q133 -241 133 -179T132 250Q132 731 133 736ZM329 739Q334 750 346 750Q353 750 361 744L362 743Q366 741 366 679T367 250T367 -178T362 -243L361 -244Q355 -250 347 -250Q335 -250 329 -239Q327 -235 327 250T329 739Z" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(500,0)"><path data-c="2207" d="M46 676Q46 679 51 683H781Q786 679 786 676Q786 674 617 326T444 -26Q439 -33 416 -33T388 -26Q385 -22 216 326T46 676ZM697 596Q697 597 445 597T193 596Q195 591 319 336T445 80L697 596Z" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(1333,0)"><path data-c="1D719" d="M409 688Q413 694 421 694H429H442Q448 688 448 686Q448 679 418 563Q411 535 404 504T392 458L388 442Q388 441 397 441T429 435T477 418Q521 397 550 357T579 260T548 151T471 65T374 11T279 -10H275L251 -105Q245 -128 238 -160Q230 -192 227 -198T215 -205H209Q189 -205 189 -198Q189 -193 211 -103L234 -11Q234 -10 226 -10Q221 -10 206 -8T161 6T107 36T62 89T43 171Q43 231 76 284T157 370T254 422T342 441Q347 441 348 445L378 567Q409 686 409 688ZM122 150Q122 116 134 91T167 53T203 35T237 27H244L337 404Q333 404 326 403T297 395T255 379T211 350T170 304Q152 276 137 237Q122 191 122 150ZM500 282Q500 320 484 347T444 385T405 400T381 404H378L332 217L284 29Q284 27 285 27Q293 27 317 33T357 47Q400 66 431 100T475 170T494 234T500 282Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(1929,0)"><path data-c="2016" d="M133 736Q138 750 153 750Q164 750 170 739Q172 735 172 250T170 -239Q164 -250 152 -250Q144 -250 138 -244L137 -243Q133 -241 133 -179T132 250Q132 731 133 736ZM329 739Q334 750 346 750Q353 750 361 744L362 743Q366 741 366 679T367 250T367 -178T362 -243L361 -244Q355 -250 347 -250Q335 -250 329 -239Q327 -235 327 250T329 739Z" style="stroke-width: 3;"/></g></g><rect width="1917.6" height="60" x="120" y="220"/></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mrow data-mjx-texclass="ORD"><mover><mi>n</mi><mo stretchy="false">^</mo></mover></mrow><mo>=</mo><mfrac><mrow><mi mathvariant="normal">∇</mi><mi>ϕ</mi></mrow><mrow><mo data-mjx-texclass="OPEN" fence="false" stretchy="false">‖</mo><mi mathvariant="normal">∇</mi><mi>ϕ</mi><mo data-mjx-texclass="CLOSE" fence="false" stretchy="false">‖</mo></mrow></mfrac></math></mjx-assistive-mml></mjx-container>, calculado a partir de las diferencias entre vóxeles, y la pendiente es <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.566ex;" xmlns="http://www.w3.org/2000/svg" width="11.911ex" height="2.398ex" role="img" focusable="false" viewBox="0 -810 5264.4 1060" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mi"><path data-c="61" d="M137 305T115 305T78 320T63 359Q63 394 97 421T218 448Q291 448 336 416T396 340Q401 326 401 309T402 194V124Q402 76 407 58T428 40Q443 40 448 56T453 109V145H493V106Q492 66 490 59Q481 29 455 12T400 -6T353 12T329 54V58L327 55Q325 52 322 49T314 40T302 29T287 17T269 6T247 -2T221 -8T190 -11Q130 -11 82 20T34 107Q34 128 41 147T68 188T116 225T194 253T304 268H318V290Q318 324 312 340Q290 411 215 411Q197 411 181 410T156 406T148 403Q170 388 170 359Q170 334 154 320ZM126 106Q126 75 150 51T209 26Q247 26 276 49T315 109Q317 116 318 175Q318 233 317 233Q309 233 296 232T251 223T193 203T147 166T126 106Z" style="stroke-width: 3;"/><path data-c="72" d="M36 46H50Q89 46 97 60V68Q97 77 97 91T98 122T98 161T98 203Q98 234 98 269T98 328L97 351Q94 370 83 376T38 385H20V408Q20 431 22 431L32 432Q42 433 60 434T96 436Q112 437 131 438T160 441T171 442H174V373Q213 441 271 441H277Q322 441 343 419T364 373Q364 352 351 337T313 322Q288 322 276 338T263 372Q263 381 265 388T270 400T273 405Q271 407 250 401Q234 393 226 386Q179 341 179 207V154Q179 141 179 127T179 101T180 81T180 66V61Q181 59 183 57T188 54T193 51T200 49T207 48T216 47T225 47T235 46T245 46H276V0H267Q249 3 140 3Q37 3 28 0H20V46H36Z" transform="translate(500,0)" style="stroke-width: 3;"/><path data-c="63" d="M370 305T349 305T313 320T297 358Q297 381 312 396Q317 401 317 402T307 404Q281 408 258 408Q209 408 178 376Q131 329 131 219Q131 137 162 90Q203 29 272 29Q313 29 338 55T374 117Q376 125 379 127T395 129H409Q415 123 415 120Q415 116 411 104T395 71T366 33T318 2T249 -11Q163 -11 99 53T34 214Q34 318 99 383T250 448T370 421T404 357Q404 334 387 320Z" transform="translate(892,0)" style="stroke-width: 3;"/><path data-c="63" d="M370 305T349 305T313 320T297 358Q297 381 312 396Q317 401 317 402T307 404Q281 408 258 408Q209 408 178 376Q131 329 131 219Q131 137 162 90Q203 29 272 29Q313 29 338 55T374 117Q376 125 379 127T395 129H409Q415 123 415 120Q415 116 411 104T395 71T366 33T318 2T249 -11Q163 -11 99 53T34 214Q34 318 99 383T250 448T370 421T404 357Q404 334 387 320Z" transform="translate(1336,0)" style="stroke-width: 3;"/><path data-c="6F" d="M28 214Q28 309 93 378T250 448Q340 448 405 380T471 215Q471 120 407 55T250 -10Q153 -10 91 57T28 214ZM250 30Q372 30 372 193V225V250Q372 272 371 288T364 326T348 362T317 390T268 410Q263 411 252 411Q222 411 195 399Q152 377 139 338T126 246V226Q126 130 145 91Q177 30 250 30Z" transform="translate(1780,0)" style="stroke-width: 3;"/><path data-c="73" d="M295 316Q295 356 268 385T190 414Q154 414 128 401Q98 382 98 349Q97 344 98 336T114 312T157 287Q175 282 201 278T245 269T277 256Q294 248 310 236T342 195T359 133Q359 71 321 31T198 -10H190Q138 -10 94 26L86 19L77 10Q71 4 65 -1L54 -11H46H42Q39 -11 33 -5V74V132Q33 153 35 157T45 162H54Q66 162 70 158T75 146T82 119T101 77Q136 26 198 26Q295 26 295 104Q295 133 277 151Q257 175 194 187T111 210Q75 227 54 256T33 318Q33 357 50 384T93 424T143 442T187 447H198Q238 447 268 432L283 424L292 431Q302 440 314 448H322H326Q329 448 335 442V310L329 304H301Q295 310 295 316Z" transform="translate(2280,0)" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(2674,0)"><path data-c="2061" d="" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(2674,0)"><path data-c="28" d="M94 250Q94 319 104 381T127 488T164 576T202 643T244 695T277 729T302 750H315H319Q333 750 333 741Q333 738 316 720T275 667T226 581T184 443T167 250T184 58T225 -81T274 -167T316 -220T333 -241Q333 -250 318 -250H315H302L274 -226Q180 -141 137 -14T94 250Z" style="stroke-width: 3;"/></g><g data-mml-node="TeXAtom" data-mjx-texclass="ORD" transform="translate(3063,0)"><g data-mml-node="mover"><g data-mml-node="mi"><path data-c="1D45B" d="M21 287Q22 293 24 303T36 341T56 388T89 425T135 442Q171 442 195 424T225 390T231 369Q231 367 232 367L243 378Q304 442 382 442Q436 442 469 415T503 336T465 179T427 52Q427 26 444 26Q450 26 453 27Q482 32 505 65T540 145Q542 153 560 153Q580 153 580 145Q580 144 576 130Q568 101 554 73T508 17T439 -10Q392 -10 371 17T350 73Q350 92 386 193T423 345Q423 404 379 404H374Q288 404 229 303L222 291L189 157Q156 26 151 16Q138 -11 108 -11Q95 -11 87 -5T76 7T74 17Q74 30 112 180T152 343Q153 348 153 366Q153 405 129 405Q91 405 66 305Q60 285 60 284Q58 278 41 278H27Q21 284 21 287Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(300,16) translate(-250 0)"><path data-c="5E" d="M112 560L249 694L257 686Q387 562 387 560L361 531Q359 532 303 581L250 627L195 580Q182 569 169 557T148 538L140 532Q138 530 125 546L112 560Z" style="stroke-width: 3;"/></g></g></g><g data-mml-node="mo" transform="translate(3885.2,0)"><path data-c="22C5" d="M78 250Q78 274 95 292T138 310Q162 310 180 294T199 251Q199 226 182 208T139 190T96 207T78 250Z" style="stroke-width: 3;"/></g><g data-mml-node="TeXAtom" data-mjx-texclass="ORD" transform="translate(4385.4,0)"><g data-mml-node="mover"><g data-mml-node="mi"><path data-c="1D466" d="M21 287Q21 301 36 335T84 406T158 442Q199 442 224 419T250 355Q248 336 247 334Q247 331 231 288T198 191T182 105Q182 62 196 45T238 27Q261 27 281 38T312 61T339 94Q339 95 344 114T358 173T377 247Q415 397 419 404Q432 431 462 431Q475 431 483 424T494 412T496 403Q496 390 447 193T391 -23Q363 -106 294 -155T156 -205Q111 -205 77 -183T43 -117Q43 -95 50 -80T69 -58T89 -48T106 -45Q150 -45 150 -87Q150 -107 138 -122T115 -142T102 -147L99 -148Q101 -153 118 -160T152 -167H160Q177 -167 186 -165Q219 -156 247 -127T290 -65T313 -9T321 21L315 17Q309 13 296 6T270 -6Q250 -11 231 -11Q185 -11 150 11T104 82Q103 89 103 113Q103 170 138 262T173 379Q173 380 173 381Q173 390 173 393T169 400T158 404H154Q131 404 112 385T82 344T65 302T57 280Q55 278 41 278H27Q21 284 21 287Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(300.6,16) translate(-250 0)"><path data-c="5E" d="M112 560L249 694L257 686Q387 562 387 560L361 531Q359 532 303 581L250 627L195 580Q182 569 169 557T148 538L140 532Q138 530 125 546L112 560Z" style="stroke-width: 3;"/></g></g></g><g data-mml-node="mo" transform="translate(4875.4,0)"><path data-c="29" d="M60 749L64 750Q69 750 74 750H86L114 726Q208 641 251 514T294 250Q294 182 284 119T261 12T224 -76T186 -143T145 -194T113 -227T90 -246Q87 -249 86 -250H74Q66 -250 63 -250T58 -247T55 -238Q56 -237 66 -225Q221 -64 221 250T66 725Q56 737 55 738Q55 746 60 749Z" style="stroke-width: 3;"/></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mi>arccos</mi><mo data-mjx-texclass="NONE">⁡</mo><mo stretchy="false">(</mo><mrow data-mjx-texclass="ORD"><mover><mi>n</mi><mo stretchy="false">^</mo></mover></mrow><mo>⋅</mo><mrow data-mjx-texclass="ORD"><mover><mi>y</mi><mo stretchy="false">^</mo></mover></mrow><mo stretchy="false">)</mo></math></mjx-assistive-mml></mjx-container>, el ángulo respecto a la vertical. Si es lo bastante suave, se coloca hierba.</p>
<p>Excava una cueva con el pincel SDF en el spike 27. Vuelve al spike 29 y habrá hierba creciendo sobre la parte superior del techo de la cueva. El código de dispersión no sabe qué es una cueva. Solo ve una superficie con la pendiente adecuada a la altitud adecuada. Ese es el tipo de comportamiento emergente que hace tan satisfactorio construir sistemas de mundo abierto.</p>
<p>El viento es una onda sinusoidal en el shader de vértices TSL, modulada por la coordenada V de la brizna para que las puntas se balanceen y las raíces permanezcan plantadas. Pulsa V para alternar entre viento suave, fuerte y desactivado. El viento actúa simultáneamente sobre las 80 000 matas sin ningún coste para la CPU porque se ejecuta por completo en el shader de vértices.</p>
<p>En el spike 7 probamos 50 000 instancias de hierba y nos preocupaba alcanzar el límite. El spike 29 ejecuta 80 000 sobre el terreno generado mediante cómputo, el cosido de uniones, el texturizado multimaterial y los pinceles. Agruparlas en menos llamadas de dibujo de <code>InstancedMesh</code> sigue siendo más importante que reducir el número de vértices por brizna. La lección del spike 7 se mantuvo.</p>
<p>Algo que dejamos para más adelante: la hierba no se actualiza cuando esculpes debajo de ella. Las matrices de las instancias se fijan al dispersarlas. Si transformas una colina en un valle, la hierba flota en el aire hasta que pulsas G para volver a dispersarla. Es suficiente para un spike. En producción habrá que volver a dispersar la vegetación de los chunks modificados.</p>
<h2 id="el-primer-paso" tabindex="-1">El primer paso <a class="header-anchor" href="#el-primer-paso" aria-label="Permalink to &quot;El primer paso&quot;"></a></h2>
<p>El spike 30 es al que no dejo de volver.</p>
<div style="position:relative;padding-bottom:56.25%;height:0;overflow:hidden;border-radius:8px;margin:1.5rem 0;border:1px solid rgba(255,255,255,0.12)">
<iframe src="/es/spikes/30-physics/" title="Spike 30: físicas del terreno" style="position:absolute;top:0;left:0;width:100%;height:100%;border:0;background:#000" loading="lazy" allowfullscreen></iframe>
</div>
<p><a href="/es/spikes/30-physics/" target="_blank">Abrir el spike 30 en una pestaña nueva ↗</a> · <a href="/es/blog/spike-source?spike=30-physics">Ver el código fuente</a></p>
<p>Sin biblioteca de físicas. Una cápsula personalizada con un paso de tiempo fijo de 120 Hz. El código de producción utiliza Rapier en un web worker —el spike 2 demostró que la latencia es aceptable—, pero este spike tenía que validar las propias consultas de colisión. ¿Puede un personaje caminar sobre terreno de mapa de alturas, pasar a terreno SDF esculpido y no caer a través de él?</p>
<p>El núcleo es una función llamada <code>terrainQuery(x, y, z)</code>. Comprueba si la posición está dentro de un chunk bloqueado en MC. Si es así, interpola trilinealmente la copia SDF de la CPU y devuelve el gradiente como normal de la superficie. En caso contrario, consulta el mapa de alturas y calcula la normal mediante diferencias centrales. El personaje no sabe sobre qué sistema de terreno se encuentra. Solo pregunta dónde está el suelo y obtiene una respuesta.</p>
<p>La colisión con SDF era la parte que esperaba que resultara difícil. Siete puntos de sondeo alrededor de la cápsula: inferior, central, superior y cuatro desplazamientos cardinales. Un punto de sondeo en la posición <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: 0;" xmlns="http://www.w3.org/2000/svg" width="1.373ex" height="1.005ex" role="img" focusable="false" viewBox="0 -444 607 444" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="TeXAtom" data-mjx-texclass="ORD"><g data-mml-node="mi"><path data-c="1D431" d="M227 0Q212 3 121 3Q40 3 28 0H21V62H117L245 213L109 382H26V444H34Q49 441 143 441Q247 441 265 444H274V382H246L281 339Q315 297 316 297Q320 297 354 341L389 382H352V444H360Q375 441 466 441Q547 441 559 444H566V382H471L355 246L504 63L545 62H586V0H578Q563 3 469 3Q365 3 347 0H338V62H366Q366 63 326 112T285 163L198 63L217 62H235V0H227Z" style="stroke-width: 3;"/></g></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mrow data-mjx-texclass="ORD"><mi mathvariant="bold">x</mi></mrow></math></mjx-assistive-mml></mjx-container> está penetrando siempre que <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.566ex;" xmlns="http://www.w3.org/2000/svg" width="8.519ex" height="2.262ex" role="img" focusable="false" viewBox="0 -750 3765.6 1000" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mi"><path data-c="1D719" d="M409 688Q413 694 421 694H429H442Q448 688 448 686Q448 679 418 563Q411 535 404 504T392 458L388 442Q388 441 397 441T429 435T477 418Q521 397 550 357T579 260T548 151T471 65T374 11T279 -10H275L251 -105Q245 -128 238 -160Q230 -192 227 -198T215 -205H209Q189 -205 189 -198Q189 -193 211 -103L234 -11Q234 -10 226 -10Q221 -10 206 -8T161 6T107 36T62 89T43 171Q43 231 76 284T157 370T254 422T342 441Q347 441 348 445L378 567Q409 686 409 688ZM122 150Q122 116 134 91T167 53T203 35T237 27H244L337 404Q333 404 326 403T297 395T255 379T211 350T170 304Q152 276 137 237Q122 191 122 150ZM500 282Q500 320 484 347T444 385T405 400T381 404H378L332 217L284 29Q284 27 285 27Q293 27 317 33T357 47Q400 66 431 100T475 170T494 234T500 282Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(596,0)"><path data-c="28" d="M94 250Q94 319 104 381T127 488T164 576T202 643T244 695T277 729T302 750H315H319Q333 750 333 741Q333 738 316 720T275 667T226 581T184 443T167 250T184 58T225 -81T274 -167T316 -220T333 -241Q333 -250 318 -250H315H302L274 -226Q180 -141 137 -14T94 250Z" style="stroke-width: 3;"/></g><g data-mml-node="TeXAtom" data-mjx-texclass="ORD" transform="translate(985,0)"><g data-mml-node="mi"><path data-c="1D431" d="M227 0Q212 3 121 3Q40 3 28 0H21V62H117L245 213L109 382H26V444H34Q49 441 143 441Q247 441 265 444H274V382H246L281 339Q315 297 316 297Q320 297 354 341L389 382H352V444H360Q375 441 466 441Q547 441 559 444H566V382H471L355 246L504 63L545 62H586V0H578Q563 3 469 3Q365 3 347 0H338V62H366Q366 63 326 112T285 163L198 63L217 62H235V0H227Z" style="stroke-width: 3;"/></g></g><g data-mml-node="mo" transform="translate(1592,0)"><path data-c="29" d="M60 749L64 750Q69 750 74 750H86L114 726Q208 641 251 514T294 250Q294 182 284 119T261 12T224 -76T186 -143T145 -194T113 -227T90 -246Q87 -249 86 -250H74Q66 -250 63 -250T58 -247T55 -238Q56 -237 66 -225Q221 -64 221 250T66 725Q56 737 55 738Q55 746 60 749Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(2258.8,0)"><path data-c="3C" d="M694 -11T694 -19T688 -33T678 -40Q671 -40 524 29T234 166L90 235Q83 240 83 250Q83 261 91 266Q664 540 678 540Q681 540 687 534T694 519T687 505Q686 504 417 376L151 250L417 124Q686 -4 687 -5Q694 -11 694 -19Z" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(3314.6,0)"><path data-c="1D45F" d="M21 287Q22 290 23 295T28 317T38 348T53 381T73 411T99 433T132 442Q161 442 183 430T214 408T225 388Q227 382 228 382T236 389Q284 441 347 441H350Q398 441 422 400Q430 381 430 363Q430 333 417 315T391 292T366 288Q346 288 334 299T322 328Q322 376 378 392Q356 405 342 405Q286 405 239 331Q229 315 224 298T190 165Q156 25 151 16Q138 -11 108 -11Q95 -11 87 -5T76 7T74 17Q74 30 114 189T154 366Q154 405 128 405Q107 405 92 377T68 316T57 280Q55 278 41 278H27Q21 284 21 287Z" style="stroke-width: 3;"/></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mi>ϕ</mi><mo stretchy="false">(</mo><mrow data-mjx-texclass="ORD"><mi mathvariant="bold">x</mi></mrow><mo stretchy="false">)</mo><mo>&lt;</mo><mi>r</mi></math></mjx-assistive-mml></mjx-container>, con una profundidad de penetración <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.566ex;" xmlns="http://www.w3.org/2000/svg" width="12.423ex" height="2.262ex" role="img" focusable="false" viewBox="0 -750 5491 1000" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mi"><path data-c="1D45D" d="M23 287Q24 290 25 295T30 317T40 348T55 381T75 411T101 433T134 442Q209 442 230 378L240 387Q302 442 358 442Q423 442 460 395T497 281Q497 173 421 82T249 -10Q227 -10 210 -4Q199 1 187 11T168 28L161 36Q160 35 139 -51T118 -138Q118 -144 126 -145T163 -148H188Q194 -155 194 -157T191 -175Q188 -187 185 -190T172 -194Q170 -194 161 -194T127 -193T65 -192Q-5 -192 -24 -194H-32Q-39 -187 -39 -183Q-37 -156 -26 -148H-6Q28 -147 33 -136Q36 -130 94 103T155 350Q156 355 156 364Q156 405 131 405Q109 405 94 377T71 316T59 280Q57 278 43 278H29Q23 284 23 287ZM178 102Q200 26 252 26Q282 26 310 49T356 107Q374 141 392 215T411 325V331Q411 405 350 405Q339 405 328 402T306 393T286 380T269 365T254 350T243 336T235 326L232 322Q232 321 229 308T218 264T204 212Q178 106 178 102Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(780.8,0)"><path data-c="3D" d="M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(1836.6,0)"><path data-c="1D45F" d="M21 287Q22 290 23 295T28 317T38 348T53 381T73 411T99 433T132 442Q161 442 183 430T214 408T225 388Q227 382 228 382T236 389Q284 441 347 441H350Q398 441 422 400Q430 381 430 363Q430 333 417 315T391 292T366 288Q346 288 334 299T322 328Q322 376 378 392Q356 405 342 405Q286 405 239 331Q229 315 224 298T190 165Q156 25 151 16Q138 -11 108 -11Q95 -11 87 -5T76 7T74 17Q74 30 114 189T154 366Q154 405 128 405Q107 405 92 377T68 316T57 280Q55 278 41 278H27Q21 284 21 287Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(2509.8,0)"><path data-c="2212" d="M84 237T84 250T98 270H679Q694 262 694 250T679 230H98Q84 237 84 250Z" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(3510,0)"><path data-c="1D719" d="M409 688Q413 694 421 694H429H442Q448 688 448 686Q448 679 418 563Q411 535 404 504T392 458L388 442Q388 441 397 441T429 435T477 418Q521 397 550 357T579 260T548 151T471 65T374 11T279 -10H275L251 -105Q245 -128 238 -160Q230 -192 227 -198T215 -205H209Q189 -205 189 -198Q189 -193 211 -103L234 -11Q234 -10 226 -10Q221 -10 206 -8T161 6T107 36T62 89T43 171Q43 231 76 284T157 370T254 422T342 441Q347 441 348 445L378 567Q409 686 409 688ZM122 150Q122 116 134 91T167 53T203 35T237 27H244L337 404Q333 404 326 403T297 395T255 379T211 350T170 304Q152 276 137 237Q122 191 122 150ZM500 282Q500 320 484 347T444 385T405 400T381 404H378L332 217L284 29Q284 27 285 27Q293 27 317 33T357 47Q400 66 431 100T475 170T494 234T500 282Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(4106,0)"><path data-c="28" d="M94 250Q94 319 104 381T127 488T164 576T202 643T244 695T277 729T302 750H315H319Q333 750 333 741Q333 738 316 720T275 667T226 581T184 443T167 250T184 58T225 -81T274 -167T316 -220T333 -241Q333 -250 318 -250H315H302L274 -226Q180 -141 137 -14T94 250Z" style="stroke-width: 3;"/></g><g data-mml-node="TeXAtom" data-mjx-texclass="ORD" transform="translate(4495,0)"><g data-mml-node="mi"><path data-c="1D431" d="M227 0Q212 3 121 3Q40 3 28 0H21V62H117L245 213L109 382H26V444H34Q49 441 143 441Q247 441 265 444H274V382H246L281 339Q315 297 316 297Q320 297 354 341L389 382H352V444H360Q375 441 466 441Q547 441 559 444H566V382H471L355 246L504 63L545 62H586V0H578Q563 3 469 3Q365 3 347 0H338V62H366Q366 63 326 112T285 163L198 63L217 62H235V0H227Z" style="stroke-width: 3;"/></g></g><g data-mml-node="mo" transform="translate(5102,0)"><path data-c="29" d="M60 749L64 750Q69 750 74 750H86L114 726Q208 641 251 514T294 250Q294 182 284 119T261 12T224 -76T186 -143T145 -194T113 -227T90 -246Q87 -249 86 -250H74Q66 -250 63 -250T58 -247T55 -238Q56 -237 66 -225Q221 -64 221 250T66 725Q56 737 55 738Q55 746 60 749Z" style="stroke-width: 3;"/></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mi>p</mi><mo>=</mo><mi>r</mi><mo>−</mo><mi>ϕ</mi><mo stretchy="false">(</mo><mrow data-mjx-texclass="ORD"><mi mathvariant="bold">x</mi></mrow><mo stretchy="false">)</mo></math></mjx-assistive-mml></mjx-container>, y la dirección de expulsión es el gradiente del campo <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -1.238ex;" xmlns="http://www.w3.org/2000/svg" width="9.256ex" height="3.445ex" role="img" focusable="false" viewBox="0 -975.7 4091.1 1522.8" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="TeXAtom" data-mjx-texclass="ORD"><g data-mml-node="mover"><g data-mml-node="mi"><path data-c="1D45B" d="M21 287Q22 293 24 303T36 341T56 388T89 425T135 442Q171 442 195 424T225 390T231 369Q231 367 232 367L243 378Q304 442 382 442Q436 442 469 415T503 336T465 179T427 52Q427 26 444 26Q450 26 453 27Q482 32 505 65T540 145Q542 153 560 153Q580 153 580 145Q580 144 576 130Q568 101 554 73T508 17T439 -10Q392 -10 371 17T350 73Q350 92 386 193T423 345Q423 404 379 404H374Q288 404 229 303L222 291L189 157Q156 26 151 16Q138 -11 108 -11Q95 -11 87 -5T76 7T74 17Q74 30 112 180T152 343Q153 348 153 366Q153 405 129 405Q91 405 66 305Q60 285 60 284Q58 278 41 278H27Q21 284 21 287Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(300,16) translate(-250 0)"><path data-c="5E" d="M112 560L249 694L257 686Q387 562 387 560L361 531Q359 532 303 581L250 627L195 580Q182 569 169 557T148 538L140 532Q138 530 125 546L112 560Z" style="stroke-width: 3;"/></g></g></g><g data-mml-node="mo" transform="translate(877.8,0)"><path data-c="3D" d="M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z" style="stroke-width: 3;"/></g><g data-mml-node="mfrac" transform="translate(1933.6,0)"><g data-mml-node="mrow" transform="translate(573.6,485) scale(0.707)"><g data-mml-node="mi"><path data-c="2207" d="M46 676Q46 679 51 683H781Q786 679 786 676Q786 674 617 326T444 -26Q439 -33 416 -33T388 -26Q385 -22 216 326T46 676ZM697 596Q697 597 445 597T193 596Q195 591 319 336T445 80L697 596Z" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(833,0)"><path data-c="1D719" d="M409 688Q413 694 421 694H429H442Q448 688 448 686Q448 679 418 563Q411 535 404 504T392 458L388 442Q388 441 397 441T429 435T477 418Q521 397 550 357T579 260T548 151T471 65T374 11T279 -10H275L251 -105Q245 -128 238 -160Q230 -192 227 -198T215 -205H209Q189 -205 189 -198Q189 -193 211 -103L234 -11Q234 -10 226 -10Q221 -10 206 -8T161 6T107 36T62 89T43 171Q43 231 76 284T157 370T254 422T342 441Q347 441 348 445L378 567Q409 686 409 688ZM122 150Q122 116 134 91T167 53T203 35T237 27H244L337 404Q333 404 326 403T297 395T255 379T211 350T170 304Q152 276 137 237Q122 191 122 150ZM500 282Q500 320 484 347T444 385T405 400T381 404H378L332 217L284 29Q284 27 285 27Q293 27 317 33T357 47Q400 66 431 100T475 170T494 234T500 282Z" style="stroke-width: 3;"/></g></g><g data-mml-node="mrow" transform="translate(220,-370.3) scale(0.707)"><g data-mml-node="mo"><path data-c="2016" d="M133 736Q138 750 153 750Q164 750 170 739Q172 735 172 250T170 -239Q164 -250 152 -250Q144 -250 138 -244L137 -243Q133 -241 133 -179T132 250Q132 731 133 736ZM329 739Q334 750 346 750Q353 750 361 744L362 743Q366 741 366 679T367 250T367 -178T362 -243L361 -244Q355 -250 347 -250Q335 -250 329 -239Q327 -235 327 250T329 739Z" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(500,0)"><path data-c="2207" d="M46 676Q46 679 51 683H781Q786 679 786 676Q786 674 617 326T444 -26Q439 -33 416 -33T388 -26Q385 -22 216 326T46 676ZM697 596Q697 597 445 597T193 596Q195 591 319 336T445 80L697 596Z" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(1333,0)"><path data-c="1D719" d="M409 688Q413 694 421 694H429H442Q448 688 448 686Q448 679 418 563Q411 535 404 504T392 458L388 442Q388 441 397 441T429 435T477 418Q521 397 550 357T579 260T548 151T471 65T374 11T279 -10H275L251 -105Q245 -128 238 -160Q230 -192 227 -198T215 -205H209Q189 -205 189 -198Q189 -193 211 -103L234 -11Q234 -10 226 -10Q221 -10 206 -8T161 6T107 36T62 89T43 171Q43 231 76 284T157 370T254 422T342 441Q347 441 348 445L378 567Q409 686 409 688ZM122 150Q122 116 134 91T167 53T203 35T237 27H244L337 404Q333 404 326 403T297 395T255 379T211 350T170 304Q152 276 137 237Q122 191 122 150ZM500 282Q500 320 484 347T444 385T405 400T381 404H378L332 217L284 29Q284 27 285 27Q293 27 317 33T357 47Q400 66 431 100T475 170T494 234T500 282Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(1929,0)"><path data-c="2016" d="M133 736Q138 750 153 750Q164 750 170 739Q172 735 172 250T170 -239Q164 -250 152 -250Q144 -250 138 -244L137 -243Q133 -241 133 -179T132 250Q132 731 133 736ZM329 739Q334 750 346 750Q353 750 361 744L362 743Q366 741 366 679T367 250T367 -178T362 -243L361 -244Q355 -250 347 -250Q335 -250 329 -239Q327 -235 327 250T329 739Z" style="stroke-width: 3;"/></g></g><rect width="1917.6" height="60" x="120" y="220"/></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mrow data-mjx-texclass="ORD"><mover><mi>n</mi><mo stretchy="false">^</mo></mover></mrow><mo>=</mo><mfrac><mrow><mi mathvariant="normal">∇</mi><mi>ϕ</mi></mrow><mrow><mo data-mjx-texclass="OPEN" fence="false" stretchy="false">‖</mo><mi mathvariant="normal">∇</mi><mi>ϕ</mi><mo data-mjx-texclass="CLOSE" fence="false" stretchy="false">‖</mo></mrow></mfrac></math></mjx-assistive-mml></mjx-container>. Para impedir que la cápsula vuelva a entrar en la superficie, se proyecta la velocidad para cancelar su componente hacia el interior:</p>
<mjx-container tabindex="0" class="MathJax" jax="SVG" display="true" style="direction: ltr; display: block; text-align: center; margin: 1em 0; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.566ex;" xmlns="http://www.w3.org/2000/svg" width="17.018ex" height="2.398ex" role="img" focusable="false" viewBox="0 -810 7521.9 1060" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="msup"><g data-mml-node="TeXAtom" data-mjx-texclass="ORD"><g data-mml-node="mi"><path data-c="1D42F" d="M401 444Q413 441 495 441Q568 441 574 444H580V382H510L409 156Q348 18 339 6Q331 -4 320 -4Q318 -4 313 -4T303 -3H288Q273 -3 264 12T221 102Q206 135 197 156L96 382H26V444H34Q49 441 145 441Q252 441 270 444H279V382H231L284 264Q335 149 338 149Q338 150 389 264T442 381Q442 382 418 382H394V444H401Z" style="stroke-width: 3;"/></g></g><g data-mml-node="mo" transform="translate(640,413) scale(0.707)"><path data-c="2032" d="M79 43Q73 43 52 49T30 61Q30 68 85 293T146 528Q161 560 198 560Q218 560 240 545T262 501Q262 496 260 486Q259 479 173 263T84 45T79 43Z" style="stroke-width: 3;"/></g></g><g data-mml-node="mo" transform="translate(1162.2,0)"><path data-c="3D" d="M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z" style="stroke-width: 3;"/></g><g data-mml-node="TeXAtom" data-mjx-texclass="ORD" transform="translate(2218,0)"><g data-mml-node="mi"><path data-c="1D42F" d="M401 444Q413 441 495 441Q568 441 574 444H580V382H510L409 156Q348 18 339 6Q331 -4 320 -4Q318 -4 313 -4T303 -3H288Q273 -3 264 12T221 102Q206 135 197 156L96 382H26V444H34Q49 441 145 441Q252 441 270 444H279V382H231L284 264Q335 149 338 149Q338 150 389 264T442 381Q442 382 418 382H394V444H401Z" style="stroke-width: 3;"/></g></g><g data-mml-node="mo" transform="translate(3047.2,0)"><path data-c="2212" d="M84 237T84 250T98 270H679Q694 262 694 250T679 230H98Q84 237 84 250Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(4047.5,0)"><path data-c="28" d="M94 250Q94 319 104 381T127 488T164 576T202 643T244 695T277 729T302 750H315H319Q333 750 333 741Q333 738 316 720T275 667T226 581T184 443T167 250T184 58T225 -81T274 -167T316 -220T333 -241Q333 -250 318 -250H315H302L274 -226Q180 -141 137 -14T94 250Z" style="stroke-width: 3;"/></g><g data-mml-node="TeXAtom" data-mjx-texclass="ORD" transform="translate(4436.5,0)"><g data-mml-node="mi"><path data-c="1D42F" d="M401 444Q413 441 495 441Q568 441 574 444H580V382H510L409 156Q348 18 339 6Q331 -4 320 -4Q318 -4 313 -4T303 -3H288Q273 -3 264 12T221 102Q206 135 197 156L96 382H26V444H34Q49 441 145 441Q252 441 270 444H279V382H231L284 264Q335 149 338 149Q338 150 389 264T442 381Q442 382 418 382H394V444H401Z" style="stroke-width: 3;"/></g></g><g data-mml-node="mo" transform="translate(5265.7,0)"><path data-c="22C5" d="M78 250Q78 274 95 292T138 310Q162 310 180 294T199 251Q199 226 182 208T139 190T96 207T78 250Z" style="stroke-width: 3;"/></g><g data-mml-node="TeXAtom" data-mjx-texclass="ORD" transform="translate(5765.9,0)"><g data-mml-node="mover"><g data-mml-node="mi"><path data-c="1D45B" d="M21 287Q22 293 24 303T36 341T56 388T89 425T135 442Q171 442 195 424T225 390T231 369Q231 367 232 367L243 378Q304 442 382 442Q436 442 469 415T503 336T465 179T427 52Q427 26 444 26Q450 26 453 27Q482 32 505 65T540 145Q542 153 560 153Q580 153 580 145Q580 144 576 130Q568 101 554 73T508 17T439 -10Q392 -10 371 17T350 73Q350 92 386 193T423 345Q423 404 379 404H374Q288 404 229 303L222 291L189 157Q156 26 151 16Q138 -11 108 -11Q95 -11 87 -5T76 7T74 17Q74 30 112 180T152 343Q153 348 153 366Q153 405 129 405Q91 405 66 305Q60 285 60 284Q58 278 41 278H27Q21 284 21 287Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(300,16) translate(-250 0)"><path data-c="5E" d="M112 560L249 694L257 686Q387 562 387 560L361 531Q359 532 303 581L250 627L195 580Q182 569 169 557T148 538L140 532Q138 530 125 546L112 560Z" style="stroke-width: 3;"/></g></g></g><g data-mml-node="mo" transform="translate(6365.9,0)"><path data-c="29" d="M60 749L64 750Q69 750 74 750H86L114 726Q208 641 251 514T294 250Q294 182 284 119T261 12T224 -76T186 -143T145 -194T113 -227T90 -246Q87 -249 86 -250H74Q66 -250 63 -250T58 -247T55 -238Q56 -237 66 -225Q221 -64 221 250T66 725Q56 737 55 738Q55 746 60 749Z" style="stroke-width: 3;"/></g><g data-mml-node="mstyle" transform="translate(6754.9,0)"><g data-mml-node="mspace"/></g><g data-mml-node="TeXAtom" data-mjx-texclass="ORD" transform="translate(6921.9,0)"><g data-mml-node="mover"><g data-mml-node="mi"><path data-c="1D45B" d="M21 287Q22 293 24 303T36 341T56 388T89 425T135 442Q171 442 195 424T225 390T231 369Q231 367 232 367L243 378Q304 442 382 442Q436 442 469 415T503 336T465 179T427 52Q427 26 444 26Q450 26 453 27Q482 32 505 65T540 145Q542 153 560 153Q580 153 580 145Q580 144 576 130Q568 101 554 73T508 17T439 -10Q392 -10 371 17T350 73Q350 92 386 193T423 345Q423 404 379 404H374Q288 404 229 303L222 291L189 157Q156 26 151 16Q138 -11 108 -11Q95 -11 87 -5T76 7T74 17Q74 30 112 180T152 343Q153 348 153 366Q153 405 129 405Q91 405 66 305Q60 285 60 284Q58 278 41 278H27Q21 284 21 287Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(300,16) translate(-250 0)"><path data-c="5E" d="M112 560L249 694L257 686Q387 562 387 560L361 531Q359 532 303 581L250 627L195 580Q182 569 169 557T148 538L140 532Q138 530 125 546L112 560Z" style="stroke-width: 3;"/></g></g></g></g></g></svg><mjx-assistive-mml unselectable="on" display="block" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; overflow: hidden; width: 100%;"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><msup><mrow data-mjx-texclass="ORD"><mi mathvariant="bold">v</mi></mrow><mo data-mjx-alternate="1">′</mo></msup><mo>=</mo><mrow data-mjx-texclass="ORD"><mi mathvariant="bold">v</mi></mrow><mo>−</mo><mo stretchy="false">(</mo><mrow data-mjx-texclass="ORD"><mi mathvariant="bold">v</mi></mrow><mo>⋅</mo><mrow data-mjx-texclass="ORD"><mover><mi>n</mi><mo stretchy="false">^</mo></mover></mrow><mo stretchy="false">)</mo><mstyle scriptlevel="0"><mspace width="0.167em"/></mstyle><mrow data-mjx-texclass="ORD"><mover><mi>n</mi><mo stretchy="false">^</mo></mover></mrow></math></mjx-assistive-mml></mjx-container><p>Esto deja únicamente la componente que se desliza a lo largo de la superficie. No es un motor de físicas. Son consultas geométricas y una respuesta sencilla. Pero gestiona cuevas, salientes y túneles esculpidos sin ningún código específico para cada forma. Entras en una cueva que excavaste diez segundos antes y la cápsula sigue con exactitud el contorno del techo.</p>
<p>El modelo de movimiento comenzó siendo práctico y acabó siendo divertido. Caminar, correr, esprintar, saltar y deslizarse por pendientes superiores a 45 grados. Después añadí un parapente al estilo BotW y el spike se convirtió en algo que no quería cerrar.</p>
<p>Pulsa Espacio mientras estás en el aire. La gravedad baja de -30 a -4. La velocidad de caída se limita a -3. Una malla con forma de ala delta se despliega desde la cápsula mediante interpolación de escala. Gira a la izquierda y el ala se inclina. La orientación de la cápsula se alinea automáticamente con el vector de velocidad, por lo que siempre miras en la dirección en la que avanzas. Suelta Espacio para caer. Toca el suelo y vuelves a correr.</p>
<p>La cámara se aleja y adopta una vista en tercera persona —pulsa P para alternarla—. Sigue al jugador desde atrás con suavizado de guiñada. Un ray marching desde el jugador hasta la cámara comprueba el terreno en 20 pasos. Si vuelas hacia el interior de una cueva, el brazo de la cámara se acorta suavemente en lugar de atravesar la roca. Al salir por el otro lado, vuelve a extenderse.</p>
<p>Este es el momento que hizo que el spike mereciera la pena: esculpe un acantilado alto con el pincel del mapa de alturas. Cambia a la cámara en tercera persona. Corre hasta el borde. Salta. Despliega el planeador. Gira a la izquierda sobre el terreno que acabas de esculpir, con la hierba que cultivaste en el spike 29 ondeando debajo, la textura de roca del spike 28 sobre la cara del acantilado y las uniones de Transvoxel manteniéndose en cada límite entre chunks. Aterriza al otro lado. Todo funcionando en conjunto dentro de una sola pestaña del navegador.</p>
<h2 id="esculpir-bajo-tus-propios-pies" tabindex="-1">Esculpir bajo tus propios pies <a class="header-anchor" href="#esculpir-bajo-tus-propios-pies" aria-label="Permalink to &quot;Esculpir bajo tus propios pies&quot;"></a></h2>
<p>Había algo sobre lo que no estaba seguro: ¿qué ocurre cuando esculpes el terreno sobre el que está el personaje? Los cambios del mapa de alturas se propagan de inmediato a través de <code>terrainQuery()</code> porque lee directamente el búfer de la CPU. Los cambios del SDF se propagan a través de la copia SDF de la CPU. La cápsula resuelve la penetración en el siguiente tick de físicas, que a 120 Hz ocurre en menos de <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.816ex;" xmlns="http://www.w3.org/2000/svg" width="9.304ex" height="2.773ex" role="img" focusable="false" viewBox="0 -864.9 4112.2 1225.5" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mfrac"><g data-mml-node="mn" transform="translate(573.6,394) scale(0.707)"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" style="stroke-width: 3;"/></g><g data-mml-node="mn" transform="translate(220,-345) scale(0.707)"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" style="stroke-width: 3;"/><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" transform="translate(500,0)" style="stroke-width: 3;"/><path data-c="30" d="M96 585Q152 666 249 666Q297 666 345 640T423 548Q460 465 460 320Q460 165 417 83Q397 41 362 16T301 -15T250 -22Q224 -22 198 -16T137 16T82 83Q39 165 39 320Q39 494 96 585ZM321 597Q291 629 250 629Q208 629 178 597Q153 571 145 525T137 333Q137 175 145 125T181 46Q209 16 250 16Q290 16 318 46Q347 76 354 130T362 333Q362 478 354 524T321 597Z" transform="translate(1000,0)" style="stroke-width: 3;"/></g><rect width="1260.7" height="60" x="120" y="220"/></g><g data-mml-node="mo" transform="translate(1778.4,0)"><path data-c="2248" d="M55 319Q55 360 72 393T114 444T163 472T205 482Q207 482 213 482T223 483Q262 483 296 468T393 413L443 381Q502 346 553 346Q609 346 649 375T694 454Q694 465 698 474T708 483Q722 483 722 452Q722 386 675 338T555 289Q514 289 468 310T388 357T308 404T224 426Q164 426 125 393T83 318Q81 289 69 289Q55 289 55 319ZM55 85Q55 126 72 159T114 210T163 238T205 248Q207 248 213 248T223 249Q262 249 296 234T393 179L443 147Q502 112 553 112Q609 112 649 141T694 220Q694 249 708 249T722 217Q722 153 675 104T555 55Q514 55 468 76T388 123T308 170T224 192Q164 192 125 159T83 84Q80 55 69 55Q55 55 55 85Z" style="stroke-width: 3;"/></g><g data-mml-node="mn" transform="translate(2834.2,0)"><path data-c="38" d="M70 417T70 494T124 618T248 666Q319 666 374 624T429 515Q429 485 418 459T392 417T361 389T335 371T324 363L338 354Q352 344 366 334T382 323Q457 264 457 174Q457 95 399 37T249 -22Q159 -22 101 29T43 155Q43 263 172 335L154 348Q133 361 127 368Q70 417 70 494ZM286 386L292 390Q298 394 301 396T311 403T323 413T334 425T345 438T355 454T364 471T369 491T371 513Q371 556 342 586T275 624Q268 625 242 625Q201 625 165 599T128 534Q128 511 141 492T167 463T217 431Q224 426 228 424L286 386ZM250 21Q308 21 350 55T392 137Q392 154 387 169T375 194T353 216T330 234T301 253T274 270Q260 279 244 289T218 306L210 311Q204 311 181 294T133 239T107 157Q107 98 150 60T250 21Z" style="stroke-width: 3;"/><path data-c="2E" d="M78 60Q78 84 95 102T138 120Q162 120 180 104T199 61Q199 36 182 18T139 0T96 17T78 60Z" transform="translate(500,0)" style="stroke-width: 3;"/><path data-c="33" d="M127 463Q100 463 85 480T69 524Q69 579 117 622T233 665Q268 665 277 664Q351 652 390 611T430 522Q430 470 396 421T302 350L299 348Q299 347 308 345T337 336T375 315Q457 262 457 175Q457 96 395 37T238 -22Q158 -22 100 21T42 130Q42 158 60 175T105 193Q133 193 151 175T169 130Q169 119 166 110T159 94T148 82T136 74T126 70T118 67L114 66Q165 21 238 21Q293 21 321 74Q338 107 338 175V195Q338 290 274 322Q259 328 213 329L171 330L168 332Q166 335 166 348Q166 366 174 366Q202 366 232 371Q266 376 294 413T322 525V533Q322 590 287 612Q265 626 240 626Q208 626 181 615T143 592T132 580H135Q138 579 143 578T153 573T165 566T175 555T183 540T186 520Q186 498 172 481T127 463Z" transform="translate(778,0)" style="stroke-width: 3;"/></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mfrac><mn>1</mn><mn>120</mn></mfrac><mo>≈</mo><mn>8.3</mn></math></mjx-assistive-mml></mjx-container> ms.</p>
<p>Simplemente funciona. Eleva el suelo bajo el jugador y este sube con él. Excava el suelo y cae. Sin tratamiento especial. Las físicas se ejecutan con suficiente rapidez para que los cambios de terreno de un solo fotograma nunca produzcan penetraciones grandes. Fue un feliz accidente de haber elegido 120 Hz para el paso de tiempo. Lo elegimos para conseguir un movimiento fluido y, de paso, hizo que editar el terreno fuera seguro sin ningún coste adicional.</p>
<h2 id="_30-spikes-despues" tabindex="-1">30 spikes después <a class="header-anchor" href="#_30-spikes-despues" aria-label="Permalink to &quot;30 spikes después&quot;"></a></h2>
<p>Comenzamos esta serie con un mapa de alturas plano y 500 cubos. Ahora tenemos terreno esculpido con cuevas volumétricas, cosido de uniones mediante Transvoxel, texturizado multimaterial que responde a la forma de la superficie, 80 000 matas de hierba meciéndose con el viento y un personaje que camina, esprinta, salta y planea sobre todo ello.</p>
<p>Nada de esto está todavía en producción. El código de <code>world/client/</code> sigue ejecutándose en WebGL con chunks sencillos de mapas de alturas. Todo lo creado en estos 30 spikes vive en páginas HTML independientes. El siguiente paso es la integración: migrar a <code>WebGPURenderer</code>, conectar la política híbrida HM/MC con el gestor de chunks y vincular los sistemas de pinceles y materiales con el multijugador.</p>
<p>Pero el sistema de renderizado ya no es el riesgo. Las preguntas abiertas tienen que ver con el flujo de datos: persistencia de las ediciones, sincronización de los trazos de pincel por red y esculpido colaborativo. Lo que ocurre entre los jugadores, no entre los triángulos.</p>
<p>Si has seguido esta serie desde la parte 1, gracias por acompañarnos durante las partes más complicadas. Si acabas de descubrirla, vuelve a la <a href="/es/blog/2026-02-25-open-world-browser-part-01-risk-first.html">parte 1</a>. Las lecciones están en los caminos equivocados.</p>
<h2 id="tecnologia-mencionada-en-este-capitulo" tabindex="-1">Tecnología mencionada en este capítulo <a class="header-anchor" href="#tecnologia-mencionada-en-este-capitulo" aria-label="Permalink to &quot;Tecnología mencionada en este capítulo&quot;"></a></h2>
<p><strong>TSL (Three Shading Language).</strong> El sistema de shaders basado en nodos de Three.js para el renderizador WebGPU. Los materiales se componen a partir de nodos (<code>positionWorld</code>, <code>normalWorld</code>, <code>smoothstep</code>, <code>triplanarTexture</code>) mediante composición de funciones en JavaScript. El grafo de shaders se compila a WGSL en tiempo de ejecución. TSL sustituye al <code>ShaderMaterial</code> de GLSL puro en los destinos WebGPU y permite la interoperabilidad entre las funciones estándar de los materiales de Three.js —luces, sombras y niebla— y la lógica personalizada por fragmento.</p>
<p><strong>Mapeado triplanar.</strong> Una técnica de proyección de texturas que muestrea una textura tres veces —planos XY, XZ e YZ— y mezcla los resultados según la dirección de la normal de la superficie. Esto elimina el estiramiento UV en geometrías de malla arbitrarias, algo esencial para la salida de marching cubes, donde los triángulos no tienen coordenadas UV significativas. TSL proporciona <code>triplanarTexture()</code> como nodo integrado.</p>
<p><strong>Vegetación instanciada con briznas de quads cruzados.</strong> Cada mata de hierba consta de tres quads que se cruzan con ángulos de 60 grados, lo que crea una apariencia volumétrica desde cualquier dirección. Los cuatro segmentos verticales de cada quad permiten una flexión suave para animar el viento. Todo el campo se renderiza como un único <code>InstancedMesh</code> por chunk. Se reserva un 25 % de capacidad adicional para que las nuevas instancias puedan ocupar los espacios reservados cuando se edite el terreno, sin tener que reasignar el búfer de la GPU. Consulta nuestra <a href="/es/guides/landscape-generation-browser.html#vegetation-and-foliage">guía de generación de paisajes sobre vegetación</a>.
<strong>Colisión entre cápsula y SDF.</strong> Colisión del personaje con terreno volumétrico sin un motor de física. Se comprueba la cápsula en varios puntos respecto al SDF. Cuando el valor del campo es menor que el radio de la cápsula, el gradiente proporciona la normal hacia el exterior y la diferencia determina la profundidad de penetración. Esto permite manejar cuevas, salientes y túneles sin código específico para cada forma. Consulta <a href="/es/guides/landscape-generation-browser.html#physics-on-sdf-terrain">colisiones con terreno SDF</a>.</p>
<p><strong>Controlador de personaje con paso de tiempo fijo.</strong> La física se actualiza a 120 Hz independientemente de la velocidad de fotogramas, acumulando tiempo real y consumiéndolo en pasos de tamaño fijo. Un número máximo de subpasos evita la espiral de la muerte en fotogramas lentos. El ajuste al suelo mantiene la cápsula adherida durante el desplazamiento por pendientes. El paso de tiempo fijo garantiza un comportamiento determinista para futuras repeticiones multijugador.</p>
<hr>
<p>Parte 14 de 29.
Anterior: <a href="/es/blog/2026-04-13-open-world-browser-part-13-terrain-sculpting.html">Parte 13 - El esculpido del terreno y la muerte de la función matemática</a>
Siguiente: <a href="/es/blog/2026-04-13-open-world-browser-part-15-multiplayer-and-water.html">Parte 15 - Sustituye la base y luego sincronízala</a>
Guía de la serie: <a href="/es/blog/2026-02-25-open-world-browser-series-guide.html">/es/blog/2026-02-25-open-world-browser-series-guide</a></p>
]]></content:encoded>
            <enclosure url="https://cdn.cinevva.com/blog/why-webgpu-engine-hero.jpg" length="0" type="image/jpg"/>
        </item>
        <item>
            <title><![CDATA[Construir un mundo abierto en el navegador, parte 15: Sustituir la base y después sincronizarla]]></title>
            <link>https://app.cinevva.com/es/blog/2026-04-13-open-world-browser-part-15-multiplayer-and-water</link>
            <guid>https://app.cinevva.com/es/blog/2026-04-13-open-world-browser-part-15-multiplayer-and-water</guid>
            <pubDate>Mon, 13 Apr 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Los experimentos 31 y 32 llevaron a sustituir el mundo heredado por el mejor experimento, demostraron el multijugador mediante repetición de parámetros del pincel y añadieron un océano con natación.]]></description>
            <content:encoded><![CDATA[<h1 id="construir-un-mundo-abierto-en-el-navegador-parte-15-sustituir-la-base-y-despues-sincronizarla" tabindex="-1">Construir un mundo abierto en el navegador, parte 15: Sustituir la base y después sincronizarla <a class="header-anchor" href="#construir-un-mundo-abierto-en-el-navegador-parte-15-sustituir-la-base-y-despues-sincronizarla" aria-label="Permalink to &quot;Construir un mundo abierto en el navegador, parte 15: Sustituir la base y después sincronizarla&quot;"></a></h1>
<p><em>Por <a href="/es/about.html">Oleg Sidorkin</a>, CTO y cofundador de Cinevva</em></p>
<p>¿Acabas de llegar? Consulta la <a href="/es/blog/2026-02-25-open-world-browser-series-guide.html">guía de la serie</a>. Explica qué es un experimento y enlaza todas las partes.</p>
<p>Las primeras catorce partes cubrieron los experimentos del 1 al 30. Esa etapa terminó con un sistema de terreno que podía esculpirse en tiempo real, además de un personaje capaz de caminar, planear y caer sobre él. Esta parte retoma la serie en el experimento 31, y lo primero que tuvimos que decidir no fue una cuestión técnica. Fue qué hacer con todo aquel código experimental.</p>
<h2 id="la-decision-de-«sustituir-no-portar»" tabindex="-1">La decisión de «sustituir, no portar» <a class="header-anchor" href="#la-decision-de-«sustituir-no-portar»" aria-label="Permalink to &quot;La decisión de «sustituir, no portar»&quot;"></a></h2>
<p>Teníamos 30 archivos HTML independientes, cada uno dedicado a demostrar un concepto aislado, y ninguna integración. El <code>world/client/</code> de producción seguía usando la pila antigua: WebGL, un mapa de alturas sencillo, un controlador de personaje de 75 líneas y un protocolo MessagePack con nueve tipos de mensajes. Sin edición, sin WebGPU, sin materiales y sin vegetación.</p>
<p>El plan obvio era portar los resultados de los experimentos a ese código de producción uno por uno. Lo descartamos. El experimento 30 ya tenía mejores terrenos, físicas, materiales, vegetación y cámara que los que jamás tuvo <code>world/client/</code>. Portarlo todo al antiguo código WebGL habría significado luchar contra él en cada paso. Así que decidimos sustituir la implementación del mundo por el experimento más logrado y seguir construyendo a partir de ahí. El experimento 30 se convirtió en la nueva base y <code>world/client/</code> pasó a ser código muerto.</p>
<p>Eso replanteó el trabajo restante. Para pasar de una «gran demostración técnica para un jugador» a un «producto» necesitábamos multijugador, persistencia, streaming de un mundo infinito y colocación de objetos. La sincronización multijugador del terreno fue lo primero, porque es lo que obliga a definir la arquitectura. La pregunta que resuelve es fácil de formular y costosa de responder mal: cuando el jugador A esculpe, ¿qué se envía realmente por la red?</p>
<h2 id="repeticion-de-parametros-del-pincel-no-sincronizacion-de-pixeles" tabindex="-1">Repetición de parámetros del pincel, no sincronización de píxeles <a class="header-anchor" href="#repeticion-de-parametros-del-pincel-no-sincronizacion-de-pixeles" aria-label="Permalink to &quot;Repetición de parámetros del pincel, no sincronización de píxeles&quot;"></a></h2>
<div style="position:relative;padding-bottom:56.25%;height:0;overflow:hidden;border-radius:8px;margin:1.5rem 0;border:1px solid rgba(255,255,255,0.12)">
<iframe src="/es/spikes/31-multiplayer-sync/" title="Experimento 31: Sincronización multijugador del terreno" style="position:absolute;top:0;left:0;width:100%;height:100%;border:0;background:#000" loading="lazy" allowfullscreen></iframe>
</div>
<p><a href="/es/spikes/31-multiplayer-sync/" target="_blank">Abrir el experimento 31 en una pestaña nueva ↗</a> · <a href="/es/blog/spike-source?spike=31-multiplayer-sync">Ver código fuente</a></p>
<p>Antes de escribir una sola línea de código de red, rastreamos con exactitud qué hace una pincelada. El pincel del mapa de alturas recorre un radio alrededor del cursor dentro de un <code>Float32Array</code> en la CPU, aplica una atenuación smoothstep y suma, resta, suaviza o aplana. El pincel SDF hace lo mismo en 3D sobre una esfera de vóxeles. Ambas rutas son operaciones matemáticas puras con arrays en la CPU. No hay cómputo en la GPU dentro del bucle, ni aleatoriedad, ni operaciones de coma flotante no deterministas. El mismo array de entrada más los mismos parámetros produce la misma salida en todas las máquinas.</p>
<p>Ese es todo el truco. No enviamos el terreno editado. Enviamos los parámetros del pincel, 56 bytes por ciclo de pincelada, y cada cliente repite la misma función determinista. El protocolo de sincronización tiene cuatro tipos de mensajes: detección de pares, el mensaje del pincel <code>{op, wx, wy, wz, radius, strength, flattenTarget}</code> y un mensaje de posición del jugador a 20 Hz.</p>
<p>Para el experimento prescindimos por completo del servidor y usamos <code>BroadcastChannel</code>, la API del navegador para enviar mensajes entre pestañas del mismo origen. Abres dos pestañas y se comunican sin ninguna infraestructura. Eso permite aislar la cuestión de la sincronización de la latencia, la autenticación y la conexión con Durable Objects. Si la repetición de parámetros converge entre pestañas, también convergerá mediante WebSocket.</p>
<p>El único punto en el que la repetición puede divergir son las operaciones que dependen del orden. Elevar y rebajar son conmutativas, por lo que <code>val + strength * falloff</code> produce el mismo resultado sin importar quién lo aplicó primero. Suavizar y aplanar leen valores vecinos, de modo que dos clientes que suavicen exactamente el mismo lugar en el mismo instante pueden desviarse fracciones de milímetro por ciclo. En la práctica eso nunca ocurre, y la solución para producción ya es evidente: dirigir las ediciones a través del DO, dejar que asigne un número de secuencia monotónico, aplicarlas de forma optimista en el cliente y corregir el orden si la secuencia autoritativa no coincide. Es concurrencia optimista clásica, y de todos modos el DO constituye un punto de serialización natural.</p>
<h2 id="la-capsula-del-otro-jugador-que-no-dejaba-de-desaparecer" tabindex="-1">La cápsula del otro jugador que no dejaba de desaparecer <a class="header-anchor" href="#la-capsula-del-otro-jugador-que-no-dejaba-de-desaparecer" aria-label="Permalink to &quot;La cápsula del otro jugador que no dejaba de desaparecer&quot;"></a></h2>
<p>Las ediciones se sincronizaron al primer intento. La cápsula del jugador remoto, no. Parpadeaba y desaparecía en la otra pestaña, y tuvimos que corregir tres errores distintos para conseguir que permaneciera visible.</p>
<p>La cápsula aparecía en el origen del mundo, enterrado bajo el terreno, porque el mensaje <code>join</code> llega antes que cualquier dato de posición. Solución: comenzar con ella oculta y mostrarla al recibir la primera actualización de posición. La emisión de la posición estaba dentro del bucle de renderizado, y Chrome limita <code>requestAnimationFrame</code> en las pestañas sin foco, por lo que la comprobación de inactividad de la otra pestaña eliminaba al jugador y el siguiente mensaje volvía a crearlo. Solución: trasladar la emisión a un <code>setInterval</code>, que no se limita en las pestañas visibles. Además, el tiempo de espera de 5 segundos era demasiado agresivo y cualquier pausa del recolector de basura lo activaba. Solución: aumentarlo a 30 segundos y confiar en el mensaje <code>leave</code> para los cierres normales.</p>
<h2 id="persistencia-e-incorporacion-tardia-con-el-mismo-formato" tabindex="-1">Persistencia e incorporación tardía con el mismo formato <a class="header-anchor" href="#persistencia-e-incorporacion-tardia-con-el-mismo-formato" aria-label="Permalink to &quot;Persistencia e incorporación tardía con el mismo formato&quot;"></a></h2>
<p>Integramos la persistencia en el mismo experimento en lugar de crear uno nuevo, porque el formato de serialización es idéntico tanto si el destino es IndexedDB como si es otra pestaña. Una instantánea contiene el mapa de alturas completo (un <code>Float32Array</code> de 129×129, unos 66 KB), únicamente los fragmentos SDF editados (cada uno de <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.05ex;" xmlns="http://www.w3.org/2000/svg" width="3.25ex" height="2.003ex" role="img" focusable="false" viewBox="0 -863.3 1436.6 885.3" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="msup"><g data-mml-node="mn"><path data-c="36" d="M42 313Q42 476 123 571T303 666Q372 666 402 630T432 550Q432 525 418 510T379 495Q356 495 341 509T326 548Q326 592 373 601Q351 623 311 626Q240 626 194 566Q147 500 147 364L148 360Q153 366 156 373Q197 433 263 433H267Q313 433 348 414Q372 400 396 374T435 317Q456 268 456 210V192Q456 169 451 149Q440 90 387 34T253 -22Q225 -22 199 -14T143 16T92 75T56 172T42 313ZM257 397Q227 397 205 380T171 335T154 278T148 216Q148 133 160 97T198 39Q222 21 251 21Q302 21 329 59Q342 77 347 104T352 209Q352 289 347 316T329 361Q302 397 257 397Z" style="stroke-width: 3;"/><path data-c="35" d="M164 157Q164 133 148 117T109 101H102Q148 22 224 22Q294 22 326 82Q345 115 345 210Q345 313 318 349Q292 382 260 382H254Q176 382 136 314Q132 307 129 306T114 304Q97 304 95 310Q93 314 93 485V614Q93 664 98 664Q100 666 102 666Q103 666 123 658T178 642T253 634Q324 634 389 662Q397 666 402 666Q410 666 410 648V635Q328 538 205 538Q174 538 149 544L139 546V374Q158 388 169 396T205 412T256 420Q337 420 393 355T449 201Q449 109 385 44T229 -22Q148 -22 99 32T50 154Q50 178 61 192T84 210T107 214Q132 214 148 197T164 157Z" transform="translate(500,0)" style="stroke-width: 3;"/></g><g data-mml-node="mn" transform="translate(1033,393.1) scale(0.707)"><path data-c="33" d="M127 463Q100 463 85 480T69 524Q69 579 117 622T233 665Q268 665 277 664Q351 652 390 611T430 522Q430 470 396 421T302 350L299 348Q299 347 308 345T337 336T375 315Q457 262 457 175Q457 96 395 37T238 -22Q158 -22 100 21T42 130Q42 158 60 175T105 193Q133 193 151 175T169 130Q169 119 166 110T159 94T148 82T136 74T126 70T118 67L114 66Q165 21 238 21Q293 21 321 74Q338 107 338 175V195Q338 290 274 322Q259 328 213 329L171 330L168 332Q166 335 166 348Q166 366 174 366Q202 366 232 371Q266 376 294 413T322 525V533Q322 590 287 612Q265 626 240 626Q208 626 181 615T143 592T132 580H135Q138 579 143 578T153 573T165 566T175 555T183 540T186 520Q186 498 172 481T127 463Z" style="stroke-width: 3;"/></g></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><msup><mn>65</mn><mn>3</mn></msup></math></mjx-assistive-mml></mjx-container>, unos 1,1 MB) y la lista de identificadores de fragmentos fijados al modo marching cubes. Un guardado con antirrebote escribe en IndexedDB dos segundos después de la última edición. Al cargar, el terreno procedimental se genera de forma síncrona y luego el estado guardado lo sobrescribe antes del primer fotograma significativo. La incorporación tardía reutiliza exactamente los mismos bytes: cuando se une una pestaña nueva, una pestaña existente con ediciones serializa su estado y lo envía específicamente al recién llegado, y la montaña que esculpiste cinco minutos antes aparece en su pantalla.</p>
<p>La primera prueba de persistencia reveló un interesante error de orden. La hierba se distribuye de forma síncrona durante la inicialización usando las alturas procedimentales, pero la restauración desde IndexedDB es asíncrona y después sobrescribe el mapa de alturas, lo que deja todas las briznas flotando o hundidas. La solución es una pasada de <code>refreshAllGrass()</code> que vuelve a muestrear la altura bajo cada instancia y oculta cualquier brizna que ahora esté en una pendiente o altitud inadecuada. La misma función sirve tanto para la carga como para la incorporación tardía.</p>
<h2 id="la-odisea-de-las-pendientes" tabindex="-1">La odisea de las pendientes <a class="header-anchor" href="#la-odisea-de-las-pendientes" aria-label="Permalink to &quot;La odisea de las pendientes&quot;"></a></h2>
<p>El terreno esculpido es más accidentado que la suave base procedimental, y dejó al descubierto tres errores de físicas que el terreno antiguo nunca pudo revelar. Al caminar cuesta arriba en línea recta, la cápsula se deslizaba lateralmente. La causa era una proyección de la velocidad destinada a mantener el movimiento tangente al suelo, pero escrita utilizando únicamente los componentes horizontales de la normal. En una pendiente diagonal con normal <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.566ex;" xmlns="http://www.w3.org/2000/svg" width="15.967ex" height="2.262ex" role="img" focusable="false" viewBox="0 -750 7057.3 1000" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mo"><path data-c="28" d="M94 250Q94 319 104 381T127 488T164 576T202 643T244 695T277 729T302 750H315H319Q333 750 333 741Q333 738 316 720T275 667T226 581T184 443T167 250T184 58T225 -81T274 -167T316 -220T333 -241Q333 -250 318 -250H315H302L274 -226Q180 -141 137 -14T94 250Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(389,0)"><path data-c="2212" d="M84 237T84 250T98 270H679Q694 262 694 250T679 230H98Q84 237 84 250Z" style="stroke-width: 3;"/></g><g data-mml-node="mn" transform="translate(1167,0)"><path data-c="30" d="M96 585Q152 666 249 666Q297 666 345 640T423 548Q460 465 460 320Q460 165 417 83Q397 41 362 16T301 -15T250 -22Q224 -22 198 -16T137 16T82 83Q39 165 39 320Q39 494 96 585ZM321 597Q291 629 250 629Q208 629 178 597Q153 571 145 525T137 333Q137 175 145 125T181 46Q209 16 250 16Q290 16 318 46Q347 76 354 130T362 333Q362 478 354 524T321 597Z" style="stroke-width: 3;"/><path data-c="2E" d="M78 60Q78 84 95 102T138 120Q162 120 180 104T199 61Q199 36 182 18T139 0T96 17T78 60Z" transform="translate(500,0)" style="stroke-width: 3;"/><path data-c="33" d="M127 463Q100 463 85 480T69 524Q69 579 117 622T233 665Q268 665 277 664Q351 652 390 611T430 522Q430 470 396 421T302 350L299 348Q299 347 308 345T337 336T375 315Q457 262 457 175Q457 96 395 37T238 -22Q158 -22 100 21T42 130Q42 158 60 175T105 193Q133 193 151 175T169 130Q169 119 166 110T159 94T148 82T136 74T126 70T118 67L114 66Q165 21 238 21Q293 21 321 74Q338 107 338 175V195Q338 290 274 322Q259 328 213 329L171 330L168 332Q166 335 166 348Q166 366 174 366Q202 366 232 371Q266 376 294 413T322 525V533Q322 590 287 612Q265 626 240 626Q208 626 181 615T143 592T132 580H135Q138 579 143 578T153 573T165 566T175 555T183 540T186 520Q186 498 172 481T127 463Z" transform="translate(778,0)" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(2445,0)"><path data-c="2C" d="M78 35T78 60T94 103T137 121Q165 121 187 96T210 8Q210 -27 201 -60T180 -117T154 -158T130 -185T117 -194Q113 -194 104 -185T95 -172Q95 -168 106 -156T131 -126T157 -76T173 -3V9L172 8Q170 7 167 6T161 3T152 1T140 0Q113 0 96 17Z" style="stroke-width: 3;"/></g><g data-mml-node="mn" transform="translate(2889.7,0)"><path data-c="30" d="M96 585Q152 666 249 666Q297 666 345 640T423 548Q460 465 460 320Q460 165 417 83Q397 41 362 16T301 -15T250 -22Q224 -22 198 -16T137 16T82 83Q39 165 39 320Q39 494 96 585ZM321 597Q291 629 250 629Q208 629 178 597Q153 571 145 525T137 333Q137 175 145 125T181 46Q209 16 250 16Q290 16 318 46Q347 76 354 130T362 333Q362 478 354 524T321 597Z" style="stroke-width: 3;"/><path data-c="2E" d="M78 60Q78 84 95 102T138 120Q162 120 180 104T199 61Q199 36 182 18T139 0T96 17T78 60Z" transform="translate(500,0)" style="stroke-width: 3;"/><path data-c="39" d="M352 287Q304 211 232 211Q154 211 104 270T44 396Q42 412 42 436V444Q42 537 111 606Q171 666 243 666Q245 666 249 666T257 665H261Q273 665 286 663T323 651T370 619T413 560Q456 472 456 334Q456 194 396 97Q361 41 312 10T208 -22Q147 -22 108 7T68 93T121 149Q143 149 158 135T173 96Q173 78 164 65T148 49T135 44L131 43Q131 41 138 37T164 27T206 22H212Q272 22 313 86Q352 142 352 280V287ZM244 248Q292 248 321 297T351 430Q351 508 343 542Q341 552 337 562T323 588T293 615T246 625Q208 625 181 598Q160 576 154 546T147 441Q147 358 152 329T172 282Q197 248 244 248Z" transform="translate(778,0)" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(4167.7,0)"><path data-c="2C" d="M78 35T78 60T94 103T137 121Q165 121 187 96T210 8Q210 -27 201 -60T180 -117T154 -158T130 -185T117 -194Q113 -194 104 -185T95 -172Q95 -168 106 -156T131 -126T157 -76T173 -3V9L172 8Q170 7 167 6T161 3T152 1T140 0Q113 0 96 17Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(4612.3,0)"><path data-c="2212" d="M84 237T84 250T98 270H679Q694 262 694 250T679 230H98Q84 237 84 250Z" style="stroke-width: 3;"/></g><g data-mml-node="mn" transform="translate(5390.3,0)"><path data-c="30" d="M96 585Q152 666 249 666Q297 666 345 640T423 548Q460 465 460 320Q460 165 417 83Q397 41 362 16T301 -15T250 -22Q224 -22 198 -16T137 16T82 83Q39 165 39 320Q39 494 96 585ZM321 597Q291 629 250 629Q208 629 178 597Q153 571 145 525T137 333Q137 175 145 125T181 46Q209 16 250 16Q290 16 318 46Q347 76 354 130T362 333Q362 478 354 524T321 597Z" style="stroke-width: 3;"/><path data-c="2E" d="M78 60Q78 84 95 102T138 120Q162 120 180 104T199 61Q199 36 182 18T139 0T96 17T78 60Z" transform="translate(500,0)" style="stroke-width: 3;"/><path data-c="33" d="M127 463Q100 463 85 480T69 524Q69 579 117 622T233 665Q268 665 277 664Q351 652 390 611T430 522Q430 470 396 421T302 350L299 348Q299 347 308 345T337 336T375 315Q457 262 457 175Q457 96 395 37T238 -22Q158 -22 100 21T42 130Q42 158 60 175T105 193Q133 193 151 175T169 130Q169 119 166 110T159 94T148 82T136 74T126 70T118 67L114 66Q165 21 238 21Q293 21 321 74Q338 107 338 175V195Q338 290 274 322Q259 328 213 329L171 330L168 332Q166 335 166 348Q166 366 174 366Q202 366 232 371Q266 376 294 413T322 525V533Q322 590 287 612Q265 626 240 626Q208 626 181 615T143 592T132 580H135Q138 579 143 578T153 573T165 566T175 555T183 540T186 520Q186 498 172 481T127 463Z" transform="translate(778,0)" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(6668.3,0)"><path data-c="29" d="M60 749L64 750Q69 750 74 750H86L114 726Q208 641 251 514T294 250Q294 182 284 119T261 12T224 -76T186 -143T145 -194T113 -227T90 -246Q87 -249 86 -250H74Q66 -250 63 -250T58 -247T55 -238Q56 -237 66 -225Q221 -64 221 250T66 725Q56 737 55 738Q55 746 60 749Z" style="stroke-width: 3;"/></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mo stretchy="false">(</mo><mo>−</mo><mn>0.3</mn><mo>,</mo><mn>0.9</mn><mo>,</mo><mo>−</mo><mn>0.3</mn><mo stretchy="false">)</mo></math></mjx-assistive-mml></mjx-container>, caminar hacia el norte introducía de la nada una velocidad lateral. El ajuste al suelo ya mantiene al jugador sobre la superficie, así que simplemente eliminamos la proyección.</p>
<p>La deriva persistía por una segunda causa. Las sondas de colisión SDF empujan el cuerpo hacia fuera a lo largo del gradiente según la profundidad de penetración. En cualquier pendiente, el gradiente tiene componentes horizontales, por lo que una penetración de 0,1 m en una pendiente de 15° empuja unos 0,026 m hacia un lado en cada paso, y a 120 Hz eso supone aproximadamente 3 m/s de deriva invisible. Solución: dividir la respuesta según la pendiente. En suelo transitable (<mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.874ex;" xmlns="http://www.w3.org/2000/svg" width="5.379ex" height="2.444ex" role="img" focusable="false" viewBox="0 -694 2377.5 1080.3" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="msub"><g data-mml-node="mtext"><path data-c="67" d="M329 409Q373 453 429 453Q459 453 472 434T485 396Q485 382 476 371T449 360Q416 360 412 390Q410 404 415 411Q415 412 416 414V415Q388 412 363 393Q355 388 355 386Q355 385 359 381T368 369T379 351T388 325T392 292Q392 230 343 187T222 143Q172 143 123 171Q112 153 112 133Q112 98 138 81Q147 75 155 75T227 73Q311 72 335 67Q396 58 431 26Q470 -13 470 -72Q470 -139 392 -175Q332 -206 250 -206Q167 -206 107 -175Q29 -140 29 -75Q29 -39 50 -15T92 18L103 24Q67 55 67 108Q67 155 96 193Q52 237 52 292Q52 355 102 398T223 442Q274 442 318 416L329 409ZM299 343Q294 371 273 387T221 404Q192 404 171 388T145 343Q142 326 142 292Q142 248 149 227T179 192Q196 182 222 182Q244 182 260 189T283 207T294 227T299 242Q302 258 302 292T299 343ZM403 -75Q403 -50 389 -34T348 -11T299 -2T245 0H218Q151 0 138 -6Q118 -15 107 -34T95 -74Q95 -84 101 -97T122 -127T170 -155T250 -167Q319 -167 361 -139T403 -75Z" style="stroke-width: 3;"/><path data-c="72" d="M36 46H50Q89 46 97 60V68Q97 77 97 91T98 122T98 161T98 203Q98 234 98 269T98 328L97 351Q94 370 83 376T38 385H20V408Q20 431 22 431L32 432Q42 433 60 434T96 436Q112 437 131 438T160 441T171 442H174V373Q213 441 271 441H277Q322 441 343 419T364 373Q364 352 351 337T313 322Q288 322 276 338T263 372Q263 381 265 388T270 400T273 405Q271 407 250 401Q234 393 226 386Q179 341 179 207V154Q179 141 179 127T179 101T180 81T180 66V61Q181 59 183 57T188 54T193 51T200 49T207 48T216 47T225 47T235 46T245 46H276V0H267Q249 3 140 3Q37 3 28 0H20V46H36Z" transform="translate(500,0)" style="stroke-width: 3;"/><path data-c="61" d="M137 305T115 305T78 320T63 359Q63 394 97 421T218 448Q291 448 336 416T396 340Q401 326 401 309T402 194V124Q402 76 407 58T428 40Q443 40 448 56T453 109V145H493V106Q492 66 490 59Q481 29 455 12T400 -6T353 12T329 54V58L327 55Q325 52 322 49T314 40T302 29T287 17T269 6T247 -2T221 -8T190 -11Q130 -11 82 20T34 107Q34 128 41 147T68 188T116 225T194 253T304 268H318V290Q318 324 312 340Q290 411 215 411Q197 411 181 410T156 406T148 403Q170 388 170 359Q170 334 154 320ZM126 106Q126 75 150 51T209 26Q247 26 276 49T315 109Q317 116 318 175Q318 233 317 233Q309 233 296 232T251 223T193 203T147 166T126 106Z" transform="translate(892,0)" style="stroke-width: 3;"/><path data-c="64" d="M376 495Q376 511 376 535T377 568Q377 613 367 624T316 637H298V660Q298 683 300 683L310 684Q320 685 339 686T376 688Q393 689 413 690T443 693T454 694H457V390Q457 84 458 81Q461 61 472 55T517 46H535V0Q533 0 459 -5T380 -11H373V44L365 37Q307 -11 235 -11Q158 -11 96 50T34 215Q34 315 97 378T244 442Q319 442 376 393V495ZM373 342Q328 405 260 405Q211 405 173 369Q146 341 139 305T131 211Q131 155 138 120T173 59Q203 26 251 26Q322 26 373 103V342Z" transform="translate(1392,0)" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(1981,-241.4) scale(0.707)"><path data-c="1D466" d="M21 287Q21 301 36 335T84 406T158 442Q199 442 224 419T250 355Q248 336 247 334Q247 331 231 288T198 191T182 105Q182 62 196 45T238 27Q261 27 281 38T312 61T339 94Q339 95 344 114T358 173T377 247Q415 397 419 404Q432 431 462 431Q475 431 483 424T494 412T496 403Q496 390 447 193T391 -23Q363 -106 294 -155T156 -205Q111 -205 77 -183T43 -117Q43 -95 50 -80T69 -58T89 -48T106 -45Q150 -45 150 -87Q150 -107 138 -122T115 -142T102 -147L99 -148Q101 -153 118 -160T152 -167H160Q177 -167 186 -165Q219 -156 247 -127T290 -65T313 -9T321 21L315 17Q309 13 296 6T270 -6Q250 -11 231 -11Q185 -11 150 11T104 82Q103 89 103 113Q103 170 138 262T173 379Q173 380 173 381Q173 390 173 393T169 400T158 404H154Q131 404 112 385T82 344T65 302T57 280Q55 278 41 278H27Q21 284 21 287Z" style="stroke-width: 3;"/></g></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><msub><mtext>grad</mtext><mi>y</mi></msub></math></mjx-assistive-mml></mjx-container> por encima del umbral transitable), el empuje es exclusivamente vertical. En paredes y acantilados se mantiene el empuje 3D completo, porque ahí es precisamente donde quieres que el personaje sea desviado. También elevamos el límite transitable de <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.05ex;" xmlns="http://www.w3.org/2000/svg" width="6.798ex" height="1.667ex" role="img" focusable="false" viewBox="0 -715 3004.7 737" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mi"><path data-c="63" d="M370 305T349 305T313 320T297 358Q297 381 312 396Q317 401 317 402T307 404Q281 408 258 408Q209 408 178 376Q131 329 131 219Q131 137 162 90Q203 29 272 29Q313 29 338 55T374 117Q376 125 379 127T395 129H409Q415 123 415 120Q415 116 411 104T395 71T366 33T318 2T249 -11Q163 -11 99 53T34 214Q34 318 99 383T250 448T370 421T404 357Q404 334 387 320Z" style="stroke-width: 3;"/><path data-c="6F" d="M28 214Q28 309 93 378T250 448Q340 448 405 380T471 215Q471 120 407 55T250 -10Q153 -10 91 57T28 214ZM250 30Q372 30 372 193V225V250Q372 272 371 288T364 326T348 362T317 390T268 410Q263 411 252 411Q222 411 195 399Q152 377 139 338T126 246V226Q126 130 145 91Q177 30 250 30Z" transform="translate(444,0)" style="stroke-width: 3;"/><path data-c="73" d="M295 316Q295 356 268 385T190 414Q154 414 128 401Q98 382 98 349Q97 344 98 336T114 312T157 287Q175 282 201 278T245 269T277 256Q294 248 310 236T342 195T359 133Q359 71 321 31T198 -10H190Q138 -10 94 26L86 19L77 10Q71 4 65 -1L54 -11H46H42Q39 -11 33 -5V74V132Q33 153 35 157T45 162H54Q66 162 70 158T75 146T82 119T101 77Q136 26 198 26Q295 26 295 104Q295 133 277 151Q257 175 194 187T111 210Q75 227 54 256T33 318Q33 357 50 384T93 424T143 442T187 447H198Q238 447 268 432L283 424L292 431Q302 440 314 448H322H326Q329 448 335 442V310L329 304H301Q295 310 295 316Z" transform="translate(944,0)" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(1338,0)"><path data-c="2061" d="" style="stroke-width: 3;"/></g><g data-mml-node="mn" transform="translate(1504.7,0)"><path data-c="34" d="M462 0Q444 3 333 3Q217 3 199 0H190V46H221Q241 46 248 46T265 48T279 53T286 61Q287 63 287 115V165H28V211L179 442Q332 674 334 675Q336 677 355 677H373L379 671V211H471V165H379V114Q379 73 379 66T385 54Q393 47 442 46H471V0H462ZM293 211V545L74 212L183 211H293Z" style="stroke-width: 3;"/><path data-c="35" d="M164 157Q164 133 148 117T109 101H102Q148 22 224 22Q294 22 326 82Q345 115 345 210Q345 313 318 349Q292 382 260 382H254Q176 382 136 314Q132 307 129 306T114 304Q97 304 95 310Q93 314 93 485V614Q93 664 98 664Q100 666 102 666Q103 666 123 658T178 642T253 634Q324 634 389 662Q397 666 402 666Q410 666 410 648V635Q328 538 205 538Q174 538 149 544L139 546V374Q158 388 169 396T205 412T256 420Q337 420 393 355T449 201Q449 109 385 44T229 -22Q148 -22 99 32T50 154Q50 178 61 192T84 210T107 214Q132 214 148 197T164 157Z" transform="translate(500,0)" style="stroke-width: 3;"/></g><g data-mml-node="TeXAtom" data-mjx-texclass="ORD" transform="translate(2504.7,0)"><g data-mml-node="mo"><path data-c="B0" d="M147 628Q147 669 179 692T244 715Q298 715 325 689T352 629Q352 592 323 567T249 542Q202 542 175 567T147 628ZM313 628Q313 660 300 669T259 678H253Q248 678 242 678T234 679Q217 679 207 674T192 659T188 644T187 629Q187 600 198 590Q210 579 250 579H265Q279 579 288 581T305 595T313 628Z" style="stroke-width: 3;"/></g></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mi>cos</mi><mo data-mjx-texclass="NONE">⁡</mo><mn>45</mn><mrow data-mjx-texclass="ORD"><mo data-mjx-pseudoscript="true">°</mo></mrow></math></mjx-assistive-mml></mjx-container> a <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.05ex;" xmlns="http://www.w3.org/2000/svg" width="6.798ex" height="1.667ex" role="img" focusable="false" viewBox="0 -715 3004.7 737" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mi"><path data-c="63" d="M370 305T349 305T313 320T297 358Q297 381 312 396Q317 401 317 402T307 404Q281 408 258 408Q209 408 178 376Q131 329 131 219Q131 137 162 90Q203 29 272 29Q313 29 338 55T374 117Q376 125 379 127T395 129H409Q415 123 415 120Q415 116 411 104T395 71T366 33T318 2T249 -11Q163 -11 99 53T34 214Q34 318 99 383T250 448T370 421T404 357Q404 334 387 320Z" style="stroke-width: 3;"/><path data-c="6F" d="M28 214Q28 309 93 378T250 448Q340 448 405 380T471 215Q471 120 407 55T250 -10Q153 -10 91 57T28 214ZM250 30Q372 30 372 193V225V250Q372 272 371 288T364 326T348 362T317 390T268 410Q263 411 252 411Q222 411 195 399Q152 377 139 338T126 246V226Q126 130 145 91Q177 30 250 30Z" transform="translate(444,0)" style="stroke-width: 3;"/><path data-c="73" d="M295 316Q295 356 268 385T190 414Q154 414 128 401Q98 382 98 349Q97 344 98 336T114 312T157 287Q175 282 201 278T245 269T277 256Q294 248 310 236T342 195T359 133Q359 71 321 31T198 -10H190Q138 -10 94 26L86 19L77 10Q71 4 65 -1L54 -11H46H42Q39 -11 33 -5V74V132Q33 153 35 157T45 162H54Q66 162 70 158T75 146T82 119T101 77Q136 26 198 26Q295 26 295 104Q295 133 277 151Q257 175 194 187T111 210Q75 227 54 256T33 318Q33 357 50 384T93 424T143 442T187 447H198Q238 447 268 432L283 424L292 431Q302 440 314 448H322H326Q329 448 335 442V310L329 304H301Q295 310 295 316Z" transform="translate(944,0)" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(1338,0)"><path data-c="2061" d="" style="stroke-width: 3;"/></g><g data-mml-node="mn" transform="translate(1504.7,0)"><path data-c="36" d="M42 313Q42 476 123 571T303 666Q372 666 402 630T432 550Q432 525 418 510T379 495Q356 495 341 509T326 548Q326 592 373 601Q351 623 311 626Q240 626 194 566Q147 500 147 364L148 360Q153 366 156 373Q197 433 263 433H267Q313 433 348 414Q372 400 396 374T435 317Q456 268 456 210V192Q456 169 451 149Q440 90 387 34T253 -22Q225 -22 199 -14T143 16T92 75T56 172T42 313ZM257 397Q227 397 205 380T171 335T154 278T148 216Q148 133 160 97T198 39Q222 21 251 21Q302 21 329 59Q342 77 347 104T352 209Q352 289 347 316T329 361Q302 397 257 397Z" style="stroke-width: 3;"/><path data-c="30" d="M96 585Q152 666 249 666Q297 666 345 640T423 548Q460 465 460 320Q460 165 417 83Q397 41 362 16T301 -15T250 -22Q224 -22 198 -16T137 16T82 83Q39 165 39 320Q39 494 96 585ZM321 597Q291 629 250 629Q208 629 178 597Q153 571 145 525T137 333Q137 175 145 125T181 46Q209 16 250 16Q290 16 318 46Q347 76 354 130T362 333Q362 478 354 524T321 597Z" transform="translate(500,0)" style="stroke-width: 3;"/></g><g data-mml-node="TeXAtom" data-mjx-texclass="ORD" transform="translate(2504.7,0)"><g data-mml-node="mo"><path data-c="B0" d="M147 628Q147 669 179 692T244 715Q298 715 325 689T352 629Q352 592 323 567T249 542Q202 542 175 567T147 628ZM313 628Q313 660 300 669T259 678H253Q248 678 242 678T234 679Q217 679 207 674T192 659T188 644T187 629Q187 600 198 590Q210 579 250 579H265Q279 579 288 581T305 595T313 628Z" style="stroke-width: 3;"/></g></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mi>cos</mi><mo data-mjx-texclass="NONE">⁡</mo><mn>60</mn><mrow data-mjx-texclass="ORD"><mo data-mjx-pseudoscript="true">°</mo></mrow></math></mjx-assistive-mml></mjx-container> para que las colinas creadas con el pincel se puedan escalar como en Breath of the Wild.</p>
<p>El tercer error inmovilizaba la cápsula en los límites entre fragmentos, porque las sondas de colisión muestreaban el SDF de un único fragmento y obtenían el valor centinela de «muy adentro del aire» cuando una sonda pasaba al fragmento vecino. La solución fue <code>sdfSampleWorld(wx, wy, wz)</code> y <code>sdfGradientWorld(...)</code>, que encuentran el fragmento correcto para cualquier posición del mundo y recurren a una estimación de distancia basada en el mapa de alturas cuando no existe ningún SDF. La transición entre las colisiones SDF y las del mapa de alturas ahora es continua.</p>
<h2 id="el-agua-completa-el-mundo" tabindex="-1">El agua completa el mundo <a class="header-anchor" href="#el-agua-completa-el-mundo" aria-label="Permalink to &quot;El agua completa el mundo&quot;"></a></h2>
<div style="position:relative;padding-bottom:56.25%;height:0;overflow:hidden;border-radius:8px;margin:1.5rem 0;border:1px solid rgba(255,255,255,0.12)">
<iframe src="/es/spikes/32-water-swimming/" title="Experimento 32: Agua y natación" style="position:absolute;top:0;left:0;width:100%;height:100%;border:0;background:#000" loading="lazy" allowfullscreen></iframe>
</div>
<p><a href="/es/spikes/32-water-swimming/" target="_blank">Abrir el experimento 32 en una pestaña nueva ↗</a> · <a href="/es/blog/spike-source?spike=32-water-swimming">Ver código fuente</a></p>
<p>Hasta este punto, todos los experimentos trataban de «tierra por encima del agua». El experimento 32 añadió un océano y, con él, una nueva acción de movimiento. Fijamos el nivel del agua en 22 dentro de un terreno que abarca aproximadamente de 8 a 58. Esto inunda los valles bajos, deja playas en la costa y conserva mucha tierra firme para jugar.</p>
<p>La superficie es un <code>MeshStandardNodeMaterial</code> construido con TSL, el mismo enfoque basado en nodos que utiliza el terreno. Tres ondas sinusoidales superpuestas de distintas frecuencias desplazan los vértices, y la normal de la superficie se obtiene a partir de las derivadas analíticas del coseno de esas ondas, en lugar de las normales de la malla. El color pasa de un turquesa de aguas poco profundas a un verde azulado oscuro en las zonas profundas mediante una estimación de profundidad <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.566ex;" xmlns="http://www.w3.org/2000/svg" width="24.614ex" height="2.262ex" role="img" focusable="false" viewBox="0 -750 10879.3 1000" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mo"><path data-c="28" d="M94 250Q94 319 104 381T127 488T164 576T202 643T244 695T277 729T302 750H315H319Q333 750 333 741Q333 738 316 720T275 667T226 581T184 443T167 250T184 58T225 -81T274 -167T316 -220T333 -241Q333 -250 318 -250H315H302L274 -226Q180 -141 137 -14T94 250Z" style="stroke-width: 3;"/></g><g data-mml-node="mtext" transform="translate(389,0)"><path data-c="6C" d="M42 46H56Q95 46 103 60V68Q103 77 103 91T103 124T104 167T104 217T104 272T104 329Q104 366 104 407T104 482T104 542T103 586T103 603Q100 622 89 628T44 637H26V660Q26 683 28 683L38 684Q48 685 67 686T104 688Q121 689 141 690T171 693T182 694H185V379Q185 62 186 60Q190 52 198 49Q219 46 247 46H263V0H255L232 1Q209 2 183 2T145 3T107 3T57 1L34 0H26V46H42Z" style="stroke-width: 3;"/><path data-c="65" d="M28 218Q28 273 48 318T98 391T163 433T229 448Q282 448 320 430T378 380T406 316T415 245Q415 238 408 231H126V216Q126 68 226 36Q246 30 270 30Q312 30 342 62Q359 79 369 104L379 128Q382 131 395 131H398Q415 131 415 121Q415 117 412 108Q393 53 349 21T250 -11Q155 -11 92 58T28 218ZM333 275Q322 403 238 411H236Q228 411 220 410T195 402T166 381T143 340T127 274V267H333V275Z" transform="translate(278,0)" style="stroke-width: 3;"/><path data-c="76" d="M338 431Q344 429 422 429Q479 429 503 431H508V385H497Q439 381 423 345Q421 341 356 172T288 -2Q283 -11 263 -11Q244 -11 239 -2Q99 359 98 364Q93 378 82 381T43 385H19V431H25L33 430Q41 430 53 430T79 430T104 429T122 428Q217 428 232 431H240V385H226Q187 384 184 370Q184 366 235 234L286 102L377 341V349Q377 363 367 372T349 383T335 385H331V431H338Z" transform="translate(722,0)" style="stroke-width: 3;"/><path data-c="65" d="M28 218Q28 273 48 318T98 391T163 433T229 448Q282 448 320 430T378 380T406 316T415 245Q415 238 408 231H126V216Q126 68 226 36Q246 30 270 30Q312 30 342 62Q359 79 369 104L379 128Q382 131 395 131H398Q415 131 415 121Q415 117 412 108Q393 53 349 21T250 -11Q155 -11 92 58T28 218ZM333 275Q322 403 238 411H236Q228 411 220 410T195 402T166 381T143 340T127 274V267H333V275Z" transform="translate(1250,0)" style="stroke-width: 3;"/><path data-c="6C" d="M42 46H56Q95 46 103 60V68Q103 77 103 91T103 124T104 167T104 217T104 272T104 329Q104 366 104 407T104 482T104 542T103 586T103 603Q100 622 89 628T44 637H26V660Q26 683 28 683L38 684Q48 685 67 686T104 688Q121 689 141 690T171 693T182 694H185V379Q185 62 186 60Q190 52 198 49Q219 46 247 46H263V0H255L232 1Q209 2 183 2T145 3T107 3T57 1L34 0H26V46H42Z" transform="translate(1694,0)" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(2583.2,0)"><path data-c="2212" d="M84 237T84 250T98 270H679Q694 262 694 250T679 230H98Q84 237 84 250Z" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(3583.4,0)"><path data-c="1D466" d="M21 287Q21 301 36 335T84 406T158 442Q199 442 224 419T250 355Q248 336 247 334Q247 331 231 288T198 191T182 105Q182 62 196 45T238 27Q261 27 281 38T312 61T339 94Q339 95 344 114T358 173T377 247Q415 397 419 404Q432 431 462 431Q475 431 483 424T494 412T496 403Q496 390 447 193T391 -23Q363 -106 294 -155T156 -205Q111 -205 77 -183T43 -117Q43 -95 50 -80T69 -58T89 -48T106 -45Q150 -45 150 -87Q150 -107 138 -122T115 -142T102 -147L99 -148Q101 -153 118 -160T152 -167H160Q177 -167 186 -165Q219 -156 247 -127T290 -65T313 -9T321 21L315 17Q309 13 296 6T270 -6Q250 -11 231 -11Q185 -11 150 11T104 82Q103 89 103 113Q103 170 138 262T173 379Q173 380 173 381Q173 390 173 393T169 400T158 404H154Q131 404 112 385T82 344T65 302T57 280Q55 278 41 278H27Q21 284 21 287Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(4295.7,0)"><path data-c="2B" d="M56 237T56 250T70 270H369V420L370 570Q380 583 389 583Q402 583 409 568V270H707Q722 262 722 250T707 230H409V-68Q401 -82 391 -82H389H387Q375 -82 369 -68V230H70Q56 237 56 250Z" style="stroke-width: 3;"/></g><g data-mml-node="mtext" transform="translate(5295.9,0)"><path data-c="77" d="M90 368Q84 378 76 380T40 385H18V431H24L43 430Q62 430 84 429T116 428Q206 428 221 431H229V385H215Q177 383 177 368Q177 367 221 239L265 113L339 328L333 345Q323 374 316 379Q308 384 278 385H258V431H264Q270 428 348 428Q439 428 454 431H461V385H452Q404 385 404 369Q404 366 418 324T449 234T481 143L496 100L537 219Q579 341 579 347Q579 363 564 373T530 385H522V431H529Q541 428 624 428Q692 428 698 431H703V385H697Q696 385 691 385T682 384Q635 377 619 334L559 161Q546 124 528 71Q508 12 503 1T487 -11H479Q460 -11 456 -4Q455 -3 407 133L361 267Q359 263 266 -4Q261 -11 243 -11H238Q225 -11 220 -3L90 368Z" style="stroke-width: 3;"/><path data-c="61" d="M137 305T115 305T78 320T63 359Q63 394 97 421T218 448Q291 448 336 416T396 340Q401 326 401 309T402 194V124Q402 76 407 58T428 40Q443 40 448 56T453 109V145H493V106Q492 66 490 59Q481 29 455 12T400 -6T353 12T329 54V58L327 55Q325 52 322 49T314 40T302 29T287 17T269 6T247 -2T221 -8T190 -11Q130 -11 82 20T34 107Q34 128 41 147T68 188T116 225T194 253T304 268H318V290Q318 324 312 340Q290 411 215 411Q197 411 181 410T156 406T148 403Q170 388 170 359Q170 334 154 320ZM126 106Q126 75 150 51T209 26Q247 26 276 49T315 109Q317 116 318 175Q318 233 317 233Q309 233 296 232T251 223T193 203T147 166T126 106Z" transform="translate(722,0)" style="stroke-width: 3;"/><path data-c="76" d="M338 431Q344 429 422 429Q479 429 503 431H508V385H497Q439 381 423 345Q421 341 356 172T288 -2Q283 -11 263 -11Q244 -11 239 -2Q99 359 98 364Q93 378 82 381T43 385H19V431H25L33 430Q41 430 53 430T79 430T104 429T122 428Q217 428 232 431H240V385H226Q187 384 184 370Q184 366 235 234L286 102L377 341V349Q377 363 367 372T349 383T335 385H331V431H338Z" transform="translate(1222,0)" style="stroke-width: 3;"/><path data-c="65" d="M28 218Q28 273 48 318T98 391T163 433T229 448Q282 448 320 430T378 380T406 316T415 245Q415 238 408 231H126V216Q126 68 226 36Q246 30 270 30Q312 30 342 62Q359 79 369 104L379 128Q382 131 395 131H398Q415 131 415 121Q415 117 412 108Q393 53 349 21T250 -11Q155 -11 92 58T28 218ZM333 275Q322 403 238 411H236Q228 411 220 410T195 402T166 381T143 340T127 274V267H333V275Z" transform="translate(1750,0)" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(7489.9,0)"><path data-c="29" d="M60 749L64 750Q69 750 74 750H86L114 726Q208 641 251 514T294 250Q294 182 284 119T261 12T224 -76T186 -143T145 -194T113 -227T90 -246Q87 -249 86 -250H74Q66 -250 63 -250T58 -247T55 -238Q56 -237 66 -225Q221 -64 221 250T66 725Q56 737 55 738Q55 746 60 749Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(8101.1,0)"><path data-c="D7" d="M630 29Q630 9 609 9Q604 9 587 25T493 118L389 222L284 117Q178 13 175 11Q171 9 168 9Q160 9 154 15T147 29Q147 36 161 51T255 146L359 250L255 354Q174 435 161 449T147 471Q147 480 153 485T168 490Q173 490 175 489Q178 487 284 383L389 278L493 382Q570 459 587 475T609 491Q630 491 630 471Q630 464 620 453T522 355L418 250L522 145Q606 61 618 48T630 29Z" style="stroke-width: 3;"/></g><g data-mml-node="mn" transform="translate(9101.3,0)"><path data-c="30" d="M96 585Q152 666 249 666Q297 666 345 640T423 548Q460 465 460 320Q460 165 417 83Q397 41 362 16T301 -15T250 -22Q224 -22 198 -16T137 16T82 83Q39 165 39 320Q39 494 96 585ZM321 597Q291 629 250 629Q208 629 178 597Q153 571 145 525T137 333Q137 175 145 125T181 46Q209 16 250 16Q290 16 318 46Q347 76 354 130T362 333Q362 478 354 524T321 597Z" style="stroke-width: 3;"/><path data-c="2E" d="M78 60Q78 84 95 102T138 120Q162 120 180 104T199 61Q199 36 182 18T139 0T96 17T78 60Z" transform="translate(500,0)" style="stroke-width: 3;"/><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" transform="translate(778,0)" style="stroke-width: 3;"/><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" transform="translate(1278,0)" style="stroke-width: 3;"/></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mo stretchy="false">(</mo><mtext>level</mtext><mo>−</mo><mi>y</mi><mo>+</mo><mtext>wave</mtext><mo stretchy="false">)</mo><mo>×</mo><mn>0.12</mn></math></mjx-assistive-mml></mjx-container> limitada a <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.566ex;" xmlns="http://www.w3.org/2000/svg" width="4.526ex" height="2.262ex" role="img" focusable="false" viewBox="0 -750 2000.7 1000" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mo"><path data-c="5B" d="M118 -250V750H255V710H158V-210H255V-250H118Z" style="stroke-width: 3;"/></g><g data-mml-node="mn" transform="translate(278,0)"><path data-c="30" d="M96 585Q152 666 249 666Q297 666 345 640T423 548Q460 465 460 320Q460 165 417 83Q397 41 362 16T301 -15T250 -22Q224 -22 198 -16T137 16T82 83Q39 165 39 320Q39 494 96 585ZM321 597Q291 629 250 629Q208 629 178 597Q153 571 145 525T137 333Q137 175 145 125T181 46Q209 16 250 16Q290 16 318 46Q347 76 354 130T362 333Q362 478 354 524T321 597Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(778,0)"><path data-c="2C" d="M78 35T78 60T94 103T137 121Q165 121 187 96T210 8Q210 -27 201 -60T180 -117T154 -158T130 -185T117 -194Q113 -194 104 -185T95 -172Q95 -168 106 -156T131 -126T157 -76T173 -3V9L172 8Q170 7 167 6T161 3T152 1T140 0Q113 0 96 17Z" style="stroke-width: 3;"/></g><g data-mml-node="mn" transform="translate(1222.7,0)"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(1722.7,0)"><path data-c="5D" d="M22 710V750H159V-250H22V-210H119V710H22Z" style="stroke-width: 3;"/></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mo stretchy="false">[</mo><mn>0</mn><mo>,</mo><mn>1</mn><mo stretchy="false">]</mo></math></mjx-assistive-mml></mjx-container>; la espuma aumenta cuando esa estimación se acerca a cero en la costa, y el alfa sigue la profundidad para que el agua poco profunda parezca transparente y la profunda, casi opaca.</p>
<p>La natación utiliza un resorte de flotabilidad. El jugador entra en modo natación cuando los pies descienden por debajo del nivel del agua y el centro del cuerpo está a menos de la mitad de la altura de la cápsula con respecto a la superficie. Un resorte tira del cuerpo hacia un objetivo situado justo debajo de la superficie y, con una constante de flotabilidad de 12 frente a una amortiguación del agua de 4, el jugador flota de manera estable con la cabeza fuera, sin oscilaciones. La velocidad de nado es inferior a la de caminar, con una aceleración y una resistencia que transmiten sensación de flotación; saltar cerca de la superficie te impulsa hacia fuera al 60 % de la velocidad normal de salto, y la entrada limita la velocidad descendente a -5 m/s para evitar que te hundas de golpe. Las colisiones con el terreno siguen funcionando bajo el agua, de modo que puedes caminar por el lecho del lago donde este se eleva por encima del objetivo de natación. El indicador de natación se incluye en la emisión de posición para que los demás jugadores te vean nadar, y una superposición HTML con degradado tiñe la vista cuando la cámara se sumerge bajo la superficie.</p>
<h2 id="tecnologia-mencionada-en-este-capitulo" tabindex="-1">Tecnología mencionada en este capítulo <a class="header-anchor" href="#tecnologia-mencionada-en-este-capitulo" aria-label="Permalink to &quot;Tecnología mencionada en este capítulo&quot;"></a></h2>
<p><strong>Repetición determinista de parámetros del pincel.</strong> En lugar de transmitir el terreno editado, cada cliente envía únicamente los parámetros del pincel y repite la misma función en la CPU. Esto funciona porque tanto los pinceles del mapa de alturas como los SDF realizan operaciones matemáticas puras con <code>Float32Array</code>, sin aleatoriedad ni no determinismo de la GPU, por lo que entradas idénticas producen resultados idénticos bit a bit en todas partes. La carga útil es de 56 bytes por ciclo de pincelada. Las operaciones conmutativas (elevar y rebajar) convergen sin importar el orden, mientras que las operaciones que leen valores vecinos (suavizar y aplanar) necesitan un punto de serialización para garantizar la convergencia, algo que el Durable Object de producción proporciona mediante números de secuencia monotónicos.</p>
<p><strong>BroadcastChannel como sustituto de WebSocket.</strong> Una API del navegador para enviar mensajes entre pestañas del mismo origen sin ningún servidor. Aquí se usa para probar el protocolo de sincronización de forma aislada de la latencia de red y la autenticación. El formato de serialización (un mapa de alturas <code>Float32Array</code> sin procesar, más los fragmentos SDF editados y los identificadores de los fragmentos fijados a MC) utiliza los mismos bytes para la persistencia en IndexedDB y la transferencia de estado al incorporarse tarde, de modo que un único formato cubre tres tareas.</p>
<p><strong>Respuesta de colisión SDF dividida según la pendiente.</strong> Cuando una sonda de la cápsula penetra en terreno volumétrico, la solución ingenua empuja el cuerpo hacia fuera siguiendo el gradiente SDF y según la profundidad de penetración. En las pendientes, ese gradiente tiene componentes horizontales que introducen deriva lateral. Dividir la respuesta para que las superficies transitables (<mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.874ex;" xmlns="http://www.w3.org/2000/svg" width="5.379ex" height="2.444ex" role="img" focusable="false" viewBox="0 -694 2377.5 1080.3" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="msub"><g data-mml-node="mtext"><path data-c="67" d="M329 409Q373 453 429 453Q459 453 472 434T485 396Q485 382 476 371T449 360Q416 360 412 390Q410 404 415 411Q415 412 416 414V415Q388 412 363 393Q355 388 355 386Q355 385 359 381T368 369T379 351T388 325T392 292Q392 230 343 187T222 143Q172 143 123 171Q112 153 112 133Q112 98 138 81Q147 75 155 75T227 73Q311 72 335 67Q396 58 431 26Q470 -13 470 -72Q470 -139 392 -175Q332 -206 250 -206Q167 -206 107 -175Q29 -140 29 -75Q29 -39 50 -15T92 18L103 24Q67 55 67 108Q67 155 96 193Q52 237 52 292Q52 355 102 398T223 442Q274 442 318 416L329 409ZM299 343Q294 371 273 387T221 404Q192 404 171 388T145 343Q142 326 142 292Q142 248 149 227T179 192Q196 182 222 182Q244 182 260 189T283 207T294 227T299 242Q302 258 302 292T299 343ZM403 -75Q403 -50 389 -34T348 -11T299 -2T245 0H218Q151 0 138 -6Q118 -15 107 -34T95 -74Q95 -84 101 -97T122 -127T170 -155T250 -167Q319 -167 361 -139T403 -75Z" style="stroke-width: 3;"/><path data-c="72" d="M36 46H50Q89 46 97 60V68Q97 77 97 91T98 122T98 161T98 203Q98 234 98 269T98 328L97 351Q94 370 83 376T38 385H20V408Q20 431 22 431L32 432Q42 433 60 434T96 436Q112 437 131 438T160 441T171 442H174V373Q213 441 271 441H277Q322 441 343 419T364 373Q364 352 351 337T313 322Q288 322 276 338T263 372Q263 381 265 388T270 400T273 405Q271 407 250 401Q234 393 226 386Q179 341 179 207V154Q179 141 179 127T179 101T180 81T180 66V61Q181 59 183 57T188 54T193 51T200 49T207 48T216 47T225 47T235 46T245 46H276V0H267Q249 3 140 3Q37 3 28 0H20V46H36Z" transform="translate(500,0)" style="stroke-width: 3;"/><path data-c="61" d="M137 305T115 305T78 320T63 359Q63 394 97 421T218 448Q291 448 336 416T396 340Q401 326 401 309T402 194V124Q402 76 407 58T428 40Q443 40 448 56T453 109V145H493V106Q492 66 490 59Q481 29 455 12T400 -6T353 12T329 54V58L327 55Q325 52 322 49T314 40T302 29T287 17T269 6T247 -2T221 -8T190 -11Q130 -11 82 20T34 107Q34 128 41 147T68 188T116 225T194 253T304 268H318V290Q318 324 312 340Q290 411 215 411Q197 411 181 410T156 406T148 403Q170 388 170 359Q170 334 154 320ZM126 106Q126 75 150 51T209 26Q247 26 276 49T315 109Q317 116 318 175Q318 233 317 233Q309 233 296 232T251 223T193 203T147 166T126 106Z" transform="translate(892,0)" style="stroke-width: 3;"/><path data-c="64" d="M376 495Q376 511 376 535T377 568Q377 613 367 624T316 637H298V660Q298 683 300 683L310 684Q320 685 339 686T376 688Q393 689 413 690T443 693T454 694H457V390Q457 84 458 81Q461 61 472 55T517 46H535V0Q533 0 459 -5T380 -11H373V44L365 37Q307 -11 235 -11Q158 -11 96 50T34 215Q34 315 97 378T244 442Q319 442 376 393V495ZM373 342Q328 405 260 405Q211 405 173 369Q146 341 139 305T131 211Q131 155 138 120T173 59Q203 26 251 26Q322 26 373 103V342Z" transform="translate(1392,0)" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(1981,-241.4) scale(0.707)"><path data-c="1D466" d="M21 287Q21 301 36 335T84 406T158 442Q199 442 224 419T250 355Q248 336 247 334Q247 331 231 288T198 191T182 105Q182 62 196 45T238 27Q261 27 281 38T312 61T339 94Q339 95 344 114T358 173T377 247Q415 397 419 404Q432 431 462 431Q475 431 483 424T494 412T496 403Q496 390 447 193T391 -23Q363 -106 294 -155T156 -205Q111 -205 77 -183T43 -117Q43 -95 50 -80T69 -58T89 -48T106 -45Q150 -45 150 -87Q150 -107 138 -122T115 -142T102 -147L99 -148Q101 -153 118 -160T152 -167H160Q177 -167 186 -165Q219 -156 247 -127T290 -65T313 -9T321 21L315 17Q309 13 296 6T270 -6Q250 -11 231 -11Q185 -11 150 11T104 82Q103 89 103 113Q103 170 138 262T173 379Q173 380 173 381Q173 390 173 393T169 400T158 404H154Q131 404 112 385T82 344T65 302T57 280Q55 278 41 278H27Q21 284 21 287Z" style="stroke-width: 3;"/></g></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><msub><mtext>grad</mtext><mi>y</mi></msub></math></mjx-assistive-mml></mjx-container> por encima del umbral) reciban un empuje exclusivamente vertical, mientras que las superficies empinadas mantienen el empuje 3D completo más la proyección de velocidad, elimina la deriva sin perder la colisión con las paredes. Consulta <a href="/es/guides/landscape-generation-browser.html#physics-on-sdf-terrain">colisiones en terrenos SDF</a>.</p>
<p><strong>Agua TSL con normales de onda analíticas.</strong> El océano utiliza un material de nodos cuyos vértices son desplazados por la suma de tres ondas sinusoidales. En lugar de volver a calcular las normales de la malla tras el desplazamiento, la normal de la superficie se obtiene analíticamente a partir de las derivadas del coseno de las funciones de onda, lo que resulta más barato y evita los artefactos de las normales por diferencias finitas en una cuadrícula de baja resolución. El color según la profundidad, la espuma de la costa y la transparencia según la profundidad parten de una única estimación de profundidad.</p>
<p><strong>Natación mediante resorte de flotabilidad.</strong> Las físicas de natación modelan el cuerpo como un resorte amortiguado atraído hacia un objetivo situado justo debajo de la superficie. Con una constante de flotabilidad de 12 y una amortiguación de 4, el jugador se estabiliza en la superficie sin oscilar. Unas constantes de movimiento diferenciadas —menor velocidad, aceleración flotante y gran resistencia— hacen que nadar se sienta distinto de caminar, mientras que la colisión existente entre la cápsula y el terreno sigue funcionando bajo el agua.</p>
<hr>
<p>Parte 15 de 29.
Anterior: <a href="/es/blog/2026-04-13-open-world-browser-part-14-world-comes-alive.html">Parte 14 - El mundo cobra vida</a>
Siguiente: <a href="/es/blog/2026-04-28-open-world-browser-part-16-structure-and-authoring.html">Parte 16 - Estructura para un mundo que no deja de crecer</a>
Guía de la serie: <a href="/es/blog/2026-02-25-open-world-browser-series-guide.html">/es/blog/2026-02-25-open-world-browser-series-guide</a></p>
]]></content:encoded>
            <enclosure url="https://cdn.cinevva.com/blog/why-webgpu-engine-hero.jpg" length="0" type="image/jpg"/>
        </item>
        <item>
            <title><![CDATA[Cubcoats × Cinevva: Ficha de conceptos de juego]]></title>
            <link>https://app.cinevva.com/es/blog/2026-03-19-cubcoats-game-concepts-one-pager</link>
            <guid>https://app.cinevva.com/es/blog/2026-03-19-cubcoats-game-concepts-one-pager</guid>
            <pubDate>Thu, 19 Mar 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Tres conceptos de juegos educativos (Árbol Dorado, La Isla de las Palabras de Kali, Historias de la Isla) basados en el flujo de trabajo de boceto a vídeo y a 3D, y en Kali la Gatita. Para licencias o presentaciones a socios.]]></description>
            <content:encoded><![CDATA[<h1 id="cubcoats-×-cinevva-ficha-de-conceptos-de-juego" tabindex="-1">Cubcoats × Cinevva: Ficha de conceptos de juego <a class="header-anchor" href="#cubcoats-×-cinevva-ficha-de-conceptos-de-juego" aria-label="Permalink to &quot;Cubcoats × Cinevva: Ficha de conceptos de juego&quot;"></a></h1>
<p><em>Basada en el flujo de trabajo de boceto a vídeo y a 3D, y en Kali la Gatita (Cubcoats). Para licencias, el blog o presentaciones a socios.</em></p>
<p><strong>Para compartir como PDF:</strong> Abre esta página y, en el navegador, selecciona <strong>Archivo → Imprimir → Guardar como PDF</strong>.</p>
<hr>
<h2 id="arbol-dorado-—-ficha-completa" tabindex="-1">Árbol Dorado — Ficha completa <a class="header-anchor" href="#arbol-dorado-—-ficha-completa" aria-label="Permalink to &quot;Árbol Dorado — Ficha completa&quot;"></a></h2>
<p><strong>Eslogan:</strong> <em>Un mundo que crece contigo. Visítalo, riégalo y observa. Sin niveles. Sin presión.</em></p>
<table tabindex="0">
<thead>
<tr>
<th></th>
<th></th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>Edades</strong></td>
<td>3–13 (público amplio)</td>
</tr>
<tr>
<td><strong>Formato</strong></td>
<td>Mundo 3D compartido y episódico + «momentos» breves semanales</td>
</tr>
<tr>
<td><strong>Plataforma</strong></td>
<td>Web (y más adelante, dispositivos móviles); acceso sencillo y sin instalación</td>
</tr>
<tr>
<td><strong>Gancho viral</strong></td>
<td>«Envía una semilla a un amigo». Crecimiento compartido y clips relajantes que se pueden compartir.</td>
</tr>
</tbody>
</table>
<h3 id="en-que-consiste" tabindex="-1">En qué consiste <a class="header-anchor" href="#en-que-consiste" aria-label="Permalink to &quot;En qué consiste&quot;"></a></h3>
<p>Un mundo tranquilo y coleccionable que evoluciona en <strong>tiempo real</strong>. Una «temporada» compartida (por ejemplo, Isla de Primavera): una única isla 3D por la que los niños pueden caminar, como en la demo jugable de Kali. No hay niveles ni puntuaciones tradicionales. El progreso se refleja en cosas como <strong>a tu árbol le ha crecido una rama nueva</strong>, <strong>has visto 12 momentos</strong> o <strong>alguien ha regado tu semilla</strong>.</p>
<p>En cada visita, el niño puede: <strong>regar una planta</strong>, <strong>dejar un deseo</strong> (texto o emoji), <strong>encontrar un personaje oculto de Cubcoats</strong> o <strong>ver un «momento» de 30 segundos</strong> (por ejemplo, Kali bajo el árbol dorado). Cada semana se publican nuevos momentos y pequeños fragmentos narrativos (formato episódico). Idioma ambiental opcional: «Hoy Kali ha dicho: [una frase en EN y ZH]».</p>
<p>El aprendizaje y el crecimiento son <strong>sutiles</strong>: los temas (la bondad, la paciencia, volver a intentarlo) están presentes en la escritura y el arte, no en lecciones. La experiencia se siente como un juguete o un lugar compartido, no como la escuela.</p>
<h3 id="bucle-principal" tabindex="-1">Bucle principal <a class="header-anchor" href="#bucle-principal" aria-label="Permalink to &quot;Bucle principal&quot;"></a></h3>
<ol>
<li><strong>Visita</strong> la isla (desde el navegador o la aplicación).</li>
<li><strong>Realiza una acción sencilla</strong> por visita: regar, pedir un deseo, encontrar un personaje o ver un momento.</li>
<li><strong>Observa cómo cambia el mundo</strong> con el paso de los días y las semanas (flores nuevas, nuevas poses de los personajes y nuevos clips breves).</li>
<li><strong>Comparte</strong> una semilla con un amigo o «visita la isla de un amigo» para que el crecimiento se sienta como una experiencia social.</li>
</ol>
<h3 id="como-utiliza-el-flujo-de-trabajo-y-los-personajes-del-articulo" tabindex="-1">Cómo utiliza el flujo de trabajo y los personajes del artículo <a class="header-anchor" href="#como-utiliza-el-flujo-de-trabajo-y-los-personajes-del-articulo" aria-label="Permalink to &quot;Cómo utiliza el flujo de trabajo y los personajes del artículo&quot;"></a></h3>
<ul>
<li><strong>Mundo 3D jugable:</strong> El mismo flujo de trabajo que en la demo de Kali: pose en T → Generador de Modelos 3D → rigging → Cinevva Engine. La isla y los personajes se pueden explorar en tercera persona, sin presión.</li>
<li><strong>Árbol dorado:</strong> Procede directamente del artículo (el paso «del miedo a la esperanza» de Kali y el árbol dorado mágico). El árbol es el centro emocional y visual de la temporada.</li>
<li><strong>«Momentos» breves:</strong> Producidos como el vídeo corto vertical del artículo: fotograma inicial + fotograma final + prompt de movimiento → Generador de Vídeo (Kling 3.0 Pro), 9:16, ~15 s. Cada entrega semanal incluye un pequeño fragmento narrativo.</li>
<li><strong>PI de Cubcoats:</strong> Kali y los otros siete personajes, el mundo de la isla y el estilo artístico cálido y redondeado. Encaja con un relanzamiento centrado en licencias (2026) mediante un producto digital y episódico.</li>
</ul>
<h3 id="por-que-puede-hacerse-viral" tabindex="-1">Por qué puede hacerse viral <a class="header-anchor" href="#por-que-puede-hacerse-viral" aria-label="Permalink to &quot;Por qué puede hacerse viral&quot;"></a></h3>
<ul>
<li><strong>Acceso sencillo:</strong> Un solo enlace, sin un proceso de incorporación pesado. «Envía una semilla a un amigo» es una acción fácil de compartir.</li>
<li><strong>Clips tranquilos y bonitos:</strong> Los momentos breves funcionan por sí solos y se pueden compartir (en redes sociales: «mira estos 15 segundos»). Tienen potencial para convertirse en memes de forma positiva.</li>
<li><strong>Formato episódico:</strong> «¿Qué hay de nuevo esta semana?» fomenta las visitas recurrentes y la conversación.</li>
<li><strong>Sutil:</strong> Los padres ven una experiencia «tranquila, creativa, sin anuncios y sin estrés»; los niños adquieren rutinas, paciencia y una agradable sensación de sorpresa sin recibir enseñanzas explícitas.</li>
</ul>
<h3 id="posible-enfoque-para-el-blog-de-cinevva" tabindex="-1">Posible enfoque para el blog de Cinevva <a class="header-anchor" href="#posible-enfoque-para-el-blog-de-cinevva" aria-label="Permalink to &quot;Posible enfoque para el blog de Cinevva&quot;"></a></h3>
<p><em>«Llevamos a Kali de un boceto a un vídeo y, después, a un personaje con el que puedes recorrer un mundo. Árbol Dorado es el siguiente paso: un mundo que crece en tiempo real, donde los niños pueden visitarlo, regarlo y ver momentos breves, sin niveles ni presión. El mismo flujo de trabajo. Un formato nuevo».</em></p>
<hr>
<h2 id="la-isla-de-las-palabras-de-kali-—-resumen" tabindex="-1">La Isla de las Palabras de Kali — Resumen <a class="header-anchor" href="#la-isla-de-las-palabras-de-kali-—-resumen" aria-label="Permalink to &quot;La Isla de las Palabras de Kali — Resumen&quot;"></a></h2>
<table tabindex="0">
<thead>
<tr>
<th></th>
<th></th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>Eslogan</strong></td>
<td>Ayuda a Kali y a sus amigos a hacer crecer la isla. Aprende inglés y chino por el camino.</td>
</tr>
<tr>
<td><strong>Edades</strong></td>
<td>5–11</td>
</tr>
<tr>
<td><strong>Enfoque</strong></td>
<td>Inglés ↔ chino para niños, con una sólida gamificación y progresión.</td>
</tr>
</tbody>
</table>
<p><strong>Idea principal:</strong> La isla de Cubcoats está dividida en zonas de personajes (el bosque de Kali, la playa de otro personaje). Los niños ayudan a los personajes mediante tareas breves que requieren comprender y expresarse en EN/ZH. Progresión = «Semillas → Brotes → Árboles → Árbol Dorado» (la siguiente zona se desbloquea cuando el árbol de la zona está completo). Recorrido diario de «faroles», tarjetas de frases coleccionables, barras de «ánimo» de los personajes y panel opcional para padres. Al completar una zona, se desbloquean momentos narrativos breves (con el estilo de fotograma inicial/final). <strong>Flujo de trabajo:</strong> El mismo flujo de trabajo 3D + vídeo para los personajes y los momentos emotivos.</p>
<hr>
<h2 id="cubcoats-historias-de-la-isla-—-resumen" tabindex="-1">Cubcoats: Historias de la Isla — Resumen <a class="header-anchor" href="#cubcoats-historias-de-la-isla-—-resumen" aria-label="Permalink to &quot;Cubcoats: Historias de la Isla — Resumen&quot;"></a></h2>
<table tabindex="0">
<thead>
<tr>
<th></th>
<th></th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>Eslogan</strong></td>
<td>Crea tu propio episodio de Cubcoats. Remezcla la historia. Comparte tu versión.</td>
</tr>
<tr>
<td><strong>Edades</strong></td>
<td>3–13 (grupos: 3–6, 7–10, 11–13)</td>
</tr>
<tr>
<td><strong>Enfoque</strong></td>
<td>Creación y remezcla de historias; la educación está integrada, pero no es el principal argumento de venta.</td>
</tr>
</tbody>
</table>
<p><strong>Idea principal:</strong> Narrativas episódicas en las que los niños eligen distintas ramas (¿qué dice Kali?, ¿adónde va?). La actividad principal consiste en <strong>remezclar</strong>: elegir un personaje, un lugar y 2–3 momentos narrativos → generar un «episodio» breve (guion + elementos visuales sencillos o, más adelante, un vídeo corto generado con IA). El aprendizaje es sutil (vocabulario y patrones presentes en los diálogos y las elecciones). Componente social: comparte tu episodio, juega la versión de otra persona y valórala como «amable / divertida / sorprendente». <strong>Flujo de trabajo:</strong> La misma apariencia de los personajes + el flujo de vídeo de dos fotogramas para los «momentos» generados por los usuarios; 3D para mantener la coherencia de los personajes y del mundo.</p>
<hr>
<p><em>Herramientas de Cinevva mencionadas: Generador de Imágenes, Generador de Vídeo (Kling 3.0 Pro), Generador de Modelos 3D, rigging automático y Cinevva Engine. Refleja el flujo de trabajo descrito en «Del boceto al vídeo y al 3D jugable» (2026-03-04).</em></p>
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Lo que realmente hace falta para crear un mundo abierto en un navegador]]></title>
            <link>https://app.cinevva.com/es/blog/2026-03-14-open-world-browser-medium-article</link>
            <guid>https://app.cinevva.com/es/blog/2026-03-14-open-world-browser-medium-article</guid>
            <pubDate>Sat, 14 Mar 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Un recorrido periodístico por la serie de ingeniería de Cinevva en 12 partes: 24 experimentos exploratorios, desde rudimentarias líneas base de terreno hasta marching cubes en la GPU, LOD por streaming y depuración de uniones con Transvoxel.]]></description>
            <content:encoded><![CDATA[<h1 id="lo-que-realmente-hace-falta-para-crear-un-mundo-abierto-en-un-navegador" tabindex="-1">Lo que realmente hace falta para crear un mundo abierto en un navegador <a class="header-anchor" href="#lo-que-realmente-hace-falta-para-crear-un-mundo-abierto-en-un-navegador" aria-label="Permalink to &quot;Lo que realmente hace falta para crear un mundo abierto en un navegador&quot;"></a></h1>
<p><em>Por <a href="/es/about.html">Mariana Muntean</a>, CEO de Cinevva</em></p>
<img src="/img/blog/open-world-browser-120fps.png" alt="El mundo abierto ejecutándose en un navegador a 120 FPS: terreno, árboles, físicas y una cápsula de jugador, todo renderizado en una sola pestaña" style="width:100%;border-radius:8px;margin:1.5rem 0" />
<p>El equipo de Cinevva acaba de publicar uno de los diarios de ingeniería más transparentes de los últimos tiempos en el desarrollo de videojuegos: una <a href="/es/blog/2026-02-25-open-world-browser-series-guide.html">serie de 12 partes</a> que documenta nuestro intento de crear un mundo abierto multijugador que se ejecute íntegramente en el navegador. Sin descargas. Sin tienda de aplicaciones. Solo una URL.</p>
<p>El proyecto abarcó 24 experimentos técnicos que llamamos «spikes»: prototipos breves y específicos, cada uno diseñado para responder una pregunta arriesgada. Todos los spikes se publicaron con código fuente funcional que puedes abrir y ejecutar ahora mismo en tu navegador. La serie fue escrita por <a href="/es/about.html">Oleg Sidorkin</a>, CTO y cofundador de Cinevva, y se lee menos como marketing y más como un diario de campo desde la primera línea de lo que los navegadores pueden hacer realmente en 2026.</p>
<p>Lo que hace que valga la pena leer la serie —aunque nunca tengas previsto crear sistemas de terreno— es el método que hay detrás. Es un caso práctico sobre cómo reducir el riesgo de un proyecto ambicioso antes de comprometer recursos costosos.</p>
<h2 id="empezar-primero-por-la-pregunta-mas-dificil" tabindex="-1">Empezar primero por la pregunta más difícil <a class="header-anchor" href="#empezar-primero-por-la-pregunta-mas-dificil" aria-label="Permalink to &quot;Empezar primero por la pregunta más difícil&quot;"></a></h2>
<p>La mayoría de los proyectos de mundo abierto fracasan siguiendo una secuencia predecible. Primero tienes un concepto precioso. Después, una escena bonita. Luego descubres que ya habías agotado el presupuesto por fotograma antes incluso de que existiera la jugabilidad.</p>
<p>Nuestro equipo invirtió el orden. El <a href="/es/blog/2026-02-25-open-world-browser-part-01-risk-first.html">primer spike</a> era feo a propósito: una malla de terreno de 512 metros, 500 objetos instanciados, ruido de altura procedural, un plano de agua y niebla. Sin sombras ni pase de embellecimiento. La única pregunta era si un navegador podía mantener una tasa de fotogramas estable mientras la cámara se desplazaba por el entorno.</p>
<p>Podía. Y ese «sí» estableció lo que Oleg denomina un «contrato de referencia»: un coste medido de una escena mínima que servía como referencia y frente al cual cada función posterior debía justificar su existencia. Si un efecto nuevo se veía genial pero hacía saltar por los aires el presupuesto por fotograma, no se publicaba. Al menos, todavía no.</p>
<p>Ese tipo de disciplina parece obvio. En la práctica, es poco frecuente en entornos de prototipado acelerado donde todo el mundo está entusiasmado con el siguiente logro visual.</p>
<h2 id="la-apuesta-por-las-fisicas" tabindex="-1">La apuesta por las físicas <a class="header-anchor" href="#la-apuesta-por-las-fisicas" aria-label="Permalink to &quot;La apuesta por las físicas&quot;"></a></h2>
<p>El <a href="/es/blog/2026-02-25-open-world-browser-part-02-worker-physics.html">segundo experimento</a> abordó un debate arquitectónico que divide a quienes desarrollan juegos para navegador: ¿deben ejecutarse las físicas en el hilo principal, donde es más sencillo, o en un Web Worker, donde no pueden bloquear el renderizado?</p>
<p>Sobre el papel, ejecutar las físicas en un worker es una solución más limpia. En la práctica, preocupa la latencia. Cada evento de entrada debe cruzar dos veces el límite de mensajería: una para llegar al worker y otra para devolver el resultado. Si ese viaje de ida y vuelta es demasiado lento, pulsar una tecla y ver cómo se mueve el personaje se sentirá pesado.</p>
<p>El equipo integró el motor de físicas Rapier —compilado de Rust a WebAssembly— en un worker dedicado, conectó el canal de mensajes y realizó mediciones. La sobrecarga era insignificante. Los controles seguían respondiendo de inmediato. Sin embargo, tuvimos cuidado de señalar que habíamos validado un escenario específico, no una regla universal. Cuando más adelante cambiaran la carga de la GPU y la complejidad del streaming, habría que volver a comprobar las suposiciones.</p>
<h2 id="los-spikes-aburridos-que-salvaron-el-proyecto" tabindex="-1">Los spikes aburridos que salvaron el proyecto <a class="header-anchor" href="#los-spikes-aburridos-que-salvaron-el-proyecto" aria-label="Permalink to &quot;Los spikes aburridos que salvaron el proyecto&quot;"></a></h2>
<p>La <a href="/es/blog/2026-02-25-open-world-browser-part-03-the-unflashy-spikes.html">tercera parte</a> de la serie no incluye capturas de pantalla. Trata sobre tres experimentos poco glamurosos, pero con consecuencias a nivel de producto.</p>
<p>El primero comprobó si los Durable Objects de Cloudflare podían gestionar emisiones de posición en tiempo real con frecuencias de actualización propias de un juego: la columna vertebral del multijugador. Si hubiera fallado, toda la arquitectura de red habría necesitado una fragmentación temprana en lugar de asignar cada isla a una única instancia.</p>
<p>El segundo validó un perfil de calidad para móviles: no un ajuste de escritorio con otro nombre, sino una ruta de renderizado explícita y de bajo coste basada en la misma línea base de terreno. La pregunta era si el mundo podía seguir siendo legible y reactivo bajo las limitaciones de las GPU móviles sin tener que reescribir el renderizador.</p>
<p>El tercero evaluó si los scripts de comportamiento generados por IA para los flujos de trabajo de los creadores serían lo bastante fiables para usarlos en producción.</p>
<p>Ninguno produjo vídeos espectaculares. Los tres fijaron límites estrictos que dieron forma a todas las decisiones arquitectónicas posteriores. Oleg escribe que estos «spikes poco vistosos cambiaron la arquitectura más rápido que los spikes visuales».</p>
<h2 id="streaming-donde-los-proyectos-bonitos-se-desmoronan" tabindex="-1">Streaming: donde los proyectos bonitos se desmoronan <a class="header-anchor" href="#streaming-donde-los-proyectos-bonitos-se-desmoronan" aria-label="Permalink to &quot;Streaming: donde los proyectos bonitos se desmoronan&quot;"></a></h2>
<img src="/img/blog/open-world-chunk-streaming.png" alt="Spike 6: streaming de chunks en acción; cada área de color es un chunk de terreno que se carga y descarga dinámicamente a medida que se mueve la cámara" style="width:100%;border-radius:8px;margin:1.5rem 0" />
<p>Puedes ocultar muchas cosas en una imagen estática. No puedes ocultar un tirón de 40 milisegundos al cruzar el límite de un chunk mientras corres.</p>
<p>El equipo probó el <a href="/es/blog/2026-02-25-open-world-browser-part-04-streaming-before-fancy.html">streaming antes de crear terreno avanzado</a>, separando deliberadamente las distintas cuestiones. El Spike 6 validó la carga de chunks vecinos con contenido sencillo. Solo después de obtener esa señal clara, el Spike 11 introdujo el streaming de mapas de altura comprimidos con refinamiento progresivo: primero cargaba el terreno con una resolución de 17 muestras, después con 33 y, por último, con la cuadrícula completa de 65 muestras.</p>
<p>La secuencia importó más de lo que esperábamos. Si hubiéramos empezado directamente con chunks de altura comprimidos, cada tirón habría sido ambiguo. ¿Era un problema de decodificación, un bloqueo al subir texturas o un problema al actualizar la geometría? Probar primero el streaming sencillo eliminó toda una categoría de incertidumbre.</p>
<p>De ahí surgió una lección práctica: hay que medir directamente los bloqueos de subida, no inferirlos a partir de los FPS medios. Los promedios ocultan los picos en los tiempos de fotograma, y esos picos son lo que los jugadores realmente perciben.</p>
<h2 id="las-guerras-por-el-presupuesto-visual" tabindex="-1">Las guerras por el presupuesto visual <a class="header-anchor" href="#las-guerras-por-el-presupuesto-visual" aria-label="Permalink to &quot;Las guerras por el presupuesto visual&quot;"></a></h2>
<p>Tres experimentos distintos atacaron los costes de renderizado de forma aislada, en vez de agruparlos. La densidad de la <a href="/es/blog/2026-02-25-open-world-browser-part-05-budgeting-the-pretty.html">vegetación</a> y su animación por el viento. Materiales de terreno multicapa con mapeado triplanar para las paredes de los acantilados. Mapas de sombras en cascada bajo una carga de terreno realista.</p>
<p>El spike de vegetación reveló que agrupar las instancias en menos mallas importaba más que reducir la cantidad de polígonos de cada brizna. El spike de materiales determinó que la proyección triplanar sobre superficies verticales justificaba su coste de GPU, pero añadir una quinta capa de mezcla de texturas no. El spike de sombras concluyó que tres cascadas con una resolución de 1024 proporcionaban sombras de contacto aceptables sin superar los 2 milisegundos de tiempo de GPU.</p>
<p>El equipo adoptó una regla tajante: una función solo avanza si puede justificar su coste con datos medidos del tiempo de fotograma. Esa restricción, fijada desde el principio, simplificó considerablemente las decisiones arquitectónicas posteriores en torno al terreno volumétrico y los clipmaps.</p>
<h2 id="el-giro-que-cambio-la-trayectoria-del-proyecto" tabindex="-1">El giro que cambió la trayectoria del proyecto <a class="header-anchor" href="#el-giro-que-cambio-la-trayectoria-del-proyecto" aria-label="Permalink to &quot;El giro que cambió la trayectoria del proyecto&quot;"></a></h2>
<p>Antes del Spike 10, nuestro modelo mental era «un mundo más grande implica más geometría». Después del <a href="/es/blog/2026-02-25-open-world-browser-part-06-clipmaps.html">Spike 10</a>, pasó a ser «presupuesto de geometría constante y actualización de anillos centrados en la cámara».</p>
<p>Los clipmaps de geometría —anillos concéntricos de terreno centrados en la cámara, cada vez menos detallados— permitían mantener aproximadamente constante la cantidad de triángulos, sin importar la distancia de dibujado. El truco práctico consistía en aplicar geomorphing en los límites de los anillos: mezclar suavemente las alturas de los vértices en el shader para que la transición entre niveles de resolución fuera invisible durante el movimiento.</p>
<p>La metodología de pruebas nos enseñó una lección sutil. Los clipmaps se ven bien en las capturas de pantalla. Sus artefactos solo aparecen durante un movimiento sostenido de la cámara a través de los límites de los anillos. El equipo dedicó tiempo a realizar recorridos a velocidad constante y observar si aparecía ruido temporal. «Las capturas de pantalla mentían», escribe Oleg. «El movimiento decía la verdad».</p>
<h2 id="adentrarse-bajo-tierra" tabindex="-1">Adentrarse bajo tierra <a class="header-anchor" href="#adentrarse-bajo-tierra" aria-label="Permalink to &quot;Adentrarse bajo tierra&quot;"></a></h2>
<p>Los mapas de altura no pueden representar cuevas. Almacenan un único valor de elevación por cada punto de una cuadrícula. En cuanto necesitas túneles, salientes o paredes de roca excavadas, necesitas terreno volumétrico.</p>
<p>El <a href="/es/blog/2026-02-25-open-world-browser-part-07-marching-cubes.html">Spike 12</a> implementó marching cubes en la GPU mediante shaders de cómputo de WebGPU, extrayendo mallas triangulares de un campo de distancia con signo tridimensional. Cuatro chunks de 64³ se ejecutaban simultáneamente, con actualizaciones de la malla en cada fotograma a partir de modificaciones animadas del SDF. El shader de cómputo se encargaba de todo —evaluar el campo, clasificar las celdas y emitir los vértices— sin ninguna lectura de vuelta en la CPU.</p>
<p>El reto no era conseguir que funcionara. Era lograr que funcionara junto con todo lo demás. La integración con el grafo de escena de Three.js, la gestión del ciclo de vida de los búferes —los búferes de WebGPU no pueden redimensionarse— y el manejo de fences para evitar destruir recursos de GPU que aún estaban en uso: la serie dedica <a href="/es/blog/2026-02-25-open-world-browser-part-08-webgpu-integration.html">dos</a> partes completas a lo que llamamos «robustecimiento incremental», el proceso poco glamuroso de añadir una capacidad cada vez y comprobar que la capa anterior sigue funcionando después de cada incorporación.</p>
<h2 id="la-pesadilla-de-las-uniones" tabindex="-1">La pesadilla de las uniones <a class="header-anchor" href="#la-pesadilla-de-las-uniones" aria-label="Permalink to &quot;La pesadilla de las uniones&quot;"></a></h2>
<p>La sección técnicamente más angustiosa de la serie abarca las <a href="/es/blog/2026-02-25-open-world-browser-part-09-transvoxel-first-cut.html">partes 9 a 11</a> y explica qué ocurre cuando se encuentran chunks de terreno con resoluciones diferentes.</p>
<p>Cuando un chunk de alta resolución se encuentra junto a uno de baja resolución, sus mallas generadas de forma independiente no se alinean en el límite. El resultado son grietas visibles, bordes parpadeantes y uniones en T por las que se filtra la luz. El algoritmo Transvoxel lo resuelve con celdas de transición especiales que salvan las diferencias de resolución, pero implementarlo correctamente en todas las configuraciones de chunks, con un orden de orientación coherente, una gestión adecuada de los búferes y rangos de dibujado precisos, requirió seis experimentos distintos.</p>
<p>La historia de depuración más memorable del equipo: pasamos dos días persiguiendo un artefacto en una unión que atribuíamos a la lógica de transición. El verdadero culpable eran datos obsoletos. El shader de cómputo de la GPU escribía N vértices en un búfer, pero la llamada de dibujado seguía configurada para renderizar N+M vértices del fotograma anterior. Esos vértices adicionales contenían basura que producía triángulos parpadeantes, finos como cuchillas. La solución fue una sola línea: limitar el rango de dibujado al número de vértices activos indicado por el contador atómico.</p>
<p>«Los errores de renderizado suelen hacerse pasar por errores de generación de mallas», observa Oleg. «La geometría había sido correcta todo el tiempo».</p>
<h2 id="del-caos-a-la-gobernanza" tabindex="-1">Del caos a la gobernanza <a class="header-anchor" href="#del-caos-a-la-gobernanza" aria-label="Permalink to &quot;Del caos a la gobernanza&quot;"></a></h2>
<p>Después de la batalla con las uniones, el equipo sustituyó el comportamiento improvisado de los chunks por un <a href="/es/blog/2026-02-25-open-world-browser-part-11-policy-modes.html">sistema explícito de políticas</a>. A partir de entonces, una función central decidía el nivel de LOD de cada chunk, el modo de renderizado —mapa de altura o marching cubes— y qué caras necesitaban celdas de transición. Los anillos de distancia determinaban el LOD base. Una restricción de adyacencia garantizaba que dos chunks vecinos no difirieran en más de un nivel de resolución. Un mapa de bits de ediciones mantenía los chunks volumétricos en modo marching cubes independientemente de la distancia si contenían modificaciones de creadores.</p>
<p>Las superposiciones de depuración codificadas por colores —verde para los chunks de mapa de altura, azul para los de marching cubes y naranja para las caras de transición— convirtieron «vi un error en algún lugar cerca de esa cresta» en «el error aparece en la posición (142, 12, -67), mirando hacia el noroeste».</p>
<p>«La política no redujo la complejidad», escribe Oleg. «Organizó la complejidad».</p>
<h2 id="el-resultado-final" tabindex="-1">El resultado final <a class="header-anchor" href="#el-resultado-final" aria-label="Permalink to &quot;El resultado final&quot;"></a></h2>
<p>El último spike combinó anillos de clipmap, niebla celeste por fragmento —muestreando el color real del skybox en la dirección de cada fragmento de terreno— y la conexión de módulos de Three.js en una demostración unificada. El resultado es un sistema de terreno que superpone edición volumétrica en el campo cercano, chunks de mapas de altura a media distancia y anillos de clipmap en la lejanía, bajo una capa de políticas que gobierna el modo, el LOD y las transiciones.</p>
<p>La serie concluye con varias <a href="/es/blog/2026-02-25-open-world-browser-part-12-lessons.html">lecciones</a> que Oleg afirma que repetiría en cualquier proyecto futuro:</p>
<ul>
<li><strong>Empieza con spikes de riesgo antes de trabajar en funciones.</strong> Resuelve las preguntas del tipo «¿podemos hacer esto siquiera?» antes de invertir en pipelines de contenido.</li>
<li><strong>Congela líneas base que sabes que funcionan antes de dar grandes saltos de integración.</strong> El día dedicado a establecer un punto de control limpio ahorra varios días posteriores buscando regresiones mediante bisección.</li>
<li><strong>Impón políticas y observabilidad antes de emprender maratones de optimización.</strong> Las condiciones identificadas y acompañadas de reglas de activación siempre superan a los errores misteriosos.</li>
<li><strong>Haz pruebas en movimiento, no con capturas de pantalla.</strong> Los saltos, el parpadeo y los tirones del streaming se esconden en las imágenes estáticas.</li>
<li><strong>Mide el tiempo de fotograma de cada función, no los FPS medios.</strong> Los promedios ocultan los picos que los usuarios perciben realmente.</li>
<li><strong>Publica las partes desordenadas.</strong> Los caminos equivocados, la búsqueda de fantasmas y los dos días culpando al sistema incorrecto. Esas son las partes de las que la gente puede aprender de verdad.</li>
</ul>
<h2 id="por-que-esto-importa-mas-alla-de-cinevva" tabindex="-1">Por qué esto importa más allá de Cinevva <a class="header-anchor" href="#por-que-esto-importa-mas-alla-de-cinevva" aria-label="Permalink to &quot;Por qué esto importa más allá de Cinevva&quot;"></a></h2>
<p>La serie es importante por tres motivos que trascienden el pipeline de terreno de una sola empresa.</p>
<p>En primer lugar, demuestra que los shaders de cómputo de WebGPU, las físicas con WebAssembly y los Durable Objects desplegados en el edge han cruzado un umbral. En 2026, un mundo abierto multijugador con terreno volumétrico, edición en tiempo real y LOD por streaming es arquitectónicamente viable en una pestaña del navegador. Hace dos años no lo era.</p>
<p>En segundo lugar, la metodología de spikes —experimentos pequeños y específicos, cada uno de los cuales responde una pregunta arriesgada mediante resultados funcionales y medibles— ofrece un modelo para cualquier equipo que intente hacer algo que podría no funcionar. La disciplina de medir antes de comprometerse, establecer líneas base antes de integrar e identificar los casos límite antes de optimizar se aplica mucho más allá de los sistemas de terreno.</p>
<p>En tercer lugar, la transparencia radical es precisamente el objetivo. Publicar el código fuente de los 24 experimentos, incluidos los callejones sin salida y los desvíos de depuración de dos días, convierte esto en algo más que un blog técnico. Es un cuaderno público de ingeniería que trata al lector como a un colega y no como a un cliente.
La serie completa está disponible en nuestra <a href="/es/blog/2026-02-25-open-world-browser-series-guide.html">guía de la serie</a>, con todos los prototipos ejecutándose en vivo en el navegador.</p>
<hr>
<p><em>Este artículo se publicó originalmente en <a href="https://vio-202020.medium.com/de-risking-an-ambitious-project-before-committing-to-anything-big-like-an-online-open-world-c94a7c05ee06" target="_blank" rel="noreferrer">Medium</a>.</em></p>
]]></content:encoded>
            <enclosure url="https://app.cinevva.com/img/blog/open-world-browser-120fps.png" length="0" type="image/png"/>
        </item>
        <item>
            <title><![CDATA[Del boceto al vídeo y al 3D jugable: personaje, escenas y rig]]></title>
            <link>https://app.cinevva.com/es/blog/2026-03-04-sketch-to-animated-3d-character</link>
            <guid>https://app.cinevva.com/es/blog/2026-03-04-sketch-to-animated-3d-character</guid>
            <pubDate>Wed, 04 Mar 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Cómo usamos el Generador de imágenes, el Generador de vídeo y el Generador de modelos 3D de Cinevva para convertir un boceto preliminar de un personaje en un corto vertical generado con IA y un modelo 3D con rig que puedes controlar en un navegador.]]></description>
            <content:encoded><![CDATA[<h1 id="del-boceto-al-video-y-al-3d-jugable" tabindex="-1">Del boceto al vídeo y al 3D jugable <a class="header-anchor" href="#del-boceto-al-video-y-al-3d-jugable" aria-label="Permalink to &quot;Del boceto al vídeo y al 3D jugable&quot;"></a></h1>
<p><em>Por <a href="/es/about.html">Oleg Sidorkin</a>, CTO de Cinevva</em></p>
<p>Antes, llevar un personaje desde un boceto plano hasta un juego 3D requería un artista conceptual, un modelador 3D, un especialista en rigging, un animador y alguien que lo integrara todo en un motor. Queríamos comprobar qué parte de ese proceso podían resolver por sí solas las <a href="/es/tools/">herramientas creativas de Cinevva</a>. Esto es lo que descubrimos.</p>
<p>El personaje es <strong>Kali the Kitty</strong>, de <a href="https://thecubcoats.com" target="_blank" rel="noreferrer">Cubcoats</a>, una marca infantil que vendió más de un millón de sudaderas con capucha y forma de peluche a través de Nordstrom, Amazon y Disney Store. Cubcoats cuenta con ocho personajes originales con personalidades definidas, un mundo insular ficticio y 14 patentes. La marca se relanzará en 2026 como una plataforma centrada en licencias, y queríamos mostrar cómo se ve esa propiedad intelectual cuando va más allá de los productos físicos: un corto vertical y un personaje 3D con rig que puedes controlar en un navegador. Todo lo que aparece a continuación es el resultado real de esa exploración.</p>
<p>Arrastra los visores 3D para rotar alrededor de los modelos. Desplázate por la tira de fotogramas para ver cómo avanza el corto vertical desde el primer fotograma hasta el último.</p>
<h2 id="de-una-ilustracion-plana-de-libro-a-un-personaje-que-puedes-girar" tabindex="-1">De una ilustración plana de libro a un personaje que puedes girar <a class="header-anchor" href="#de-una-ilustracion-plana-de-libro-a-un-personaje-que-puedes-girar" aria-label="Permalink to &quot;De una ilustración plana de libro a un personaje que puedes girar&quot;"></a></h2>
<p>Cubcoats ya contaba con preciosas ilustraciones 2D. La dirección artística de Mimi Chao dio a cada personaje un aspecto cálido, redondeado y dibujado a mano que funciona a la perfección tanto en sudaderas como en libros ilustrados. Pero el arte plano no sirve directamente para un flujo de trabajo 3D. Necesitábamos un personaje de alta fidelidad que pudiera utilizarse como referencia para la generación de vídeo, la creación de la malla y el rigging, siempre con el mismo rostro.</p>
<p>Empezamos introduciendo las ilustraciones originales del libro en nuestro <a href="/es/tools/flux.html">Generador de imágenes</a> y pidiéndole que produjera una versión renderizada en 3D del mismo personaje.</p>
<figure class="pipeline-media pipeline-media--single">
<img src="/blog/sketch-to-3d-pipeline/kali-flat-book-art.png" alt="Ilustraciones planas originales de Kali the Kitty para los libros de Cubcoats" loading="lazy">
<figcaption><strong>El punto de partida.</strong> Las ilustraciones 2D originales de Kali para los libros. Cálidas, expresivas y completamente planas.</figcaption>
</figure>
<p>Se mantuvieron las proporciones, la personalidad quedó reflejada y el suave aspecto de dibujo animado en 3D proporcionó a todas las herramientas posteriores una referencia coherente. A partir de ahí, ajustamos la pose y el encuadre exactos hasta fijar una referencia principal.</p>
<div class="pipeline-media pipeline-media--two">
<figure>
<img src="/blog/sketch-to-3d-pipeline/kali-3d-chatgpt.png" alt="Referencia definitiva de Kali como personaje con estilo 3D" loading="lazy">
<figcaption><strong>Referencia principal definitiva.</strong> Aspecto de dibujo animado 3D de cuerpo entero utilizado para el vídeo y como referencia visual de la malla.</figcaption>
</figure>
<figure>
<img src="/blog/sketch-to-3d-pipeline/kali-3d-tpose.png" alt="Referencia en pose T para la generación 3D y el rigging" loading="lazy">
<figcaption><strong>Lámina en pose T.</strong> El mismo personaje, con los brazos extendidos. Se utilizó tanto en el [Generador de modelos 3D](/es/tools/hunyuan3d) como en la [herramienta de rigging automático](/es/tools/rigger).</figcaption>
</figure>
</div>
<p>La pose T es importante porque el rigging requiere que los brazos estén separados del torso. Si te la saltas, la herramienta de rigging automático fusiona los brazos con el cuerpo y no puede continuar. Generamos la pose T a partir del mismo diseño definitivo del personaje para que la silueta y las proporciones se mantuvieran coherentes en cada paso.</p>
<h2 id="escribe-la-historia-antes-de-generar-nada" tabindex="-1">Escribe la historia antes de generar nada <a class="header-anchor" href="#escribe-la-historia-antes-de-generar-nada" aria-label="Permalink to &quot;Escribe la historia antes de generar nada&quot;"></a></h2>
<p>Antes de utilizar las herramientas de vídeo, escribimos una escaleta en lenguaje sencillo. El rasgo de personalidad de Kali en el universo de Cubcoats es «Positiva». Es quien consigue que todo el mundo se sienta incluido y mantiene el optimismo cuando las cosas se ponen difíciles. Por eso construimos un arco de diez segundos en torno a esa idea:</p>
<blockquote>
<p>Kali entra de noche en un bosque oscuro y brumoso mientras sostiene una pequeña linterna luminosa. Se asusta, se sienta sola y está a punto de rendirse. Entonces descubre detrás de ella un árbol mágico dorado que lo ilumina todo. Asombro, alegría y partículas doradas cayendo como lluvia. Del miedo a la esperanza en un instante.</p>
</blockquote>
<p>Ese es todo el argumento. No tiene que ser complejo. Debe condensar un giro emocional en una única toma continua para que el fotograma inicial y el final puedan conectarse de verdad.</p>
<h2 id="dos-fotogramas-que-enmarcan-toda-la-historia" tabindex="-1">Dos fotogramas que enmarcan toda la historia <a class="header-anchor" href="#dos-fotogramas-que-enmarcan-toda-la-historia" aria-label="Permalink to &quot;Dos fotogramas que enmarcan toda la historia&quot;"></a></h2>
<p>Generamos dos imágenes estáticas clave a partir de ese argumento mediante nuestro <a href="/es/tools/flux.html">Generador de imágenes</a>. Utilizamos una relación de aspecto vertical para adaptarlas al corto. Los prompts describen exactamente al mismo personaje en dos momentos diferentes.</p>
<p><strong>Prompt del fotograma inicial:</strong></p>
<blockquote>
<p>Render 3D animado con estilo Pixar de Kali, una pequeña gatita rosa con grandes ojos oscuros y redondos, orejas rosas y puntiagudas, vientre rosa claro y un rostro redondo y alegre. Está de pie en el límite de un bosque oscuro y brumoso por la noche, sosteniendo una pequeña linterna luminosa con ambas patas. Tiene las orejas ligeramente agachadas y su expresión es nerviosa pero decidida. Iluminación cinematográfica con luz de luna azul y fría desde arriba y un resplandor naranja y cálido procedente de la linterna. Niebla densa entre los troncos oscuros de los árboles del fondo. Ángulo de cámara: plano medio, ligeramente contrapicado. Sin texto ni marca de agua.</p>
</blockquote>
<p><strong>Prompt del fotograma final:</strong></p>
<blockquote>
<p>Render 3D animado con estilo Pixar de Kali, una pequeña gatita rosa con grandes ojos oscuros y redondos, orejas rosas y puntiagudas y vientre rosa claro. Está de pie frente a un enorme árbol mágico cubierto de flores doradas y resplandecientes, con los brazos completamente extendidos y una enorme sonrisa de alegría. A su alrededor flotan pétalos dorados. El árbol irradia una luz dorada y cálida que ilumina todo el claro del bosque. Sobre ella puede verse el cielo nocturno estrellado. Ángulo de cámara: plano general ligeramente contrapicado, composición de revelación épica. Sin texto ni marca de agua.</p>
</blockquote>
<div class="pipeline-media pipeline-media--two">
<figure>
<img src="/blog/sketch-to-3d-pipeline/kali-start-frame.png" alt="Fotograma inicial del vídeo vertical generado con IA" loading="lazy">
<figcaption><strong>Fotograma inicial.</strong> Kali, nerviosa, en el límite del bosque con su linterna.</figcaption>
</figure>
<figure>
<img src="/blog/sketch-to-3d-pipeline/kali-end-frame.png" alt="Fotograma final del vídeo vertical generado con IA" loading="lazy">
<figcaption><strong>Fotograma final.</strong> Kali, llena de alegría, frente al árbol dorado.</figcaption>
</figure>
</div>
<p>Seedance interpola entre estos dos extremos. La descripción del personaje se mantiene idéntica en ambos prompts para que el modelo sepa que se trata del mismo personaje. Solo cambian la escena, la emoción y la cámara.</p>
<h2 id="el-video-quedo-mejor-de-lo-esperado" tabindex="-1">El vídeo quedó mejor de lo esperado <a class="header-anchor" href="#el-video-quedo-mejor-de-lo-esperado" aria-label="Permalink to &quot;El vídeo quedó mejor de lo esperado&quot;"></a></h2>
<p>Cargamos ambos fotogramas en el <a href="/es/tools/video.html">Generador de vídeo</a> de Cinevva, elegimos Seedance 1.5 Pro, configuramos una relación de aspecto de 9:16 y una duración de 15 segundos, escribimos el argumento en el prompt de movimiento y pulsamos Generar.</p>
<figure class="pipeline-media pipeline-media--single">
<img src="/blog/sketch-to-3d-pipeline/video-generator-setup.png" alt="Generador de vídeo de Cinevva con los fotogramas inicial y final cargados" loading="lazy">
<figcaption><strong>La configuración real.</strong> Fotograma inicial, fotograma final, prompt de movimiento, formato vertical 9:16, 15 segundos y audio activado.</figcaption>
</figure>
<p>El clip interpola entre los dos extremos. El audio nativo se generó en el mismo proceso. Estos son algunos fotogramas extraídos a lo largo de la línea temporal.</p>
<div class="pipeline-filmstrip" aria-label="Fotogramas del vídeo vertical generado">
<img src="/blog/sketch-to-3d-pipeline/seedance-frames/frame_01.jpg" alt="Fotograma 1 del vídeo" loading="lazy">
<img src="/blog/sketch-to-3d-pipeline/seedance-frames/frame_02.jpg" alt="Fotograma 2 del vídeo" loading="lazy">
<img src="/blog/sketch-to-3d-pipeline/seedance-frames/frame_03.jpg" alt="Fotograma 3 del vídeo" loading="lazy">
<img src="/blog/sketch-to-3d-pipeline/seedance-frames/frame_04.jpg" alt="Fotograma 4 del vídeo" loading="lazy">
<img src="/blog/sketch-to-3d-pipeline/seedance-frames/frame_05.jpg" alt="Fotograma 5 del vídeo" loading="lazy">
<img src="/blog/sketch-to-3d-pipeline/seedance-frames/frame_06.jpg" alt="Fotograma 6 del vídeo" loading="lazy">
<img src="/blog/sketch-to-3d-pipeline/seedance-frames/frame_07.jpg" alt="Fotograma 7 del vídeo" loading="lazy">
<img src="/blog/sketch-to-3d-pipeline/seedance-frames/frame_08.jpg" alt="Fotograma 8 del vídeo" loading="lazy">
<img src="/blog/sketch-to-3d-pipeline/seedance-frames/frame_09.jpg" alt="Fotograma 9 del vídeo" loading="lazy">
</div>
<p class="pipeline-caption">De izquierda a derecha: progresión del corto vertical generado.</p>
<p>Usar un fotograma inicial y otro final fue el modo adecuado cuando queríamos conseguir una pose de cierre exacta. Para arcos emocionales más largos, una sola referencia combinada con un prompt funcionó bien con el modo de guion gráfico Kling 3.0 Pro del <a href="/es/tools/video.html">Generador de vídeo</a>. Distintas configuraciones para distintos objetivos.</p>
<h2 id="el-mismo-personaje-ahora-en-3d" tabindex="-1">El mismo personaje, ahora en 3D <a class="header-anchor" href="#el-mismo-personaje-ahora-en-3d" aria-label="Permalink to &quot;El mismo personaje, ahora en 3D&quot;"></a></h2>
<p>Aquí es donde se pone interesante. La imagen en pose T, perteneciente a la misma familia visual que las referencias del vídeo, se procesó con nuestro <a href="/es/tools/hunyuan3d.html">Generador de modelos 3D</a> para crear un modelo 3D a partir de una imagen. No se trata de hacer que la malla del juego coincida píxel por píxel con el vídeo. Se trata de hacerla coincidir con el recuerdo del jugador. El personaje del juego debe transmitir la misma personalidad que el del vídeo. Y como fijamos una única identidad visual desde el principio, así fue.</p>
<figure class="pipeline-media pipeline-media--single">
<img src="/blog/sketch-to-3d-pipeline/kali-preview.png" alt="Vista previa renderizada de la malla de Hunyuan3D" loading="lazy">
<figcaption>Render de vista previa de la malla generada. Texturas y proporciones antes del rigging.</figcaption>
</figure>
<p>El <a href="/es/tools/hunyuan3d.html">Generador de modelos 3D</a> produce un archivo GLB con texturas. No está listo para incorporarlo directamente a un juego, pero es claramente Kali. La silueta coincidía. Los materiales se aproximaban bastante. Era suficiente para seguir adelante.</p>
<h2 id="arrastra-estos-modelos-para-girarlos" tabindex="-1">Arrastra estos modelos para girarlos <a class="header-anchor" href="#arrastra-estos-modelos-para-girarlos" aria-label="Permalink to &quot;Arrastra estos modelos para girarlos&quot;"></a></h2>
<p>Resultado sin procesar del <a href="/es/tools/hunyuan3d.html">Generador de modelos 3D</a>. Sin rig, solo una malla con texturas. A su lado, el mismo personaje después de aplicar rigging automático y una animación de caminar integrada.</p>
<ClientOnly>
  <SketchPipelineModels />
</ClientOnly>
<h2 id="rigging-y-animacion" tabindex="-1">Rigging y animación <a class="header-anchor" href="#rigging-y-animacion" aria-label="Permalink to &quot;Rigging y animación&quot;"></a></h2>
<p>El <a href="/es/tools/hunyuan3d.html">Generador de modelos 3D</a> proporciona una malla. Para que esa malla pueda moverse, necesita un esqueleto y animaciones. Nuestra plataforma se encarga automáticamente del rigging: subes el GLB y recibes un modelo con rig y una biblioteca completa de animaciones. Ciclos de caminar, respiración en reposo, saltos y todo lo que necesita un personaje de videojuego.</p>
<p>La animación de caminar predeterminada parecía casi correcta, pero no del todo. Los brazos de Kali quedaban demasiado pegados al cuerpo y su cabeza se inclinaba en un ángulo ligeramente incorrecto. Ambas cosas tenían sentido para un humanoide genérico, pero no encajaban con una gatita de dibujos animados y formas redondeadas. Así que añadimos correcciones de huesos en tiempo de ejecución al código del juego: un desplazamiento en los hombros que empuja los brazos hacia fuera y una corrección de la rotación de la cabeza que elimina la inclinación. Pequeños ajustes, gran diferencia. Sin ellos, parecía rígida y robótica. Con ellos, volvía a parecer Kali.</p>
<h2 id="controlar-al-personaje-en-un-navegador" tabindex="-1">Controlar al personaje en un navegador <a class="header-anchor" href="#controlar-al-personaje-en-un-navegador" aria-label="Permalink to &quot;Controlar al personaje en un navegador&quot;"></a></h2>
<p>Incorporamos el modelo con rig al <a href="/es/engine.html">motor de Cinevva</a>. Cámara en tercera persona, movimiento con WASD, objetos coleccionables repartidos por el escenario y cámara orbital cuando el personaje está inactivo. Conseguir que la mezcla de animaciones funcionara correctamente requirió varias iteraciones: fundidos entre las animaciones de reposo y de caminar, normalización de la altura, corrección del eje frontal y ajuste de los desplazamientos de los huesos. La cámara en tercera persona detrás del personaje completa el recorrido desde el boceto hasta algo que puedes controlar.</p>
<p>Pruébalo. Usa WASD para moverte.</p>
<div class="pipeline-game-embed">
<iframe src="https://api.cinevva.com/games/game-mmbijtzp-d63d/" allow="fullscreen" loading="lazy"></iframe>
</div>
<h2 id="lo-que-le-diria-a-alguien-que-quisiera-hacerlo-manana" tabindex="-1">Lo que le diría a alguien que quisiera hacerlo mañana <a class="header-anchor" href="#lo-que-le-diria-a-alguien-que-quisiera-hacerlo-manana" aria-label="Permalink to &quot;Lo que le diría a alguien que quisiera hacerlo mañana&quot;"></a></h2>
<p>Fija un único diseño del personaje antes de utilizar cualquier herramienta de generación. Cada minuto que dediques a perfeccionar esa referencia te ahorrará una hora persiguiendo la coherencia más adelante.</p>
<p>Escribe primero un argumento breve. Después, genera los fotogramas inicial y final con el <a href="/es/tools/flux.html">Generador de imágenes</a>. Mantén las imágenes de referencia dentro de los límites de tamaño de la API. Utiliza una pose T procedente del mismo sistema de diseño cuando la introduzcas en el <a href="/es/tools/hunyuan3d.html">Generador de modelos 3D</a>.</p>
<p>Carga ambos fotogramas en el <a href="/es/tools/video.html">Generador de vídeo</a> y deja que interpole entre ellos. Para la malla del juego, aplica rigging al modelo mediante la plataforma y ajusta los desplazamientos de los huesos en tiempo de ejecución si las animaciones predeterminadas no se adaptan del todo a las proporciones de tu personaje.</p>
<p>Hace dos años, este flujo de trabajo no existía. Habrías necesitado un equipo y un presupuesto. Ahora solo necesitas un boceto y las <a href="/es/tools/">herramientas creativas</a> de Cinevva. Creo que es un cambio importante en cuanto a quién puede dar vida a un personaje.</p>
<hr>
<p><em>Herramientas de Cinevva utilizadas: <a href="/es/tools/flux.html">Generador de imágenes</a>, <a href="/es/tools/video.html">Generador de vídeo</a>, <a href="/es/tools/hunyuan3d.html">Generador de modelos 3D</a>, rigging automático y <a href="/es/engine.html">motor de Cinevva</a>. Refleja el estado de las herramientas a principios de 2026.</em></p>
]]></content:encoded>
            <enclosure url="https://app.cinevva.com/blog/sketch-to-3d-pipeline/kali-start-frame.png" length="0" type="image/png"/>
        </item>
        <item>
            <title><![CDATA[Construir un mundo abierto en el navegador, parte 1: Empezamos intentando romperlo]]></title>
            <link>https://app.cinevva.com/es/blog/2026-02-25-open-world-browser-part-01-risk-first</link>
            <guid>https://app.cinevva.com/es/blog/2026-02-25-open-world-browser-part-01-risk-first</guid>
            <pubDate>Wed, 25 Feb 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Antes de construir cuevas o shaders sofisticados, necesitábamos responder una pregunta incómoda: ¿puede esto siquiera ejecutarse en un navegador?]]></description>
            <content:encoded><![CDATA[<h1 id="construir-un-mundo-abierto-en-el-navegador-parte-1-empezamos-intentando-romperlo" tabindex="-1">Construir un mundo abierto en el navegador, parte 1: Empezamos intentando romperlo <a class="header-anchor" href="#construir-un-mundo-abierto-en-el-navegador-parte-1-empezamos-intentando-romperlo" aria-label="Permalink to &quot;Construir un mundo abierto en el navegador, parte 1: Empezamos intentando romperlo&quot;"></a></h1>
<p><em>Por <a href="/es/about.html">Oleg Sidorkin</a>, CTO y cofundador de Cinevva</em></p>
<p>¿Acabas de llegar? Consulta la <a href="/es/blog/2026-02-25-open-world-browser-series-guide.html">guía de la serie</a>. Explica qué es un spike y enlaza todas las partes.</p>
<p>Estamos construyendo un mundo abierto multijugador que se ejecuta íntegramente en el navegador. Sin instalación, sin tienda de aplicaciones, solo una URL. El mayor riesgo inicial era evidente: ¿puede un navegador renderizar un mundo 3D persistente con una tasa de fotogramas jugable y, al mismo tiempo, dejar margen para la jugabilidad, la física y la red?</p>
<p>La mayoría de los proyectos de mundo abierto fracasan en un orden predecible. Primero tienes un buen concepto. Después, una escena bonita. Luego te das cuenta de que ya has agotado el presupuesto por fotograma antes de que exista la jugabilidad.</p>
<p>Queríamos resolver la cuestión del presupuesto de renderizado antes de invertir en cualquier otra cosa. Por eso, el Spike 1 se saltó el tráiler vistoso y fue directamente a las mediciones.</p>
<div style="position:relative;padding-bottom:56.25%;height:0;overflow:hidden;border-radius:8px;margin:1.5rem 0;border:1px solid rgba(255,255,255,0.12)">
<iframe src="/es/spikes/01-terrain/" title="Spike 1: terreno e instanciación" style="position:absolute;top:0;left:0;width:100%;height:100%;border:0;background:#000" loading="lazy" allowfullscreen></iframe>
</div>
<p><a href="/es/spikes/01-terrain/" target="_blank">Abrir el Spike 1 en una pestaña nueva ↗</a> · <a href="/es/blog/spike-source?spike=01-terrain">Ver el código fuente</a></p>
<p>La configuración era sencilla a propósito. Una malla de terreno de 512 metros, altura procedural generada mediante varias capas de ruido sinusoidal con atenuación hacia los bordes de la isla, un plano de agua, niebla atmosférica y 500 objetos instanciados. Usamos WebGL puro con Three.js, mapeo de tonos ACES y sin sombras.</p>
<p>No nos importaba su aspecto. Nos importaba que la escena se mantuviera estable al mover la cámara por ella.</p>
<p>De este spike surgieron dos conclusiones que dieron forma a todo el proyecto.</p>
<p>En primer lugar, confirmamos que teníamos un margen real en equipos de escritorio si manteníamos una primera implementación disciplinada. Eso nos dio confianza para intentar más adelante una arquitectura de terreno más compleja.</p>
<p>En segundo lugar, establecimos un contrato de referencia. Cada spike posterior tenía que explicar su coste en relación con esta escena. Si una funcionalidad se veía bien, pero costaba demasiado, no avanzaba a la siguiente fase.</p>
<p>Esa disciplina basada en una referencia se volvió crucial más adelante, cuando nos encontramos con artefactos en las uniones, transiciones entre distintos niveles de LOD y mallado controlado por cómputo. Sin una referencia estable, todos los errores parecen más grandes de lo que son.</p>
<p>En la parte 2 pasamos del renderizado a la respuesta de los controles. La física en un worker suena muy bien en los documentos de arquitectura. Pero solo importa si el personaje sigue respondiendo de inmediato al pulsar una tecla.</p>
<h2 id="tecnologia-mencionada-en-este-capitulo" tabindex="-1">Tecnología mencionada en este capítulo <a class="header-anchor" href="#tecnologia-mencionada-en-este-capitulo" aria-label="Permalink to &quot;Tecnología mencionada en este capítulo&quot;"></a></h2>
<p><strong>Terreno basado en mapas de altura.</strong> Una cuadrícula 2D en la que cada celda almacena un único valor de elevación. La GPU desplaza una malla plana en el shader de vértices para crear la superficie del terreno. Los mapas de altura son compactos (un chunk de 65x65 ocupa unos 8 KB a 16 bits), están bien adaptados a la GPU y se renderizan con rapidez. Su limitación es que no pueden representar cuevas, salientes ni ninguna superficie que se pliegue sobre sí misma. Para obtener más información sobre las limitaciones de los mapas de altura y las alternativas posteriores, consulta nuestra <a href="/es/guides/landscape-generation-browser.html#why-heightmaps-arent-enough">guía de generación de paisajes</a>.</p>
<p><strong>Three.js.</strong> La biblioteca de renderizado que usamos durante todo este proyecto. Three.js abstrae WebGL 2 —y, posteriormente, WebGPU— mediante un grafo de escena con cámaras, luces, materiales y objetos geométricos. Proporciona <code>InstancedMesh</code> para renderizar muchas copias de una misma geometría en una sola llamada de dibujo, además de descarte por frustum, materiales PBR y posprocesamiento. Consulta <a href="https://github.com/mrdoob/three.js" target="_blank" rel="noreferrer">Three.js en GitHub</a>. Para saber cómo encaja Three.js en la pila tecnológica de un mundo abierto para navegador, consulta nuestra <a href="/es/guides/browser-3d-open-world-tech.html#three-js">guía de tecnologías 3D para el navegador</a>.</p>
<p><strong>InstancedMesh.</strong> Una funcionalidad de Three.js que renderiza N copias de una misma geometría con una sola llamada de dibujo, cada una con una posición, rotación y escala diferentes. Las transformaciones de cada instancia se almacenan en un búfer de atributos matriciales. Así renderizamos 500 objetos en el Spike 1 sin realizar 500 llamadas de dibujo independientes. Para vegetación a gran escala, el descarte de instancias controlado por la GPU lleva este enfoque aún más lejos. Consulta nuestra <a href="/es/guides/landscape-generation-browser.html#gpu-driven-vegetation-culling">guía de paisajes sobre el descarte de vegetación mediante la GPU</a>.</p>
<p><strong>Presupuesto por fotograma.</strong> A 60 fps, cada fotograma dispone de <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.816ex;" xmlns="http://www.w3.org/2000/svg" width="13.598ex" height="2.773ex" role="img" focusable="false" viewBox="0 -864.9 6010.2 1225.5" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mfrac"><g data-mml-node="mrow" transform="translate(220,394) scale(0.707)"><g data-mml-node="mn"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" style="stroke-width: 3;"/><path data-c="30" d="M96 585Q152 666 249 666Q297 666 345 640T423 548Q460 465 460 320Q460 165 417 83Q397 41 362 16T301 -15T250 -22Q224 -22 198 -16T137 16T82 83Q39 165 39 320Q39 494 96 585ZM321 597Q291 629 250 629Q208 629 178 597Q153 571 145 525T137 333Q137 175 145 125T181 46Q209 16 250 16Q290 16 318 46Q347 76 354 130T362 333Q362 478 354 524T321 597Z" transform="translate(500,0)" style="stroke-width: 3;"/><path data-c="30" d="M96 585Q152 666 249 666Q297 666 345 640T423 548Q460 465 460 320Q460 165 417 83Q397 41 362 16T301 -15T250 -22Q224 -22 198 -16T137 16T82 83Q39 165 39 320Q39 494 96 585ZM321 597Q291 629 250 629Q208 629 178 597Q153 571 145 525T137 333Q137 175 145 125T181 46Q209 16 250 16Q290 16 318 46Q347 76 354 130T362 333Q362 478 354 524T321 597Z" transform="translate(1000,0)" style="stroke-width: 3;"/><path data-c="30" d="M96 585Q152 666 249 666Q297 666 345 640T423 548Q460 465 460 320Q460 165 417 83Q397 41 362 16T301 -15T250 -22Q224 -22 198 -16T137 16T82 83Q39 165 39 320Q39 494 96 585ZM321 597Q291 629 250 629Q208 629 178 597Q153 571 145 525T137 333Q137 175 145 125T181 46Q209 16 250 16Q290 16 318 46Q347 76 354 130T362 333Q362 478 354 524T321 597Z" transform="translate(1500,0)" style="stroke-width: 3;"/></g><g data-mml-node="mtext" transform="translate(2000,0)"><path data-c="A0" d="" style="stroke-width: 3;"/></g><g data-mml-node="mtext" transform="translate(2250,0)"><path data-c="6D" d="M41 46H55Q94 46 102 60V68Q102 77 102 91T102 122T103 161T103 203Q103 234 103 269T102 328V351Q99 370 88 376T43 385H25V408Q25 431 27 431L37 432Q47 433 65 434T102 436Q119 437 138 438T167 441T178 442H181V402Q181 364 182 364T187 369T199 384T218 402T247 421T285 437Q305 442 336 442Q351 442 364 440T387 434T406 426T421 417T432 406T441 395T448 384T452 374T455 366L457 361L460 365Q463 369 466 373T475 384T488 397T503 410T523 422T546 432T572 439T603 442Q729 442 740 329Q741 322 741 190V104Q741 66 743 59T754 49Q775 46 803 46H819V0H811L788 1Q764 2 737 2T699 3Q596 3 587 0H579V46H595Q656 46 656 62Q657 64 657 200Q656 335 655 343Q649 371 635 385T611 402T585 404Q540 404 506 370Q479 343 472 315T464 232V168V108Q464 78 465 68T468 55T477 49Q498 46 526 46H542V0H534L510 1Q487 2 460 2T422 3Q319 3 310 0H302V46H318Q379 46 379 62Q380 64 380 200Q379 335 378 343Q372 371 358 385T334 402T308 404Q263 404 229 370Q202 343 195 315T187 232V168V108Q187 78 188 68T191 55T200 49Q221 46 249 46H265V0H257L234 1Q210 2 183 2T145 3Q42 3 33 0H25V46H41Z" style="stroke-width: 3;"/><path data-c="73" d="M295 316Q295 356 268 385T190 414Q154 414 128 401Q98 382 98 349Q97 344 98 336T114 312T157 287Q175 282 201 278T245 269T277 256Q294 248 310 236T342 195T359 133Q359 71 321 31T198 -10H190Q138 -10 94 26L86 19L77 10Q71 4 65 -1L54 -11H46H42Q39 -11 33 -5V74V132Q33 153 35 157T45 162H54Q66 162 70 158T75 146T82 119T101 77Q136 26 198 26Q295 26 295 104Q295 133 277 151Q257 175 194 187T111 210Q75 227 54 256T33 318Q33 357 50 384T93 424T143 442T187 447H198Q238 447 268 432L283 424L292 431Q302 440 314 448H322H326Q329 448 335 442V310L329 304H301Q295 310 295 316Z" transform="translate(833,0)" style="stroke-width: 3;"/></g></g><g data-mml-node="mn" transform="translate(1095.8,-345) scale(0.707)"><path data-c="36" d="M42 313Q42 476 123 571T303 666Q372 666 402 630T432 550Q432 525 418 510T379 495Q356 495 341 509T326 548Q326 592 373 601Q351 623 311 626Q240 626 194 566Q147 500 147 364L148 360Q153 366 156 373Q197 433 263 433H267Q313 433 348 414Q372 400 396 374T435 317Q456 268 456 210V192Q456 169 451 149Q440 90 387 34T253 -22Q225 -22 199 -14T143 16T92 75T56 172T42 313ZM257 397Q227 397 205 380T171 335T154 278T148 216Q148 133 160 97T198 39Q222 21 251 21Q302 21 329 59Q342 77 347 104T352 209Q352 289 347 316T329 361Q302 397 257 397Z" style="stroke-width: 3;"/><path data-c="30" d="M96 585Q152 666 249 666Q297 666 345 640T423 548Q460 465 460 320Q460 165 417 83Q397 41 362 16T301 -15T250 -22Q224 -22 198 -16T137 16T82 83Q39 165 39 320Q39 494 96 585ZM321 597Q291 629 250 629Q208 629 178 597Q153 571 145 525T137 333Q137 175 145 125T181 46Q209 16 250 16Q290 16 318 46Q347 76 354 130T362 333Q362 478 354 524T321 597Z" transform="translate(500,0)" style="stroke-width: 3;"/></g><rect width="2658.6" height="60" x="120" y="220"/></g><g data-mml-node="mo" transform="translate(3176.4,0)"><path data-c="2248" d="M55 319Q55 360 72 393T114 444T163 472T205 482Q207 482 213 482T223 483Q262 483 296 468T393 413L443 381Q502 346 553 346Q609 346 649 375T694 454Q694 465 698 474T708 483Q722 483 722 452Q722 386 675 338T555 289Q514 289 468 310T388 357T308 404T224 426Q164 426 125 393T83 318Q81 289 69 289Q55 289 55 319ZM55 85Q55 126 72 159T114 210T163 238T205 248Q207 248 213 248T223 249Q262 249 296 234T393 179L443 147Q502 112 553 112Q609 112 649 141T694 220Q694 249 708 249T722 217Q722 153 675 104T555 55Q514 55 468 76T388 123T308 170T224 192Q164 192 125 159T83 84Q80 55 69 55Q55 55 55 85Z" style="stroke-width: 3;"/></g><g data-mml-node="mn" transform="translate(4232.2,0)"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" style="stroke-width: 3;"/><path data-c="36" d="M42 313Q42 476 123 571T303 666Q372 666 402 630T432 550Q432 525 418 510T379 495Q356 495 341 509T326 548Q326 592 373 601Q351 623 311 626Q240 626 194 566Q147 500 147 364L148 360Q153 366 156 373Q197 433 263 433H267Q313 433 348 414Q372 400 396 374T435 317Q456 268 456 210V192Q456 169 451 149Q440 90 387 34T253 -22Q225 -22 199 -14T143 16T92 75T56 172T42 313ZM257 397Q227 397 205 380T171 335T154 278T148 216Q148 133 160 97T198 39Q222 21 251 21Q302 21 329 59Q342 77 347 104T352 209Q352 289 347 316T329 361Q302 397 257 397Z" transform="translate(500,0)" style="stroke-width: 3;"/><path data-c="2E" d="M78 60Q78 84 95 102T138 120Q162 120 180 104T199 61Q199 36 182 18T139 0T96 17T78 60Z" transform="translate(1000,0)" style="stroke-width: 3;"/><path data-c="37" d="M55 458Q56 460 72 567L88 674Q88 676 108 676H128V672Q128 662 143 655T195 646T364 644H485V605L417 512Q408 500 387 472T360 435T339 403T319 367T305 330T292 284T284 230T278 162T275 80Q275 66 275 52T274 28V19Q270 2 255 -10T221 -22Q210 -22 200 -19T179 0T168 40Q168 198 265 368Q285 400 349 489L395 552H302Q128 552 119 546Q113 543 108 522T98 479L95 458V455H55V458Z" transform="translate(1278,0)" style="stroke-width: 3;"/></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mfrac><mrow><mn>1000</mn><mtext> </mtext><mtext>ms</mtext></mrow><mn>60</mn></mfrac><mo>≈</mo><mn>16.7</mn></math></mjx-assistive-mml></mjx-container> ms para todo: lógica de JavaScript, física, renderizado y composición. Un spike de «comprobación de presupuesto» mide cuánto consume una escena de referencia, de modo que el margen restante para todo lo que se añada después sea <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.357ex;" xmlns="http://www.w3.org/2000/svg" width="22.813ex" height="1.886ex" role="img" focusable="false" viewBox="0 -676 10083.4 833.8" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="msub"><g data-mml-node="mi"><path data-c="1D461" d="M26 385Q19 392 19 395Q19 399 22 411T27 425Q29 430 36 430T87 431H140L159 511Q162 522 166 540T173 566T179 586T187 603T197 615T211 624T229 626Q247 625 254 615T261 596Q261 589 252 549T232 470L222 433Q222 431 272 431H323Q330 424 330 420Q330 398 317 385H210L174 240Q135 80 135 68Q135 26 162 26Q197 26 230 60T283 144Q285 150 288 151T303 153H307Q322 153 322 145Q322 142 319 133Q314 117 301 95T267 48T216 6T155 -11Q125 -11 98 4T59 56Q57 64 57 83V101L92 241Q127 382 128 383Q128 385 77 385H26Z" style="stroke-width: 3;"/></g><g data-mml-node="mtext" transform="translate(394,-150) scale(0.707)"><path data-c="66" d="M273 0Q255 3 146 3Q43 3 34 0H26V46H42Q70 46 91 49Q99 52 103 60Q104 62 104 224V385H33V431H104V497L105 564L107 574Q126 639 171 668T266 704Q267 704 275 704T289 705Q330 702 351 679T372 627Q372 604 358 590T321 576T284 590T270 627Q270 647 288 667H284Q280 668 273 668Q245 668 223 647T189 592Q183 572 182 497V431H293V385H185V225Q185 63 186 61T189 57T194 54T199 51T206 49T213 48T222 47T231 47T241 46T251 46H282V0H273Z" style="stroke-width: 3;"/><path data-c="65" d="M28 218Q28 273 48 318T98 391T163 433T229 448Q282 448 320 430T378 380T406 316T415 245Q415 238 408 231H126V216Q126 68 226 36Q246 30 270 30Q312 30 342 62Q359 79 369 104L379 128Q382 131 395 131H398Q415 131 415 121Q415 117 412 108Q393 53 349 21T250 -11Q155 -11 92 58T28 218ZM333 275Q322 403 238 411H236Q228 411 220 410T195 402T166 381T143 340T127 274V267H333V275Z" transform="translate(306,0)" style="stroke-width: 3;"/><path data-c="61" d="M137 305T115 305T78 320T63 359Q63 394 97 421T218 448Q291 448 336 416T396 340Q401 326 401 309T402 194V124Q402 76 407 58T428 40Q443 40 448 56T453 109V145H493V106Q492 66 490 59Q481 29 455 12T400 -6T353 12T329 54V58L327 55Q325 52 322 49T314 40T302 29T287 17T269 6T247 -2T221 -8T190 -11Q130 -11 82 20T34 107Q34 128 41 147T68 188T116 225T194 253T304 268H318V290Q318 324 312 340Q290 411 215 411Q197 411 181 410T156 406T148 403Q170 388 170 359Q170 334 154 320ZM126 106Q126 75 150 51T209 26Q247 26 276 49T315 109Q317 116 318 175Q318 233 317 233Q309 233 296 232T251 223T193 203T147 166T126 106Z" transform="translate(750,0)" style="stroke-width: 3;"/><path data-c="74" d="M27 422Q80 426 109 478T141 600V615H181V431H316V385H181V241Q182 116 182 100T189 68Q203 29 238 29Q282 29 292 100Q293 108 293 146V181H333V146V134Q333 57 291 17Q264 -10 221 -10Q187 -10 162 2T124 33T105 68T98 100Q97 107 97 248V385H18V422H27Z" transform="translate(1250,0)" style="stroke-width: 3;"/><path data-c="75" d="M383 58Q327 -10 256 -10H249Q124 -10 105 89Q104 96 103 226Q102 335 102 348T96 369Q86 385 36 385H25V408Q25 431 27 431L38 432Q48 433 67 434T105 436Q122 437 142 438T172 441T184 442H187V261Q188 77 190 64Q193 49 204 40Q224 26 264 26Q290 26 311 35T343 58T363 90T375 120T379 144Q379 145 379 161T380 201T380 248V315Q380 361 370 372T320 385H302V431Q304 431 378 436T457 442H464V264Q464 84 465 81Q468 61 479 55T524 46H542V0Q540 0 467 -5T390 -11H383V58Z" transform="translate(1639,0)" style="stroke-width: 3;"/><path data-c="72" d="M36 46H50Q89 46 97 60V68Q97 77 97 91T98 122T98 161T98 203Q98 234 98 269T98 328L97 351Q94 370 83 376T38 385H20V408Q20 431 22 431L32 432Q42 433 60 434T96 436Q112 437 131 438T160 441T171 442H174V373Q213 441 271 441H277Q322 441 343 419T364 373Q364 352 351 337T313 322Q288 322 276 338T263 372Q263 381 265 388T270 400T273 405Q271 407 250 401Q234 393 226 386Q179 341 179 207V154Q179 141 179 127T179 101T180 81T180 66V61Q181 59 183 57T188 54T193 51T200 49T207 48T216 47T225 47T235 46T245 46H276V0H267Q249 3 140 3Q37 3 28 0H20V46H36Z" transform="translate(2195,0)" style="stroke-width: 3;"/><path data-c="65" d="M28 218Q28 273 48 318T98 391T163 433T229 448Q282 448 320 430T378 380T406 316T415 245Q415 238 408 231H126V216Q126 68 226 36Q246 30 270 30Q312 30 342 62Q359 79 369 104L379 128Q382 131 395 131H398Q415 131 415 121Q415 117 412 108Q393 53 349 21T250 -11Q155 -11 92 58T28 218ZM333 275Q322 403 238 411H236Q228 411 220 410T195 402T166 381T143 340T127 274V267H333V275Z" transform="translate(2587,0)" style="stroke-width: 3;"/><path data-c="73" d="M295 316Q295 356 268 385T190 414Q154 414 128 401Q98 382 98 349Q97 344 98 336T114 312T157 287Q175 282 201 278T245 269T277 256Q294 248 310 236T342 195T359 133Q359 71 321 31T198 -10H190Q138 -10 94 26L86 19L77 10Q71 4 65 -1L54 -11H46H42Q39 -11 33 -5V74V132Q33 153 35 157T45 162H54Q66 162 70 158T75 146T82 119T101 77Q136 26 198 26Q295 26 295 104Q295 133 277 151Q257 175 194 187T111 210Q75 227 54 256T33 318Q33 357 50 384T93 424T143 442T187 447H198Q238 447 268 432L283 424L292 431Q302 440 314 448H322H326Q329 448 335 442V310L329 304H301Q295 310 295 316Z" transform="translate(3031,0)" style="stroke-width: 3;"/></g></g><g data-mml-node="mo" transform="translate(3143.6,0)"><path data-c="3D" d="M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z" style="stroke-width: 3;"/></g><g data-mml-node="mn" transform="translate(4199.4,0)"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" style="stroke-width: 3;"/><path data-c="36" d="M42 313Q42 476 123 571T303 666Q372 666 402 630T432 550Q432 525 418 510T379 495Q356 495 341 509T326 548Q326 592 373 601Q351 623 311 626Q240 626 194 566Q147 500 147 364L148 360Q153 366 156 373Q197 433 263 433H267Q313 433 348 414Q372 400 396 374T435 317Q456 268 456 210V192Q456 169 451 149Q440 90 387 34T253 -22Q225 -22 199 -14T143 16T92 75T56 172T42 313ZM257 397Q227 397 205 380T171 335T154 278T148 216Q148 133 160 97T198 39Q222 21 251 21Q302 21 329 59Q342 77 347 104T352 209Q352 289 347 316T329 361Q302 397 257 397Z" transform="translate(500,0)" style="stroke-width: 3;"/><path data-c="2E" d="M78 60Q78 84 95 102T138 120Q162 120 180 104T199 61Q199 36 182 18T139 0T96 17T78 60Z" transform="translate(1000,0)" style="stroke-width: 3;"/><path data-c="37" d="M55 458Q56 460 72 567L88 674Q88 676 108 676H128V672Q128 662 143 655T195 646T364 644H485V605L417 512Q408 500 387 472T360 435T339 403T319 367T305 330T292 284T284 230T278 162T275 80Q275 66 275 52T274 28V19Q270 2 255 -10T221 -22Q210 -22 200 -19T179 0T168 40Q168 198 265 368Q285 400 349 489L395 552H302Q128 552 119 546Q113 543 108 522T98 479L95 458V455H55V458Z" transform="translate(1278,0)" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(6199.6,0)"><path data-c="2212" d="M84 237T84 250T98 270H679Q694 262 694 250T679 230H98Q84 237 84 250Z" style="stroke-width: 3;"/></g><g data-mml-node="msub" transform="translate(7199.8,0)"><g data-mml-node="mi"><path data-c="1D461" d="M26 385Q19 392 19 395Q19 399 22 411T27 425Q29 430 36 430T87 431H140L159 511Q162 522 166 540T173 566T179 586T187 603T197 615T211 624T229 626Q247 625 254 615T261 596Q261 589 252 549T232 470L222 433Q222 431 272 431H323Q330 424 330 420Q330 398 317 385H210L174 240Q135 80 135 68Q135 26 162 26Q197 26 230 60T283 144Q285 150 288 151T303 153H307Q322 153 322 145Q322 142 319 133Q314 117 301 95T267 48T216 6T155 -11Q125 -11 98 4T59 56Q57 64 57 83V101L92 241Q127 382 128 383Q128 385 77 385H26Z" style="stroke-width: 3;"/></g><g data-mml-node="mtext" transform="translate(394,-150) scale(0.707)"><path data-c="62" d="M307 -11Q234 -11 168 55L158 37Q156 34 153 28T147 17T143 10L138 1L118 0H98V298Q98 599 97 603Q94 622 83 628T38 637H20V660Q20 683 22 683L32 684Q42 685 61 686T98 688Q115 689 135 690T165 693T176 694H179V543Q179 391 180 391L183 394Q186 397 192 401T207 411T228 421T254 431T286 439T323 442Q401 442 461 379T522 216Q522 115 458 52T307 -11ZM182 98Q182 97 187 90T196 79T206 67T218 55T233 44T250 35T271 29T295 26Q330 26 363 46T412 113Q424 148 424 212Q424 287 412 323Q385 405 300 405Q270 405 239 390T188 347L182 339V98Z" style="stroke-width: 3;"/><path data-c="61" d="M137 305T115 305T78 320T63 359Q63 394 97 421T218 448Q291 448 336 416T396 340Q401 326 401 309T402 194V124Q402 76 407 58T428 40Q443 40 448 56T453 109V145H493V106Q492 66 490 59Q481 29 455 12T400 -6T353 12T329 54V58L327 55Q325 52 322 49T314 40T302 29T287 17T269 6T247 -2T221 -8T190 -11Q130 -11 82 20T34 107Q34 128 41 147T68 188T116 225T194 253T304 268H318V290Q318 324 312 340Q290 411 215 411Q197 411 181 410T156 406T148 403Q170 388 170 359Q170 334 154 320ZM126 106Q126 75 150 51T209 26Q247 26 276 49T315 109Q317 116 318 175Q318 233 317 233Q309 233 296 232T251 223T193 203T147 166T126 106Z" transform="translate(556,0)" style="stroke-width: 3;"/><path data-c="73" d="M295 316Q295 356 268 385T190 414Q154 414 128 401Q98 382 98 349Q97 344 98 336T114 312T157 287Q175 282 201 278T245 269T277 256Q294 248 310 236T342 195T359 133Q359 71 321 31T198 -10H190Q138 -10 94 26L86 19L77 10Q71 4 65 -1L54 -11H46H42Q39 -11 33 -5V74V132Q33 153 35 157T45 162H54Q66 162 70 158T75 146T82 119T101 77Q136 26 198 26Q295 26 295 104Q295 133 277 151Q257 175 194 187T111 210Q75 227 54 256T33 318Q33 357 50 384T93 424T143 442T187 447H198Q238 447 268 432L283 424L292 431Q302 440 314 448H322H326Q329 448 335 442V310L329 304H301Q295 310 295 316Z" transform="translate(1056,0)" style="stroke-width: 3;"/><path data-c="65" d="M28 218Q28 273 48 318T98 391T163 433T229 448Q282 448 320 430T378 380T406 316T415 245Q415 238 408 231H126V216Q126 68 226 36Q246 30 270 30Q312 30 342 62Q359 79 369 104L379 128Q382 131 395 131H398Q415 131 415 121Q415 117 412 108Q393 53 349 21T250 -11Q155 -11 92 58T28 218ZM333 275Q322 403 238 411H236Q228 411 220 410T195 402T166 381T143 340T127 274V267H333V275Z" transform="translate(1450,0)" style="stroke-width: 3;"/><path data-c="6C" d="M42 46H56Q95 46 103 60V68Q103 77 103 91T103 124T104 167T104 217T104 272T104 329Q104 366 104 407T104 482T104 542T103 586T103 603Q100 622 89 628T44 637H26V660Q26 683 28 683L38 684Q48 685 67 686T104 688Q121 689 141 690T171 693T182 694H185V379Q185 62 186 60Q190 52 198 49Q219 46 247 46H263V0H255L232 1Q209 2 183 2T145 3T107 3T57 1L34 0H26V46H42Z" transform="translate(1894,0)" style="stroke-width: 3;"/><path data-c="69" d="M69 609Q69 637 87 653T131 669Q154 667 171 652T188 609Q188 579 171 564T129 549Q104 549 87 564T69 609ZM247 0Q232 3 143 3Q132 3 106 3T56 1L34 0H26V46H42Q70 46 91 49Q100 53 102 60T104 102V205V293Q104 345 102 359T88 378Q74 385 41 385H30V408Q30 431 32 431L42 432Q52 433 70 434T106 436Q123 437 142 438T171 441T182 442H185V62Q190 52 197 50T232 46H255V0H247Z" transform="translate(2172,0)" style="stroke-width: 3;"/><path data-c="6E" d="M41 46H55Q94 46 102 60V68Q102 77 102 91T102 122T103 161T103 203Q103 234 103 269T102 328V351Q99 370 88 376T43 385H25V408Q25 431 27 431L37 432Q47 433 65 434T102 436Q119 437 138 438T167 441T178 442H181V402Q181 364 182 364T187 369T199 384T218 402T247 421T285 437Q305 442 336 442Q450 438 463 329Q464 322 464 190V104Q464 66 466 59T477 49Q498 46 526 46H542V0H534L510 1Q487 2 460 2T422 3Q319 3 310 0H302V46H318Q379 46 379 62Q380 64 380 200Q379 335 378 343Q372 371 358 385T334 402T308 404Q263 404 229 370Q202 343 195 315T187 232V168V108Q187 78 188 68T191 55T200 49Q221 46 249 46H265V0H257L234 1Q210 2 183 2T145 3Q42 3 33 0H25V46H41Z" transform="translate(2450,0)" style="stroke-width: 3;"/><path data-c="65" d="M28 218Q28 273 48 318T98 391T163 433T229 448Q282 448 320 430T378 380T406 316T415 245Q415 238 408 231H126V216Q126 68 226 36Q246 30 270 30Q312 30 342 62Q359 79 369 104L379 128Q382 131 395 131H398Q415 131 415 121Q415 117 412 108Q393 53 349 21T250 -11Q155 -11 92 58T28 218ZM333 275Q322 403 238 411H236Q228 411 220 410T195 402T166 381T143 340T127 274V267H333V275Z" transform="translate(3006,0)" style="stroke-width: 3;"/></g></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><msub><mi>t</mi><mtext>features</mtext></msub><mo>=</mo><mn>16.7</mn><mo>−</mo><msub><mi>t</mi><mtext>baseline</mtext></msub></math></mjx-assistive-mml></mjx-container>. Si la escena de referencia ya consume 12 ms, solo quedan unos 4,7 ms para la jugabilidad, la física y la red en conjunto. Este enfoque procede del desarrollo de mundos abiertos AAA, donde <a href="/es/guides/browser-3d-open-world-tech.html#what-we-can-learn-from-skyrim-and-the-witcher">GTA V, Skyrim y Elden Ring</a> emplean técnicas agresivas de LOD y streaming para mantenerse dentro de presupuestos por fotograma fijos.</p>
<hr>
<p>Parte 1 de 12.<br>
Siguiente: <a href="/es/blog/2026-02-25-open-world-browser-part-02-worker-physics.html">Parte 2: Física en un worker y el temor al retardo de entrada</a><br>
Guía de la serie: <a href="/es/blog/2026-02-25-open-world-browser-series-guide.html">/es/blog/2026-02-25-open-world-browser-series-guide</a></p>
]]></content:encoded>
            <enclosure url="https://cdn.cinevva.com/blog/why-webgpu-engine-hero.jpg" length="0" type="image/jpg"/>
        </item>
        <item>
            <title><![CDATA[Cómo crear un mundo abierto en el navegador, parte 2: físicas en un Worker y el temor al retardo de entrada]]></title>
            <link>https://app.cinevva.com/es/blog/2026-02-25-open-world-browser-part-02-worker-physics</link>
            <guid>https://app.cinevva.com/es/blog/2026-02-25-open-world-browser-part-02-worker-physics</guid>
            <pubDate>Wed, 25 Feb 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Trasladamos Rapier a un Web Worker y medimos lo primero que preocupa a todo el mundo: ¿se percibe tarde el movimiento?]]></description>
            <content:encoded><![CDATA[<h1 id="como-crear-un-mundo-abierto-en-el-navegador-parte-2-fisicas-en-un-worker-y-el-temor-al-retardo-de-entrada" tabindex="-1">Cómo crear un mundo abierto en el navegador, parte 2: físicas en un Worker y el temor al retardo de entrada <a class="header-anchor" href="#como-crear-un-mundo-abierto-en-el-navegador-parte-2-fisicas-en-un-worker-y-el-temor-al-retardo-de-entrada" aria-label="Permalink to &quot;Cómo crear un mundo abierto en el navegador, parte 2: físicas en un Worker y el temor al retardo de entrada&quot;"></a></h1>
<p><em>Por <a href="/es/about.html">Oleg Sidorkin</a>, CTO y cofundador de Cinevva</em></p>
<p>¿Acabas de llegar? Consulta la <a href="/es/blog/2026-02-25-open-world-browser-series-guide.html">guía de la serie</a>. Explica qué es un spike y enlaza todas las partes.</p>
<p>Si desarrollas multijugador para navegador durante suficiente tiempo, tarde o temprano surge este debate.</p>
<p>«Ejecutar las físicas en un worker ofrece una arquitectura limpia. Ejecutarlas en el hilo principal parece más seguro».</p>
<p>Ambas afirmaciones pueden ser ciertas. Lo importante es cómo se sienten los controles y cuál es la latencia con entradas reales.</p>
<p>Creamos el Spike 2 para responder a esa cuestión con mediciones, no con opiniones.</p>
<div style="position:relative;padding-bottom:56.25%;height:0;overflow:hidden;border-radius:8px;margin:1.5rem 0;border:1px solid rgba(255,255,255,0.12)">
<iframe src="/es/spikes/02-rapier-worker/" title="Spike 2: Rapier en un Worker" style="position:absolute;top:0;left:0;width:100%;height:100%;border:0;background:#000" loading="lazy" allowfullscreen></iframe>
</div>
<p><a href="/es/spikes/02-rapier-worker/" target="_blank">Abrir el Spike 2 en una pestaña nueva ↗</a> · <a href="/es/blog/spike-source?spike=02-rapier-worker">Ver el código fuente</a></p>
<p>Reutilizamos el terreno del Spike 1 e integramos Rapier en un worker de módulo dedicado. Enviábamos el estado de entrada al worker en cada fotograma, ejecutábamos allí el paso de simulación y devolvíamos la posición autoritativa al renderizador.</p>
<p>Las métricas clave fueron la latencia entre la entrada y el movimiento visible, así como el tiempo de cada paso de físicas. También observamos si aparecían tirones durante el movimiento normal, las aceleraciones al esprintar y la cadencia de los saltos.</p>
<p>El resultado fue mejor de lo esperado. Con la estructura y la cadencia de nuestros mensajes, el límite entre hilos no fue el factor dominante de la latencia. Los controles seguían respondiendo de inmediato, que era lo único que les importaría a los jugadores.</p>
<p>Uno de los desafíos de esta fase fue el riesgo de interpretar mal los resultados. Tras un resultado satisfactorio, los equipos suelen generalizar en exceso y dar por zanjada para siempre la cuestión arquitectónica. No es así. Solo validamos un escenario concreto y un perfil de hardware. Los spikes posteriores aún debían volver a comprobar esas suposiciones cuando cambiara la carga sobre la GPU y el streaming.</p>
<p>Este spike también mejoró nuestro proceso. Empezamos a mostrar de forma predeterminada la telemetría de tiempos en el HUD de los spikes interactivos. Eso hizo que las conversaciones del equipo pasaran de «algo no se siente bien» a «esta ruta añadió 1,2 ms».</p>
<p>En la parte 3 abordamos los experimentos menos vistosos que evitaron costosas sorpresas más adelante: carga de difusión, limitaciones de los dispositivos móviles y fiabilidad de la generación de comportamientos.</p>
<h2 id="tecnologia-mencionada-en-este-capitulo" tabindex="-1">Tecnología mencionada en este capítulo <a class="header-anchor" href="#tecnologia-mencionada-en-este-capitulo" aria-label="Permalink to &quot;Tecnología mencionada en este capítulo&quot;"></a></h2>
<p><strong>Rapier.</strong> Un motor de físicas escrito en Rust que se compila a WebAssembly para utilizarse en el navegador. Gestiona cuerpos rígidos, colisionadores, articulaciones, controladores de personajes y lanzamiento de rayos con un rendimiento entre 2 y 3 veces superior al código nativo. Para los mundos abiertos, Rapier proporciona controladores para los personajes de los jugadores (caminar sobre el terreno, subir escalones y deslizarse por pendientes), colisiones de objetos, lanzamiento de rayos para las interacciones y volúmenes de activación. Consulta la <a href="https://rapier.rs/" target="_blank" rel="noreferrer">documentación de Rapier</a> y nuestra <a href="/es/guides/browser-3d-open-world-tech.html#rapier-rust-wasm">guía tecnológica de 3D para navegador sobre físicas</a>.</p>
<p><strong>Web Workers.</strong> Hilos del navegador que ejecutan JavaScript (o Wasm) fuera del hilo principal. Ejecutar la simulación de físicas en un worker significa que una llamada pesada a <code>world.step()</code> no bloquea el renderizado. El hilo principal envía el estado de entrada al worker en cada fotograma mediante <code>postMessage</code> y recibe a cambio las posiciones autoritativas. La penalización de latencia corresponde a los dos saltos de los mensajes (aproximadamente entre 0,1 y 0,5 ms cada uno en equipos de escritorio). La ventaja es que el hilo de renderizado nunca se bloquea al detectar colisiones. Los objetos transferibles (transferencia de <code>ArrayBuffer</code>) eliminan el coste de las copias para matrices de posiciones grandes.</p>
<p><strong>WebAssembly (Wasm).</strong> Un formato de instrucciones binarias que se ejecuta en los navegadores a una velocidad cercana a la nativa. Rapier, Havok y Recast se compilan a Wasm. En Rapier-Wasm, el paso de físicas suele tardar entre 0,5 y 2 ms para unos cientos de cuerpos, frente a los 5-15 ms de una implementación equivalente en JavaScript. Los módulos Wasm se cargan como archivos <code>.wasm</code> obtenidos junto con el código de enlace de JavaScript. Consulta la <a href="https://webassembly.org/" target="_blank" rel="noreferrer">especificación de WebAssembly</a>.</p>
<p><strong>Latencia entre la entrada y la imagen.</strong> El tiempo transcurrido entre una pulsación de tecla y el cambio visual resultante en pantalla. Para que el movimiento se perciba como «inmediato», debe mantenerse por debajo de unos 80 ms. En una configuración con las físicas ejecutándose en un worker, los tiempos de la cadena se suman:</p>
<mjx-container tabindex="0" class="MathJax" jax="SVG" display="true" style="direction: ltr; display: block; text-align: center; margin: 1em 0; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.669ex;" xmlns="http://www.w3.org/2000/svg" width="39.876ex" height="2.214ex" role="img" focusable="false" viewBox="0 -683 17625.4 978.7" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mi"><path data-c="1D43F" d="M228 637Q194 637 192 641Q191 643 191 649Q191 673 202 682Q204 683 217 683Q271 680 344 680Q485 680 506 683H518Q524 677 524 674T522 656Q517 641 513 637H475Q406 636 394 628Q387 624 380 600T313 336Q297 271 279 198T252 88L243 52Q243 48 252 48T311 46H328Q360 46 379 47T428 54T478 72T522 106T564 161Q580 191 594 228T611 270Q616 273 628 273H641Q647 264 647 262T627 203T583 83T557 9Q555 4 553 3T537 0T494 -1Q483 -1 418 -1T294 0H116Q32 0 32 10Q32 17 34 24Q39 43 44 45Q48 46 59 46H65Q92 46 125 49Q139 52 144 61Q147 65 216 339T285 628Q285 635 228 637Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(958.8,0)"><path data-c="3D" d="M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z" style="stroke-width: 3;"/></g><g data-mml-node="msub" transform="translate(2014.6,0)"><g data-mml-node="mi"><path data-c="1D461" d="M26 385Q19 392 19 395Q19 399 22 411T27 425Q29 430 36 430T87 431H140L159 511Q162 522 166 540T173 566T179 586T187 603T197 615T211 624T229 626Q247 625 254 615T261 596Q261 589 252 549T232 470L222 433Q222 431 272 431H323Q330 424 330 420Q330 398 317 385H210L174 240Q135 80 135 68Q135 26 162 26Q197 26 230 60T283 144Q285 150 288 151T303 153H307Q322 153 322 145Q322 142 319 133Q314 117 301 95T267 48T216 6T155 -11Q125 -11 98 4T59 56Q57 64 57 83V101L92 241Q127 382 128 383Q128 385 77 385H26Z" style="stroke-width: 3;"/></g><g data-mml-node="mtext" transform="translate(394,-150) scale(0.707)"><path data-c="69" d="M69 609Q69 637 87 653T131 669Q154 667 171 652T188 609Q188 579 171 564T129 549Q104 549 87 564T69 609ZM247 0Q232 3 143 3Q132 3 106 3T56 1L34 0H26V46H42Q70 46 91 49Q100 53 102 60T104 102V205V293Q104 345 102 359T88 378Q74 385 41 385H30V408Q30 431 32 431L42 432Q52 433 70 434T106 436Q123 437 142 438T171 441T182 442H185V62Q190 52 197 50T232 46H255V0H247Z" style="stroke-width: 3;"/><path data-c="6E" d="M41 46H55Q94 46 102 60V68Q102 77 102 91T102 122T103 161T103 203Q103 234 103 269T102 328V351Q99 370 88 376T43 385H25V408Q25 431 27 431L37 432Q47 433 65 434T102 436Q119 437 138 438T167 441T178 442H181V402Q181 364 182 364T187 369T199 384T218 402T247 421T285 437Q305 442 336 442Q450 438 463 329Q464 322 464 190V104Q464 66 466 59T477 49Q498 46 526 46H542V0H534L510 1Q487 2 460 2T422 3Q319 3 310 0H302V46H318Q379 46 379 62Q380 64 380 200Q379 335 378 343Q372 371 358 385T334 402T308 404Q263 404 229 370Q202 343 195 315T187 232V168V108Q187 78 188 68T191 55T200 49Q221 46 249 46H265V0H257L234 1Q210 2 183 2T145 3Q42 3 33 0H25V46H41Z" transform="translate(278,0)" style="stroke-width: 3;"/><path data-c="70" d="M36 -148H50Q89 -148 97 -134V-126Q97 -119 97 -107T97 -77T98 -38T98 6T98 55T98 106Q98 140 98 177T98 243T98 296T97 335T97 351Q94 370 83 376T38 385H20V408Q20 431 22 431L32 432Q42 433 61 434T98 436Q115 437 135 438T165 441T176 442H179V416L180 390L188 397Q247 441 326 441Q407 441 464 377T522 216Q522 115 457 52T310 -11Q242 -11 190 33L182 40V-45V-101Q182 -128 184 -134T195 -145Q216 -148 244 -148H260V-194H252L228 -193Q205 -192 178 -192T140 -191Q37 -191 28 -194H20V-148H36ZM424 218Q424 292 390 347T305 402Q234 402 182 337V98Q222 26 294 26Q345 26 384 80T424 218Z" transform="translate(834,0)" style="stroke-width: 3;"/><path data-c="75" d="M383 58Q327 -10 256 -10H249Q124 -10 105 89Q104 96 103 226Q102 335 102 348T96 369Q86 385 36 385H25V408Q25 431 27 431L38 432Q48 433 67 434T105 436Q122 437 142 438T172 441T184 442H187V261Q188 77 190 64Q193 49 204 40Q224 26 264 26Q290 26 311 35T343 58T363 90T375 120T379 144Q379 145 379 161T380 201T380 248V315Q380 361 370 372T320 385H302V431Q304 431 378 436T457 442H464V264Q464 84 465 81Q468 61 479 55T524 46H542V0Q540 0 467 -5T390 -11H383V58Z" transform="translate(1390,0)" style="stroke-width: 3;"/><path data-c="74" d="M27 422Q80 426 109 478T141 600V615H181V431H316V385H181V241Q182 116 182 100T189 68Q203 29 238 29Q282 29 292 100Q293 108 293 146V181H333V146V134Q333 57 291 17Q264 -10 221 -10Q187 -10 162 2T124 33T105 68T98 100Q97 107 97 248V385H18V422H27Z" transform="translate(1946,0)" style="stroke-width: 3;"/></g></g><g data-mml-node="mo" transform="translate(4331.9,0)"><path data-c="2B" d="M56 237T56 250T70 270H369V420L370 570Q380 583 389 583Q402 583 409 568V270H707Q722 262 722 250T707 230H409V-68Q401 -82 391 -82H389H387Q375 -82 369 -68V230H70Q56 237 56 250Z" style="stroke-width: 3;"/></g><g data-mml-node="mn" transform="translate(5332.1,0)"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"/></g><g data-mml-node="mstyle" transform="translate(5832.1,0)"><g data-mml-node="mspace"/></g><g data-mml-node="msub" transform="translate(5999.1,0)"><g data-mml-node="mi"><path data-c="1D461" d="M26 385Q19 392 19 395Q19 399 22 411T27 425Q29 430 36 430T87 431H140L159 511Q162 522 166 540T173 566T179 586T187 603T197 615T211 624T229 626Q247 625 254 615T261 596Q261 589 252 549T232 470L222 433Q222 431 272 431H323Q330 424 330 420Q330 398 317 385H210L174 240Q135 80 135 68Q135 26 162 26Q197 26 230 60T283 144Q285 150 288 151T303 153H307Q322 153 322 145Q322 142 319 133Q314 117 301 95T267 48T216 6T155 -11Q125 -11 98 4T59 56Q57 64 57 83V101L92 241Q127 382 128 383Q128 385 77 385H26Z" style="stroke-width: 3;"/></g><g data-mml-node="mtext" transform="translate(394,-150) scale(0.707)"><path data-c="6D" d="M41 46H55Q94 46 102 60V68Q102 77 102 91T102 122T103 161T103 203Q103 234 103 269T102 328V351Q99 370 88 376T43 385H25V408Q25 431 27 431L37 432Q47 433 65 434T102 436Q119 437 138 438T167 441T178 442H181V402Q181 364 182 364T187 369T199 384T218 402T247 421T285 437Q305 442 336 442Q351 442 364 440T387 434T406 426T421 417T432 406T441 395T448 384T452 374T455 366L457 361L460 365Q463 369 466 373T475 384T488 397T503 410T523 422T546 432T572 439T603 442Q729 442 740 329Q741 322 741 190V104Q741 66 743 59T754 49Q775 46 803 46H819V0H811L788 1Q764 2 737 2T699 3Q596 3 587 0H579V46H595Q656 46 656 62Q657 64 657 200Q656 335 655 343Q649 371 635 385T611 402T585 404Q540 404 506 370Q479 343 472 315T464 232V168V108Q464 78 465 68T468 55T477 49Q498 46 526 46H542V0H534L510 1Q487 2 460 2T422 3Q319 3 310 0H302V46H318Q379 46 379 62Q380 64 380 200Q379 335 378 343Q372 371 358 385T334 402T308 404Q263 404 229 370Q202 343 195 315T187 232V168V108Q187 78 188 68T191 55T200 49Q221 46 249 46H265V0H257L234 1Q210 2 183 2T145 3Q42 3 33 0H25V46H41Z" style="stroke-width: 3;"/><path data-c="73" d="M295 316Q295 356 268 385T190 414Q154 414 128 401Q98 382 98 349Q97 344 98 336T114 312T157 287Q175 282 201 278T245 269T277 256Q294 248 310 236T342 195T359 133Q359 71 321 31T198 -10H190Q138 -10 94 26L86 19L77 10Q71 4 65 -1L54 -11H46H42Q39 -11 33 -5V74V132Q33 153 35 157T45 162H54Q66 162 70 158T75 146T82 119T101 77Q136 26 198 26Q295 26 295 104Q295 133 277 151Q257 175 194 187T111 210Q75 227 54 256T33 318Q33 357 50 384T93 424T143 442T187 447H198Q238 447 268 432L283 424L292 431Q302 440 314 448H322H326Q329 448 335 442V310L329 304H301Q295 310 295 316Z" transform="translate(833,0)" style="stroke-width: 3;"/><path data-c="67" d="M329 409Q373 453 429 453Q459 453 472 434T485 396Q485 382 476 371T449 360Q416 360 412 390Q410 404 415 411Q415 412 416 414V415Q388 412 363 393Q355 388 355 386Q355 385 359 381T368 369T379 351T388 325T392 292Q392 230 343 187T222 143Q172 143 123 171Q112 153 112 133Q112 98 138 81Q147 75 155 75T227 73Q311 72 335 67Q396 58 431 26Q470 -13 470 -72Q470 -139 392 -175Q332 -206 250 -206Q167 -206 107 -175Q29 -140 29 -75Q29 -39 50 -15T92 18L103 24Q67 55 67 108Q67 155 96 193Q52 237 52 292Q52 355 102 398T223 442Q274 442 318 416L329 409ZM299 343Q294 371 273 387T221 404Q192 404 171 388T145 343Q142 326 142 292Q142 248 149 227T179 192Q196 182 222 182Q244 182 260 189T283 207T294 227T299 242Q302 258 302 292T299 343ZM403 -75Q403 -50 389 -34T348 -11T299 -2T245 0H218Q151 0 138 -6Q118 -15 107 -34T95 -74Q95 -84 101 -97T122 -127T170 -155T250 -167Q319 -167 361 -139T403 -75Z" transform="translate(1227,0)" style="stroke-width: 3;"/></g></g><g data-mml-node="mo" transform="translate(7886.5,0)"><path data-c="2B" d="M56 237T56 250T70 270H369V420L370 570Q380 583 389 583Q402 583 409 568V270H707Q722 262 722 250T707 230H409V-68Q401 -82 391 -82H389H387Q375 -82 369 -68V230H70Q56 237 56 250Z" style="stroke-width: 3;"/></g><g data-mml-node="msub" transform="translate(8886.7,0)"><g data-mml-node="mi"><path data-c="1D461" d="M26 385Q19 392 19 395Q19 399 22 411T27 425Q29 430 36 430T87 431H140L159 511Q162 522 166 540T173 566T179 586T187 603T197 615T211 624T229 626Q247 625 254 615T261 596Q261 589 252 549T232 470L222 433Q222 431 272 431H323Q330 424 330 420Q330 398 317 385H210L174 240Q135 80 135 68Q135 26 162 26Q197 26 230 60T283 144Q285 150 288 151T303 153H307Q322 153 322 145Q322 142 319 133Q314 117 301 95T267 48T216 6T155 -11Q125 -11 98 4T59 56Q57 64 57 83V101L92 241Q127 382 128 383Q128 385 77 385H26Z" style="stroke-width: 3;"/></g><g data-mml-node="mtext" transform="translate(394,-150) scale(0.707)"><path data-c="73" d="M295 316Q295 356 268 385T190 414Q154 414 128 401Q98 382 98 349Q97 344 98 336T114 312T157 287Q175 282 201 278T245 269T277 256Q294 248 310 236T342 195T359 133Q359 71 321 31T198 -10H190Q138 -10 94 26L86 19L77 10Q71 4 65 -1L54 -11H46H42Q39 -11 33 -5V74V132Q33 153 35 157T45 162H54Q66 162 70 158T75 146T82 119T101 77Q136 26 198 26Q295 26 295 104Q295 133 277 151Q257 175 194 187T111 210Q75 227 54 256T33 318Q33 357 50 384T93 424T143 442T187 447H198Q238 447 268 432L283 424L292 431Q302 440 314 448H322H326Q329 448 335 442V310L329 304H301Q295 310 295 316Z" style="stroke-width: 3;"/><path data-c="74" d="M27 422Q80 426 109 478T141 600V615H181V431H316V385H181V241Q182 116 182 100T189 68Q203 29 238 29Q282 29 292 100Q293 108 293 146V181H333V146V134Q333 57 291 17Q264 -10 221 -10Q187 -10 162 2T124 33T105 68T98 100Q97 107 97 248V385H18V422H27Z" transform="translate(394,0)" style="stroke-width: 3;"/><path data-c="65" d="M28 218Q28 273 48 318T98 391T163 433T229 448Q282 448 320 430T378 380T406 316T415 245Q415 238 408 231H126V216Q126 68 226 36Q246 30 270 30Q312 30 342 62Q359 79 369 104L379 128Q382 131 395 131H398Q415 131 415 121Q415 117 412 108Q393 53 349 21T250 -11Q155 -11 92 58T28 218ZM333 275Q322 403 238 411H236Q228 411 220 410T195 402T166 381T143 340T127 274V267H333V275Z" transform="translate(783,0)" style="stroke-width: 3;"/><path data-c="70" d="M36 -148H50Q89 -148 97 -134V-126Q97 -119 97 -107T97 -77T98 -38T98 6T98 55T98 106Q98 140 98 177T98 243T98 296T97 335T97 351Q94 370 83 376T38 385H20V408Q20 431 22 431L32 432Q42 433 61 434T98 436Q115 437 135 438T165 441T176 442H179V416L180 390L188 397Q247 441 326 441Q407 441 464 377T522 216Q522 115 457 52T310 -11Q242 -11 190 33L182 40V-45V-101Q182 -128 184 -134T195 -145Q216 -148 244 -148H260V-194H252L228 -193Q205 -192 178 -192T140 -191Q37 -191 28 -194H20V-148H36ZM424 218Q424 292 390 347T305 402Q234 402 182 337V98Q222 26 294 26Q345 26 384 80T424 218Z" transform="translate(1227,0)" style="stroke-width: 3;"/></g></g><g data-mml-node="mo" transform="translate(10813.7,0)"><path data-c="2B" d="M56 237T56 250T70 270H369V420L370 570Q380 583 389 583Q402 583 409 568V270H707Q722 262 722 250T707 230H409V-68Q401 -82 391 -82H389H387Q375 -82 369 -68V230H70Q56 237 56 250Z" style="stroke-width: 3;"/></g><g data-mml-node="msub" transform="translate(11813.9,0)"><g data-mml-node="mi"><path data-c="1D461" d="M26 385Q19 392 19 395Q19 399 22 411T27 425Q29 430 36 430T87 431H140L159 511Q162 522 166 540T173 566T179 586T187 603T197 615T211 624T229 626Q247 625 254 615T261 596Q261 589 252 549T232 470L222 433Q222 431 272 431H323Q330 424 330 420Q330 398 317 385H210L174 240Q135 80 135 68Q135 26 162 26Q197 26 230 60T283 144Q285 150 288 151T303 153H307Q322 153 322 145Q322 142 319 133Q314 117 301 95T267 48T216 6T155 -11Q125 -11 98 4T59 56Q57 64 57 83V101L92 241Q127 382 128 383Q128 385 77 385H26Z" style="stroke-width: 3;"/></g><g data-mml-node="mtext" transform="translate(394,-150) scale(0.707)"><path data-c="72" d="M36 46H50Q89 46 97 60V68Q97 77 97 91T98 122T98 161T98 203Q98 234 98 269T98 328L97 351Q94 370 83 376T38 385H20V408Q20 431 22 431L32 432Q42 433 60 434T96 436Q112 437 131 438T160 441T171 442H174V373Q213 441 271 441H277Q322 441 343 419T364 373Q364 352 351 337T313 322Q288 322 276 338T263 372Q263 381 265 388T270 400T273 405Q271 407 250 401Q234 393 226 386Q179 341 179 207V154Q179 141 179 127T179 101T180 81T180 66V61Q181 59 183 57T188 54T193 51T200 49T207 48T216 47T225 47T235 46T245 46H276V0H267Q249 3 140 3Q37 3 28 0H20V46H36Z" style="stroke-width: 3;"/><path data-c="65" d="M28 218Q28 273 48 318T98 391T163 433T229 448Q282 448 320 430T378 380T406 316T415 245Q415 238 408 231H126V216Q126 68 226 36Q246 30 270 30Q312 30 342 62Q359 79 369 104L379 128Q382 131 395 131H398Q415 131 415 121Q415 117 412 108Q393 53 349 21T250 -11Q155 -11 92 58T28 218ZM333 275Q322 403 238 411H236Q228 411 220 410T195 402T166 381T143 340T127 274V267H333V275Z" transform="translate(392,0)" style="stroke-width: 3;"/><path data-c="6E" d="M41 46H55Q94 46 102 60V68Q102 77 102 91T102 122T103 161T103 203Q103 234 103 269T102 328V351Q99 370 88 376T43 385H25V408Q25 431 27 431L37 432Q47 433 65 434T102 436Q119 437 138 438T167 441T178 442H181V402Q181 364 182 364T187 369T199 384T218 402T247 421T285 437Q305 442 336 442Q450 438 463 329Q464 322 464 190V104Q464 66 466 59T477 49Q498 46 526 46H542V0H534L510 1Q487 2 460 2T422 3Q319 3 310 0H302V46H318Q379 46 379 62Q380 64 380 200Q379 335 378 343Q372 371 358 385T334 402T308 404Q263 404 229 370Q202 343 195 315T187 232V168V108Q187 78 188 68T191 55T200 49Q221 46 249 46H265V0H257L234 1Q210 2 183 2T145 3Q42 3 33 0H25V46H41Z" transform="translate(836,0)" style="stroke-width: 3;"/><path data-c="64" d="M376 495Q376 511 376 535T377 568Q377 613 367 624T316 637H298V660Q298 683 300 683L310 684Q320 685 339 686T376 688Q393 689 413 690T443 693T454 694H457V390Q457 84 458 81Q461 61 472 55T517 46H535V0Q533 0 459 -5T380 -11H373V44L365 37Q307 -11 235 -11Q158 -11 96 50T34 215Q34 315 97 378T244 442Q319 442 376 393V495ZM373 342Q328 405 260 405Q211 405 173 369Q146 341 139 305T131 211Q131 155 138 120T173 59Q203 26 251 26Q322 26 373 103V342Z" transform="translate(1392,0)" style="stroke-width: 3;"/><path data-c="65" d="M28 218Q28 273 48 318T98 391T163 433T229 448Q282 448 320 430T378 380T406 316T415 245Q415 238 408 231H126V216Q126 68 226 36Q246 30 270 30Q312 30 342 62Q359 79 369 104L379 128Q382 131 395 131H398Q415 131 415 121Q415 117 412 108Q393 53 349 21T250 -11Q155 -11 92 58T28 218ZM333 275Q322 403 238 411H236Q228 411 220 410T195 402T166 381T143 340T127 274V267H333V275Z" transform="translate(1948,0)" style="stroke-width: 3;"/><path data-c="72" d="M36 46H50Q89 46 97 60V68Q97 77 97 91T98 122T98 161T98 203Q98 234 98 269T98 328L97 351Q94 370 83 376T38 385H20V408Q20 431 22 431L32 432Q42 433 60 434T96 436Q112 437 131 438T160 441T171 442H174V373Q213 441 271 441H277Q322 441 343 419T364 373Q364 352 351 337T313 322Q288 322 276 338T263 372Q263 381 265 388T270 400T273 405Q271 407 250 401Q234 393 226 386Q179 341 179 207V154Q179 141 179 127T179 101T180 81T180 66V61Q181 59 183 57T188 54T193 51T200 49T207 48T216 47T225 47T235 46T245 46H276V0H267Q249 3 140 3Q37 3 28 0H20V46H36Z" transform="translate(2392,0)" style="stroke-width: 3;"/></g></g><g data-mml-node="mo" transform="translate(14448.7,0)"><path data-c="2B" d="M56 237T56 250T70 270H369V420L370 570Q380 583 389 583Q402 583 409 568V270H707Q722 262 722 250T707 230H409V-68Q401 -82 391 -82H389H387Q375 -82 369 -68V230H70Q56 237 56 250Z" style="stroke-width: 3;"/></g><g data-mml-node="msub" transform="translate(15449,0)"><g data-mml-node="mi"><path data-c="1D461" d="M26 385Q19 392 19 395Q19 399 22 411T27 425Q29 430 36 430T87 431H140L159 511Q162 522 166 540T173 566T179 586T187 603T197 615T211 624T229 626Q247 625 254 615T261 596Q261 589 252 549T232 470L222 433Q222 431 272 431H323Q330 424 330 420Q330 398 317 385H210L174 240Q135 80 135 68Q135 26 162 26Q197 26 230 60T283 144Q285 150 288 151T303 153H307Q322 153 322 145Q322 142 319 133Q314 117 301 95T267 48T216 6T155 -11Q125 -11 98 4T59 56Q57 64 57 83V101L92 241Q127 382 128 383Q128 385 77 385H26Z" style="stroke-width: 3;"/></g><g data-mml-node="mtext" transform="translate(394,-150) scale(0.707)"><path data-c="76" d="M338 431Q344 429 422 429Q479 429 503 431H508V385H497Q439 381 423 345Q421 341 356 172T288 -2Q283 -11 263 -11Q244 -11 239 -2Q99 359 98 364Q93 378 82 381T43 385H19V431H25L33 430Q41 430 53 430T79 430T104 429T122 428Q217 428 232 431H240V385H226Q187 384 184 370Q184 366 235 234L286 102L377 341V349Q377 363 367 372T349 383T335 385H331V431H338Z" style="stroke-width: 3;"/><path data-c="73" d="M295 316Q295 356 268 385T190 414Q154 414 128 401Q98 382 98 349Q97 344 98 336T114 312T157 287Q175 282 201 278T245 269T277 256Q294 248 310 236T342 195T359 133Q359 71 321 31T198 -10H190Q138 -10 94 26L86 19L77 10Q71 4 65 -1L54 -11H46H42Q39 -11 33 -5V74V132Q33 153 35 157T45 162H54Q66 162 70 158T75 146T82 119T101 77Q136 26 198 26Q295 26 295 104Q295 133 277 151Q257 175 194 187T111 210Q75 227 54 256T33 318Q33 357 50 384T93 424T143 442T187 447H198Q238 447 268 432L283 424L292 431Q302 440 314 448H322H326Q329 448 335 442V310L329 304H301Q295 310 295 316Z" transform="translate(528,0)" style="stroke-width: 3;"/><path data-c="79" d="M69 -66Q91 -66 104 -80T118 -116Q118 -134 109 -145T91 -160Q84 -163 97 -166Q104 -168 111 -168Q131 -168 148 -159T175 -138T197 -106T213 -75T225 -43L242 0L170 183Q150 233 125 297Q101 358 96 368T80 381Q79 382 78 382Q66 385 34 385H19V431H26L46 430Q65 430 88 429T122 428Q129 428 142 428T171 429T200 430T224 430L233 431H241V385H232Q183 385 185 366L286 112Q286 113 332 227L376 341V350Q376 365 366 373T348 383T334 385H331V431H337H344Q351 431 361 431T382 430T405 429T422 429Q477 429 503 431H508V385H497Q441 380 422 345Q420 343 378 235T289 9T227 -131Q180 -204 113 -204Q69 -204 44 -177T19 -116Q19 -89 35 -78T69 -66Z" transform="translate(922,0)" style="stroke-width: 3;"/><path data-c="6E" d="M41 46H55Q94 46 102 60V68Q102 77 102 91T102 122T103 161T103 203Q103 234 103 269T102 328V351Q99 370 88 376T43 385H25V408Q25 431 27 431L37 432Q47 433 65 434T102 436Q119 437 138 438T167 441T178 442H181V402Q181 364 182 364T187 369T199 384T218 402T247 421T285 437Q305 442 336 442Q450 438 463 329Q464 322 464 190V104Q464 66 466 59T477 49Q498 46 526 46H542V0H534L510 1Q487 2 460 2T422 3Q319 3 310 0H302V46H318Q379 46 379 62Q380 64 380 200Q379 335 378 343Q372 371 358 385T334 402T308 404Q263 404 229 370Q202 343 195 315T187 232V168V108Q187 78 188 68T191 55T200 49Q221 46 249 46H265V0H257L234 1Q210 2 183 2T145 3Q42 3 33 0H25V46H41Z" transform="translate(1450,0)" style="stroke-width: 3;"/><path data-c="63" d="M370 305T349 305T313 320T297 358Q297 381 312 396Q317 401 317 402T307 404Q281 408 258 408Q209 408 178 376Q131 329 131 219Q131 137 162 90Q203 29 272 29Q313 29 338 55T374 117Q376 125 379 127T395 129H409Q415 123 415 120Q415 116 411 104T395 71T366 33T318 2T249 -11Q163 -11 99 53T34 214Q34 318 99 383T250 448T370 421T404 357Q404 334 387 320Z" transform="translate(2006,0)" style="stroke-width: 3;"/></g></g></g></g></svg><mjx-assistive-mml unselectable="on" display="block" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; overflow: hidden; width: 100%;"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><mi>L</mi><mo>=</mo><msub><mi>t</mi><mtext>input</mtext></msub><mo>+</mo><mn>2</mn><mstyle scriptlevel="0"><mspace width="0.167em"/></mstyle><msub><mi>t</mi><mtext>msg</mtext></msub><mo>+</mo><msub><mi>t</mi><mtext>step</mtext></msub><mo>+</mo><msub><mi>t</mi><mtext>render</mtext></msub><mo>+</mo><msub><mi>t</mi><mtext>vsync</mtext></msub></math></mjx-assistive-mml></mjx-container><p>Evento keydown (hilo principal), <code>postMessage</code> al worker y de vuelta (<mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.669ex;" xmlns="http://www.w3.org/2000/svg" width="5.276ex" height="2.176ex" role="img" focusable="false" viewBox="0 -666 2332.2 961.7" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mn"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"/></g><g data-mml-node="mstyle" transform="translate(500,0)"><g data-mml-node="mspace"/></g><g data-mml-node="msub" transform="translate(667,0)"><g data-mml-node="mi"><path data-c="1D461" d="M26 385Q19 392 19 395Q19 399 22 411T27 425Q29 430 36 430T87 431H140L159 511Q162 522 166 540T173 566T179 586T187 603T197 615T211 624T229 626Q247 625 254 615T261 596Q261 589 252 549T232 470L222 433Q222 431 272 431H323Q330 424 330 420Q330 398 317 385H210L174 240Q135 80 135 68Q135 26 162 26Q197 26 230 60T283 144Q285 150 288 151T303 153H307Q322 153 322 145Q322 142 319 133Q314 117 301 95T267 48T216 6T155 -11Q125 -11 98 4T59 56Q57 64 57 83V101L92 241Q127 382 128 383Q128 385 77 385H26Z" style="stroke-width: 3;"/></g><g data-mml-node="mtext" transform="translate(394,-150) scale(0.707)"><path data-c="6D" d="M41 46H55Q94 46 102 60V68Q102 77 102 91T102 122T103 161T103 203Q103 234 103 269T102 328V351Q99 370 88 376T43 385H25V408Q25 431 27 431L37 432Q47 433 65 434T102 436Q119 437 138 438T167 441T178 442H181V402Q181 364 182 364T187 369T199 384T218 402T247 421T285 437Q305 442 336 442Q351 442 364 440T387 434T406 426T421 417T432 406T441 395T448 384T452 374T455 366L457 361L460 365Q463 369 466 373T475 384T488 397T503 410T523 422T546 432T572 439T603 442Q729 442 740 329Q741 322 741 190V104Q741 66 743 59T754 49Q775 46 803 46H819V0H811L788 1Q764 2 737 2T699 3Q596 3 587 0H579V46H595Q656 46 656 62Q657 64 657 200Q656 335 655 343Q649 371 635 385T611 402T585 404Q540 404 506 370Q479 343 472 315T464 232V168V108Q464 78 465 68T468 55T477 49Q498 46 526 46H542V0H534L510 1Q487 2 460 2T422 3Q319 3 310 0H302V46H318Q379 46 379 62Q380 64 380 200Q379 335 378 343Q372 371 358 385T334 402T308 404Q263 404 229 370Q202 343 195 315T187 232V168V108Q187 78 188 68T191 55T200 49Q221 46 249 46H265V0H257L234 1Q210 2 183 2T145 3Q42 3 33 0H25V46H41Z" style="stroke-width: 3;"/><path data-c="73" d="M295 316Q295 356 268 385T190 414Q154 414 128 401Q98 382 98 349Q97 344 98 336T114 312T157 287Q175 282 201 278T245 269T277 256Q294 248 310 236T342 195T359 133Q359 71 321 31T198 -10H190Q138 -10 94 26L86 19L77 10Q71 4 65 -1L54 -11H46H42Q39 -11 33 -5V74V132Q33 153 35 157T45 162H54Q66 162 70 158T75 146T82 119T101 77Q136 26 198 26Q295 26 295 104Q295 133 277 151Q257 175 194 187T111 210Q75 227 54 256T33 318Q33 357 50 384T93 424T143 442T187 447H198Q238 447 268 432L283 424L292 431Q302 440 314 448H322H326Q329 448 335 442V310L329 304H301Q295 310 295 316Z" transform="translate(833,0)" style="stroke-width: 3;"/><path data-c="67" d="M329 409Q373 453 429 453Q459 453 472 434T485 396Q485 382 476 371T449 360Q416 360 412 390Q410 404 415 411Q415 412 416 414V415Q388 412 363 393Q355 388 355 386Q355 385 359 381T368 369T379 351T388 325T392 292Q392 230 343 187T222 143Q172 143 123 171Q112 153 112 133Q112 98 138 81Q147 75 155 75T227 73Q311 72 335 67Q396 58 431 26Q470 -13 470 -72Q470 -139 392 -175Q332 -206 250 -206Q167 -206 107 -175Q29 -140 29 -75Q29 -39 50 -15T92 18L103 24Q67 55 67 108Q67 155 96 193Q52 237 52 292Q52 355 102 398T223 442Q274 442 318 416L329 409ZM299 343Q294 371 273 387T221 404Q192 404 171 388T145 343Q142 326 142 292Q142 248 149 227T179 192Q196 182 222 182Q244 182 260 189T283 207T294 227T299 242Q302 258 302 292T299 343ZM403 -75Q403 -50 389 -34T348 -11T299 -2T245 0H218Q151 0 138 -6Q118 -15 107 -34T95 -74Q95 -84 101 -97T122 -127T170 -155T250 -167Q319 -167 361 -139T403 -75Z" transform="translate(1227,0)" style="stroke-width: 3;"/></g></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mn>2</mn><mstyle scriptlevel="0"><mspace width="0.167em"/></mstyle><msub><mi>t</mi><mtext>msg</mtext></msub></math></mjx-assistive-mml></mjx-container>), paso de físicas, aplicación de la nueva posición por parte del renderizador y, por último, la siguiente sincronización vertical. Cada término es pequeño por sí solo (aproximadamente entre 0,1 y 0,5 ms por salto de mensaje en equipos de escritorio), pero se acumulan; por eso medimos <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: 0;" xmlns="http://www.w3.org/2000/svg" width="1.541ex" height="1.545ex" role="img" focusable="false" viewBox="0 -683 681 683" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mi"><path data-c="1D43F" d="M228 637Q194 637 192 641Q191 643 191 649Q191 673 202 682Q204 683 217 683Q271 680 344 680Q485 680 506 683H518Q524 677 524 674T522 656Q517 641 513 637H475Q406 636 394 628Q387 624 380 600T313 336Q297 271 279 198T252 88L243 52Q243 48 252 48T311 46H328Q360 46 379 47T428 54T478 72T522 106T564 161Q580 191 594 228T611 270Q616 273 628 273H641Q647 264 647 262T627 203T583 83T557 9Q555 4 553 3T537 0T494 -1Q483 -1 418 -1T294 0H116Q32 0 32 10Q32 17 34 24Q39 43 44 45Q48 46 59 46H65Q92 46 125 49Q139 52 144 61Q147 65 216 339T285 628Q285 635 228 637Z" style="stroke-width: 3;"/></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mi>L</mi></math></mjx-assistive-mml></mjx-container> directamente en lugar de confiar en el diagrama de arquitectura.</p>
<hr>
<p>Parte 2 de 12.<br>
Anterior: <a href="/es/blog/2026-02-25-open-world-browser-part-01-risk-first.html">Parte 1: Empezamos intentando romperlo</a><br>
Siguiente: <a href="/es/blog/2026-02-25-open-world-browser-part-03-the-unflashy-spikes.html">Parte 3: Los spikes poco vistosos que nos salvaron</a><br>
Guía de la serie: <a href="/es/blog/2026-02-25-open-world-browser-series-guide.html">/es/blog/2026-02-25-open-world-browser-series-guide</a></p>
]]></content:encoded>
            <enclosure url="https://cdn.cinevva.com/blog/why-webgpu-engine-hero.jpg" length="0" type="image/jpg"/>
        </item>
        <item>
            <title><![CDATA[Cómo construir un mundo abierto en el navegador, parte 3: Las pruebas poco vistosas que nos salvaron]]></title>
            <link>https://app.cinevva.com/es/blog/2026-02-25-open-world-browser-part-03-the-unflashy-spikes</link>
            <guid>https://app.cinevva.com/es/blog/2026-02-25-open-world-browser-part-03-the-unflashy-spikes</guid>
            <pubDate>Wed, 25 Feb 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[La carga de difusión de Durable Objects, las limitaciones de calidad en móviles y la fiabilidad de la generación de comportamientos no eran temas glamurosos, pero evitaron sorpresas costosas.]]></description>
            <content:encoded><![CDATA[<h1 id="como-construir-un-mundo-abierto-en-el-navegador-parte-3-las-pruebas-poco-vistosas-que-nos-salvaron" tabindex="-1">Cómo construir un mundo abierto en el navegador, parte 3: Las pruebas poco vistosas que nos salvaron <a class="header-anchor" href="#como-construir-un-mundo-abierto-en-el-navegador-parte-3-las-pruebas-poco-vistosas-que-nos-salvaron" aria-label="Permalink to &quot;Cómo construir un mundo abierto en el navegador, parte 3: Las pruebas poco vistosas que nos salvaron&quot;"></a></h1>
<p><em>Por <a href="/es/about.html">Oleg Sidorkin</a>, CTO y cofundador de Cinevva</em></p>
<p>¿Es tu primera vez aquí? Consulta la <a href="/es/blog/2026-02-25-open-world-browser-series-guide.html">guía de la serie</a>. Explica qué es una prueba técnica y enlaza todas las partes.</p>
<p>Esta parte tiene menos capturas de pantalla llamativas y más garantías arquitectónicas.</p>
<p>Después de las pruebas 1 y 2, realizamos tres comprobaciones de riesgo que parecían pequeñas, pero tuvieron un impacto a nivel de producto.</p>
<p>La primera fue la distribución de difusiones con Durable Objects. Probamos la distribución de posiciones entre múltiples clientes con frecuencias de actualización similares a las de un juego y medimos la distribución de la latencia, el uso de CPU por actualización y la integridad de la entrega. Si hubiera fallado, habríamos adoptado desde el principio una arquitectura fragmentada, en lugar de asignar cada isla a una única instancia.</p>
<p>La segunda fue la validación de las limitaciones móviles. No se trataba de un ajuste predefinido para escritorio rebautizado como móvil, sino de un perfil explícito de bajo coste basado en el mismo terreno de referencia.</p>
<div style="position:relative;padding-bottom:56.25%;height:0;overflow:hidden;border-radius:8px;margin:1.5rem 0;border:1px solid rgba(255,255,255,0.12)">
<iframe src="/es/spikes/01-terrain/?quality=mobile" title="Perfil de calidad móvil basado en la prueba 1" style="position:absolute;top:0;left:0;width:100%;height:100%;border:0;background:#000" loading="lazy" allowfullscreen></iframe>
</div>
<p><a href="/es/spikes/01-terrain/?quality=mobile" target="_blank">Abrir el perfil móvil en una pestaña nueva ↗</a> · <a href="/es/blog/spike-source?spike=01-terrain">Ver el código fuente</a></p>
<p>Redujimos la densidad de segmentos, el número de objetos, la presión sobre la resolución de renderizado y el alcance de la niebla. La pregunta era sencilla: ¿puede este mundo seguir siendo legible y ágil bajo las limitaciones propias de los dispositivos móviles sin tener que reescribir todo el renderizador?</p>
<p>La tercera fue la fiabilidad de la generación de comportamientos para los flujos de trabajo de los creadores. Evaluamos la tasa de JSON válido, la corrección semántica respecto a las primitivas esperadas y la latencia de respuesta. Si hubiera fallado, habríamos pasado a una creación de comportamientos estrictamente basada en formularios.</p>
<p>La idea clave de este capítulo es que estas pruebas poco vistosas cambiaron la arquitectura más rápido que las pruebas visuales. Establecieron límites firmes para la topología de red, las promesas en móviles y la experiencia de usuario de las herramientas.</p>
<p>En la parte 4 volvemos al trabajo visible sobre el terreno y probamos el comportamiento de la carga progresiva durante el movimiento, no solo mediante capturas de pantalla de cargas estáticas.</p>
<h2 id="tecnologia-mencionada-en-este-capitulo" tabindex="-1">Tecnología mencionada en este capítulo <a class="header-anchor" href="#tecnologia-mencionada-en-este-capitulo" aria-label="Permalink to &quot;Tecnología mencionada en este capítulo&quot;"></a></h2>
<p><strong>Cloudflare Durable Objects.</strong> Instancias sin servidor con estado, desplegadas en el edge, con persistencia integrada y compatibilidad con WebSocket. Cada Durable Object mantiene el estado autoritativo de un fragmento —o chunk— del mundo. Los jugadores se conectan mediante WebSocket y reciben difusiones de posición de otros jugadores del mismo fragmento. Cuando un jugador se desplaza a un chunk adyacente, se conecta al Durable Object de ese chunk. Los Durable Objects guardan automáticamente el estado en disco y pueden escalar hasta miles de instancias simultáneas. Consulta la <a href="https://developers.cloudflare.com/durable-objects/" target="_blank" rel="noreferrer">documentación de Cloudflare Durable Objects</a> y nuestra <a href="/es/guides/browser-3d-open-world-tech.html#multiplayer-networking">guía de tecnología 3D para navegador sobre redes multijugador</a>.</p>
<p><strong>Fragmentación espacial.</strong> División del mundo entre instancias de servidor según la región geográfica. Cada fragmento controla un área rectangular de la cuadrícula del mundo. A medida que cambia la densidad de jugadores, los fragmentos pueden dividirse o fusionarse. Los jugadores próximos al límite de un fragmento ven el contenido de ambos mediante consultas de visibilidad entre fragmentos. Así es como <a href="/es/guides/browser-3d-open-world-tech.html#server-architecture">EVE Online gestiona a miles de jugadores</a> en un único universo.</p>
<p><strong>Distribución de difusiones mediante WebSocket.</strong> Distribución de actualizaciones de posición en tiempo real desde un servidor a numerosos clientes conectados. El ancho de banda descendente por cliente aumenta linealmente con la cantidad de jugadores visibles:</p>
<mjx-container tabindex="0" class="MathJax" jax="SVG" display="true" style="direction: ltr; display: block; text-align: center; margin: 1em 0; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.666ex;" xmlns="http://www.w3.org/2000/svg" width="23.398ex" height="2.236ex" role="img" focusable="false" viewBox="0 -694 10341.8 988.2" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="msub"><g data-mml-node="mi"><path data-c="1D435" d="M231 637Q204 637 199 638T194 649Q194 676 205 682Q206 683 335 683Q594 683 608 681Q671 671 713 636T756 544Q756 480 698 429T565 360L555 357Q619 348 660 311T702 219Q702 146 630 78T453 1Q446 0 242 0Q42 0 39 2Q35 5 35 10Q35 17 37 24Q42 43 47 45Q51 46 62 46H68Q95 46 128 49Q142 52 147 61Q150 65 219 339T288 628Q288 635 231 637ZM649 544Q649 574 634 600T585 634Q578 636 493 637Q473 637 451 637T416 636H403Q388 635 384 626Q382 622 352 506Q352 503 351 500L320 374H401Q482 374 494 376Q554 386 601 434T649 544ZM595 229Q595 273 572 302T512 336Q506 337 429 337Q311 337 310 336Q310 334 293 263T258 122L240 52Q240 48 252 48T333 46Q422 46 429 47Q491 54 543 105T595 229Z" style="stroke-width: 3;"/></g><g data-mml-node="mtext" transform="translate(792,-150) scale(0.707)"><path data-c="63" d="M370 305T349 305T313 320T297 358Q297 381 312 396Q317 401 317 402T307 404Q281 408 258 408Q209 408 178 376Q131 329 131 219Q131 137 162 90Q203 29 272 29Q313 29 338 55T374 117Q376 125 379 127T395 129H409Q415 123 415 120Q415 116 411 104T395 71T366 33T318 2T249 -11Q163 -11 99 53T34 214Q34 318 99 383T250 448T370 421T404 357Q404 334 387 320Z" style="stroke-width: 3;"/><path data-c="6C" d="M42 46H56Q95 46 103 60V68Q103 77 103 91T103 124T104 167T104 217T104 272T104 329Q104 366 104 407T104 482T104 542T103 586T103 603Q100 622 89 628T44 637H26V660Q26 683 28 683L38 684Q48 685 67 686T104 688Q121 689 141 690T171 693T182 694H185V379Q185 62 186 60Q190 52 198 49Q219 46 247 46H263V0H255L232 1Q209 2 183 2T145 3T107 3T57 1L34 0H26V46H42Z" transform="translate(444,0)" style="stroke-width: 3;"/><path data-c="69" d="M69 609Q69 637 87 653T131 669Q154 667 171 652T188 609Q188 579 171 564T129 549Q104 549 87 564T69 609ZM247 0Q232 3 143 3Q132 3 106 3T56 1L34 0H26V46H42Q70 46 91 49Q100 53 102 60T104 102V205V293Q104 345 102 359T88 378Q74 385 41 385H30V408Q30 431 32 431L42 432Q52 433 70 434T106 436Q123 437 142 438T171 441T182 442H185V62Q190 52 197 50T232 46H255V0H247Z" transform="translate(722,0)" style="stroke-width: 3;"/><path data-c="65" d="M28 218Q28 273 48 318T98 391T163 433T229 448Q282 448 320 430T378 380T406 316T415 245Q415 238 408 231H126V216Q126 68 226 36Q246 30 270 30Q312 30 342 62Q359 79 369 104L379 128Q382 131 395 131H398Q415 131 415 121Q415 117 412 108Q393 53 349 21T250 -11Q155 -11 92 58T28 218ZM333 275Q322 403 238 411H236Q228 411 220 410T195 402T166 381T143 340T127 274V267H333V275Z" transform="translate(1000,0)" style="stroke-width: 3;"/><path data-c="6E" d="M41 46H55Q94 46 102 60V68Q102 77 102 91T102 122T103 161T103 203Q103 234 103 269T102 328V351Q99 370 88 376T43 385H25V408Q25 431 27 431L37 432Q47 433 65 434T102 436Q119 437 138 438T167 441T178 442H181V402Q181 364 182 364T187 369T199 384T218 402T247 421T285 437Q305 442 336 442Q450 438 463 329Q464 322 464 190V104Q464 66 466 59T477 49Q498 46 526 46H542V0H534L510 1Q487 2 460 2T422 3Q319 3 310 0H302V46H318Q379 46 379 62Q380 64 380 200Q379 335 378 343Q372 371 358 385T334 402T308 404Q263 404 229 370Q202 343 195 315T187 232V168V108Q187 78 188 68T191 55T200 49Q221 46 249 46H265V0H257L234 1Q210 2 183 2T145 3Q42 3 33 0H25V46H41Z" transform="translate(1444,0)" style="stroke-width: 3;"/><path data-c="74" d="M27 422Q80 426 109 478T141 600V615H181V431H316V385H181V241Q182 116 182 100T189 68Q203 29 238 29Q282 29 292 100Q293 108 293 146V181H333V146V134Q333 57 291 17Q264 -10 221 -10Q187 -10 162 2T124 33T105 68T98 100Q97 107 97 248V385H18V422H27Z" transform="translate(2000,0)" style="stroke-width: 3;"/></g></g><g data-mml-node="mo" transform="translate(2809.1,0)"><path data-c="3D" d="M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z" style="stroke-width: 3;"/></g><g data-mml-node="msub" transform="translate(3864.8,0)"><g data-mml-node="mi"><path data-c="1D441" d="M234 637Q231 637 226 637Q201 637 196 638T191 649Q191 676 202 682Q204 683 299 683Q376 683 387 683T401 677Q612 181 616 168L670 381Q723 592 723 606Q723 633 659 637Q635 637 635 648Q635 650 637 660Q641 676 643 679T653 683Q656 683 684 682T767 680Q817 680 843 681T873 682Q888 682 888 672Q888 650 880 642Q878 637 858 637Q787 633 769 597L620 7Q618 0 599 0Q585 0 582 2Q579 5 453 305L326 604L261 344Q196 88 196 79Q201 46 268 46H278Q284 41 284 38T282 19Q278 6 272 0H259Q228 2 151 2Q123 2 100 2T63 2T46 1Q31 1 31 10Q31 14 34 26T39 40Q41 46 62 46Q130 49 150 85Q154 91 221 362L289 634Q287 635 234 637Z" style="stroke-width: 3;"/></g><g data-mml-node="mtext" transform="translate(836,-150) scale(0.707)"><path data-c="76" d="M338 431Q344 429 422 429Q479 429 503 431H508V385H497Q439 381 423 345Q421 341 356 172T288 -2Q283 -11 263 -11Q244 -11 239 -2Q99 359 98 364Q93 378 82 381T43 385H19V431H25L33 430Q41 430 53 430T79 430T104 429T122 428Q217 428 232 431H240V385H226Q187 384 184 370Q184 366 235 234L286 102L377 341V349Q377 363 367 372T349 383T335 385H331V431H338Z" style="stroke-width: 3;"/><path data-c="69" d="M69 609Q69 637 87 653T131 669Q154 667 171 652T188 609Q188 579 171 564T129 549Q104 549 87 564T69 609ZM247 0Q232 3 143 3Q132 3 106 3T56 1L34 0H26V46H42Q70 46 91 49Q100 53 102 60T104 102V205V293Q104 345 102 359T88 378Q74 385 41 385H30V408Q30 431 32 431L42 432Q52 433 70 434T106 436Q123 437 142 438T171 441T182 442H185V62Q190 52 197 50T232 46H255V0H247Z" transform="translate(528,0)" style="stroke-width: 3;"/><path data-c="73" d="M295 316Q295 356 268 385T190 414Q154 414 128 401Q98 382 98 349Q97 344 98 336T114 312T157 287Q175 282 201 278T245 269T277 256Q294 248 310 236T342 195T359 133Q359 71 321 31T198 -10H190Q138 -10 94 26L86 19L77 10Q71 4 65 -1L54 -11H46H42Q39 -11 33 -5V74V132Q33 153 35 157T45 162H54Q66 162 70 158T75 146T82 119T101 77Q136 26 198 26Q295 26 295 104Q295 133 277 151Q257 175 194 187T111 210Q75 227 54 256T33 318Q33 357 50 384T93 424T143 442T187 447H198Q238 447 268 432L283 424L292 431Q302 440 314 448H322H326Q329 448 335 442V310L329 304H301Q295 310 295 316Z" transform="translate(806,0)" style="stroke-width: 3;"/><path data-c="69" d="M69 609Q69 637 87 653T131 669Q154 667 171 652T188 609Q188 579 171 564T129 549Q104 549 87 564T69 609ZM247 0Q232 3 143 3Q132 3 106 3T56 1L34 0H26V46H42Q70 46 91 49Q100 53 102 60T104 102V205V293Q104 345 102 359T88 378Q74 385 41 385H30V408Q30 431 32 431L42 432Q52 433 70 434T106 436Q123 437 142 438T171 441T182 442H185V62Q190 52 197 50T232 46H255V0H247Z" transform="translate(1200,0)" style="stroke-width: 3;"/><path data-c="62" d="M307 -11Q234 -11 168 55L158 37Q156 34 153 28T147 17T143 10L138 1L118 0H98V298Q98 599 97 603Q94 622 83 628T38 637H20V660Q20 683 22 683L32 684Q42 685 61 686T98 688Q115 689 135 690T165 693T176 694H179V543Q179 391 180 391L183 394Q186 397 192 401T207 411T228 421T254 431T286 439T323 442Q401 442 461 379T522 216Q522 115 458 52T307 -11ZM182 98Q182 97 187 90T196 79T206 67T218 55T233 44T250 35T271 29T295 26Q330 26 363 46T412 113Q424 148 424 212Q424 287 412 323Q385 405 300 405Q270 405 239 390T188 347L182 339V98Z" transform="translate(1478,0)" style="stroke-width: 3;"/><path data-c="6C" d="M42 46H56Q95 46 103 60V68Q103 77 103 91T103 124T104 167T104 217T104 272T104 329Q104 366 104 407T104 482T104 542T103 586T103 603Q100 622 89 628T44 637H26V660Q26 683 28 683L38 684Q48 685 67 686T104 688Q121 689 141 690T171 693T182 694H185V379Q185 62 186 60Q190 52 198 49Q219 46 247 46H263V0H255L232 1Q209 2 183 2T145 3T107 3T57 1L34 0H26V46H42Z" transform="translate(2034,0)" style="stroke-width: 3;"/><path data-c="65" d="M28 218Q28 273 48 318T98 391T163 433T229 448Q282 448 320 430T378 380T406 316T415 245Q415 238 408 231H126V216Q126 68 226 36Q246 30 270 30Q312 30 342 62Q359 79 369 104L379 128Q382 131 395 131H398Q415 131 415 121Q415 117 412 108Q393 53 349 21T250 -11Q155 -11 92 58T28 218ZM333 275Q322 403 238 411H236Q228 411 220 410T195 402T166 381T143 340T127 274V267H333V275Z" transform="translate(2312,0)" style="stroke-width: 3;"/></g></g><g data-mml-node="mo" transform="translate(6921.8,0)"><path data-c="D7" d="M630 29Q630 9 609 9Q604 9 587 25T493 118L389 222L284 117Q178 13 175 11Q171 9 168 9Q160 9 154 15T147 29Q147 36 161 51T255 146L359 250L255 354Q174 435 161 449T147 471Q147 480 153 485T168 490Q173 490 175 489Q178 487 284 383L389 278L493 382Q570 459 587 475T609 491Q630 491 630 471Q630 464 620 453T522 355L418 250L522 145Q606 61 618 48T630 29Z" style="stroke-width: 3;"/></g><g data-mml-node="msub" transform="translate(7922.1,0)"><g data-mml-node="mi"><path data-c="1D44F" d="M73 647Q73 657 77 670T89 683Q90 683 161 688T234 694Q246 694 246 685T212 542Q204 508 195 472T180 418L176 399Q176 396 182 402Q231 442 283 442Q345 442 383 396T422 280Q422 169 343 79T173 -11Q123 -11 82 27T40 150V159Q40 180 48 217T97 414Q147 611 147 623T109 637Q104 637 101 637H96Q86 637 83 637T76 640T73 647ZM336 325V331Q336 405 275 405Q258 405 240 397T207 376T181 352T163 330L157 322L136 236Q114 150 114 114Q114 66 138 42Q154 26 178 26Q211 26 245 58Q270 81 285 114T318 219Q336 291 336 325Z" style="stroke-width: 3;"/></g><g data-mml-node="mtext" transform="translate(462,-150) scale(0.707)"><path data-c="70" d="M36 -148H50Q89 -148 97 -134V-126Q97 -119 97 -107T97 -77T98 -38T98 6T98 55T98 106Q98 140 98 177T98 243T98 296T97 335T97 351Q94 370 83 376T38 385H20V408Q20 431 22 431L32 432Q42 433 61 434T98 436Q115 437 135 438T165 441T176 442H179V416L180 390L188 397Q247 441 326 441Q407 441 464 377T522 216Q522 115 457 52T310 -11Q242 -11 190 33L182 40V-45V-101Q182 -128 184 -134T195 -145Q216 -148 244 -148H260V-194H252L228 -193Q205 -192 178 -192T140 -191Q37 -191 28 -194H20V-148H36ZM424 218Q424 292 390 347T305 402Q234 402 182 337V98Q222 26 294 26Q345 26 384 80T424 218Z" style="stroke-width: 3;"/><path data-c="6C" d="M42 46H56Q95 46 103 60V68Q103 77 103 91T103 124T104 167T104 217T104 272T104 329Q104 366 104 407T104 482T104 542T103 586T103 603Q100 622 89 628T44 637H26V660Q26 683 28 683L38 684Q48 685 67 686T104 688Q121 689 141 690T171 693T182 694H185V379Q185 62 186 60Q190 52 198 49Q219 46 247 46H263V0H255L232 1Q209 2 183 2T145 3T107 3T57 1L34 0H26V46H42Z" transform="translate(556,0)" style="stroke-width: 3;"/><path data-c="61" d="M137 305T115 305T78 320T63 359Q63 394 97 421T218 448Q291 448 336 416T396 340Q401 326 401 309T402 194V124Q402 76 407 58T428 40Q443 40 448 56T453 109V145H493V106Q492 66 490 59Q481 29 455 12T400 -6T353 12T329 54V58L327 55Q325 52 322 49T314 40T302 29T287 17T269 6T247 -2T221 -8T190 -11Q130 -11 82 20T34 107Q34 128 41 147T68 188T116 225T194 253T304 268H318V290Q318 324 312 340Q290 411 215 411Q197 411 181 410T156 406T148 403Q170 388 170 359Q170 334 154 320ZM126 106Q126 75 150 51T209 26Q247 26 276 49T315 109Q317 116 318 175Q318 233 317 233Q309 233 296 232T251 223T193 203T147 166T126 106Z" transform="translate(834,0)" style="stroke-width: 3;"/><path data-c="79" d="M69 -66Q91 -66 104 -80T118 -116Q118 -134 109 -145T91 -160Q84 -163 97 -166Q104 -168 111 -168Q131 -168 148 -159T175 -138T197 -106T213 -75T225 -43L242 0L170 183Q150 233 125 297Q101 358 96 368T80 381Q79 382 78 382Q66 385 34 385H19V431H26L46 430Q65 430 88 429T122 428Q129 428 142 428T171 429T200 430T224 430L233 431H241V385H232Q183 385 185 366L286 112Q286 113 332 227L376 341V350Q376 365 366 373T348 383T334 385H331V431H337H344Q351 431 361 431T382 430T405 429T422 429Q477 429 503 431H508V385H497Q441 380 422 345Q420 343 378 235T289 9T227 -131Q180 -204 113 -204Q69 -204 44 -177T19 -116Q19 -89 35 -78T69 -66Z" transform="translate(1334,0)" style="stroke-width: 3;"/><path data-c="65" d="M28 218Q28 273 48 318T98 391T163 433T229 448Q282 448 320 430T378 380T406 316T415 245Q415 238 408 231H126V216Q126 68 226 36Q246 30 270 30Q312 30 342 62Q359 79 369 104L379 128Q382 131 395 131H398Q415 131 415 121Q415 117 412 108Q393 53 349 21T250 -11Q155 -11 92 58T28 218ZM333 275Q322 403 238 411H236Q228 411 220 410T195 402T166 381T143 340T127 274V267H333V275Z" transform="translate(1862,0)" style="stroke-width: 3;"/><path data-c="72" d="M36 46H50Q89 46 97 60V68Q97 77 97 91T98 122T98 161T98 203Q98 234 98 269T98 328L97 351Q94 370 83 376T38 385H20V408Q20 431 22 431L32 432Q42 433 60 434T96 436Q112 437 131 438T160 441T171 442H174V373Q213 441 271 441H277Q322 441 343 419T364 373Q364 352 351 337T313 322Q288 322 276 338T263 372Q263 381 265 388T270 400T273 405Q271 407 250 401Q234 393 226 386Q179 341 179 207V154Q179 141 179 127T179 101T180 81T180 66V61Q181 59 183 57T188 54T193 51T200 49T207 48T216 47T225 47T235 46T245 46H276V0H267Q249 3 140 3Q37 3 28 0H20V46H36Z" transform="translate(2306,0)" style="stroke-width: 3;"/></g></g></g></g></svg><mjx-assistive-mml unselectable="on" display="block" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; overflow: hidden; width: 100%;"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><msub><mi>B</mi><mtext>client</mtext></msub><mo>=</mo><msub><mi>N</mi><mtext>visible</mtext></msub><mo>×</mo><msub><mi>b</mi><mtext>player</mtext></msub></math></mjx-assistive-mml></mjx-container><p>Con frecuencias de actualización propias de un juego (20-30 Hz), cada jugador genera <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.666ex;" xmlns="http://www.w3.org/2000/svg" width="11.885ex" height="2.236ex" role="img" focusable="false" viewBox="0 -694 5253.3 988.2" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="msub"><g data-mml-node="mi"><path data-c="1D44F" d="M73 647Q73 657 77 670T89 683Q90 683 161 688T234 694Q246 694 246 685T212 542Q204 508 195 472T180 418L176 399Q176 396 182 402Q231 442 283 442Q345 442 383 396T422 280Q422 169 343 79T173 -11Q123 -11 82 27T40 150V159Q40 180 48 217T97 414Q147 611 147 623T109 637Q104 637 101 637H96Q86 637 83 637T76 640T73 647ZM336 325V331Q336 405 275 405Q258 405 240 397T207 376T181 352T163 330L157 322L136 236Q114 150 114 114Q114 66 138 42Q154 26 178 26Q211 26 245 58Q270 81 285 114T318 219Q336 291 336 325Z" style="stroke-width: 3;"/></g><g data-mml-node="mtext" transform="translate(462,-150) scale(0.707)"><path data-c="70" d="M36 -148H50Q89 -148 97 -134V-126Q97 -119 97 -107T97 -77T98 -38T98 6T98 55T98 106Q98 140 98 177T98 243T98 296T97 335T97 351Q94 370 83 376T38 385H20V408Q20 431 22 431L32 432Q42 433 61 434T98 436Q115 437 135 438T165 441T176 442H179V416L180 390L188 397Q247 441 326 441Q407 441 464 377T522 216Q522 115 457 52T310 -11Q242 -11 190 33L182 40V-45V-101Q182 -128 184 -134T195 -145Q216 -148 244 -148H260V-194H252L228 -193Q205 -192 178 -192T140 -191Q37 -191 28 -194H20V-148H36ZM424 218Q424 292 390 347T305 402Q234 402 182 337V98Q222 26 294 26Q345 26 384 80T424 218Z" style="stroke-width: 3;"/><path data-c="6C" d="M42 46H56Q95 46 103 60V68Q103 77 103 91T103 124T104 167T104 217T104 272T104 329Q104 366 104 407T104 482T104 542T103 586T103 603Q100 622 89 628T44 637H26V660Q26 683 28 683L38 684Q48 685 67 686T104 688Q121 689 141 690T171 693T182 694H185V379Q185 62 186 60Q190 52 198 49Q219 46 247 46H263V0H255L232 1Q209 2 183 2T145 3T107 3T57 1L34 0H26V46H42Z" transform="translate(556,0)" style="stroke-width: 3;"/><path data-c="61" d="M137 305T115 305T78 320T63 359Q63 394 97 421T218 448Q291 448 336 416T396 340Q401 326 401 309T402 194V124Q402 76 407 58T428 40Q443 40 448 56T453 109V145H493V106Q492 66 490 59Q481 29 455 12T400 -6T353 12T329 54V58L327 55Q325 52 322 49T314 40T302 29T287 17T269 6T247 -2T221 -8T190 -11Q130 -11 82 20T34 107Q34 128 41 147T68 188T116 225T194 253T304 268H318V290Q318 324 312 340Q290 411 215 411Q197 411 181 410T156 406T148 403Q170 388 170 359Q170 334 154 320ZM126 106Q126 75 150 51T209 26Q247 26 276 49T315 109Q317 116 318 175Q318 233 317 233Q309 233 296 232T251 223T193 203T147 166T126 106Z" transform="translate(834,0)" style="stroke-width: 3;"/><path data-c="79" d="M69 -66Q91 -66 104 -80T118 -116Q118 -134 109 -145T91 -160Q84 -163 97 -166Q104 -168 111 -168Q131 -168 148 -159T175 -138T197 -106T213 -75T225 -43L242 0L170 183Q150 233 125 297Q101 358 96 368T80 381Q79 382 78 382Q66 385 34 385H19V431H26L46 430Q65 430 88 429T122 428Q129 428 142 428T171 429T200 430T224 430L233 431H241V385H232Q183 385 185 366L286 112Q286 113 332 227L376 341V350Q376 365 366 373T348 383T334 385H331V431H337H344Q351 431 361 431T382 430T405 429T422 429Q477 429 503 431H508V385H497Q441 380 422 345Q420 343 378 235T289 9T227 -131Q180 -204 113 -204Q69 -204 44 -177T19 -116Q19 -89 35 -78T69 -66Z" transform="translate(1334,0)" style="stroke-width: 3;"/><path data-c="65" d="M28 218Q28 273 48 318T98 391T163 433T229 448Q282 448 320 430T378 380T406 316T415 245Q415 238 408 231H126V216Q126 68 226 36Q246 30 270 30Q312 30 342 62Q359 79 369 104L379 128Q382 131 395 131H398Q415 131 415 121Q415 117 412 108Q393 53 349 21T250 -11Q155 -11 92 58T28 218ZM333 275Q322 403 238 411H236Q228 411 220 410T195 402T166 381T143 340T127 274V267H333V275Z" transform="translate(1862,0)" style="stroke-width: 3;"/><path data-c="72" d="M36 46H50Q89 46 97 60V68Q97 77 97 91T98 122T98 161T98 203Q98 234 98 269T98 328L97 351Q94 370 83 376T38 385H20V408Q20 431 22 431L32 432Q42 433 60 434T96 436Q112 437 131 438T160 441T171 442H174V373Q213 441 271 441H277Q322 441 343 419T364 373Q364 352 351 337T313 322Q288 322 276 338T263 372Q263 381 265 388T270 400T273 405Q271 407 250 401Q234 393 226 386Q179 341 179 207V154Q179 141 179 127T179 101T180 81T180 66V61Q181 59 183 57T188 54T193 51T200 49T207 48T216 47T225 47T235 46T245 46H276V0H267Q249 3 140 3Q37 3 28 0H20V46H36Z" transform="translate(2306,0)" style="stroke-width: 3;"/></g></g><g data-mml-node="mo" transform="translate(2697.6,0)"><path data-c="2248" d="M55 319Q55 360 72 393T114 444T163 472T205 482Q207 482 213 482T223 483Q262 483 296 468T393 413L443 381Q502 346 553 346Q609 346 649 375T694 454Q694 465 698 474T708 483Q722 483 722 452Q722 386 675 338T555 289Q514 289 468 310T388 357T308 404T224 426Q164 426 125 393T83 318Q81 289 69 289Q55 289 55 319ZM55 85Q55 126 72 159T114 210T163 238T205 248Q207 248 213 248T223 249Q262 249 296 234T393 179L443 147Q502 112 553 112Q609 112 649 141T694 220Q694 249 708 249T722 217Q722 153 675 104T555 55Q514 55 468 76T388 123T308 170T224 192Q164 192 125 159T83 84Q80 55 69 55Q55 55 55 85Z" style="stroke-width: 3;"/></g><g data-mml-node="mn" transform="translate(3753.3,0)"><path data-c="38" d="M70 417T70 494T124 618T248 666Q319 666 374 624T429 515Q429 485 418 459T392 417T361 389T335 371T324 363L338 354Q352 344 366 334T382 323Q457 264 457 174Q457 95 399 37T249 -22Q159 -22 101 29T43 155Q43 263 172 335L154 348Q133 361 127 368Q70 417 70 494ZM286 386L292 390Q298 394 301 396T311 403T323 413T334 425T345 438T355 454T364 471T369 491T371 513Q371 556 342 586T275 624Q268 625 242 625Q201 625 165 599T128 534Q128 511 141 492T167 463T217 431Q224 426 228 424L286 386ZM250 21Q308 21 350 55T392 137Q392 154 387 169T375 194T353 216T330 234T301 253T274 270Q260 279 244 289T218 306L210 311Q204 311 181 294T133 239T107 157Q107 98 150 60T250 21Z" style="stroke-width: 3;"/><path data-c="30" d="M96 585Q152 666 249 666Q297 666 345 640T423 548Q460 465 460 320Q460 165 417 83Q397 41 362 16T301 -15T250 -22Q224 -22 198 -16T137 16T82 83Q39 165 39 320Q39 494 96 585ZM321 597Q291 629 250 629Q208 629 178 597Q153 571 145 525T137 333Q137 175 145 125T181 46Q209 16 250 16Q290 16 318 46Q347 76 354 130T362 333Q362 478 354 524T321 597Z" transform="translate(500,0)" style="stroke-width: 3;"/><path data-c="30" d="M96 585Q152 666 249 666Q297 666 345 640T423 548Q460 465 460 320Q460 165 417 83Q397 41 362 16T301 -15T250 -22Q224 -22 198 -16T137 16T82 83Q39 165 39 320Q39 494 96 585ZM321 597Q291 629 250 629Q208 629 178 597Q153 571 145 525T137 333Q137 175 145 125T181 46Q209 16 250 16Q290 16 318 46Q347 76 354 130T362 333Q362 478 354 524T321 597Z" transform="translate(1000,0)" style="stroke-width: 3;"/></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><msub><mi>b</mi><mtext>player</mtext></msub><mo>≈</mo><mn>800</mn></math></mjx-assistive-mml></mjx-container> bytes/segundo de datos de posición, por lo que tener 200 jugadores visibles consume <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.186ex;" xmlns="http://www.w3.org/2000/svg" width="15.964ex" height="1.692ex" role="img" focusable="false" viewBox="0 -666 7056 748" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mn"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"/><path data-c="30" d="M96 585Q152 666 249 666Q297 666 345 640T423 548Q460 465 460 320Q460 165 417 83Q397 41 362 16T301 -15T250 -22Q224 -22 198 -16T137 16T82 83Q39 165 39 320Q39 494 96 585ZM321 597Q291 629 250 629Q208 629 178 597Q153 571 145 525T137 333Q137 175 145 125T181 46Q209 16 250 16Q290 16 318 46Q347 76 354 130T362 333Q362 478 354 524T321 597Z" transform="translate(500,0)" style="stroke-width: 3;"/><path data-c="30" d="M96 585Q152 666 249 666Q297 666 345 640T423 548Q460 465 460 320Q460 165 417 83Q397 41 362 16T301 -15T250 -22Q224 -22 198 -16T137 16T82 83Q39 165 39 320Q39 494 96 585ZM321 597Q291 629 250 629Q208 629 178 597Q153 571 145 525T137 333Q137 175 145 125T181 46Q209 16 250 16Q290 16 318 46Q347 76 354 130T362 333Q362 478 354 524T321 597Z" transform="translate(1000,0)" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(1722.2,0)"><path data-c="D7" d="M630 29Q630 9 609 9Q604 9 587 25T493 118L389 222L284 117Q178 13 175 11Q171 9 168 9Q160 9 154 15T147 29Q147 36 161 51T255 146L359 250L255 354Q174 435 161 449T147 471Q147 480 153 485T168 490Q173 490 175 489Q178 487 284 383L389 278L493 382Q570 459 587 475T609 491Q630 491 630 471Q630 464 620 453T522 355L418 250L522 145Q606 61 618 48T630 29Z" style="stroke-width: 3;"/></g><g data-mml-node="mn" transform="translate(2722.4,0)"><path data-c="38" d="M70 417T70 494T124 618T248 666Q319 666 374 624T429 515Q429 485 418 459T392 417T361 389T335 371T324 363L338 354Q352 344 366 334T382 323Q457 264 457 174Q457 95 399 37T249 -22Q159 -22 101 29T43 155Q43 263 172 335L154 348Q133 361 127 368Q70 417 70 494ZM286 386L292 390Q298 394 301 396T311 403T323 413T334 425T345 438T355 454T364 471T369 491T371 513Q371 556 342 586T275 624Q268 625 242 625Q201 625 165 599T128 534Q128 511 141 492T167 463T217 431Q224 426 228 424L286 386ZM250 21Q308 21 350 55T392 137Q392 154 387 169T375 194T353 216T330 234T301 253T274 270Q260 279 244 289T218 306L210 311Q204 311 181 294T133 239T107 157Q107 98 150 60T250 21Z" style="stroke-width: 3;"/><path data-c="30" d="M96 585Q152 666 249 666Q297 666 345 640T423 548Q460 465 460 320Q460 165 417 83Q397 41 362 16T301 -15T250 -22Q224 -22 198 -16T137 16T82 83Q39 165 39 320Q39 494 96 585ZM321 597Q291 629 250 629Q208 629 178 597Q153 571 145 525T137 333Q137 175 145 125T181 46Q209 16 250 16Q290 16 318 46Q347 76 354 130T362 333Q362 478 354 524T321 597Z" transform="translate(500,0)" style="stroke-width: 3;"/><path data-c="30" d="M96 585Q152 666 249 666Q297 666 345 640T423 548Q460 465 460 320Q460 165 417 83Q397 41 362 16T301 -15T250 -22Q224 -22 198 -16T137 16T82 83Q39 165 39 320Q39 494 96 585ZM321 597Q291 629 250 629Q208 629 178 597Q153 571 145 525T137 333Q137 175 145 125T181 46Q209 16 250 16Q290 16 318 46Q347 76 354 130T362 333Q362 478 354 524T321 597Z" transform="translate(1000,0)" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(4500.2,0)"><path data-c="3D" d="M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z" style="stroke-width: 3;"/></g><g data-mml-node="mn" transform="translate(5556,0)"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" style="stroke-width: 3;"/><path data-c="36" d="M42 313Q42 476 123 571T303 666Q372 666 402 630T432 550Q432 525 418 510T379 495Q356 495 341 509T326 548Q326 592 373 601Q351 623 311 626Q240 626 194 566Q147 500 147 364L148 360Q153 366 156 373Q197 433 263 433H267Q313 433 348 414Q372 400 396 374T435 317Q456 268 456 210V192Q456 169 451 149Q440 90 387 34T253 -22Q225 -22 199 -14T143 16T92 75T56 172T42 313ZM257 397Q227 397 205 380T171 335T154 278T148 216Q148 133 160 97T198 39Q222 21 251 21Q302 21 329 59Q342 77 347 104T352 209Q352 289 347 316T329 361Q302 397 257 397Z" transform="translate(500,0)" style="stroke-width: 3;"/><path data-c="30" d="M96 585Q152 666 249 666Q297 666 345 640T423 548Q460 465 460 320Q460 165 417 83Q397 41 362 16T301 -15T250 -22Q224 -22 198 -16T137 16T82 83Q39 165 39 320Q39 494 96 585ZM321 597Q291 629 250 629Q208 629 178 597Q153 571 145 525T137 333Q137 175 145 125T181 46Q209 16 250 16Q290 16 318 46Q347 76 354 130T362 333Q362 478 354 524T321 597Z" transform="translate(1000,0)" style="stroke-width: 3;"/></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mn>200</mn><mo>×</mo><mn>800</mn><mo>=</mo><mn>160</mn></math></mjx-assistive-mml></mjx-container> KB/s por cliente. El coste para el servidor de un enfoque ingenuo de todos contra todos es aún peor, pues crece como <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: 0;" xmlns="http://www.w3.org/2000/svg" width="3.119ex" height="1.887ex" role="img" focusable="false" viewBox="0 -833.9 1378.8 833.9" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="msup"><g data-mml-node="mi"><path data-c="1D441" d="M234 637Q231 637 226 637Q201 637 196 638T191 649Q191 676 202 682Q204 683 299 683Q376 683 387 683T401 677Q612 181 616 168L670 381Q723 592 723 606Q723 633 659 637Q635 637 635 648Q635 650 637 660Q641 676 643 679T653 683Q656 683 684 682T767 680Q817 680 843 681T873 682Q888 682 888 672Q888 650 880 642Q878 637 858 637Q787 633 769 597L620 7Q618 0 599 0Q585 0 582 2Q579 5 453 305L326 604L261 344Q196 88 196 79Q201 46 268 46H278Q284 41 284 38T282 19Q278 6 272 0H259Q228 2 151 2Q123 2 100 2T63 2T46 1Q31 1 31 10Q31 14 34 26T39 40Q41 46 62 46Q130 49 150 85Q154 91 221 362L289 634Q287 635 234 637Z" style="stroke-width: 3;"/></g><g data-mml-node="mn" transform="translate(975.3,363) scale(0.707)"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"/></g></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><msup><mi>N</mi><mn>2</mn></msup></math></mjx-assistive-mml></mjx-container>. Precisamente por eso, el filtrado por relevancia —la gestión espacial de áreas de interés— limita <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.357ex;" xmlns="http://www.w3.org/2000/svg" width="6.414ex" height="1.902ex" role="img" focusable="false" viewBox="0 -683 2834.8 840.8" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="msub"><g data-mml-node="mi"><path data-c="1D441" d="M234 637Q231 637 226 637Q201 637 196 638T191 649Q191 676 202 682Q204 683 299 683Q376 683 387 683T401 677Q612 181 616 168L670 381Q723 592 723 606Q723 633 659 637Q635 637 635 648Q635 650 637 660Q641 676 643 679T653 683Q656 683 684 682T767 680Q817 680 843 681T873 682Q888 682 888 672Q888 650 880 642Q878 637 858 637Q787 633 769 597L620 7Q618 0 599 0Q585 0 582 2Q579 5 453 305L326 604L261 344Q196 88 196 79Q201 46 268 46H278Q284 41 284 38T282 19Q278 6 272 0H259Q228 2 151 2Q123 2 100 2T63 2T46 1Q31 1 31 10Q31 14 34 26T39 40Q41 46 62 46Q130 49 150 85Q154 91 221 362L289 634Q287 635 234 637Z" style="stroke-width: 3;"/></g><g data-mml-node="mtext" transform="translate(836,-150) scale(0.707)"><path data-c="76" d="M338 431Q344 429 422 429Q479 429 503 431H508V385H497Q439 381 423 345Q421 341 356 172T288 -2Q283 -11 263 -11Q244 -11 239 -2Q99 359 98 364Q93 378 82 381T43 385H19V431H25L33 430Q41 430 53 430T79 430T104 429T122 428Q217 428 232 431H240V385H226Q187 384 184 370Q184 366 235 234L286 102L377 341V349Q377 363 367 372T349 383T335 385H331V431H338Z" style="stroke-width: 3;"/><path data-c="69" d="M69 609Q69 637 87 653T131 669Q154 667 171 652T188 609Q188 579 171 564T129 549Q104 549 87 564T69 609ZM247 0Q232 3 143 3Q132 3 106 3T56 1L34 0H26V46H42Q70 46 91 49Q100 53 102 60T104 102V205V293Q104 345 102 359T88 378Q74 385 41 385H30V408Q30 431 32 431L42 432Q52 433 70 434T106 436Q123 437 142 438T171 441T182 442H185V62Q190 52 197 50T232 46H255V0H247Z" transform="translate(528,0)" style="stroke-width: 3;"/><path data-c="73" d="M295 316Q295 356 268 385T190 414Q154 414 128 401Q98 382 98 349Q97 344 98 336T114 312T157 287Q175 282 201 278T245 269T277 256Q294 248 310 236T342 195T359 133Q359 71 321 31T198 -10H190Q138 -10 94 26L86 19L77 10Q71 4 65 -1L54 -11H46H42Q39 -11 33 -5V74V132Q33 153 35 157T45 162H54Q66 162 70 158T75 146T82 119T101 77Q136 26 198 26Q295 26 295 104Q295 133 277 151Q257 175 194 187T111 210Q75 227 54 256T33 318Q33 357 50 384T93 424T143 442T187 447H198Q238 447 268 432L283 424L292 431Q302 440 314 448H322H326Q329 448 335 442V310L329 304H301Q295 310 295 316Z" transform="translate(806,0)" style="stroke-width: 3;"/><path data-c="69" d="M69 609Q69 637 87 653T131 669Q154 667 171 652T188 609Q188 579 171 564T129 549Q104 549 87 564T69 609ZM247 0Q232 3 143 3Q132 3 106 3T56 1L34 0H26V46H42Q70 46 91 49Q100 53 102 60T104 102V205V293Q104 345 102 359T88 378Q74 385 41 385H30V408Q30 431 32 431L42 432Q52 433 70 434T106 436Q123 437 142 438T171 441T182 442H185V62Q190 52 197 50T232 46H255V0H247Z" transform="translate(1200,0)" style="stroke-width: 3;"/><path data-c="62" d="M307 -11Q234 -11 168 55L158 37Q156 34 153 28T147 17T143 10L138 1L118 0H98V298Q98 599 97 603Q94 622 83 628T38 637H20V660Q20 683 22 683L32 684Q42 685 61 686T98 688Q115 689 135 690T165 693T176 694H179V543Q179 391 180 391L183 394Q186 397 192 401T207 411T228 421T254 431T286 439T323 442Q401 442 461 379T522 216Q522 115 458 52T307 -11ZM182 98Q182 97 187 90T196 79T206 67T218 55T233 44T250 35T271 29T295 26Q330 26 363 46T412 113Q424 148 424 212Q424 287 412 323Q385 405 300 405Q270 405 239 390T188 347L182 339V98Z" transform="translate(1478,0)" style="stroke-width: 3;"/><path data-c="6C" d="M42 46H56Q95 46 103 60V68Q103 77 103 91T103 124T104 167T104 217T104 272T104 329Q104 366 104 407T104 482T104 542T103 586T103 603Q100 622 89 628T44 637H26V660Q26 683 28 683L38 684Q48 685 67 686T104 688Q121 689 141 690T171 693T182 694H185V379Q185 62 186 60Q190 52 198 49Q219 46 247 46H263V0H255L232 1Q209 2 183 2T145 3T107 3T57 1L34 0H26V46H42Z" transform="translate(2034,0)" style="stroke-width: 3;"/><path data-c="65" d="M28 218Q28 273 48 318T98 391T163 433T229 448Q282 448 320 430T378 380T406 316T415 245Q415 238 408 231H126V216Q126 68 226 36Q246 30 270 30Q312 30 342 62Q359 79 369 104L379 128Q382 131 395 131H398Q415 131 415 121Q415 117 412 108Q393 53 349 21T250 -11Q155 -11 92 58T28 218ZM333 275Q322 403 238 411H236Q228 411 220 410T195 402T166 381T143 340T127 274V267H333V275Z" transform="translate(2312,0)" style="stroke-width: 3;"/></g></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><msub><mi>N</mi><mtext>visible</mtext></msub></math></mjx-assistive-mml></mjx-container> antes de enviar los datos a cada conexión dentro del tiempo disponible por actualización. Consulta nuestra <a href="/es/guides/browser-3d-open-world-tech.html#client-server-communication">guía sobre redes</a> para conocer las ventajas y desventajas de la compresión delta y de las distintas frecuencias de actualización.</p>
<p><strong>Limitaciones del renderizado móvil.</strong> Las GPU móviles ofrecen entre 1/5 y 1/10 del rendimiento de las GPU de escritorio, tienen un límite de memoria de aproximadamente 1 GB —frente a 2-4 GB en equipos de escritorio— y reducen su rendimiento por temperatura bajo cargas prolongadas. Un perfil de calidad móvil reduce la densidad de segmentos, el número de objetos, la resolución de renderizado, la distancia de dibujado y la calidad de las sombras. El objetivo no es igualar la calidad de escritorio, sino mantener la legibilidad y la capacidad de respuesta. Consulta las <a href="/es/guides/browser-3d-open-world-tech.html#browser-3d-performance-real-numbers">cifras de rendimiento 3D en el navegador</a> para ver pruebas de rendimiento con GPU reales.</p>
<hr>
<p>Parte 3 de 12.<br>
Anterior: <a href="/es/blog/2026-02-25-open-world-browser-part-02-worker-physics.html">Parte 2 - La física en un worker y el temor al retardo de entrada</a><br>
Siguiente: <a href="/es/blog/2026-02-25-open-world-browser-part-04-streaming-before-fancy.html">Parte 4 - Carga progresiva antes que terrenos sofisticados</a><br>
Guía de la serie: <a href="/es/blog/2026-02-25-open-world-browser-series-guide.html">/es/blog/2026-02-25-open-world-browser-series-guide</a></p>
]]></content:encoded>
            <enclosure url="https://cdn.cinevva.com/blog/why-webgpu-engine-hero.jpg" length="0" type="image/jpg"/>
        </item>
        <item>
            <title><![CDATA[Construyendo un mundo abierto en el navegador, parte 4: Streaming antes que terrenos sofisticados]]></title>
            <link>https://app.cinevva.com/es/blog/2026-02-25-open-world-browser-part-04-streaming-before-fancy</link>
            <guid>https://app.cinevva.com/es/blog/2026-02-25-open-world-browser-part-04-streaming-before-fancy</guid>
            <pubDate>Wed, 25 Feb 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Primero probamos la carga y el intercambio de chunks con contenido sencillo y después pasamos al refinamiento progresivo de mapas de alturas. Ese orden dio sus frutos.]]></description>
            <content:encoded><![CDATA[<h1 id="construyendo-un-mundo-abierto-en-el-navegador-parte-4-streaming-antes-que-terrenos-sofisticados" tabindex="-1">Construyendo un mundo abierto en el navegador, parte 4: Streaming antes que terrenos sofisticados <a class="header-anchor" href="#construyendo-un-mundo-abierto-en-el-navegador-parte-4-streaming-antes-que-terrenos-sofisticados" aria-label="Permalink to &quot;Construyendo un mundo abierto en el navegador, parte 4: Streaming antes que terrenos sofisticados&quot;"></a></h1>
<p><em>Por <a href="/es/about.html">Oleg Sidorkin</a>, CTO y cofundador de Cinevva</em></p>
<p>¿Acabas de llegar? Consulta la <a href="/es/blog/2026-02-25-open-world-browser-series-guide.html">guía de la serie</a>. Explica qué es un spike y enlaza todas las partes.</p>
<p>El streaming es donde suelen venirse abajo los proyectos que «se ven bien».</p>
<p>Se pueden ocultar muchas cosas en una imagen estática. No se puede ocultar un tirón de 40 ms al cruzar el límite de un chunk.</p>
<p>Probamos deliberadamente el streaming antes de crear una representación avanzada del terreno. Así obtuvimos una señal clara sobre el comportamiento de carga y descarga.</p>
<p>El Spike 6 validó la renovación de los chunks vecinos con contenido sencillo.</p>
<div style="position:relative;padding-bottom:56.25%;height:0;overflow:hidden;border-radius:8px;margin:1.5rem 0;border:1px solid rgba(255,255,255,0.12)">
<iframe src="/es/spikes/06-chunk-streaming/" title="Spike 6: carga e intercambio de chunks" style="position:absolute;top:0;left:0;width:100%;height:100%;border:0;background:#000" loading="lazy" allowfullscreen></iframe>
</div>
<p><a href="/es/spikes/06-chunk-streaming/" target="_blank">Abrir el Spike 6 en una pestaña nueva ↗</a> · <a href="/es/blog/spike-source?spike=06-chunk-streaming">Ver código fuente</a></p>
<p>Después pasamos al sistema de terreno real en el Spike 11: streaming de chunks de altura, con decodificación en un worker y refinamiento progresivo mediante cuadrículas de 17, 33 y 65 muestras.</p>
<div style="position:relative;padding-bottom:56.25%;height:0;overflow:hidden;border-radius:8px;margin:1.5rem 0;border:1px solid rgba(255,255,255,0.12)">
<iframe src="/es/spikes/11-chunk-streaming/" title="Spike 11: streaming de chunks de mapas de alturas" style="position:absolute;top:0;left:0;width:100%;height:100%;border:0;background:#000" loading="lazy" allowfullscreen></iframe>
</div>
<p><a href="/es/spikes/11-chunk-streaming/" target="_blank">Abrir el Spike 11 en una pestaña nueva ↗</a> · <a href="/es/blog/spike-source?spike=11-chunk-streaming">Ver código fuente</a></p>
<p>El orden importó más de lo que esperábamos. Si hubiéramos empezado directamente con chunks de altura comprimidos, la causa de cada tirón habría sido ambigua: un problema de decodificación, de subida de texturas o de actualización de geometría. El Spike 6 eliminó una capa de incertidumbre antes de que el Spike 11 añadiera complejidad.</p>
<p>Una lección práctica de este capítulo se trasladó a los spikes posteriores. Las pausas provocadas por las subidas deben medirse directamente, no deducirse a partir de los FPS medios. Los FPS medios ocultan los picos en el tiempo de fotograma, y esos picos son lo que realmente perciben los usuarios.</p>
<p>En la parte 5 entramos en el capítulo del coste visual, donde la vegetación, los shaders del terreno y las sombras en cascada compiten por el mismo presupuesto de fotograma.</p>
<h2 id="tecnologia-mencionada-en-este-capitulo" tabindex="-1">Tecnología mencionada en este capítulo <a class="header-anchor" href="#tecnologia-mencionada-en-este-capitulo" aria-label="Permalink to &quot;Tecnología mencionada en este capítulo&quot;"></a></h2>
<p><strong>Streaming basado en chunks.</strong> El mundo se divide en una cuadrícula de chunks independientes (normalmente de 64x64 metros). A medida que el jugador se mueve, los chunks del borde posterior se descargan mientras se cargan por streaming los del borde delantero. Así funciona el <a href="/es/guides/browser-3d-open-world-tech.html#skyrim-s-cell-system">sistema de celdas de Skyrim</a>: una cuadrícula de 5x5 celdas cargada alrededor del jugador que se va intercambiando a medida que este se desplaza. La versión para navegador añade la latencia de red a la ecuación, por lo que la precarga predictiva basada en la velocidad del jugador resulta fundamental. Consulta nuestra <a href="/es/guides/landscape-generation-browser.html#streaming-architecture-for-terrain">guía de arquitectura de streaming</a>.</p>
<p><strong>Refinamiento progresivo de mapas de alturas.</strong> Primero se envía el terreno a baja resolución y después se refina. Los tamaños de las cuadrículas no son arbitrarios: cada nivel es una cuadrícula de <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.566ex;" xmlns="http://www.w3.org/2000/svg" width="18.385ex" height="2.497ex" role="img" focusable="false" viewBox="0 -853.7 8126.1 1103.7" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mo"><path data-c="28" d="M94 250Q94 319 104 381T127 488T164 576T202 643T244 695T277 729T302 750H315H319Q333 750 333 741Q333 738 316 720T275 667T226 581T184 443T167 250T184 58T225 -81T274 -167T316 -220T333 -241Q333 -250 318 -250H315H302L274 -226Q180 -141 137 -14T94 250Z" style="stroke-width: 3;"/></g><g data-mml-node="msup" transform="translate(389,0)"><g data-mml-node="mn"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(533,363) scale(0.707)"><path data-c="1D458" d="M121 647Q121 657 125 670T137 683Q138 683 209 688T282 694Q294 694 294 686Q294 679 244 477Q194 279 194 272Q213 282 223 291Q247 309 292 354T362 415Q402 442 438 442Q468 442 485 423T503 369Q503 344 496 327T477 302T456 291T438 288Q418 288 406 299T394 328Q394 353 410 369T442 390L458 393Q446 405 434 405H430Q398 402 367 380T294 316T228 255Q230 254 243 252T267 246T293 238T320 224T342 206T359 180T365 147Q365 130 360 106T354 66Q354 26 381 26Q429 26 459 145Q461 153 479 153H483Q499 153 499 144Q499 139 496 130Q455 -11 378 -11Q333 -11 305 15T277 90Q277 108 280 121T283 145Q283 167 269 183T234 206T200 217T182 220H180Q168 178 159 139T145 81T136 44T129 20T122 7T111 -2Q98 -11 83 -11Q66 -11 57 -1T48 16Q48 26 85 176T158 471L195 616Q196 629 188 632T149 637H144Q134 637 131 637T124 640T121 647Z" style="stroke-width: 3;"/></g></g><g data-mml-node="mo" transform="translate(1562.6,0)"><path data-c="2B" d="M56 237T56 250T70 270H369V420L370 570Q380 583 389 583Q402 583 409 568V270H707Q722 262 722 250T707 230H409V-68Q401 -82 391 -82H389H387Q375 -82 369 -68V230H70Q56 237 56 250Z" style="stroke-width: 3;"/></g><g data-mml-node="mn" transform="translate(2562.8,0)"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(3062.8,0)"><path data-c="29" d="M60 749L64 750Q69 750 74 750H86L114 726Q208 641 251 514T294 250Q294 182 284 119T261 12T224 -76T186 -143T145 -194T113 -227T90 -246Q87 -249 86 -250H74Q66 -250 63 -250T58 -247T55 -238Q56 -237 66 -225Q221 -64 221 250T66 725Q56 737 55 738Q55 746 60 749Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(3674.1,0)"><path data-c="D7" d="M630 29Q630 9 609 9Q604 9 587 25T493 118L389 222L284 117Q178 13 175 11Q171 9 168 9Q160 9 154 15T147 29Q147 36 161 51T255 146L359 250L255 354Q174 435 161 449T147 471Q147 480 153 485T168 490Q173 490 175 489Q178 487 284 383L389 278L493 382Q570 459 587 475T609 491Q630 491 630 471Q630 464 620 453T522 355L418 250L522 145Q606 61 618 48T630 29Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(4674.3,0)"><path data-c="28" d="M94 250Q94 319 104 381T127 488T164 576T202 643T244 695T277 729T302 750H315H319Q333 750 333 741Q333 738 316 720T275 667T226 581T184 443T167 250T184 58T225 -81T274 -167T316 -220T333 -241Q333 -250 318 -250H315H302L274 -226Q180 -141 137 -14T94 250Z" style="stroke-width: 3;"/></g><g data-mml-node="msup" transform="translate(5063.3,0)"><g data-mml-node="mn"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(533,363) scale(0.707)"><path data-c="1D458" d="M121 647Q121 657 125 670T137 683Q138 683 209 688T282 694Q294 694 294 686Q294 679 244 477Q194 279 194 272Q213 282 223 291Q247 309 292 354T362 415Q402 442 438 442Q468 442 485 423T503 369Q503 344 496 327T477 302T456 291T438 288Q418 288 406 299T394 328Q394 353 410 369T442 390L458 393Q446 405 434 405H430Q398 402 367 380T294 316T228 255Q230 254 243 252T267 246T293 238T320 224T342 206T359 180T365 147Q365 130 360 106T354 66Q354 26 381 26Q429 26 459 145Q461 153 479 153H483Q499 153 499 144Q499 139 496 130Q455 -11 378 -11Q333 -11 305 15T277 90Q277 108 280 121T283 145Q283 167 269 183T234 206T200 217T182 220H180Q168 178 159 139T145 81T136 44T129 20T122 7T111 -2Q98 -11 83 -11Q66 -11 57 -1T48 16Q48 26 85 176T158 471L195 616Q196 629 188 632T149 637H144Q134 637 131 637T124 640T121 647Z" style="stroke-width: 3;"/></g></g><g data-mml-node="mo" transform="translate(6236.9,0)"><path data-c="2B" d="M56 237T56 250T70 270H369V420L370 570Q380 583 389 583Q402 583 409 568V270H707Q722 262 722 250T707 230H409V-68Q401 -82 391 -82H389H387Q375 -82 369 -68V230H70Q56 237 56 250Z" style="stroke-width: 3;"/></g><g data-mml-node="mn" transform="translate(7237.1,0)"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(7737.1,0)"><path data-c="29" d="M60 749L64 750Q69 750 74 750H86L114 726Q208 641 251 514T294 250Q294 182 284 119T261 12T224 -76T186 -143T145 -194T113 -227T90 -246Q87 -249 86 -250H74Q66 -250 63 -250T58 -247T55 -238Q56 -237 66 -225Q221 -64 221 250T66 725Q56 737 55 738Q55 746 60 749Z" style="stroke-width: 3;"/></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mo stretchy="false">(</mo><msup><mn>2</mn><mi>k</mi></msup><mo>+</mo><mn>1</mn><mo stretchy="false">)</mo><mo>×</mo><mo stretchy="false">(</mo><msup><mn>2</mn><mi>k</mi></msup><mo>+</mo><mn>1</mn><mo stretchy="false">)</mo></math></mjx-assistive-mml></mjx-container>, de modo que <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.186ex;" xmlns="http://www.w3.org/2000/svg" width="11.295ex" height="2.09ex" role="img" focusable="false" viewBox="0 -841.7 4992.6 923.7" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mn"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" style="stroke-width: 3;"/><path data-c="37" d="M55 458Q56 460 72 567L88 674Q88 676 108 676H128V672Q128 662 143 655T195 646T364 644H485V605L417 512Q408 500 387 472T360 435T339 403T319 367T305 330T292 284T284 230T278 162T275 80Q275 66 275 52T274 28V19Q270 2 255 -10T221 -22Q210 -22 200 -19T179 0T168 40Q168 198 265 368Q285 400 349 489L395 552H302Q128 552 119 546Q113 543 108 522T98 479L95 458V455H55V458Z" transform="translate(500,0)" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(1277.8,0)"><path data-c="3D" d="M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z" style="stroke-width: 3;"/></g><g data-mml-node="msup" transform="translate(2333.6,0)"><g data-mml-node="mn"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"/></g><g data-mml-node="mn" transform="translate(533,363) scale(0.707)"><path data-c="34" d="M462 0Q444 3 333 3Q217 3 199 0H190V46H221Q241 46 248 46T265 48T279 53T286 61Q287 63 287 115V165H28V211L179 442Q332 674 334 675Q336 677 355 677H373L379 671V211H471V165H379V114Q379 73 379 66T385 54Q393 47 442 46H471V0H462ZM293 211V545L74 212L183 211H293Z" style="stroke-width: 3;"/></g></g><g data-mml-node="mo" transform="translate(3492.3,0)"><path data-c="2B" d="M56 237T56 250T70 270H369V420L370 570Q380 583 389 583Q402 583 409 568V270H707Q722 262 722 250T707 230H409V-68Q401 -82 391 -82H389H387Q375 -82 369 -68V230H70Q56 237 56 250Z" style="stroke-width: 3;"/></g><g data-mml-node="mn" transform="translate(4492.6,0)"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" style="stroke-width: 3;"/></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mn>17</mn><mo>=</mo><msup><mn>2</mn><mn>4</mn></msup><mo>+</mo><mn>1</mn></math></mjx-assistive-mml></mjx-container>, <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.186ex;" xmlns="http://www.w3.org/2000/svg" width="11.295ex" height="2.072ex" role="img" focusable="false" viewBox="0 -833.9 4992.6 915.9" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mn"><path data-c="33" d="M127 463Q100 463 85 480T69 524Q69 579 117 622T233 665Q268 665 277 664Q351 652 390 611T430 522Q430 470 396 421T302 350L299 348Q299 347 308 345T337 336T375 315Q457 262 457 175Q457 96 395 37T238 -22Q158 -22 100 21T42 130Q42 158 60 175T105 193Q133 193 151 175T169 130Q169 119 166 110T159 94T148 82T136 74T126 70T118 67L114 66Q165 21 238 21Q293 21 321 74Q338 107 338 175V195Q338 290 274 322Q259 328 213 329L171 330L168 332Q166 335 166 348Q166 366 174 366Q202 366 232 371Q266 376 294 413T322 525V533Q322 590 287 612Q265 626 240 626Q208 626 181 615T143 592T132 580H135Q138 579 143 578T153 573T165 566T175 555T183 540T186 520Q186 498 172 481T127 463Z" style="stroke-width: 3;"/><path data-c="33" d="M127 463Q100 463 85 480T69 524Q69 579 117 622T233 665Q268 665 277 664Q351 652 390 611T430 522Q430 470 396 421T302 350L299 348Q299 347 308 345T337 336T375 315Q457 262 457 175Q457 96 395 37T238 -22Q158 -22 100 21T42 130Q42 158 60 175T105 193Q133 193 151 175T169 130Q169 119 166 110T159 94T148 82T136 74T126 70T118 67L114 66Q165 21 238 21Q293 21 321 74Q338 107 338 175V195Q338 290 274 322Q259 328 213 329L171 330L168 332Q166 335 166 348Q166 366 174 366Q202 366 232 371Q266 376 294 413T322 525V533Q322 590 287 612Q265 626 240 626Q208 626 181 615T143 592T132 580H135Q138 579 143 578T153 573T165 566T175 555T183 540T186 520Q186 498 172 481T127 463Z" transform="translate(500,0)" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(1277.8,0)"><path data-c="3D" d="M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z" style="stroke-width: 3;"/></g><g data-mml-node="msup" transform="translate(2333.6,0)"><g data-mml-node="mn"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"/></g><g data-mml-node="mn" transform="translate(533,363) scale(0.707)"><path data-c="35" d="M164 157Q164 133 148 117T109 101H102Q148 22 224 22Q294 22 326 82Q345 115 345 210Q345 313 318 349Q292 382 260 382H254Q176 382 136 314Q132 307 129 306T114 304Q97 304 95 310Q93 314 93 485V614Q93 664 98 664Q100 666 102 666Q103 666 123 658T178 642T253 634Q324 634 389 662Q397 666 402 666Q410 666 410 648V635Q328 538 205 538Q174 538 149 544L139 546V374Q158 388 169 396T205 412T256 420Q337 420 393 355T449 201Q449 109 385 44T229 -22Q148 -22 99 32T50 154Q50 178 61 192T84 210T107 214Q132 214 148 197T164 157Z" style="stroke-width: 3;"/></g></g><g data-mml-node="mo" transform="translate(3492.3,0)"><path data-c="2B" d="M56 237T56 250T70 270H369V420L370 570Q380 583 389 583Q402 583 409 568V270H707Q722 262 722 250T707 230H409V-68Q401 -82 391 -82H389H387Q375 -82 369 -68V230H70Q56 237 56 250Z" style="stroke-width: 3;"/></g><g data-mml-node="mn" transform="translate(4492.6,0)"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" style="stroke-width: 3;"/></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mn>33</mn><mo>=</mo><msup><mn>2</mn><mn>5</mn></msup><mo>+</mo><mn>1</mn></math></mjx-assistive-mml></mjx-container> y <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.186ex;" xmlns="http://www.w3.org/2000/svg" width="11.295ex" height="2.072ex" role="img" focusable="false" viewBox="0 -833.9 4992.6 915.9" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mn"><path data-c="36" d="M42 313Q42 476 123 571T303 666Q372 666 402 630T432 550Q432 525 418 510T379 495Q356 495 341 509T326 548Q326 592 373 601Q351 623 311 626Q240 626 194 566Q147 500 147 364L148 360Q153 366 156 373Q197 433 263 433H267Q313 433 348 414Q372 400 396 374T435 317Q456 268 456 210V192Q456 169 451 149Q440 90 387 34T253 -22Q225 -22 199 -14T143 16T92 75T56 172T42 313ZM257 397Q227 397 205 380T171 335T154 278T148 216Q148 133 160 97T198 39Q222 21 251 21Q302 21 329 59Q342 77 347 104T352 209Q352 289 347 316T329 361Q302 397 257 397Z" style="stroke-width: 3;"/><path data-c="35" d="M164 157Q164 133 148 117T109 101H102Q148 22 224 22Q294 22 326 82Q345 115 345 210Q345 313 318 349Q292 382 260 382H254Q176 382 136 314Q132 307 129 306T114 304Q97 304 95 310Q93 314 93 485V614Q93 664 98 664Q100 666 102 666Q103 666 123 658T178 642T253 634Q324 634 389 662Q397 666 402 666Q410 666 410 648V635Q328 538 205 538Q174 538 149 544L139 546V374Q158 388 169 396T205 412T256 420Q337 420 393 355T449 201Q449 109 385 44T229 -22Q148 -22 99 32T50 154Q50 178 61 192T84 210T107 214Q132 214 148 197T164 157Z" transform="translate(500,0)" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(1277.8,0)"><path data-c="3D" d="M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z" style="stroke-width: 3;"/></g><g data-mml-node="msup" transform="translate(2333.6,0)"><g data-mml-node="mn"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"/></g><g data-mml-node="mn" transform="translate(533,363) scale(0.707)"><path data-c="36" d="M42 313Q42 476 123 571T303 666Q372 666 402 630T432 550Q432 525 418 510T379 495Q356 495 341 509T326 548Q326 592 373 601Q351 623 311 626Q240 626 194 566Q147 500 147 364L148 360Q153 366 156 373Q197 433 263 433H267Q313 433 348 414Q372 400 396 374T435 317Q456 268 456 210V192Q456 169 451 149Q440 90 387 34T253 -22Q225 -22 199 -14T143 16T92 75T56 172T42 313ZM257 397Q227 397 205 380T171 335T154 278T148 216Q148 133 160 97T198 39Q222 21 251 21Q302 21 329 59Q342 77 347 104T352 209Q352 289 347 316T329 361Q302 397 257 397Z" style="stroke-width: 3;"/></g></g><g data-mml-node="mo" transform="translate(3492.3,0)"><path data-c="2B" d="M56 237T56 250T70 270H369V420L370 570Q380 583 389 583Q402 583 409 568V270H707Q722 262 722 250T707 230H409V-68Q401 -82 391 -82H389H387Q375 -82 369 -68V230H70Q56 237 56 250Z" style="stroke-width: 3;"/></g><g data-mml-node="mn" transform="translate(4492.6,0)"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" style="stroke-width: 3;"/></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mn>65</mn><mo>=</mo><msup><mn>2</mn><mn>6</mn></msup><mo>+</mo><mn>1</mn></math></mjx-assistive-mml></mjx-container>. El <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.186ex;" xmlns="http://www.w3.org/2000/svg" width="2.891ex" height="1.692ex" role="img" focusable="false" viewBox="0 -666 1278 748" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mo"><path data-c="2B" d="M56 237T56 250T70 270H369V420L370 570Q380 583 389 583Q402 583 409 568V270H707Q722 262 722 250T707 230H409V-68Q401 -82 391 -82H389H387Q375 -82 369 -68V230H70Q56 237 56 250Z" style="stroke-width: 3;"/></g><g data-mml-node="mn" transform="translate(778,0)"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" style="stroke-width: 3;"/></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mo>+</mo><mn>1</mn></math></mjx-assistive-mml></mjx-container> mantiene una muestra compartida en cada límite para que los chunks vecinos encajen, y cada paso cuadruplica aproximadamente el número de muestras (<mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.025ex;" xmlns="http://www.w3.org/2000/svg" width="2.345ex" height="1.912ex" role="img" focusable="false" viewBox="0 -833.9 1036.6 844.9" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="msup"><g data-mml-node="mi"><path data-c="1D45B" d="M21 287Q22 293 24 303T36 341T56 388T89 425T135 442Q171 442 195 424T225 390T231 369Q231 367 232 367L243 378Q304 442 382 442Q436 442 469 415T503 336T465 179T427 52Q427 26 444 26Q450 26 453 27Q482 32 505 65T540 145Q542 153 560 153Q580 153 580 145Q580 144 576 130Q568 101 554 73T508 17T439 -10Q392 -10 371 17T350 73Q350 92 386 193T423 345Q423 404 379 404H374Q288 404 229 303L222 291L189 157Q156 26 151 16Q138 -11 108 -11Q95 -11 87 -5T76 7T74 17Q74 30 112 180T152 343Q153 348 153 366Q153 405 129 405Q91 405 66 305Q60 285 60 284Q58 278 41 278H27Q21 284 21 287Z" style="stroke-width: 3;"/></g><g data-mml-node="mn" transform="translate(633,363) scale(0.707)"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"/></g></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><msup><mi>n</mi><mn>2</mn></msup></math></mjx-assistive-mml></mjx-container> crece al duplicarse el lado). Una cuadrícula de 17x17 (el mínimo para un chunk de 64 m con un espaciado de 4 m) ocupa unos 200 bytes comprimida y permite renderizar al instante una superficie visible. Después se transmite el refinamiento de 33x33 y, por último, la resolución completa de 65x65. Cada nivel añade muestras sin sustituir los datos anteriores. Esto se corresponde directamente con los anillos de LOD de los clipmaps geométricos, donde el terreno lejano utiliza datos de baja resolución y el terreno cercano emplea la resolución completa. Consulta la <a href="/es/guides/landscape-generation-browser.html#progressive-chunk-loading">carga progresiva de chunks</a>.</p>
<p><strong>Codificación delta y compresión.</strong> Los datos de los mapas de alturas se comprimen bien porque las celdas adyacentes tienen valores similares. La codificación delta almacena la diferencia entre cada celda y su valor previsto (el promedio de sus vecinas), concentrando los valores cerca de cero. Combinada con zlib o brotli, reduce un chunk de 65x65 de 8,4 KB sin comprimir a 1-2 KB comprimido. Con precisión reducida para chunks lejanos (8 bits en lugar de 16 bits): 0,5-1 KB. Consulta la <a href="/es/guides/landscape-generation-browser.html#terrain-data-compression-for-streaming">compresión de datos del terreno</a>.</p>
<p><strong>Precarga predictiva.</strong> Consiste en cargar los chunks antes de que llegue el jugador. La distancia de anticipación debe cubrir cuánto recorre el jugador mientras se carga un chunk, <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.65ex;" xmlns="http://www.w3.org/2000/svg" width="16.701ex" height="2.22ex" role="img" focusable="false" viewBox="0 -694 7381.6 981.2" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="msub"><g data-mml-node="mi"><path data-c="1D451" d="M366 683Q367 683 438 688T511 694Q523 694 523 686Q523 679 450 384T375 83T374 68Q374 26 402 26Q411 27 422 35Q443 55 463 131Q469 151 473 152Q475 153 483 153H487H491Q506 153 506 145Q506 140 503 129Q490 79 473 48T445 8T417 -8Q409 -10 393 -10Q359 -10 336 5T306 36L300 51Q299 52 296 50Q294 48 292 46Q233 -10 172 -10Q117 -10 75 30T33 157Q33 205 53 255T101 341Q148 398 195 420T280 442Q336 442 364 400Q369 394 369 396Q370 400 396 505T424 616Q424 629 417 632T378 637H357Q351 643 351 645T353 664Q358 683 366 683ZM352 326Q329 405 277 405Q242 405 210 374T160 293Q131 214 119 129Q119 126 119 118T118 106Q118 61 136 44T179 26Q233 26 290 98L298 109L352 326Z" style="stroke-width: 3;"/></g><g data-mml-node="mtext" transform="translate(553,-150) scale(0.707)"><path data-c="70" d="M36 -148H50Q89 -148 97 -134V-126Q97 -119 97 -107T97 -77T98 -38T98 6T98 55T98 106Q98 140 98 177T98 243T98 296T97 335T97 351Q94 370 83 376T38 385H20V408Q20 431 22 431L32 432Q42 433 61 434T98 436Q115 437 135 438T165 441T176 442H179V416L180 390L188 397Q247 441 326 441Q407 441 464 377T522 216Q522 115 457 52T310 -11Q242 -11 190 33L182 40V-45V-101Q182 -128 184 -134T195 -145Q216 -148 244 -148H260V-194H252L228 -193Q205 -192 178 -192T140 -191Q37 -191 28 -194H20V-148H36ZM424 218Q424 292 390 347T305 402Q234 402 182 337V98Q222 26 294 26Q345 26 384 80T424 218Z" style="stroke-width: 3;"/><path data-c="72" d="M36 46H50Q89 46 97 60V68Q97 77 97 91T98 122T98 161T98 203Q98 234 98 269T98 328L97 351Q94 370 83 376T38 385H20V408Q20 431 22 431L32 432Q42 433 60 434T96 436Q112 437 131 438T160 441T171 442H174V373Q213 441 271 441H277Q322 441 343 419T364 373Q364 352 351 337T313 322Q288 322 276 338T263 372Q263 381 265 388T270 400T273 405Q271 407 250 401Q234 393 226 386Q179 341 179 207V154Q179 141 179 127T179 101T180 81T180 66V61Q181 59 183 57T188 54T193 51T200 49T207 48T216 47T225 47T235 46T245 46H276V0H267Q249 3 140 3Q37 3 28 0H20V46H36Z" transform="translate(556,0)" style="stroke-width: 3;"/><path data-c="65" d="M28 218Q28 273 48 318T98 391T163 433T229 448Q282 448 320 430T378 380T406 316T415 245Q415 238 408 231H126V216Q126 68 226 36Q246 30 270 30Q312 30 342 62Q359 79 369 104L379 128Q382 131 395 131H398Q415 131 415 121Q415 117 412 108Q393 53 349 21T250 -11Q155 -11 92 58T28 218ZM333 275Q322 403 238 411H236Q228 411 220 410T195 402T166 381T143 340T127 274V267H333V275Z" transform="translate(948,0)" style="stroke-width: 3;"/><path data-c="66" d="M273 0Q255 3 146 3Q43 3 34 0H26V46H42Q70 46 91 49Q99 52 103 60Q104 62 104 224V385H33V431H104V497L105 564L107 574Q126 639 171 668T266 704Q267 704 275 704T289 705Q330 702 351 679T372 627Q372 604 358 590T321 576T284 590T270 627Q270 647 288 667H284Q280 668 273 668Q245 668 223 647T189 592Q183 572 182 497V431H293V385H185V225Q185 63 186 61T189 57T194 54T199 51T206 49T213 48T222 47T231 47T241 46T251 46H282V0H273Z" transform="translate(1392,0)" style="stroke-width: 3;"/><path data-c="65" d="M28 218Q28 273 48 318T98 391T163 433T229 448Q282 448 320 430T378 380T406 316T415 245Q415 238 408 231H126V216Q126 68 226 36Q246 30 270 30Q312 30 342 62Q359 79 369 104L379 128Q382 131 395 131H398Q415 131 415 121Q415 117 412 108Q393 53 349 21T250 -11Q155 -11 92 58T28 218ZM333 275Q322 403 238 411H236Q228 411 220 410T195 402T166 381T143 340T127 274V267H333V275Z" transform="translate(1698,0)" style="stroke-width: 3;"/><path data-c="74" d="M27 422Q80 426 109 478T141 600V615H181V431H316V385H181V241Q182 116 182 100T189 68Q203 29 238 29Q282 29 292 100Q293 108 293 146V181H333V146V134Q333 57 291 17Q264 -10 221 -10Q187 -10 162 2T124 33T105 68T98 100Q97 107 97 248V385H18V422H27Z" transform="translate(2142,0)" style="stroke-width: 3;"/><path data-c="63" d="M370 305T349 305T313 320T297 358Q297 381 312 396Q317 401 317 402T307 404Q281 408 258 408Q209 408 178 376Q131 329 131 219Q131 137 162 90Q203 29 272 29Q313 29 338 55T374 117Q376 125 379 127T395 129H409Q415 123 415 120Q415 116 411 104T395 71T366 33T318 2T249 -11Q163 -11 99 53T34 214Q34 318 99 383T250 448T370 421T404 357Q404 334 387 320Z" transform="translate(2531,0)" style="stroke-width: 3;"/><path data-c="68" d="M41 46H55Q94 46 102 60V68Q102 77 102 91T102 124T102 167T103 217T103 272T103 329Q103 366 103 407T103 482T102 542T102 586T102 603Q99 622 88 628T43 637H25V660Q25 683 27 683L37 684Q47 685 66 686T103 688Q120 689 140 690T170 693T181 694H184V367Q244 442 328 442Q451 442 463 329Q464 322 464 190V104Q464 66 466 59T477 49Q498 46 526 46H542V0H534L510 1Q487 2 460 2T422 3Q319 3 310 0H302V46H318Q379 46 379 62Q380 64 380 200Q379 335 378 343Q372 371 358 385T334 402T308 404Q263 404 229 370Q202 343 195 315T187 232V168V108Q187 78 188 68T191 55T200 49Q221 46 249 46H265V0H257L234 1Q210 2 183 2T145 3Q42 3 33 0H25V46H41Z" transform="translate(2975,0)" style="stroke-width: 3;"/></g></g><g data-mml-node="mo" transform="translate(3377.6,0)"><path data-c="3D" d="M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(4433.3,0)"><path data-c="1D463" d="M173 380Q173 405 154 405Q130 405 104 376T61 287Q60 286 59 284T58 281T56 279T53 278T49 278T41 278H27Q21 284 21 287Q21 294 29 316T53 368T97 419T160 441Q202 441 225 417T249 361Q249 344 246 335Q246 329 231 291T200 202T182 113Q182 86 187 69Q200 26 250 26Q287 26 319 60T369 139T398 222T409 277Q409 300 401 317T383 343T365 361T357 383Q357 405 376 424T417 443Q436 443 451 425T467 367Q467 340 455 284T418 159T347 40T241 -11Q177 -11 139 22Q102 54 102 117Q102 148 110 181T151 298Q173 362 173 380Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(5140.6,0)"><path data-c="22C5" d="M78 250Q78 274 95 292T138 310Q162 310 180 294T199 251Q199 226 182 208T139 190T96 207T78 250Z" style="stroke-width: 3;"/></g><g data-mml-node="msub" transform="translate(5640.8,0)"><g data-mml-node="mi"><path data-c="1D461" d="M26 385Q19 392 19 395Q19 399 22 411T27 425Q29 430 36 430T87 431H140L159 511Q162 522 166 540T173 566T179 586T187 603T197 615T211 624T229 626Q247 625 254 615T261 596Q261 589 252 549T232 470L222 433Q222 431 272 431H323Q330 424 330 420Q330 398 317 385H210L174 240Q135 80 135 68Q135 26 162 26Q197 26 230 60T283 144Q285 150 288 151T303 153H307Q322 153 322 145Q322 142 319 133Q314 117 301 95T267 48T216 6T155 -11Q125 -11 98 4T59 56Q57 64 57 83V101L92 241Q127 382 128 383Q128 385 77 385H26Z" style="stroke-width: 3;"/></g><g data-mml-node="mtext" transform="translate(394,-150) scale(0.707)"><path data-c="6C" d="M42 46H56Q95 46 103 60V68Q103 77 103 91T103 124T104 167T104 217T104 272T104 329Q104 366 104 407T104 482T104 542T103 586T103 603Q100 622 89 628T44 637H26V660Q26 683 28 683L38 684Q48 685 67 686T104 688Q121 689 141 690T171 693T182 694H185V379Q185 62 186 60Q190 52 198 49Q219 46 247 46H263V0H255L232 1Q209 2 183 2T145 3T107 3T57 1L34 0H26V46H42Z" style="stroke-width: 3;"/><path data-c="6F" d="M28 214Q28 309 93 378T250 448Q340 448 405 380T471 215Q471 120 407 55T250 -10Q153 -10 91 57T28 214ZM250 30Q372 30 372 193V225V250Q372 272 371 288T364 326T348 362T317 390T268 410Q263 411 252 411Q222 411 195 399Q152 377 139 338T126 246V226Q126 130 145 91Q177 30 250 30Z" transform="translate(278,0)" style="stroke-width: 3;"/><path data-c="61" d="M137 305T115 305T78 320T63 359Q63 394 97 421T218 448Q291 448 336 416T396 340Q401 326 401 309T402 194V124Q402 76 407 58T428 40Q443 40 448 56T453 109V145H493V106Q492 66 490 59Q481 29 455 12T400 -6T353 12T329 54V58L327 55Q325 52 322 49T314 40T302 29T287 17T269 6T247 -2T221 -8T190 -11Q130 -11 82 20T34 107Q34 128 41 147T68 188T116 225T194 253T304 268H318V290Q318 324 312 340Q290 411 215 411Q197 411 181 410T156 406T148 403Q170 388 170 359Q170 334 154 320ZM126 106Q126 75 150 51T209 26Q247 26 276 49T315 109Q317 116 318 175Q318 233 317 233Q309 233 296 232T251 223T193 203T147 166T126 106Z" transform="translate(778,0)" style="stroke-width: 3;"/><path data-c="64" d="M376 495Q376 511 376 535T377 568Q377 613 367 624T316 637H298V660Q298 683 300 683L310 684Q320 685 339 686T376 688Q393 689 413 690T443 693T454 694H457V390Q457 84 458 81Q461 61 472 55T517 46H535V0Q533 0 459 -5T380 -11H373V44L365 37Q307 -11 235 -11Q158 -11 96 50T34 215Q34 315 97 378T244 442Q319 442 376 393V495ZM373 342Q328 405 260 405Q211 405 173 369Q146 341 139 305T131 211Q131 155 138 120T173 59Q203 26 251 26Q322 26 373 103V342Z" transform="translate(1278,0)" style="stroke-width: 3;"/></g></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><msub><mi>d</mi><mtext>prefetch</mtext></msub><mo>=</mo><mi>v</mi><mo>⋅</mo><msub><mi>t</mi><mtext>load</mtext></msub></math></mjx-assistive-mml></mjx-container>, por lo que aumenta con la velocidad: al caminar (5 km/h), se precargan 2 chunks por delante (128 m); al correr (15 km/h), se precargan 4. El anillo de carga se desplaza según la dirección de la velocidad. Una cola de prioridad ordena las solicitudes pendientes por urgencia y cancela las de chunks de los que el jugador se ha alejado. Consulta la <a href="/es/guides/landscape-generation-browser.html#predictive-pre-fetching">precarga predictiva</a>.</p>
<hr>
<p>Parte 4 de 12.<br>
Anterior: <a href="/es/blog/2026-02-25-open-world-browser-part-03-the-unflashy-spikes.html">Parte 3 - Los spikes poco vistosos que nos salvaron</a><br>
Siguiente: <a href="/es/blog/2026-02-25-open-world-browser-part-05-budgeting-the-pretty.html">Parte 5 - Presupuestar los elementos visuales</a><br>
Guía de la serie: <a href="/es/blog/2026-02-25-open-world-browser-series-guide.html">/es/blog/2026-02-25-open-world-browser-series-guide</a></p>
]]></content:encoded>
            <enclosure url="https://cdn.cinevva.com/blog/why-webgpu-engine-hero.jpg" length="0" type="image/jpg"/>
        </item>
        <item>
            <title><![CDATA[Construir un mundo abierto en el navegador, parte 5: Presupuestar los elementos visuales]]></title>
            <link>https://app.cinevva.com/es/blog/2026-02-25-open-world-browser-part-05-budgeting-the-pretty</link>
            <guid>https://app.cinevva.com/es/blog/2026-02-25-open-world-browser-part-05-budgeting-the-pretty</guid>
            <pubDate>Wed, 25 Feb 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[La vegetación, los materiales del terreno y las sombras en cascada se veían muy bien. El verdadero trabajo consistía en demostrar que cabían en el presupuesto por fotograma.]]></description>
            <content:encoded><![CDATA[<h1 id="construir-un-mundo-abierto-en-el-navegador-parte-5-presupuestar-los-elementos-visuales" tabindex="-1">Construir un mundo abierto en el navegador, parte 5: Presupuestar los elementos visuales <a class="header-anchor" href="#construir-un-mundo-abierto-en-el-navegador-parte-5-presupuestar-los-elementos-visuales" aria-label="Permalink to &quot;Construir un mundo abierto en el navegador, parte 5: Presupuestar los elementos visuales&quot;"></a></h1>
<p><em>Por <a href="/es/about.html">Oleg Sidorkin</a>, CTO y cofundador de Cinevva</em></p>
<p>¿Acabas de llegar? Consulta la <a href="/es/blog/2026-02-25-open-world-browser-series-guide.html">guía de la serie</a>. Explica qué es un spike y enlaza todas las partes.</p>
<p>Este fue el capítulo en el que la ambición visual se encontró con la aritmética.</p>
<p>Dividimos el coste de renderizado en spikes independientes porque los resultados combinados son difíciles de diagnosticar. Si activas todo a la vez, solo descubres que el fotograma tarda demasiado. No descubres qué función se ha comido el presupuesto.</p>
<p>El spike 7 se centró en la densidad de la vegetación y el coste de la animación. El enfoque consistía en dispersarla en tiempo de ejecución a partir de mapas de densidad de 32x32 por fragmento de terreno, que alimentaban grandes conjuntos de <code>InstancedMesh</code>. Cada brizna de hierba y grupo de arbustos recibía viento en el sombreador de vértices, controlado mediante una textura de ruido en desplazamiento. La cifra clave que vigilábamos no era el número de triángulos, sino la sobrecarga de las llamadas de dibujado y el rendimiento de vértices en GPU de gama media. Descubrimos que agrupar las instancias en menos mallas importaba más que reducir el número de polígonos de cada brizna.</p>
<div style="position:relative;padding-bottom:56.25%;height:0;overflow:hidden;border-radius:8px;margin:1.5rem 0;border:1px solid rgba(255,255,255,0.12)">
<iframe src="/es/spikes/07-gpu-vegetation/" title="Spike 7: vegetación en la GPU" style="position:absolute;top:0;left:0;width:100%;height:100%;border:0;background:#000" loading="lazy" allowfullscreen></iframe>
</div>
<p><a href="/es/spikes/07-gpu-vegetation/" target="_blank">Abrir el spike 7 en una pestaña nueva ↗</a> · <a href="/es/blog/spike-source?spike=07-gpu-vegetation">Ver el código fuente</a></p>
<p>El spike 8 llevó más lejos la complejidad de los materiales del terreno. Mezcla multicapa ponderada según el ángulo de la pendiente y la altitud, proyección triplanar opcional para las paredes de los acantilados y mapas de normales por capa. El sombreador realizaba splatting en función de la pendiente con cuatro capas de texturas, cada una de las cuales requería una muestra difusa y otra de normales. Eso supone <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.186ex;" xmlns="http://www.w3.org/2000/svg" width="9.176ex" height="1.717ex" role="img" focusable="false" viewBox="0 -677 4056 759" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mn"><path data-c="34" d="M462 0Q444 3 333 3Q217 3 199 0H190V46H221Q241 46 248 46T265 48T279 53T286 61Q287 63 287 115V165H28V211L179 442Q332 674 334 675Q336 677 355 677H373L379 671V211H471V165H379V114Q379 73 379 66T385 54Q393 47 442 46H471V0H462ZM293 211V545L74 212L183 211H293Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(722.2,0)"><path data-c="D7" d="M630 29Q630 9 609 9Q604 9 587 25T493 118L389 222L284 117Q178 13 175 11Q171 9 168 9Q160 9 154 15T147 29Q147 36 161 51T255 146L359 250L255 354Q174 435 161 449T147 471Q147 480 153 485T168 490Q173 490 175 489Q178 487 284 383L389 278L493 382Q570 459 587 475T609 491Q630 491 630 471Q630 464 620 453T522 355L418 250L522 145Q606 61 618 48T630 29Z" style="stroke-width: 3;"/></g><g data-mml-node="mn" transform="translate(1722.4,0)"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(2500.2,0)"><path data-c="3D" d="M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z" style="stroke-width: 3;"/></g><g data-mml-node="mn" transform="translate(3556,0)"><path data-c="38" d="M70 417T70 494T124 618T248 666Q319 666 374 624T429 515Q429 485 418 459T392 417T361 389T335 371T324 363L338 354Q352 344 366 334T382 323Q457 264 457 174Q457 95 399 37T249 -22Q159 -22 101 29T43 155Q43 263 172 335L154 348Q133 361 127 368Q70 417 70 494ZM286 386L292 390Q298 394 301 396T311 403T323 413T334 425T345 438T355 454T364 471T369 491T371 513Q371 556 342 586T275 624Q268 625 242 625Q201 625 165 599T128 534Q128 511 141 492T167 463T217 431Q224 426 228 424L286 386ZM250 21Q308 21 350 55T392 137Q392 154 387 169T375 194T353 216T330 234T301 253T274 270Q260 279 244 289T218 306L210 311Q204 311 181 294T133 239T107 157Q107 98 150 60T250 21Z" style="stroke-width: 3;"/></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mn>4</mn><mo>×</mo><mn>2</mn><mo>=</mo><mn>8</mn></math></mjx-assistive-mml></mjx-container> lecturas de textura por fragmento antes de añadir cualquier iluminación, y la cifra aumenta linealmente con el número de capas, por lo que una quinta capa implica 10 lecturas por píxel. Hicimos perfiles específicamente en GPU integradas de Intel para determinar el mínimo. La conclusión fue que la proyección triplanar en superficies verticales justificaba su coste, pero añadir una quinta capa de splat no.</p>
<p><a href="/es/spikes/08-terrain-material/" target="_blank">Abrir el spike 8 en una pestaña nueva ↗</a> · <a href="/es/blog/spike-source?spike=08-terrain-material">Ver el código fuente</a></p>
<p>El spike 9 se centró en el coste de los mapas de sombras en cascada con una carga realista de terreno y objetos. La referencia inicial era CSM con tres cascadas. Hicimos pruebas específicamente con el sol en posiciones de ángulo bajo, porque es ahí donde la presión sobre las cascadas alcanza su punto máximo. La cascada lejana cubre una enorme sección del frustum, y el detalle de las sombras viene determinado por la densidad de téxeles, <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.783ex;" xmlns="http://www.w3.org/2000/svg" width="7.095ex" height="3.009ex" role="img" focusable="false" viewBox="0 -983.7 3135.9 1330" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mi"><path data-c="1D70C" d="M58 -216Q25 -216 23 -186Q23 -176 73 26T127 234Q143 289 182 341Q252 427 341 441Q343 441 349 441T359 442Q432 442 471 394T510 276Q510 219 486 165T425 74T345 13T266 -10H255H248Q197 -10 165 35L160 41L133 -71Q108 -168 104 -181T92 -202Q76 -216 58 -216ZM424 322Q424 359 407 382T357 405Q322 405 287 376T231 300Q217 269 193 170L176 102Q193 26 260 26Q298 26 334 62Q367 92 389 158T418 266T424 322Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(794.8,0)"><path data-c="2248" d="M55 319Q55 360 72 393T114 444T163 472T205 482Q207 482 213 482T223 483Q262 483 296 468T393 413L443 381Q502 346 553 346Q609 346 649 375T694 454Q694 465 698 474T708 483Q722 483 722 452Q722 386 675 338T555 289Q514 289 468 310T388 357T308 404T224 426Q164 426 125 393T83 318Q81 289 69 289Q55 289 55 319ZM55 85Q55 126 72 159T114 210T163 238T205 248Q207 248 213 248T223 249Q262 249 296 234T393 179L443 147Q502 112 553 112Q609 112 649 141T694 220Q694 249 708 249T722 217Q722 153 675 104T555 55Q514 55 468 76T388 123T308 170T224 192Q164 192 125 159T83 84Q80 55 69 55Q55 55 55 85Z" style="stroke-width: 3;"/></g><g data-mml-node="mfrac" transform="translate(1850.6,0)"><g data-mml-node="msup" transform="translate(220,394) scale(0.707)"><g data-mml-node="mi"><path data-c="1D445" d="M230 637Q203 637 198 638T193 649Q193 676 204 682Q206 683 378 683Q550 682 564 680Q620 672 658 652T712 606T733 563T739 529Q739 484 710 445T643 385T576 351T538 338L545 333Q612 295 612 223Q612 212 607 162T602 80V71Q602 53 603 43T614 25T640 16Q668 16 686 38T712 85Q717 99 720 102T735 105Q755 105 755 93Q755 75 731 36Q693 -21 641 -21H632Q571 -21 531 4T487 82Q487 109 502 166T517 239Q517 290 474 313Q459 320 449 321T378 323H309L277 193Q244 61 244 59Q244 55 245 54T252 50T269 48T302 46H333Q339 38 339 37T336 19Q332 6 326 0H311Q275 2 180 2Q146 2 117 2T71 2T50 1Q33 1 33 10Q33 12 36 24Q41 43 46 45Q50 46 61 46H67Q94 46 127 49Q141 52 146 61Q149 65 218 339T287 628Q287 635 230 637ZM630 554Q630 586 609 608T523 636Q521 636 500 636T462 637H440Q393 637 386 627Q385 624 352 494T319 361Q319 360 388 360Q466 361 492 367Q556 377 592 426Q608 449 619 486T630 554Z" style="stroke-width: 3;"/></g><g data-mml-node="mn" transform="translate(792,363) scale(0.707)"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"/></g></g><g data-mml-node="mi" transform="translate(377.5,-346.3) scale(0.707)"><path data-c="1D434" d="M208 74Q208 50 254 46Q272 46 272 35Q272 34 270 22Q267 8 264 4T251 0Q249 0 239 0T205 1T141 2Q70 2 50 0H42Q35 7 35 11Q37 38 48 46H62Q132 49 164 96Q170 102 345 401T523 704Q530 716 547 716H555H572Q578 707 578 706L606 383Q634 60 636 57Q641 46 701 46Q726 46 726 36Q726 34 723 22Q720 7 718 4T704 0Q701 0 690 0T651 1T578 2Q484 2 455 0H443Q437 6 437 9T439 27Q443 40 445 43L449 46H469Q523 49 533 63L521 213H283L249 155Q208 86 208 74ZM516 260Q516 271 504 416T490 562L463 519Q447 492 400 412L310 260L413 259Q516 259 516 260Z" style="stroke-width: 3;"/></g><rect width="1045.4" height="60" x="120" y="220"/></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mi>ρ</mi><mo>≈</mo><mfrac><msup><mi>R</mi><mn>2</mn></msup><mi>A</mi></mfrac></math></mjx-assistive-mml></mjx-container> (un mapa de sombras de resolución <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.048ex;" xmlns="http://www.w3.org/2000/svg" width="1.717ex" height="1.593ex" role="img" focusable="false" viewBox="0 -683 759 704" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mi"><path data-c="1D445" d="M230 637Q203 637 198 638T193 649Q193 676 204 682Q206 683 378 683Q550 682 564 680Q620 672 658 652T712 606T733 563T739 529Q739 484 710 445T643 385T576 351T538 338L545 333Q612 295 612 223Q612 212 607 162T602 80V71Q602 53 603 43T614 25T640 16Q668 16 686 38T712 85Q717 99 720 102T735 105Q755 105 755 93Q755 75 731 36Q693 -21 641 -21H632Q571 -21 531 4T487 82Q487 109 502 166T517 239Q517 290 474 313Q459 320 449 321T378 323H309L277 193Q244 61 244 59Q244 55 245 54T252 50T269 48T302 46H333Q339 38 339 37T336 19Q332 6 326 0H311Q275 2 180 2Q146 2 117 2T71 2T50 1Q33 1 33 10Q33 12 36 24Q41 43 46 45Q50 46 61 46H67Q94 46 127 49Q141 52 146 61Q149 65 218 339T287 628Q287 635 230 637ZM630 554Q630 586 609 608T523 636Q521 636 500 636T462 637H440Q393 637 386 627Q385 624 352 494T319 361Q319 360 388 360Q466 361 492 367Q556 377 592 426Q608 449 619 486T630 554Z" style="stroke-width: 3;"/></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mi>R</mi></math></mjx-assistive-mml></mjx-container> extendido sobre un área de terreno <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: 0;" xmlns="http://www.w3.org/2000/svg" width="1.697ex" height="1.62ex" role="img" focusable="false" viewBox="0 -716 750 716" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mi"><path data-c="1D434" d="M208 74Q208 50 254 46Q272 46 272 35Q272 34 270 22Q267 8 264 4T251 0Q249 0 239 0T205 1T141 2Q70 2 50 0H42Q35 7 35 11Q37 38 48 46H62Q132 49 164 96Q170 102 345 401T523 704Q530 716 547 716H555H572Q578 707 578 706L606 383Q634 60 636 57Q641 46 701 46Q726 46 726 36Q726 34 723 22Q720 7 718 4T704 0Q701 0 690 0T651 1T578 2Q484 2 455 0H443Q437 6 437 9T439 27Q443 40 445 43L449 46H469Q523 49 533 63L521 213H283L249 155Q208 86 208 74ZM516 260Q516 271 504 416T490 562L463 519Q447 492 400 412L310 260L413 259Q516 259 516 260Z" style="stroke-width: 3;"/></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mi>A</mi></math></mjx-assistive-mml></mjx-container>). Un único mapa para toda la distancia de visión hace que <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: 0;" xmlns="http://www.w3.org/2000/svg" width="1.697ex" height="1.62ex" role="img" focusable="false" viewBox="0 -716 750 716" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mi"><path data-c="1D434" d="M208 74Q208 50 254 46Q272 46 272 35Q272 34 270 22Q267 8 264 4T251 0Q249 0 239 0T205 1T141 2Q70 2 50 0H42Q35 7 35 11Q37 38 48 46H62Q132 49 164 96Q170 102 345 401T523 704Q530 716 547 716H555H572Q578 707 578 706L606 383Q634 60 636 57Q641 46 701 46Q726 46 726 36Q726 34 723 22Q720 7 718 4T704 0Q701 0 690 0T651 1T578 2Q484 2 455 0H443Q437 6 437 9T439 27Q443 40 445 43L449 46H469Q523 49 533 63L521 213H283L249 155Q208 86 208 74ZM516 260Q516 271 504 416T490 562L463 519Q447 492 400 412L310 260L413 259Q516 259 516 260Z" style="stroke-width: 3;"/></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mi>A</mi></math></mjx-assistive-mml></mjx-container> sea enorme y que <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.489ex;" xmlns="http://www.w3.org/2000/svg" width="1.17ex" height="1.489ex" role="img" focusable="false" viewBox="0 -442 517 658" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mi"><path data-c="1D70C" d="M58 -216Q25 -216 23 -186Q23 -176 73 26T127 234Q143 289 182 341Q252 427 341 441Q343 441 349 441T359 442Q432 442 471 394T510 276Q510 219 486 165T425 74T345 13T266 -10H255H248Q197 -10 165 35L160 41L133 -71Q108 -168 104 -181T92 -202Q76 -216 58 -216ZM424 322Q424 359 407 382T357 405Q322 405 287 376T231 300Q217 269 193 170L176 102Q193 26 260 26Q298 26 334 62Q367 92 389 158T418 266T424 322Z" style="stroke-width: 3;"/></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mi>ρ</mi></math></mjx-assistive-mml></mjx-container> se desplome. Las cascadas solucionan esto dividiendo el frustum para que cada sección tenga su propio mapa de <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.048ex;" xmlns="http://www.w3.org/2000/svg" width="6.2ex" height="1.593ex" role="img" focusable="false" viewBox="0 -683 2740.4 704" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mi"><path data-c="1D445" d="M230 637Q203 637 198 638T193 649Q193 676 204 682Q206 683 378 683Q550 682 564 680Q620 672 658 652T712 606T733 563T739 529Q739 484 710 445T643 385T576 351T538 338L545 333Q612 295 612 223Q612 212 607 162T602 80V71Q602 53 603 43T614 25T640 16Q668 16 686 38T712 85Q717 99 720 102T735 105Q755 105 755 93Q755 75 731 36Q693 -21 641 -21H632Q571 -21 531 4T487 82Q487 109 502 166T517 239Q517 290 474 313Q459 320 449 321T378 323H309L277 193Q244 61 244 59Q244 55 245 54T252 50T269 48T302 46H333Q339 38 339 37T336 19Q332 6 326 0H311Q275 2 180 2Q146 2 117 2T71 2T50 1Q33 1 33 10Q33 12 36 24Q41 43 46 45Q50 46 61 46H67Q94 46 127 49Q141 52 146 61Q149 65 218 339T287 628Q287 635 230 637ZM630 554Q630 586 609 608T523 636Q521 636 500 636T462 637H440Q393 637 386 627Q385 624 352 494T319 361Q319 360 388 360Q466 361 492 367Q556 377 592 426Q608 449 619 486T630 554Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(981.2,0)"><path data-c="D7" d="M630 29Q630 9 609 9Q604 9 587 25T493 118L389 222L284 117Q178 13 175 11Q171 9 168 9Q160 9 154 15T147 29Q147 36 161 51T255 146L359 250L255 354Q174 435 161 449T147 471Q147 480 153 485T168 490Q173 490 175 489Q178 487 284 383L389 278L493 382Q570 459 587 475T609 491Q630 491 630 471Q630 464 620 453T522 355L418 250L522 145Q606 61 618 48T630 29Z" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(1981.4,0)"><path data-c="1D445" d="M230 637Q203 637 198 638T193 649Q193 676 204 682Q206 683 378 683Q550 682 564 680Q620 672 658 652T712 606T733 563T739 529Q739 484 710 445T643 385T576 351T538 338L545 333Q612 295 612 223Q612 212 607 162T602 80V71Q602 53 603 43T614 25T640 16Q668 16 686 38T712 85Q717 99 720 102T735 105Q755 105 755 93Q755 75 731 36Q693 -21 641 -21H632Q571 -21 531 4T487 82Q487 109 502 166T517 239Q517 290 474 313Q459 320 449 321T378 323H309L277 193Q244 61 244 59Q244 55 245 54T252 50T269 48T302 46H333Q339 38 339 37T336 19Q332 6 326 0H311Q275 2 180 2Q146 2 117 2T71 2T50 1Q33 1 33 10Q33 12 36 24Q41 43 46 45Q50 46 61 46H67Q94 46 127 49Q141 52 146 61Q149 65 218 339T287 628Q287 635 230 637ZM630 554Q630 586 609 608T523 636Q521 636 500 636T462 637H440Q393 637 386 627Q385 624 352 494T319 361Q319 360 388 360Q466 361 492 367Q556 377 592 426Q608 449 619 486T630 554Z" style="stroke-width: 3;"/></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mi>R</mi><mo>×</mo><mi>R</mi></math></mjx-assistive-mml></mjx-container> sobre un <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: 0;" xmlns="http://www.w3.org/2000/svg" width="1.697ex" height="1.62ex" role="img" focusable="false" viewBox="0 -716 750 716" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mi"><path data-c="1D434" d="M208 74Q208 50 254 46Q272 46 272 35Q272 34 270 22Q267 8 264 4T251 0Q249 0 239 0T205 1T141 2Q70 2 50 0H42Q35 7 35 11Q37 38 48 46H62Q132 49 164 96Q170 102 345 401T523 704Q530 716 547 716H555H572Q578 707 578 706L606 383Q634 60 636 57Q641 46 701 46Q726 46 726 36Q726 34 723 22Q720 7 718 4T704 0Q701 0 690 0T651 1T578 2Q484 2 455 0H443Q437 6 437 9T439 27Q443 40 445 43L449 46H469Q523 49 533 63L521 213H283L249 155Q208 86 208 74ZM516 260Q516 271 504 416T490 562L463 519Q447 492 400 412L310 260L413 259Q516 259 516 260Z" style="stroke-width: 3;"/></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mi>A</mi></math></mjx-assistive-mml></mjx-container> pequeño, lo que mantiene <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.489ex;" xmlns="http://www.w3.org/2000/svg" width="1.17ex" height="1.489ex" role="img" focusable="false" viewBox="0 -442 517 658" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mi"><path data-c="1D70C" d="M58 -216Q25 -216 23 -186Q23 -176 73 26T127 234Q143 289 182 341Q252 427 341 441Q343 441 349 441T359 442Q432 442 471 394T510 276Q510 219 486 165T425 74T345 13T266 -10H255H248Q197 -10 165 35L160 41L133 -71Q108 -168 104 -181T92 -202Q76 -216 58 -216ZM424 322Q424 359 407 382T357 405Q322 405 287 376T231 300Q217 269 193 170L176 102Q193 26 260 26Q298 26 334 62Q367 92 389 158T418 266T424 322Z" style="stroke-width: 3;"/></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mi>ρ</mi></math></mjx-assistive-mml></mjx-container> aproximadamente constante desde las zonas cercanas hasta las lejanas. Medimos la diferencia de tiempo de GPU entre dos y cuatro cascadas, y después entre resoluciones de mapa de sombras de 1024 y 2048. El resultado fue que tres cascadas a 1024 nos proporcionaban sombras de contacto aceptables cerca de la cámara sin superar los 2 ms de tiempo de GPU en nuestro hardware objetivo.</p>
<div style="position:relative;padding-bottom:56.25%;height:0;overflow:hidden;border-radius:8px;margin:1.5rem 0;border:1px solid rgba(255,255,255,0.12)">
<iframe src="/es/spikes/09-csm-shadows/" title="Spike 9: sombras CSM" style="position:absolute;top:0;left:0;width:100%;height:100%;border:0;background:#000" loading="lazy" allowfullscreen></iframe>
</div>
<p><a href="/es/spikes/09-csm-shadows/" target="_blank">Abrir el spike 9 en una pestaña nueva ↗</a> · <a href="/es/blog/spike-source?spike=09-csm-shadows">Ver el código fuente</a></p>
<p>Lo difícil de esta fase fue mantener la disciplina de producto. Algunos efectos se veían excelentes y, aun así, tuvimos que limitarlos porque consumían una parte excesiva del presupuesto por fotograma en relación con su impacto visual.</p>
<p>Nuestra regla pasó a ser sencilla. Una función solo sigue adelante si puede justificar su coste con datos medidos de tiempo por fotograma.</p>
<p>Parece obvio. No es habitual en ciclos de prototipado rápido, donde todo el mundo está entusiasmado con la siguiente mejora visual. Aplicar esta regla desde el principio simplificó mucho las decisiones arquitectónicas posteriores sobre clipmaps y zonas volumétricas, porque ya conocíamos el coste individual de cada función que competía por los mismos 16 ms.</p>
<p>En la parte 6 llegamos al primer gran cambio de rumbo en la arquitectura del terreno con los clipmaps de geometría.</p>
<h2 id="tecnologia-mencionada-en-este-capitulo" tabindex="-1">Tecnología mencionada en este capítulo <a class="header-anchor" href="#tecnologia-mencionada-en-este-capitulo" aria-label="Permalink to &quot;Tecnología mencionada en este capítulo&quot;"></a></h2>
<p><strong>InstancedMesh y vegetación en la GPU.</strong> <code>InstancedMesh</code> de Three.js renderiza N copias de la misma geometría con una sola llamada de dibujado. Para la vegetación, un mapa de densidad (32x32 por fragmento) controla la dispersión en tiempo de ejecución de briznas de hierba y grupos de arbustos en búferes de instancias. La animación del viento se ejecuta en el sombreador de vértices mediante una textura de ruido en desplazamiento. A gran escala, <code>ComputeInstanceCulling</code> de WebGPU elimina las instancias que están fuera de pantalla o demasiado lejos antes de la rasterización, e <code>IndirectBatchedMesh</code> empaqueta varios tipos de vegetación en un único búfer que se dibuja mediante multi-draw indirecto. Consulta nuestra <a href="/es/guides/landscape-generation-browser.html#gpu-driven-vegetation-culling">guía de paisajes sobre el culling de vegetación en la GPU</a>.</p>
<p><strong>Mapeado triplanar.</strong> Las texturas con mapeado UV estándar se estiran en pendientes pronunciadas porque las coordenadas UV se comprimen. El mapeado triplanar proyecta las texturas a lo largo de los tres ejes (X, Y, Z) y las mezcla según la normal de la superficie. Las paredes de los acantilados reciben la proyección X o Z (sin estiramiento) y el terreno llano recibe la proyección Y. La mezcla es suave y automática, sin necesidad de desplegar las UV. Para terrenos PBR, se aplican los mismos pesos de mezcla a los canales de albedo, normales, rugosidad y oclusión ambiental. Consulta los <a href="/es/guides/landscape-generation-browser.html#triplanar-mapping">detalles del mapeado triplanar</a>.</p>
<p><strong>Splatting de materiales basado en la pendiente y la altitud.</strong> En lugar de usar mapas de splat pintados a mano, los materiales se asignan mediante procedimientos en el sombreador de fragmentos según las propiedades del terreno. El terreno llano a baja altitud recibe hierba; las pendientes pronunciadas, roca; las zonas de gran altitud, nieve (solo en superficies lo bastante planas como para que se acumule); y las zonas cercanas al nivel del mar, arena. Las transiciones usan <code>smoothstep</code> para lograr una mezcla suave. En nuestra implementación, cada fragmento de terreno evalúa cuatro capas de texturas con muestras difusas y de normales por capa, lo que da como resultado ocho lecturas de textura por fragmento antes de la iluminación. Consulta la <a href="/es/guides/landscape-generation-browser.html#slope-and-altitude-based-material-assignment">asignación de materiales según la pendiente y la altitud</a>.</p>
<p><strong>Mapas de sombras en cascada (CSM).</strong> CSM divide el frustum de visión de la cámara en 3-4 intervalos de distancia (cascadas). Cada cascada renderiza un mapa de sombras desde la perspectiva del sol con una resolución adaptada a su distancia. Las cascadas cercanas reciben sombras de alta resolución (sombras de contacto detalladas bajo árboles y edificios), mientras que las lejanas reciben una resolución menor (amplias sombras de montañas). El sombreador del terreno toma muestras de todas las cascadas y selecciona la adecuada para cada fragmento. Coste de rendimiento: 3-4 cascadas a 1024x1024 añaden unos 0,5-1 ms para renderizar los mapas de sombras, más unos 0,2-0,3 ms para el muestreo. Consulta <a href="/es/guides/landscape-generation-browser.html#shadows-for-terrain">sombras para terrenos</a>.</p>
<hr>
<p>Parte 5 de 12.<br>
Anterior: <a href="/es/blog/2026-02-25-open-world-browser-part-04-streaming-before-fancy.html">Parte 4 - Streaming antes que terrenos sofisticados</a><br>
Siguiente: <a href="/es/blog/2026-02-25-open-world-browser-part-06-clipmaps.html">Parte 6 - Los clipmaps cambiaron el rumbo</a><br>
Guía de la serie: <a href="/es/blog/2026-02-25-open-world-browser-series-guide.html">/es/blog/2026-02-25-open-world-browser-series-guide</a></p>
]]></content:encoded>
            <enclosure url="https://cdn.cinevva.com/blog/why-webgpu-engine-hero.jpg" length="0" type="image/jpg"/>
        </item>
        <item>
            <title><![CDATA[Construyendo un mundo abierto en el navegador, parte 6: Los clipmaps cambiaron el rumbo]]></title>
            <link>https://app.cinevva.com/es/blog/2026-02-25-open-world-browser-part-06-clipmaps</link>
            <guid>https://app.cinevva.com/es/blog/2026-02-25-open-world-browser-part-06-clipmaps</guid>
            <pubDate>Wed, 25 Feb 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Los clipmaps de geometría nos permitieron mantener predecible el coste del terreno mientras nos desplazábamos por un mundo mucho más grande.]]></description>
            <content:encoded><![CDATA[<h1 id="construyendo-un-mundo-abierto-en-el-navegador-parte-6-los-clipmaps-cambiaron-el-rumbo" tabindex="-1">Construyendo un mundo abierto en el navegador, parte 6: Los clipmaps cambiaron el rumbo <a class="header-anchor" href="#construyendo-un-mundo-abierto-en-el-navegador-parte-6-los-clipmaps-cambiaron-el-rumbo" aria-label="Permalink to &quot;Construyendo un mundo abierto en el navegador, parte 6: Los clipmaps cambiaron el rumbo&quot;"></a></h1>
<p><em>Por <a href="/es/about.html">Oleg Sidorkin</a>, CTO y cofundador de Cinevva</em></p>
<p>¿Acabas de llegar? Consulta la <a href="/es/blog/2026-02-25-open-world-browser-series-guide.html">guía de la serie</a>. Explica qué es un spike y enlaza todas las partes.</p>
<p>Antes del Spike 10, nuestro modelo mental seguía siendo «un mundo más grande implica más geometría». Después del Spike 10, pasó a ser «un presupuesto de geometría constante con actualizaciones de anillos centrados en la cámara». Ese cambio alteró la trayectoria del proyecto.</p>
<p>La idea en la que se basan los clipmaps de geometría es sencilla. El terreno se renderiza como un conjunto de anillos concéntricos centrados en la cámara. El anillo más interno tiene la mayor densidad de vértices. Cada anillo exterior <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.025ex;" xmlns="http://www.w3.org/2000/svg" width="1.179ex" height="1.595ex" role="img" focusable="false" viewBox="0 -694 521 705" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mi"><path data-c="1D458" d="M121 647Q121 657 125 670T137 683Q138 683 209 688T282 694Q294 694 294 686Q294 679 244 477Q194 279 194 272Q213 282 223 291Q247 309 292 354T362 415Q402 442 438 442Q468 442 485 423T503 369Q503 344 496 327T477 302T456 291T438 288Q418 288 406 299T394 328Q394 353 410 369T442 390L458 393Q446 405 434 405H430Q398 402 367 380T294 316T228 255Q230 254 243 252T267 246T293 238T320 224T342 206T359 180T365 147Q365 130 360 106T354 66Q354 26 381 26Q429 26 459 145Q461 153 479 153H483Q499 153 499 144Q499 139 496 130Q455 -11 378 -11Q333 -11 305 15T277 90Q277 108 280 121T283 145Q283 167 269 183T234 206T200 217T182 220H180Q168 178 159 139T145 81T136 44T129 20T122 7T111 -2Q98 -11 83 -11Q66 -11 57 -1T48 16Q48 26 85 176T158 471L195 616Q196 629 188 632T149 637H144Q134 637 131 637T124 640T121 647Z" style="stroke-width: 3;"/></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mi>k</mi></math></mjx-assistive-mml></mjx-container> duplica el espaciado entre vértices, <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.375ex;" xmlns="http://www.w3.org/2000/svg" width="10.935ex" height="2.306ex" role="img" focusable="false" viewBox="0 -853.7 4833.4 1019.3" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="msub"><g data-mml-node="mi"><path data-c="1D460" d="M131 289Q131 321 147 354T203 415T300 442Q362 442 390 415T419 355Q419 323 402 308T364 292Q351 292 340 300T328 326Q328 342 337 354T354 372T367 378Q368 378 368 379Q368 382 361 388T336 399T297 405Q249 405 227 379T204 326Q204 301 223 291T278 274T330 259Q396 230 396 163Q396 135 385 107T352 51T289 7T195 -10Q118 -10 86 19T53 87Q53 126 74 143T118 160Q133 160 146 151T160 120Q160 94 142 76T111 58Q109 57 108 57T107 55Q108 52 115 47T146 34T201 27Q237 27 263 38T301 66T318 97T323 122Q323 150 302 164T254 181T195 196T148 231Q131 256 131 289Z" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(502,-150) scale(0.707)"><path data-c="1D458" d="M121 647Q121 657 125 670T137 683Q138 683 209 688T282 694Q294 694 294 686Q294 679 244 477Q194 279 194 272Q213 282 223 291Q247 309 292 354T362 415Q402 442 438 442Q468 442 485 423T503 369Q503 344 496 327T477 302T456 291T438 288Q418 288 406 299T394 328Q394 353 410 369T442 390L458 393Q446 405 434 405H430Q398 402 367 380T294 316T228 255Q230 254 243 252T267 246T293 238T320 224T342 206T359 180T365 147Q365 130 360 106T354 66Q354 26 381 26Q429 26 459 145Q461 153 479 153H483Q499 153 499 144Q499 139 496 130Q455 -11 378 -11Q333 -11 305 15T277 90Q277 108 280 121T283 145Q283 167 269 183T234 206T200 217T182 220H180Q168 178 159 139T145 81T136 44T129 20T122 7T111 -2Q98 -11 83 -11Q66 -11 57 -1T48 16Q48 26 85 176T158 471L195 616Q196 629 188 632T149 637H144Q134 637 131 637T124 640T121 647Z" style="stroke-width: 3;"/></g></g><g data-mml-node="mo" transform="translate(1198.2,0)"><path data-c="3D" d="M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z" style="stroke-width: 3;"/></g><g data-mml-node="msub" transform="translate(2254,0)"><g data-mml-node="mi"><path data-c="1D460" d="M131 289Q131 321 147 354T203 415T300 442Q362 442 390 415T419 355Q419 323 402 308T364 292Q351 292 340 300T328 326Q328 342 337 354T354 372T367 378Q368 378 368 379Q368 382 361 388T336 399T297 405Q249 405 227 379T204 326Q204 301 223 291T278 274T330 259Q396 230 396 163Q396 135 385 107T352 51T289 7T195 -10Q118 -10 86 19T53 87Q53 126 74 143T118 160Q133 160 146 151T160 120Q160 94 142 76T111 58Q109 57 108 57T107 55Q108 52 115 47T146 34T201 27Q237 27 263 38T301 66T318 97T323 122Q323 150 302 164T254 181T195 196T148 231Q131 256 131 289Z" style="stroke-width: 3;"/></g><g data-mml-node="mn" transform="translate(502,-150) scale(0.707)"><path data-c="30" d="M96 585Q152 666 249 666Q297 666 345 640T423 548Q460 465 460 320Q460 165 417 83Q397 41 362 16T301 -15T250 -22Q224 -22 198 -16T137 16T82 83Q39 165 39 320Q39 494 96 585ZM321 597Q291 629 250 629Q208 629 178 597Q153 571 145 525T137 333Q137 175 145 125T181 46Q209 16 250 16Q290 16 318 46Q347 76 354 130T362 333Q362 478 354 524T321 597Z" style="stroke-width: 3;"/></g></g><g data-mml-node="mo" transform="translate(3381.7,0)"><path data-c="22C5" d="M78 250Q78 274 95 292T138 310Q162 310 180 294T199 251Q199 226 182 208T139 190T96 207T78 250Z" style="stroke-width: 3;"/></g><g data-mml-node="msup" transform="translate(3882,0)"><g data-mml-node="mn"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(533,363) scale(0.707)"><path data-c="1D458" d="M121 647Q121 657 125 670T137 683Q138 683 209 688T282 694Q294 694 294 686Q294 679 244 477Q194 279 194 272Q213 282 223 291Q247 309 292 354T362 415Q402 442 438 442Q468 442 485 423T503 369Q503 344 496 327T477 302T456 291T438 288Q418 288 406 299T394 328Q394 353 410 369T442 390L458 393Q446 405 434 405H430Q398 402 367 380T294 316T228 255Q230 254 243 252T267 246T293 238T320 224T342 206T359 180T365 147Q365 130 360 106T354 66Q354 26 381 26Q429 26 459 145Q461 153 479 153H483Q499 153 499 144Q499 139 496 130Q455 -11 378 -11Q333 -11 305 15T277 90Q277 108 280 121T283 145Q283 167 269 183T234 206T200 217T182 220H180Q168 178 159 139T145 81T136 44T129 20T122 7T111 -2Q98 -11 83 -11Q66 -11 57 -1T48 16Q48 26 85 176T158 471L195 616Q196 629 188 632T149 637H144Q134 637 131 637T124 640T121 647Z" style="stroke-width: 3;"/></g></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><msub><mi>s</mi><mi>k</mi></msub><mo>=</mo><msub><mi>s</mi><mn>0</mn></msub><mo>⋅</mo><msup><mn>2</mn><mi>k</mi></msup></math></mjx-assistive-mml></mjx-container>, por lo que cubre <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: 0;" xmlns="http://www.w3.org/2000/svg" width="2.891ex" height="1.532ex" role="img" focusable="false" viewBox="0 -677 1278 677" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mn"><path data-c="34" d="M462 0Q444 3 333 3Q217 3 199 0H190V46H221Q241 46 248 46T265 48T279 53T286 61Q287 63 287 115V165H28V211L179 442Q332 674 334 675Q336 677 355 677H373L379 671V211H471V165H379V114Q379 73 379 66T385 54Q393 47 442 46H471V0H462ZM293 211V545L74 212L183 211H293Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(500,0)"><path data-c="D7" d="M630 29Q630 9 609 9Q604 9 587 25T493 118L389 222L284 117Q178 13 175 11Q171 9 168 9Q160 9 154 15T147 29Q147 36 161 51T255 146L359 250L255 354Q174 435 161 449T147 471Q147 480 153 485T168 490Q173 490 175 489Q178 487 284 383L389 278L493 382Q570 459 587 475T609 491Q630 491 630 471Q630 464 620 453T522 355L418 250L522 145Q606 61 618 48T630 29Z" style="stroke-width: 3;"/></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mn>4</mn><mo>×</mo></math></mjx-assistive-mml></mjx-container> el área de terreno del anillo situado en su interior.</p>
<p>Esa duplicación es el verdadero truco. La distancia de visión crece geométricamente con el número de anillos, <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.375ex;" xmlns="http://www.w3.org/2000/svg" width="13.628ex" height="2.288ex" role="img" focusable="false" viewBox="0 -846 6023.5 1011.5" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="msub"><g data-mml-node="mi"><path data-c="1D451" d="M366 683Q367 683 438 688T511 694Q523 694 523 686Q523 679 450 384T375 83T374 68Q374 26 402 26Q411 27 422 35Q443 55 463 131Q469 151 473 152Q475 153 483 153H487H491Q506 153 506 145Q506 140 503 129Q490 79 473 48T445 8T417 -8Q409 -10 393 -10Q359 -10 336 5T306 36L300 51Q299 52 296 50Q294 48 292 46Q233 -10 172 -10Q117 -10 75 30T33 157Q33 205 53 255T101 341Q148 398 195 420T280 442Q336 442 364 400Q369 394 369 396Q370 400 396 505T424 616Q424 629 417 632T378 637H357Q351 643 351 645T353 664Q358 683 366 683ZM352 326Q329 405 277 405Q242 405 210 374T160 293Q131 214 119 129Q119 126 119 118T118 106Q118 61 136 44T179 26Q233 26 290 98L298 109L352 326Z" style="stroke-width: 3;"/></g><g data-mml-node="mtext" transform="translate(553,-150) scale(0.707)"><path data-c="76" d="M338 431Q344 429 422 429Q479 429 503 431H508V385H497Q439 381 423 345Q421 341 356 172T288 -2Q283 -11 263 -11Q244 -11 239 -2Q99 359 98 364Q93 378 82 381T43 385H19V431H25L33 430Q41 430 53 430T79 430T104 429T122 428Q217 428 232 431H240V385H226Q187 384 184 370Q184 366 235 234L286 102L377 341V349Q377 363 367 372T349 383T335 385H331V431H338Z" style="stroke-width: 3;"/><path data-c="69" d="M69 609Q69 637 87 653T131 669Q154 667 171 652T188 609Q188 579 171 564T129 549Q104 549 87 564T69 609ZM247 0Q232 3 143 3Q132 3 106 3T56 1L34 0H26V46H42Q70 46 91 49Q100 53 102 60T104 102V205V293Q104 345 102 359T88 378Q74 385 41 385H30V408Q30 431 32 431L42 432Q52 433 70 434T106 436Q123 437 142 438T171 441T182 442H185V62Q190 52 197 50T232 46H255V0H247Z" transform="translate(528,0)" style="stroke-width: 3;"/><path data-c="65" d="M28 218Q28 273 48 318T98 391T163 433T229 448Q282 448 320 430T378 380T406 316T415 245Q415 238 408 231H126V216Q126 68 226 36Q246 30 270 30Q312 30 342 62Q359 79 369 104L379 128Q382 131 395 131H398Q415 131 415 121Q415 117 412 108Q393 53 349 21T250 -11Q155 -11 92 58T28 218ZM333 275Q322 403 238 411H236Q228 411 220 410T195 402T166 381T143 340T127 274V267H333V275Z" transform="translate(806,0)" style="stroke-width: 3;"/><path data-c="77" d="M90 368Q84 378 76 380T40 385H18V431H24L43 430Q62 430 84 429T116 428Q206 428 221 431H229V385H215Q177 383 177 368Q177 367 221 239L265 113L339 328L333 345Q323 374 316 379Q308 384 278 385H258V431H264Q270 428 348 428Q439 428 454 431H461V385H452Q404 385 404 369Q404 366 418 324T449 234T481 143L496 100L537 219Q579 341 579 347Q579 363 564 373T530 385H522V431H529Q541 428 624 428Q692 428 698 431H703V385H697Q696 385 691 385T682 384Q635 377 619 334L559 161Q546 124 528 71Q508 12 503 1T487 -11H479Q460 -11 456 -4Q455 -3 407 133L361 267Q359 263 266 -4Q261 -11 243 -11H238Q225 -11 220 -3L90 368Z" transform="translate(1250,0)" style="stroke-width: 3;"/></g></g><g data-mml-node="mo" transform="translate(2275.2,0)"><path data-c="2248" d="M55 319Q55 360 72 393T114 444T163 472T205 482Q207 482 213 482T223 483Q262 483 296 468T393 413L443 381Q502 346 553 346Q609 346 649 375T694 454Q694 465 698 474T708 483Q722 483 722 452Q722 386 675 338T555 289Q514 289 468 310T388 357T308 404T224 426Q164 426 125 393T83 318Q81 289 69 289Q55 289 55 319ZM55 85Q55 126 72 159T114 210T163 238T205 248Q207 248 213 248T223 249Q262 249 296 234T393 179L443 147Q502 112 553 112Q609 112 649 141T694 220Q694 249 708 249T722 217Q722 153 675 104T555 55Q514 55 468 76T388 123T308 170T224 192Q164 192 125 159T83 84Q80 55 69 55Q55 55 55 85Z" style="stroke-width: 3;"/></g><g data-mml-node="msub" transform="translate(3331,0)"><g data-mml-node="mi"><path data-c="1D460" d="M131 289Q131 321 147 354T203 415T300 442Q362 442 390 415T419 355Q419 323 402 308T364 292Q351 292 340 300T328 326Q328 342 337 354T354 372T367 378Q368 378 368 379Q368 382 361 388T336 399T297 405Q249 405 227 379T204 326Q204 301 223 291T278 274T330 259Q396 230 396 163Q396 135 385 107T352 51T289 7T195 -10Q118 -10 86 19T53 87Q53 126 74 143T118 160Q133 160 146 151T160 120Q160 94 142 76T111 58Q109 57 108 57T107 55Q108 52 115 47T146 34T201 27Q237 27 263 38T301 66T318 97T323 122Q323 150 302 164T254 181T195 196T148 231Q131 256 131 289Z" style="stroke-width: 3;"/></g><g data-mml-node="mn" transform="translate(502,-150) scale(0.707)"><path data-c="30" d="M96 585Q152 666 249 666Q297 666 345 640T423 548Q460 465 460 320Q460 165 417 83Q397 41 362 16T301 -15T250 -22Q224 -22 198 -16T137 16T82 83Q39 165 39 320Q39 494 96 585ZM321 597Q291 629 250 629Q208 629 178 597Q153 571 145 525T137 333Q137 175 145 125T181 46Q209 16 250 16Q290 16 318 46Q347 76 354 130T362 333Q362 478 354 524T321 597Z" style="stroke-width: 3;"/></g></g><g data-mml-node="mo" transform="translate(4458.7,0)"><path data-c="22C5" d="M78 250Q78 274 95 292T138 310Q162 310 180 294T199 251Q199 226 182 208T139 190T96 207T78 250Z" style="stroke-width: 3;"/></g><g data-mml-node="msup" transform="translate(4959,0)"><g data-mml-node="mn"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"/></g><g data-mml-node="TeXAtom" transform="translate(533,363) scale(0.707)" data-mjx-texclass="ORD"><g data-mml-node="mi"><path data-c="1D43F" d="M228 637Q194 637 192 641Q191 643 191 649Q191 673 202 682Q204 683 217 683Q271 680 344 680Q485 680 506 683H518Q524 677 524 674T522 656Q517 641 513 637H475Q406 636 394 628Q387 624 380 600T313 336Q297 271 279 198T252 88L243 52Q243 48 252 48T311 46H328Q360 46 379 47T428 54T478 72T522 106T564 161Q580 191 594 228T611 270Q616 273 628 273H641Q647 264 647 262T627 203T583 83T557 9Q555 4 553 3T537 0T494 -1Q483 -1 418 -1T294 0H116Q32 0 32 10Q32 17 34 24Q39 43 44 45Q48 46 59 46H65Q92 46 125 49Q139 52 144 61Q147 65 216 339T285 628Q285 635 228 637Z" style="stroke-width: 3;"/></g></g></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><msub><mi>d</mi><mtext>view</mtext></msub><mo>≈</mo><msub><mi>s</mi><mn>0</mn></msub><mo>⋅</mo><msup><mn>2</mn><mrow data-mjx-texclass="ORD"><mi>L</mi></mrow></msup></math></mjx-assistive-mml></mjx-container>, mientras que el coste en vértices solo crece de forma lineal:</p>
<mjx-container tabindex="0" class="MathJax" jax="SVG" display="true" style="direction: ltr; display: block; text-align: center; margin: 1em 0; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.357ex;" xmlns="http://www.w3.org/2000/svg" width="14.108ex" height="2.357ex" role="img" focusable="false" viewBox="0 -883.9 6235.6 1041.7" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="msub"><g data-mml-node="mi"><path data-c="1D449" d="M52 648Q52 670 65 683H76Q118 680 181 680Q299 680 320 683H330Q336 677 336 674T334 656Q329 641 325 637H304Q282 635 274 635Q245 630 242 620Q242 618 271 369T301 118L374 235Q447 352 520 471T595 594Q599 601 599 609Q599 633 555 637Q537 637 537 648Q537 649 539 661Q542 675 545 679T558 683Q560 683 570 683T604 682T668 681Q737 681 755 683H762Q769 676 769 672Q769 655 760 640Q757 637 743 637Q730 636 719 635T698 630T682 623T670 615T660 608T652 599T645 592L452 282Q272 -9 266 -16Q263 -18 259 -21L241 -22H234Q216 -22 216 -15Q213 -9 177 305Q139 623 138 626Q133 637 76 637H59Q52 642 52 648Z" style="stroke-width: 3;"/></g><g data-mml-node="mtext" transform="translate(616,-150) scale(0.707)"><path data-c="74" d="M27 422Q80 426 109 478T141 600V615H181V431H316V385H181V241Q182 116 182 100T189 68Q203 29 238 29Q282 29 292 100Q293 108 293 146V181H333V146V134Q333 57 291 17Q264 -10 221 -10Q187 -10 162 2T124 33T105 68T98 100Q97 107 97 248V385H18V422H27Z" style="stroke-width: 3;"/><path data-c="6F" d="M28 214Q28 309 93 378T250 448Q340 448 405 380T471 215Q471 120 407 55T250 -10Q153 -10 91 57T28 214ZM250 30Q372 30 372 193V225V250Q372 272 371 288T364 326T348 362T317 390T268 410Q263 411 252 411Q222 411 195 399Q152 377 139 338T126 246V226Q126 130 145 91Q177 30 250 30Z" transform="translate(389,0)" style="stroke-width: 3;"/><path data-c="74" d="M27 422Q80 426 109 478T141 600V615H181V431H316V385H181V241Q182 116 182 100T189 68Q203 29 238 29Q282 29 292 100Q293 108 293 146V181H333V146V134Q333 57 291 17Q264 -10 221 -10Q187 -10 162 2T124 33T105 68T98 100Q97 107 97 248V385H18V422H27Z" transform="translate(889,0)" style="stroke-width: 3;"/><path data-c="61" d="M137 305T115 305T78 320T63 359Q63 394 97 421T218 448Q291 448 336 416T396 340Q401 326 401 309T402 194V124Q402 76 407 58T428 40Q443 40 448 56T453 109V145H493V106Q492 66 490 59Q481 29 455 12T400 -6T353 12T329 54V58L327 55Q325 52 322 49T314 40T302 29T287 17T269 6T247 -2T221 -8T190 -11Q130 -11 82 20T34 107Q34 128 41 147T68 188T116 225T194 253T304 268H318V290Q318 324 312 340Q290 411 215 411Q197 411 181 410T156 406T148 403Q170 388 170 359Q170 334 154 320ZM126 106Q126 75 150 51T209 26Q247 26 276 49T315 109Q317 116 318 175Q318 233 317 233Q309 233 296 232T251 223T193 203T147 166T126 106Z" transform="translate(1278,0)" style="stroke-width: 3;"/><path data-c="6C" d="M42 46H56Q95 46 103 60V68Q103 77 103 91T103 124T104 167T104 217T104 272T104 329Q104 366 104 407T104 482T104 542T103 586T103 603Q100 622 89 628T44 637H26V660Q26 683 28 683L38 684Q48 685 67 686T104 688Q121 689 141 690T171 693T182 694H185V379Q185 62 186 60Q190 52 198 49Q219 46 247 46H263V0H255L232 1Q209 2 183 2T145 3T107 3T57 1L34 0H26V46H42Z" transform="translate(1778,0)" style="stroke-width: 3;"/></g></g><g data-mml-node="mo" transform="translate(2397.6,0)"><path data-c="2248" d="M55 319Q55 360 72 393T114 444T163 472T205 482Q207 482 213 482T223 483Q262 483 296 468T393 413L443 381Q502 346 553 346Q609 346 649 375T694 454Q694 465 698 474T708 483Q722 483 722 452Q722 386 675 338T555 289Q514 289 468 310T388 357T308 404T224 426Q164 426 125 393T83 318Q81 289 69 289Q55 289 55 319ZM55 85Q55 126 72 159T114 210T163 238T205 248Q207 248 213 248T223 249Q262 249 296 234T393 179L443 147Q502 112 553 112Q609 112 649 141T694 220Q694 249 708 249T722 217Q722 153 675 104T555 55Q514 55 468 76T388 123T308 170T224 192Q164 192 125 159T83 84Q80 55 69 55Q55 55 55 85Z" style="stroke-width: 3;"/></g><g data-mml-node="msup" transform="translate(3453.4,0)"><g data-mml-node="mi"><path data-c="1D441" d="M234 637Q231 637 226 637Q201 637 196 638T191 649Q191 676 202 682Q204 683 299 683Q376 683 387 683T401 677Q612 181 616 168L670 381Q723 592 723 606Q723 633 659 637Q635 637 635 648Q635 650 637 660Q641 676 643 679T653 683Q656 683 684 682T767 680Q817 680 843 681T873 682Q888 682 888 672Q888 650 880 642Q878 637 858 637Q787 633 769 597L620 7Q618 0 599 0Q585 0 582 2Q579 5 453 305L326 604L261 344Q196 88 196 79Q201 46 268 46H278Q284 41 284 38T282 19Q278 6 272 0H259Q228 2 151 2Q123 2 100 2T63 2T46 1Q31 1 31 10Q31 14 34 26T39 40Q41 46 62 46Q130 49 150 85Q154 91 221 362L289 634Q287 635 234 637Z" style="stroke-width: 3;"/></g><g data-mml-node="mn" transform="translate(975.3,413) scale(0.707)"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"/></g></g><g data-mml-node="mo" transform="translate(5054.4,0)"><path data-c="22C5" d="M78 250Q78 274 95 292T138 310Q162 310 180 294T199 251Q199 226 182 208T139 190T96 207T78 250Z" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(5554.6,0)"><path data-c="1D43F" d="M228 637Q194 637 192 641Q191 643 191 649Q191 673 202 682Q204 683 217 683Q271 680 344 680Q485 680 506 683H518Q524 677 524 674T522 656Q517 641 513 637H475Q406 636 394 628Q387 624 380 600T313 336Q297 271 279 198T252 88L243 52Q243 48 252 48T311 46H328Q360 46 379 47T428 54T478 72T522 106T564 161Q580 191 594 228T611 270Q616 273 628 273H641Q647 264 647 262T627 203T583 83T557 9Q555 4 553 3T537 0T494 -1Q483 -1 418 -1T294 0H116Q32 0 32 10Q32 17 34 24Q39 43 44 45Q48 46 59 46H65Q92 46 125 49Q139 52 144 61Q147 65 216 339T285 628Q285 635 228 637Z" style="stroke-width: 3;"/></g></g></g></svg><mjx-assistive-mml unselectable="on" display="block" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; overflow: hidden; width: 100%;"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><msub><mi>V</mi><mtext>total</mtext></msub><mo>≈</mo><msup><mi>N</mi><mn>2</mn></msup><mo>⋅</mo><mi>L</mi></math></mjx-assistive-mml></mjx-container><p>para <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: 0;" xmlns="http://www.w3.org/2000/svg" width="1.541ex" height="1.545ex" role="img" focusable="false" viewBox="0 -683 681 683" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mi"><path data-c="1D43F" d="M228 637Q194 637 192 641Q191 643 191 649Q191 673 202 682Q204 683 217 683Q271 680 344 680Q485 680 506 683H518Q524 677 524 674T522 656Q517 641 513 637H475Q406 636 394 628Q387 624 380 600T313 336Q297 271 279 198T252 88L243 52Q243 48 252 48T311 46H328Q360 46 379 47T428 54T478 72T522 106T564 161Q580 191 594 228T611 270Q616 273 628 273H641Q647 264 647 262T627 203T583 83T557 9Q555 4 553 3T537 0T494 -1Q483 -1 418 -1T294 0H116Q32 0 32 10Q32 17 34 24Q39 43 44 45Q48 46 59 46H65Q92 46 125 49Q139 52 144 61Q147 65 216 339T285 628Q285 635 228 637Z" style="stroke-width: 3;"/></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mi>L</mi></math></mjx-assistive-mml></mjx-container> anillos de <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: 0;" xmlns="http://www.w3.org/2000/svg" width="6.784ex" height="1.545ex" role="img" focusable="false" viewBox="0 -683 2998.4 683" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mi"><path data-c="1D441" d="M234 637Q231 637 226 637Q201 637 196 638T191 649Q191 676 202 682Q204 683 299 683Q376 683 387 683T401 677Q612 181 616 168L670 381Q723 592 723 606Q723 633 659 637Q635 637 635 648Q635 650 637 660Q641 676 643 679T653 683Q656 683 684 682T767 680Q817 680 843 681T873 682Q888 682 888 672Q888 650 880 642Q878 637 858 637Q787 633 769 597L620 7Q618 0 599 0Q585 0 582 2Q579 5 453 305L326 604L261 344Q196 88 196 79Q201 46 268 46H278Q284 41 284 38T282 19Q278 6 272 0H259Q228 2 151 2Q123 2 100 2T63 2T46 1Q31 1 31 10Q31 14 34 26T39 40Q41 46 62 46Q130 49 150 85Q154 91 221 362L289 634Q287 635 234 637Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(1110.2,0)"><path data-c="D7" d="M630 29Q630 9 609 9Q604 9 587 25T493 118L389 222L284 117Q178 13 175 11Q171 9 168 9Q160 9 154 15T147 29Q147 36 161 51T255 146L359 250L255 354Q174 435 161 449T147 471Q147 480 153 485T168 490Q173 490 175 489Q178 487 284 383L389 278L493 382Q570 459 587 475T609 491Q630 491 630 471Q630 464 620 453T522 355L418 250L522 145Q606 61 618 48T630 29Z" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(2110.4,0)"><path data-c="1D441" d="M234 637Q231 637 226 637Q201 637 196 638T191 649Q191 676 202 682Q204 683 299 683Q376 683 387 683T401 677Q612 181 616 168L670 381Q723 592 723 606Q723 633 659 637Q635 637 635 648Q635 650 637 660Q641 676 643 679T653 683Q656 683 684 682T767 680Q817 680 843 681T873 682Q888 682 888 672Q888 650 880 642Q878 637 858 637Q787 633 769 597L620 7Q618 0 599 0Q585 0 582 2Q579 5 453 305L326 604L261 344Q196 88 196 79Q201 46 268 46H278Q284 41 284 38T282 19Q278 6 272 0H259Q228 2 151 2Q123 2 100 2T63 2T46 1Q31 1 31 10Q31 14 34 26T39 40Q41 46 62 46Q130 49 150 85Q154 91 221 362L289 634Q287 635 234 637Z" style="stroke-width: 3;"/></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mi>N</mi><mo>×</mo><mi>N</mi></math></mjx-assistive-mml></mjx-container> vértices cada uno. Duplicar la distancia visible cuesta un anillo más, no cuatro veces más geometría. El número de triángulos se mantiene aproximadamente constante sin importar el tamaño del mundo, porque siempre se renderizan los mismos <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: 0;" xmlns="http://www.w3.org/2000/svg" width="1.541ex" height="1.545ex" role="img" focusable="false" viewBox="0 -683 681 683" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mi"><path data-c="1D43F" d="M228 637Q194 637 192 641Q191 643 191 649Q191 673 202 682Q204 683 217 683Q271 680 344 680Q485 680 506 683H518Q524 677 524 674T522 656Q517 641 513 637H475Q406 636 394 628Q387 624 380 600T313 336Q297 271 279 198T252 88L243 52Q243 48 252 48T311 46H328Q360 46 379 47T428 54T478 72T522 106T564 161Q580 191 594 228T611 270Q616 273 628 273H641Q647 264 647 262T627 203T583 83T557 9Q555 4 553 3T537 0T494 -1Q483 -1 418 -1T294 0H116Q32 0 32 10Q32 17 34 24Q39 43 44 45Q48 46 59 46H65Q92 46 125 49Q139 52 144 61Q147 65 216 339T285 628Q285 635 228 637Z" style="stroke-width: 3;"/></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mi>L</mi></math></mjx-assistive-mml></mjx-container> anillos con la misma resolución.</p>
<div style="position:relative;padding-bottom:56.25%;height:0;overflow:hidden;border-radius:8px;margin:1.5rem 0;border:1px solid rgba(255,255,255,0.12)">
<iframe src="/es/spikes/10-clipmap-geomorph/" title="Geomorfismo de clipmaps de geometría del Spike 10" style="position:absolute;top:0;left:0;width:100%;height:100%;border:0;background:#000" loading="lazy" allowfullscreen></iframe>
</div>
<p><a href="/es/spikes/10-clipmap-geomorph/" target="_blank">Abrir el Spike 10 en una pestaña nueva ↗</a> · <a href="/es/blog/spike-source?spike=10-clipmap-geomorph">Ver el código fuente</a></p>
<p>El truco práctico fue aplicar geomorfismo en los límites de los anillos. Cuando un vértice pasa de un anillo de LOD al siguiente, su altura debe mezclarse suavemente entre la muestra de alta resolución y la de baja resolución. De lo contrario, aparecen saltos visibles cada vez que la cámara se mueve y los anillos cambian de posición. Lo resolvimos con un factor de mezcla basado en la distancia del vértice al borde del anillo, interpolando la altura en el shader de vértices:</p>
<mjx-container tabindex="0" class="MathJax" jax="SVG" display="true" style="direction: ltr; display: block; text-align: center; margin: 1em 0; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.566ex;" xmlns="http://www.w3.org/2000/svg" width="58.451ex" height="2.262ex" role="img" focusable="false" viewBox="0 -750 25835.3 1000" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mi"><path data-c="210E" d="M137 683Q138 683 209 688T282 694Q294 694 294 685Q294 674 258 534Q220 386 220 383Q220 381 227 388Q288 442 357 442Q411 442 444 415T478 336Q478 285 440 178T402 50Q403 36 407 31T422 26Q450 26 474 56T513 138Q516 149 519 151T535 153Q555 153 555 145Q555 144 551 130Q535 71 500 33Q466 -10 419 -10H414Q367 -10 346 17T325 74Q325 90 361 192T398 345Q398 404 354 404H349Q266 404 205 306L198 293L164 158Q132 28 127 16Q114 -11 83 -11Q69 -11 59 -2T48 16Q48 30 121 320L195 616Q195 629 188 632T149 637H128Q122 643 122 645T124 664Q129 683 137 683Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(853.8,0)"><path data-c="3D" d="M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(1909.6,0)"><path data-c="6C" d="M42 46H56Q95 46 103 60V68Q103 77 103 91T103 124T104 167T104 217T104 272T104 329Q104 366 104 407T104 482T104 542T103 586T103 603Q100 622 89 628T44 637H26V660Q26 683 28 683L38 684Q48 685 67 686T104 688Q121 689 141 690T171 693T182 694H185V379Q185 62 186 60Q190 52 198 49Q219 46 247 46H263V0H255L232 1Q209 2 183 2T145 3T107 3T57 1L34 0H26V46H42Z" style="stroke-width: 3;"/><path data-c="65" d="M28 218Q28 273 48 318T98 391T163 433T229 448Q282 448 320 430T378 380T406 316T415 245Q415 238 408 231H126V216Q126 68 226 36Q246 30 270 30Q312 30 342 62Q359 79 369 104L379 128Q382 131 395 131H398Q415 131 415 121Q415 117 412 108Q393 53 349 21T250 -11Q155 -11 92 58T28 218ZM333 275Q322 403 238 411H236Q228 411 220 410T195 402T166 381T143 340T127 274V267H333V275Z" transform="translate(278,0)" style="stroke-width: 3;"/><path data-c="72" d="M36 46H50Q89 46 97 60V68Q97 77 97 91T98 122T98 161T98 203Q98 234 98 269T98 328L97 351Q94 370 83 376T38 385H20V408Q20 431 22 431L32 432Q42 433 60 434T96 436Q112 437 131 438T160 441T171 442H174V373Q213 441 271 441H277Q322 441 343 419T364 373Q364 352 351 337T313 322Q288 322 276 338T263 372Q263 381 265 388T270 400T273 405Q271 407 250 401Q234 393 226 386Q179 341 179 207V154Q179 141 179 127T179 101T180 81T180 66V61Q181 59 183 57T188 54T193 51T200 49T207 48T216 47T225 47T235 46T245 46H276V0H267Q249 3 140 3Q37 3 28 0H20V46H36Z" transform="translate(722,0)" style="stroke-width: 3;"/><path data-c="70" d="M36 -148H50Q89 -148 97 -134V-126Q97 -119 97 -107T97 -77T98 -38T98 6T98 55T98 106Q98 140 98 177T98 243T98 296T97 335T97 351Q94 370 83 376T38 385H20V408Q20 431 22 431L32 432Q42 433 61 434T98 436Q115 437 135 438T165 441T176 442H179V416L180 390L188 397Q247 441 326 441Q407 441 464 377T522 216Q522 115 457 52T310 -11Q242 -11 190 33L182 40V-45V-101Q182 -128 184 -134T195 -145Q216 -148 244 -148H260V-194H252L228 -193Q205 -192 178 -192T140 -191Q37 -191 28 -194H20V-148H36ZM424 218Q424 292 390 347T305 402Q234 402 182 337V98Q222 26 294 26Q345 26 384 80T424 218Z" transform="translate(1114,0)" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(3579.6,0)"><path data-c="28" d="M94 250Q94 319 104 381T127 488T164 576T202 643T244 695T277 729T302 750H315H319Q333 750 333 741Q333 738 316 720T275 667T226 581T184 443T167 250T184 58T225 -81T274 -167T316 -220T333 -241Q333 -250 318 -250H315H302L274 -226Q180 -141 137 -14T94 250Z" style="stroke-width: 3;"/></g><g data-mml-node="msub" transform="translate(3968.6,0)"><g data-mml-node="mi"><path data-c="210E" d="M137 683Q138 683 209 688T282 694Q294 694 294 685Q294 674 258 534Q220 386 220 383Q220 381 227 388Q288 442 357 442Q411 442 444 415T478 336Q478 285 440 178T402 50Q403 36 407 31T422 26Q450 26 474 56T513 138Q516 149 519 151T535 153Q555 153 555 145Q555 144 551 130Q535 71 500 33Q466 -10 419 -10H414Q367 -10 346 17T325 74Q325 90 361 192T398 345Q398 404 354 404H349Q266 404 205 306L198 293L164 158Q132 28 127 16Q114 -11 83 -11Q69 -11 59 -2T48 16Q48 30 121 320L195 616Q195 629 188 632T149 637H128Q122 643 122 645T124 664Q129 683 137 683Z" style="stroke-width: 3;"/></g><g data-mml-node="mtext" transform="translate(609,-150) scale(0.707)"><path data-c="66" d="M273 0Q255 3 146 3Q43 3 34 0H26V46H42Q70 46 91 49Q99 52 103 60Q104 62 104 224V385H33V431H104V497L105 564L107 574Q126 639 171 668T266 704Q267 704 275 704T289 705Q330 702 351 679T372 627Q372 604 358 590T321 576T284 590T270 627Q270 647 288 667H284Q280 668 273 668Q245 668 223 647T189 592Q183 572 182 497V431H293V385H185V225Q185 63 186 61T189 57T194 54T199 51T206 49T213 48T222 47T231 47T241 46T251 46H282V0H273Z" style="stroke-width: 3;"/><path data-c="69" d="M69 609Q69 637 87 653T131 669Q154 667 171 652T188 609Q188 579 171 564T129 549Q104 549 87 564T69 609ZM247 0Q232 3 143 3Q132 3 106 3T56 1L34 0H26V46H42Q70 46 91 49Q100 53 102 60T104 102V205V293Q104 345 102 359T88 378Q74 385 41 385H30V408Q30 431 32 431L42 432Q52 433 70 434T106 436Q123 437 142 438T171 441T182 442H185V62Q190 52 197 50T232 46H255V0H247Z" transform="translate(306,0)" style="stroke-width: 3;"/><path data-c="6E" d="M41 46H55Q94 46 102 60V68Q102 77 102 91T102 122T103 161T103 203Q103 234 103 269T102 328V351Q99 370 88 376T43 385H25V408Q25 431 27 431L37 432Q47 433 65 434T102 436Q119 437 138 438T167 441T178 442H181V402Q181 364 182 364T187 369T199 384T218 402T247 421T285 437Q305 442 336 442Q450 438 463 329Q464 322 464 190V104Q464 66 466 59T477 49Q498 46 526 46H542V0H534L510 1Q487 2 460 2T422 3Q319 3 310 0H302V46H318Q379 46 379 62Q380 64 380 200Q379 335 378 343Q372 371 358 385T334 402T308 404Q263 404 229 370Q202 343 195 315T187 232V168V108Q187 78 188 68T191 55T200 49Q221 46 249 46H265V0H257L234 1Q210 2 183 2T145 3Q42 3 33 0H25V46H41Z" transform="translate(584,0)" style="stroke-width: 3;"/><path data-c="65" d="M28 218Q28 273 48 318T98 391T163 433T229 448Q282 448 320 430T378 380T406 316T415 245Q415 238 408 231H126V216Q126 68 226 36Q246 30 270 30Q312 30 342 62Q359 79 369 104L379 128Q382 131 395 131H398Q415 131 415 121Q415 117 412 108Q393 53 349 21T250 -11Q155 -11 92 58T28 218ZM333 275Q322 403 238 411H236Q228 411 220 410T195 402T166 381T143 340T127 274V267H333V275Z" transform="translate(1140,0)" style="stroke-width: 3;"/></g></g><g data-mml-node="mo" transform="translate(5747.6,0)"><path data-c="2C" d="M78 35T78 60T94 103T137 121Q165 121 187 96T210 8Q210 -27 201 -60T180 -117T154 -158T130 -185T117 -194Q113 -194 104 -185T95 -172Q95 -168 106 -156T131 -126T157 -76T173 -3V9L172 8Q170 7 167 6T161 3T152 1T140 0Q113 0 96 17Z" style="stroke-width: 3;"/></g><g data-mml-node="mstyle" transform="translate(6025.6,0)"><g data-mml-node="mspace"/></g><g data-mml-node="msub" transform="translate(6359.3,0)"><g data-mml-node="mi"><path data-c="210E" d="M137 683Q138 683 209 688T282 694Q294 694 294 685Q294 674 258 534Q220 386 220 383Q220 381 227 388Q288 442 357 442Q411 442 444 415T478 336Q478 285 440 178T402 50Q403 36 407 31T422 26Q450 26 474 56T513 138Q516 149 519 151T535 153Q555 153 555 145Q555 144 551 130Q535 71 500 33Q466 -10 419 -10H414Q367 -10 346 17T325 74Q325 90 361 192T398 345Q398 404 354 404H349Q266 404 205 306L198 293L164 158Q132 28 127 16Q114 -11 83 -11Q69 -11 59 -2T48 16Q48 30 121 320L195 616Q195 629 188 632T149 637H128Q122 643 122 645T124 664Q129 683 137 683Z" style="stroke-width: 3;"/></g><g data-mml-node="mtext" transform="translate(609,-150) scale(0.707)"><path data-c="63" d="M370 305T349 305T313 320T297 358Q297 381 312 396Q317 401 317 402T307 404Q281 408 258 408Q209 408 178 376Q131 329 131 219Q131 137 162 90Q203 29 272 29Q313 29 338 55T374 117Q376 125 379 127T395 129H409Q415 123 415 120Q415 116 411 104T395 71T366 33T318 2T249 -11Q163 -11 99 53T34 214Q34 318 99 383T250 448T370 421T404 357Q404 334 387 320Z" style="stroke-width: 3;"/><path data-c="6F" d="M28 214Q28 309 93 378T250 448Q340 448 405 380T471 215Q471 120 407 55T250 -10Q153 -10 91 57T28 214ZM250 30Q372 30 372 193V225V250Q372 272 371 288T364 326T348 362T317 390T268 410Q263 411 252 411Q222 411 195 399Q152 377 139 338T126 246V226Q126 130 145 91Q177 30 250 30Z" transform="translate(444,0)" style="stroke-width: 3;"/><path data-c="61" d="M137 305T115 305T78 320T63 359Q63 394 97 421T218 448Q291 448 336 416T396 340Q401 326 401 309T402 194V124Q402 76 407 58T428 40Q443 40 448 56T453 109V145H493V106Q492 66 490 59Q481 29 455 12T400 -6T353 12T329 54V58L327 55Q325 52 322 49T314 40T302 29T287 17T269 6T247 -2T221 -8T190 -11Q130 -11 82 20T34 107Q34 128 41 147T68 188T116 225T194 253T304 268H318V290Q318 324 312 340Q290 411 215 411Q197 411 181 410T156 406T148 403Q170 388 170 359Q170 334 154 320ZM126 106Q126 75 150 51T209 26Q247 26 276 49T315 109Q317 116 318 175Q318 233 317 233Q309 233 296 232T251 223T193 203T147 166T126 106Z" transform="translate(944,0)" style="stroke-width: 3;"/><path data-c="72" d="M36 46H50Q89 46 97 60V68Q97 77 97 91T98 122T98 161T98 203Q98 234 98 269T98 328L97 351Q94 370 83 376T38 385H20V408Q20 431 22 431L32 432Q42 433 60 434T96 436Q112 437 131 438T160 441T171 442H174V373Q213 441 271 441H277Q322 441 343 419T364 373Q364 352 351 337T313 322Q288 322 276 338T263 372Q263 381 265 388T270 400T273 405Q271 407 250 401Q234 393 226 386Q179 341 179 207V154Q179 141 179 127T179 101T180 81T180 66V61Q181 59 183 57T188 54T193 51T200 49T207 48T216 47T225 47T235 46T245 46H276V0H267Q249 3 140 3Q37 3 28 0H20V46H36Z" transform="translate(1444,0)" style="stroke-width: 3;"/><path data-c="73" d="M295 316Q295 356 268 385T190 414Q154 414 128 401Q98 382 98 349Q97 344 98 336T114 312T157 287Q175 282 201 278T245 269T277 256Q294 248 310 236T342 195T359 133Q359 71 321 31T198 -10H190Q138 -10 94 26L86 19L77 10Q71 4 65 -1L54 -11H46H42Q39 -11 33 -5V74V132Q33 153 35 157T45 162H54Q66 162 70 158T75 146T82 119T101 77Q136 26 198 26Q295 26 295 104Q295 133 277 151Q257 175 194 187T111 210Q75 227 54 256T33 318Q33 357 50 384T93 424T143 442T187 447H198Q238 447 268 432L283 424L292 431Q302 440 314 448H322H326Q329 448 335 442V310L329 304H301Q295 310 295 316Z" transform="translate(1836,0)" style="stroke-width: 3;"/><path data-c="65" d="M28 218Q28 273 48 318T98 391T163 433T229 448Q282 448 320 430T378 380T406 316T415 245Q415 238 408 231H126V216Q126 68 226 36Q246 30 270 30Q312 30 342 62Q359 79 369 104L379 128Q382 131 395 131H398Q415 131 415 121Q415 117 412 108Q393 53 349 21T250 -11Q155 -11 92 58T28 218ZM333 275Q322 403 238 411H236Q228 411 220 410T195 402T166 381T143 340T127 274V267H333V275Z" transform="translate(2230,0)" style="stroke-width: 3;"/></g></g><g data-mml-node="mo" transform="translate(8909.1,0)"><path data-c="2C" d="M78 35T78 60T94 103T137 121Q165 121 187 96T210 8Q210 -27 201 -60T180 -117T154 -158T130 -185T117 -194Q113 -194 104 -185T95 -172Q95 -168 106 -156T131 -126T157 -76T173 -3V9L172 8Q170 7 167 6T161 3T152 1T140 0Q113 0 96 17Z" style="stroke-width: 3;"/></g><g data-mml-node="mstyle" transform="translate(9187.1,0)"><g data-mml-node="mspace"/></g><g data-mml-node="mi" transform="translate(9520.7,0)"><path data-c="1D6FC" d="M34 156Q34 270 120 356T309 442Q379 442 421 402T478 304Q484 275 485 237V208Q534 282 560 374Q564 388 566 390T582 393Q603 393 603 385Q603 376 594 346T558 261T497 161L486 147L487 123Q489 67 495 47T514 26Q528 28 540 37T557 60Q559 67 562 68T577 70Q597 70 597 62Q597 56 591 43Q579 19 556 5T512 -10H505Q438 -10 414 62L411 69L400 61Q390 53 370 41T325 18T267 -2T203 -11Q124 -11 79 39T34 156ZM208 26Q257 26 306 47T379 90L403 112Q401 255 396 290Q382 405 304 405Q235 405 183 332Q156 292 139 224T121 120Q121 71 146 49T208 26Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(10160.7,0)"><path data-c="29" d="M60 749L64 750Q69 750 74 750H86L114 726Q208 641 251 514T294 250Q294 182 284 119T261 12T224 -76T186 -143T145 -194T113 -227T90 -246Q87 -249 86 -250H74Q66 -250 63 -250T58 -247T55 -238Q56 -237 66 -225Q221 -64 221 250T66 725Q56 737 55 738Q55 746 60 749Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(10549.7,0)"><path data-c="2C" d="M78 35T78 60T94 103T137 121Q165 121 187 96T210 8Q210 -27 201 -60T180 -117T154 -158T130 -185T117 -194Q113 -194 104 -185T95 -172Q95 -168 106 -156T131 -126T157 -76T173 -3V9L172 8Q170 7 167 6T161 3T152 1T140 0Q113 0 96 17Z" style="stroke-width: 3;"/></g><g data-mml-node="mstyle" transform="translate(10827.7,0)"><g data-mml-node="mspace"/></g><g data-mml-node="mi" transform="translate(12994.4,0)"><path data-c="1D6FC" d="M34 156Q34 270 120 356T309 442Q379 442 421 402T478 304Q484 275 485 237V208Q534 282 560 374Q564 388 566 390T582 393Q603 393 603 385Q603 376 594 346T558 261T497 161L486 147L487 123Q489 67 495 47T514 26Q528 28 540 37T557 60Q559 67 562 68T577 70Q597 70 597 62Q597 56 591 43Q579 19 556 5T512 -10H505Q438 -10 414 62L411 69L400 61Q390 53 370 41T325 18T267 -2T203 -11Q124 -11 79 39T34 156ZM208 26Q257 26 306 47T379 90L403 112Q401 255 396 290Q382 405 304 405Q235 405 183 332Q156 292 139 224T121 120Q121 71 146 49T208 26Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(13912.2,0)"><path data-c="3D" d="M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(14968,0)"><path data-c="73" d="M295 316Q295 356 268 385T190 414Q154 414 128 401Q98 382 98 349Q97 344 98 336T114 312T157 287Q175 282 201 278T245 269T277 256Q294 248 310 236T342 195T359 133Q359 71 321 31T198 -10H190Q138 -10 94 26L86 19L77 10Q71 4 65 -1L54 -11H46H42Q39 -11 33 -5V74V132Q33 153 35 157T45 162H54Q66 162 70 158T75 146T82 119T101 77Q136 26 198 26Q295 26 295 104Q295 133 277 151Q257 175 194 187T111 210Q75 227 54 256T33 318Q33 357 50 384T93 424T143 442T187 447H198Q238 447 268 432L283 424L292 431Q302 440 314 448H322H326Q329 448 335 442V310L329 304H301Q295 310 295 316Z" style="stroke-width: 3;"/><path data-c="6D" d="M41 46H55Q94 46 102 60V68Q102 77 102 91T102 122T103 161T103 203Q103 234 103 269T102 328V351Q99 370 88 376T43 385H25V408Q25 431 27 431L37 432Q47 433 65 434T102 436Q119 437 138 438T167 441T178 442H181V402Q181 364 182 364T187 369T199 384T218 402T247 421T285 437Q305 442 336 442Q351 442 364 440T387 434T406 426T421 417T432 406T441 395T448 384T452 374T455 366L457 361L460 365Q463 369 466 373T475 384T488 397T503 410T523 422T546 432T572 439T603 442Q729 442 740 329Q741 322 741 190V104Q741 66 743 59T754 49Q775 46 803 46H819V0H811L788 1Q764 2 737 2T699 3Q596 3 587 0H579V46H595Q656 46 656 62Q657 64 657 200Q656 335 655 343Q649 371 635 385T611 402T585 404Q540 404 506 370Q479 343 472 315T464 232V168V108Q464 78 465 68T468 55T477 49Q498 46 526 46H542V0H534L510 1Q487 2 460 2T422 3Q319 3 310 0H302V46H318Q379 46 379 62Q380 64 380 200Q379 335 378 343Q372 371 358 385T334 402T308 404Q263 404 229 370Q202 343 195 315T187 232V168V108Q187 78 188 68T191 55T200 49Q221 46 249 46H265V0H257L234 1Q210 2 183 2T145 3Q42 3 33 0H25V46H41Z" transform="translate(394,0)" style="stroke-width: 3;"/><path data-c="6F" d="M28 214Q28 309 93 378T250 448Q340 448 405 380T471 215Q471 120 407 55T250 -10Q153 -10 91 57T28 214ZM250 30Q372 30 372 193V225V250Q372 272 371 288T364 326T348 362T317 390T268 410Q263 411 252 411Q222 411 195 399Q152 377 139 338T126 246V226Q126 130 145 91Q177 30 250 30Z" transform="translate(1227,0)" style="stroke-width: 3;"/><path data-c="6F" d="M28 214Q28 309 93 378T250 448Q340 448 405 380T471 215Q471 120 407 55T250 -10Q153 -10 91 57T28 214ZM250 30Q372 30 372 193V225V250Q372 272 371 288T364 326T348 362T317 390T268 410Q263 411 252 411Q222 411 195 399Q152 377 139 338T126 246V226Q126 130 145 91Q177 30 250 30Z" transform="translate(1727,0)" style="stroke-width: 3;"/><path data-c="74" d="M27 422Q80 426 109 478T141 600V615H181V431H316V385H181V241Q182 116 182 100T189 68Q203 29 238 29Q282 29 292 100Q293 108 293 146V181H333V146V134Q333 57 291 17Q264 -10 221 -10Q187 -10 162 2T124 33T105 68T98 100Q97 107 97 248V385H18V422H27Z" transform="translate(2227,0)" style="stroke-width: 3;"/><path data-c="68" d="M41 46H55Q94 46 102 60V68Q102 77 102 91T102 124T102 167T103 217T103 272T103 329Q103 366 103 407T103 482T102 542T102 586T102 603Q99 622 88 628T43 637H25V660Q25 683 27 683L37 684Q47 685 66 686T103 688Q120 689 140 690T170 693T181 694H184V367Q244 442 328 442Q451 442 463 329Q464 322 464 190V104Q464 66 466 59T477 49Q498 46 526 46H542V0H534L510 1Q487 2 460 2T422 3Q319 3 310 0H302V46H318Q379 46 379 62Q380 64 380 200Q379 335 378 343Q372 371 358 385T334 402T308 404Q263 404 229 370Q202 343 195 315T187 232V168V108Q187 78 188 68T191 55T200 49Q221 46 249 46H265V0H257L234 1Q210 2 183 2T145 3Q42 3 33 0H25V46H41Z" transform="translate(2616,0)" style="stroke-width: 3;"/><path data-c="73" d="M295 316Q295 356 268 385T190 414Q154 414 128 401Q98 382 98 349Q97 344 98 336T114 312T157 287Q175 282 201 278T245 269T277 256Q294 248 310 236T342 195T359 133Q359 71 321 31T198 -10H190Q138 -10 94 26L86 19L77 10Q71 4 65 -1L54 -11H46H42Q39 -11 33 -5V74V132Q33 153 35 157T45 162H54Q66 162 70 158T75 146T82 119T101 77Q136 26 198 26Q295 26 295 104Q295 133 277 151Q257 175 194 187T111 210Q75 227 54 256T33 318Q33 357 50 384T93 424T143 442T187 447H198Q238 447 268 432L283 424L292 431Q302 440 314 448H322H326Q329 448 335 442V310L329 304H301Q295 310 295 316Z" transform="translate(3172,0)" style="stroke-width: 3;"/><path data-c="74" d="M27 422Q80 426 109 478T141 600V615H181V431H316V385H181V241Q182 116 182 100T189 68Q203 29 238 29Q282 29 292 100Q293 108 293 146V181H333V146V134Q333 57 291 17Q264 -10 221 -10Q187 -10 162 2T124 33T105 68T98 100Q97 107 97 248V385H18V422H27Z" transform="translate(3566,0)" style="stroke-width: 3;"/><path data-c="65" d="M28 218Q28 273 48 318T98 391T163 433T229 448Q282 448 320 430T378 380T406 316T415 245Q415 238 408 231H126V216Q126 68 226 36Q246 30 270 30Q312 30 342 62Q359 79 369 104L379 128Q382 131 395 131H398Q415 131 415 121Q415 117 412 108Q393 53 349 21T250 -11Q155 -11 92 58T28 218ZM333 275Q322 403 238 411H236Q228 411 220 410T195 402T166 381T143 340T127 274V267H333V275Z" transform="translate(3955,0)" style="stroke-width: 3;"/><path data-c="70" d="M36 -148H50Q89 -148 97 -134V-126Q97 -119 97 -107T97 -77T98 -38T98 6T98 55T98 106Q98 140 98 177T98 243T98 296T97 335T97 351Q94 370 83 376T38 385H20V408Q20 431 22 431L32 432Q42 433 61 434T98 436Q115 437 135 438T165 441T176 442H179V416L180 390L188 397Q247 441 326 441Q407 441 464 377T522 216Q522 115 457 52T310 -11Q242 -11 190 33L182 40V-45V-101Q182 -128 184 -134T195 -145Q216 -148 244 -148H260V-194H252L228 -193Q205 -192 178 -192T140 -191Q37 -191 28 -194H20V-148H36ZM424 218Q424 292 390 347T305 402Q234 402 182 337V98Q222 26 294 26Q345 26 384 80T424 218Z" transform="translate(4399,0)" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(19923,0)"><path data-c="28" d="M94 250Q94 319 104 381T127 488T164 576T202 643T244 695T277 729T302 750H315H319Q333 750 333 741Q333 738 316 720T275 667T226 581T184 443T167 250T184 58T225 -81T274 -167T316 -220T333 -241Q333 -250 318 -250H315H302L274 -226Q180 -141 137 -14T94 250Z" style="stroke-width: 3;"/></g><g data-mml-node="msub" transform="translate(20312,0)"><g data-mml-node="mi"><path data-c="1D451" d="M366 683Q367 683 438 688T511 694Q523 694 523 686Q523 679 450 384T375 83T374 68Q374 26 402 26Q411 27 422 35Q443 55 463 131Q469 151 473 152Q475 153 483 153H487H491Q506 153 506 145Q506 140 503 129Q490 79 473 48T445 8T417 -8Q409 -10 393 -10Q359 -10 336 5T306 36L300 51Q299 52 296 50Q294 48 292 46Q233 -10 172 -10Q117 -10 75 30T33 157Q33 205 53 255T101 341Q148 398 195 420T280 442Q336 442 364 400Q369 394 369 396Q370 400 396 505T424 616Q424 629 417 632T378 637H357Q351 643 351 645T353 664Q358 683 366 683ZM352 326Q329 405 277 405Q242 405 210 374T160 293Q131 214 119 129Q119 126 119 118T118 106Q118 61 136 44T179 26Q233 26 290 98L298 109L352 326Z" style="stroke-width: 3;"/></g><g data-mml-node="mtext" transform="translate(553,-150) scale(0.707)"><path data-c="6E" d="M41 46H55Q94 46 102 60V68Q102 77 102 91T102 122T103 161T103 203Q103 234 103 269T102 328V351Q99 370 88 376T43 385H25V408Q25 431 27 431L37 432Q47 433 65 434T102 436Q119 437 138 438T167 441T178 442H181V402Q181 364 182 364T187 369T199 384T218 402T247 421T285 437Q305 442 336 442Q450 438 463 329Q464 322 464 190V104Q464 66 466 59T477 49Q498 46 526 46H542V0H534L510 1Q487 2 460 2T422 3Q319 3 310 0H302V46H318Q379 46 379 62Q380 64 380 200Q379 335 378 343Q372 371 358 385T334 402T308 404Q263 404 229 370Q202 343 195 315T187 232V168V108Q187 78 188 68T191 55T200 49Q221 46 249 46H265V0H257L234 1Q210 2 183 2T145 3Q42 3 33 0H25V46H41Z" style="stroke-width: 3;"/><path data-c="65" d="M28 218Q28 273 48 318T98 391T163 433T229 448Q282 448 320 430T378 380T406 316T415 245Q415 238 408 231H126V216Q126 68 226 36Q246 30 270 30Q312 30 342 62Q359 79 369 104L379 128Q382 131 395 131H398Q415 131 415 121Q415 117 412 108Q393 53 349 21T250 -11Q155 -11 92 58T28 218ZM333 275Q322 403 238 411H236Q228 411 220 410T195 402T166 381T143 340T127 274V267H333V275Z" transform="translate(556,0)" style="stroke-width: 3;"/><path data-c="61" d="M137 305T115 305T78 320T63 359Q63 394 97 421T218 448Q291 448 336 416T396 340Q401 326 401 309T402 194V124Q402 76 407 58T428 40Q443 40 448 56T453 109V145H493V106Q492 66 490 59Q481 29 455 12T400 -6T353 12T329 54V58L327 55Q325 52 322 49T314 40T302 29T287 17T269 6T247 -2T221 -8T190 -11Q130 -11 82 20T34 107Q34 128 41 147T68 188T116 225T194 253T304 268H318V290Q318 324 312 340Q290 411 215 411Q197 411 181 410T156 406T148 403Q170 388 170 359Q170 334 154 320ZM126 106Q126 75 150 51T209 26Q247 26 276 49T315 109Q317 116 318 175Q318 233 317 233Q309 233 296 232T251 223T193 203T147 166T126 106Z" transform="translate(1000,0)" style="stroke-width: 3;"/><path data-c="72" d="M36 46H50Q89 46 97 60V68Q97 77 97 91T98 122T98 161T98 203Q98 234 98 269T98 328L97 351Q94 370 83 376T38 385H20V408Q20 431 22 431L32 432Q42 433 60 434T96 436Q112 437 131 438T160 441T171 442H174V373Q213 441 271 441H277Q322 441 343 419T364 373Q364 352 351 337T313 322Q288 322 276 338T263 372Q263 381 265 388T270 400T273 405Q271 407 250 401Q234 393 226 386Q179 341 179 207V154Q179 141 179 127T179 101T180 81T180 66V61Q181 59 183 57T188 54T193 51T200 49T207 48T216 47T225 47T235 46T245 46H276V0H267Q249 3 140 3Q37 3 28 0H20V46H36Z" transform="translate(1500,0)" style="stroke-width: 3;"/></g></g><g data-mml-node="mo" transform="translate(22252.8,0)"><path data-c="2C" d="M78 35T78 60T94 103T137 121Q165 121 187 96T210 8Q210 -27 201 -60T180 -117T154 -158T130 -185T117 -194Q113 -194 104 -185T95 -172Q95 -168 106 -156T131 -126T157 -76T173 -3V9L172 8Q170 7 167 6T161 3T152 1T140 0Q113 0 96 17Z" style="stroke-width: 3;"/></g><g data-mml-node="mstyle" transform="translate(22530.8,0)"><g data-mml-node="mspace"/></g><g data-mml-node="msub" transform="translate(22864.5,0)"><g data-mml-node="mi"><path data-c="1D451" d="M366 683Q367 683 438 688T511 694Q523 694 523 686Q523 679 450 384T375 83T374 68Q374 26 402 26Q411 27 422 35Q443 55 463 131Q469 151 473 152Q475 153 483 153H487H491Q506 153 506 145Q506 140 503 129Q490 79 473 48T445 8T417 -8Q409 -10 393 -10Q359 -10 336 5T306 36L300 51Q299 52 296 50Q294 48 292 46Q233 -10 172 -10Q117 -10 75 30T33 157Q33 205 53 255T101 341Q148 398 195 420T280 442Q336 442 364 400Q369 394 369 396Q370 400 396 505T424 616Q424 629 417 632T378 637H357Q351 643 351 645T353 664Q358 683 366 683ZM352 326Q329 405 277 405Q242 405 210 374T160 293Q131 214 119 129Q119 126 119 118T118 106Q118 61 136 44T179 26Q233 26 290 98L298 109L352 326Z" style="stroke-width: 3;"/></g><g data-mml-node="mtext" transform="translate(553,-150) scale(0.707)"><path data-c="66" d="M273 0Q255 3 146 3Q43 3 34 0H26V46H42Q70 46 91 49Q99 52 103 60Q104 62 104 224V385H33V431H104V497L105 564L107 574Q126 639 171 668T266 704Q267 704 275 704T289 705Q330 702 351 679T372 627Q372 604 358 590T321 576T284 590T270 627Q270 647 288 667H284Q280 668 273 668Q245 668 223 647T189 592Q183 572 182 497V431H293V385H185V225Q185 63 186 61T189 57T194 54T199 51T206 49T213 48T222 47T231 47T241 46T251 46H282V0H273Z" style="stroke-width: 3;"/><path data-c="61" d="M137 305T115 305T78 320T63 359Q63 394 97 421T218 448Q291 448 336 416T396 340Q401 326 401 309T402 194V124Q402 76 407 58T428 40Q443 40 448 56T453 109V145H493V106Q492 66 490 59Q481 29 455 12T400 -6T353 12T329 54V58L327 55Q325 52 322 49T314 40T302 29T287 17T269 6T247 -2T221 -8T190 -11Q130 -11 82 20T34 107Q34 128 41 147T68 188T116 225T194 253T304 268H318V290Q318 324 312 340Q290 411 215 411Q197 411 181 410T156 406T148 403Q170 388 170 359Q170 334 154 320ZM126 106Q126 75 150 51T209 26Q247 26 276 49T315 109Q317 116 318 175Q318 233 317 233Q309 233 296 232T251 223T193 203T147 166T126 106Z" transform="translate(306,0)" style="stroke-width: 3;"/><path data-c="72" d="M36 46H50Q89 46 97 60V68Q97 77 97 91T98 122T98 161T98 203Q98 234 98 269T98 328L97 351Q94 370 83 376T38 385H20V408Q20 431 22 431L32 432Q42 433 60 434T96 436Q112 437 131 438T160 441T171 442H174V373Q213 441 271 441H277Q322 441 343 419T364 373Q364 352 351 337T313 322Q288 322 276 338T263 372Q263 381 265 388T270 400T273 405Q271 407 250 401Q234 393 226 386Q179 341 179 207V154Q179 141 179 127T179 101T180 81T180 66V61Q181 59 183 57T188 54T193 51T200 49T207 48T216 47T225 47T235 46T245 46H276V0H267Q249 3 140 3Q37 3 28 0H20V46H36Z" transform="translate(806,0)" style="stroke-width: 3;"/></g></g><g data-mml-node="mo" transform="translate(24314.6,0)"><path data-c="2C" d="M78 35T78 60T94 103T137 121Q165 121 187 96T210 8Q210 -27 201 -60T180 -117T154 -158T130 -185T117 -194Q113 -194 104 -185T95 -172Q95 -168 106 -156T131 -126T157 -76T173 -3V9L172 8Q170 7 167 6T161 3T152 1T140 0Q113 0 96 17Z" style="stroke-width: 3;"/></g><g data-mml-node="mstyle" transform="translate(24592.6,0)"><g data-mml-node="mspace"/></g><g data-mml-node="mi" transform="translate(24926.3,0)"><path data-c="1D451" d="M366 683Q367 683 438 688T511 694Q523 694 523 686Q523 679 450 384T375 83T374 68Q374 26 402 26Q411 27 422 35Q443 55 463 131Q469 151 473 152Q475 153 483 153H487H491Q506 153 506 145Q506 140 503 129Q490 79 473 48T445 8T417 -8Q409 -10 393 -10Q359 -10 336 5T306 36L300 51Q299 52 296 50Q294 48 292 46Q233 -10 172 -10Q117 -10 75 30T33 157Q33 205 53 255T101 341Q148 398 195 420T280 442Q336 442 364 400Q369 394 369 396Q370 400 396 505T424 616Q424 629 417 632T378 637H357Q351 643 351 645T353 664Q358 683 366 683ZM352 326Q329 405 277 405Q242 405 210 374T160 293Q131 214 119 129Q119 126 119 118T118 106Q118 61 136 44T179 26Q233 26 290 98L298 109L352 326Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(25446.3,0)"><path data-c="29" d="M60 749L64 750Q69 750 74 750H86L114 726Q208 641 251 514T294 250Q294 182 284 119T261 12T224 -76T186 -143T145 -194T113 -227T90 -246Q87 -249 86 -250H74Q66 -250 63 -250T58 -247T55 -238Q56 -237 66 -225Q221 -64 221 250T66 725Q56 737 55 738Q55 746 60 749Z" style="stroke-width: 3;"/></g></g></g></svg><mjx-assistive-mml unselectable="on" display="block" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; overflow: hidden; width: 100%;"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><mi>h</mi><mo>=</mo><mi>lerp</mi><mo stretchy="false">(</mo><msub><mi>h</mi><mtext>fine</mtext></msub><mo>,</mo><mstyle scriptlevel="0"><mspace width="0.167em"/></mstyle><msub><mi>h</mi><mtext>coarse</mtext></msub><mo>,</mo><mstyle scriptlevel="0"><mspace width="0.167em"/></mstyle><mi>α</mi><mo stretchy="false">)</mo><mo>,</mo><mstyle scriptlevel="0"><mspace width="2em"/></mstyle><mi>α</mi><mo>=</mo><mi>smoothstep</mi><mo stretchy="false">(</mo><msub><mi>d</mi><mtext>near</mtext></msub><mo>,</mo><mstyle scriptlevel="0"><mspace width="0.167em"/></mstyle><msub><mi>d</mi><mtext>far</mtext></msub><mo>,</mo><mstyle scriptlevel="0"><mspace width="0.167em"/></mstyle><mi>d</mi><mo stretchy="false">)</mo></math></mjx-assistive-mml></mjx-container><p>donde <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.023ex;" xmlns="http://www.w3.org/2000/svg" width="1.176ex" height="1.593ex" role="img" focusable="false" viewBox="0 -694 520 704" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mi"><path data-c="1D451" d="M366 683Q367 683 438 688T511 694Q523 694 523 686Q523 679 450 384T375 83T374 68Q374 26 402 26Q411 27 422 35Q443 55 463 131Q469 151 473 152Q475 153 483 153H487H491Q506 153 506 145Q506 140 503 129Q490 79 473 48T445 8T417 -8Q409 -10 393 -10Q359 -10 336 5T306 36L300 51Q299 52 296 50Q294 48 292 46Q233 -10 172 -10Q117 -10 75 30T33 157Q33 205 53 255T101 341Q148 398 195 420T280 442Q336 442 364 400Q369 394 369 396Q370 400 396 505T424 616Q424 629 417 632T378 637H357Q351 643 351 645T353 664Q358 683 366 683ZM352 326Q329 405 277 405Q242 405 210 374T160 293Q131 214 119 129Q119 126 119 118T118 106Q118 61 136 44T179 26Q233 26 290 98L298 109L352 326Z" style="stroke-width: 3;"/></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mi>d</mi></math></mjx-assistive-mml></mjx-container> es la distancia del vértice a la cámara. Dentro del anillo (<mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.357ex;" xmlns="http://www.w3.org/2000/svg" width="8.585ex" height="1.927ex" role="img" focusable="false" viewBox="0 -694 3794.4 851.8" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mi"><path data-c="1D451" d="M366 683Q367 683 438 688T511 694Q523 694 523 686Q523 679 450 384T375 83T374 68Q374 26 402 26Q411 27 422 35Q443 55 463 131Q469 151 473 152Q475 153 483 153H487H491Q506 153 506 145Q506 140 503 129Q490 79 473 48T445 8T417 -8Q409 -10 393 -10Q359 -10 336 5T306 36L300 51Q299 52 296 50Q294 48 292 46Q233 -10 172 -10Q117 -10 75 30T33 157Q33 205 53 255T101 341Q148 398 195 420T280 442Q336 442 364 400Q369 394 369 396Q370 400 396 505T424 616Q424 629 417 632T378 637H357Q351 643 351 645T353 664Q358 683 366 683ZM352 326Q329 405 277 405Q242 405 210 374T160 293Q131 214 119 129Q119 126 119 118T118 106Q118 61 136 44T179 26Q233 26 290 98L298 109L352 326Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(797.8,0)"><path data-c="2264" d="M674 636Q682 636 688 630T694 615T687 601Q686 600 417 472L151 346L399 228Q687 92 691 87Q694 81 694 76Q694 58 676 56H670L382 192Q92 329 90 331Q83 336 83 348Q84 359 96 365Q104 369 382 500T665 634Q669 636 674 636ZM84 -118Q84 -108 99 -98H678Q694 -104 694 -118Q694 -130 679 -138H98Q84 -131 84 -118Z" style="stroke-width: 3;"/></g><g data-mml-node="msub" transform="translate(1853.6,0)"><g data-mml-node="mi"><path data-c="1D451" d="M366 683Q367 683 438 688T511 694Q523 694 523 686Q523 679 450 384T375 83T374 68Q374 26 402 26Q411 27 422 35Q443 55 463 131Q469 151 473 152Q475 153 483 153H487H491Q506 153 506 145Q506 140 503 129Q490 79 473 48T445 8T417 -8Q409 -10 393 -10Q359 -10 336 5T306 36L300 51Q299 52 296 50Q294 48 292 46Q233 -10 172 -10Q117 -10 75 30T33 157Q33 205 53 255T101 341Q148 398 195 420T280 442Q336 442 364 400Q369 394 369 396Q370 400 396 505T424 616Q424 629 417 632T378 637H357Q351 643 351 645T353 664Q358 683 366 683ZM352 326Q329 405 277 405Q242 405 210 374T160 293Q131 214 119 129Q119 126 119 118T118 106Q118 61 136 44T179 26Q233 26 290 98L298 109L352 326Z" style="stroke-width: 3;"/></g><g data-mml-node="mtext" transform="translate(553,-150) scale(0.707)"><path data-c="6E" d="M41 46H55Q94 46 102 60V68Q102 77 102 91T102 122T103 161T103 203Q103 234 103 269T102 328V351Q99 370 88 376T43 385H25V408Q25 431 27 431L37 432Q47 433 65 434T102 436Q119 437 138 438T167 441T178 442H181V402Q181 364 182 364T187 369T199 384T218 402T247 421T285 437Q305 442 336 442Q450 438 463 329Q464 322 464 190V104Q464 66 466 59T477 49Q498 46 526 46H542V0H534L510 1Q487 2 460 2T422 3Q319 3 310 0H302V46H318Q379 46 379 62Q380 64 380 200Q379 335 378 343Q372 371 358 385T334 402T308 404Q263 404 229 370Q202 343 195 315T187 232V168V108Q187 78 188 68T191 55T200 49Q221 46 249 46H265V0H257L234 1Q210 2 183 2T145 3Q42 3 33 0H25V46H41Z" style="stroke-width: 3;"/><path data-c="65" d="M28 218Q28 273 48 318T98 391T163 433T229 448Q282 448 320 430T378 380T406 316T415 245Q415 238 408 231H126V216Q126 68 226 36Q246 30 270 30Q312 30 342 62Q359 79 369 104L379 128Q382 131 395 131H398Q415 131 415 121Q415 117 412 108Q393 53 349 21T250 -11Q155 -11 92 58T28 218ZM333 275Q322 403 238 411H236Q228 411 220 410T195 402T166 381T143 340T127 274V267H333V275Z" transform="translate(556,0)" style="stroke-width: 3;"/><path data-c="61" d="M137 305T115 305T78 320T63 359Q63 394 97 421T218 448Q291 448 336 416T396 340Q401 326 401 309T402 194V124Q402 76 407 58T428 40Q443 40 448 56T453 109V145H493V106Q492 66 490 59Q481 29 455 12T400 -6T353 12T329 54V58L327 55Q325 52 322 49T314 40T302 29T287 17T269 6T247 -2T221 -8T190 -11Q130 -11 82 20T34 107Q34 128 41 147T68 188T116 225T194 253T304 268H318V290Q318 324 312 340Q290 411 215 411Q197 411 181 410T156 406T148 403Q170 388 170 359Q170 334 154 320ZM126 106Q126 75 150 51T209 26Q247 26 276 49T315 109Q317 116 318 175Q318 233 317 233Q309 233 296 232T251 223T193 203T147 166T126 106Z" transform="translate(1000,0)" style="stroke-width: 3;"/><path data-c="72" d="M36 46H50Q89 46 97 60V68Q97 77 97 91T98 122T98 161T98 203Q98 234 98 269T98 328L97 351Q94 370 83 376T38 385H20V408Q20 431 22 431L32 432Q42 433 60 434T96 436Q112 437 131 438T160 441T171 442H174V373Q213 441 271 441H277Q322 441 343 419T364 373Q364 352 351 337T313 322Q288 322 276 338T263 372Q263 381 265 388T270 400T273 405Q271 407 250 401Q234 393 226 386Q179 341 179 207V154Q179 141 179 127T179 101T180 81T180 66V61Q181 59 183 57T188 54T193 51T200 49T207 48T216 47T225 47T235 46T245 46H276V0H267Q249 3 140 3Q37 3 28 0H20V46H36Z" transform="translate(1500,0)" style="stroke-width: 3;"/></g></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mi>d</mi><mo>≤</mo><msub><mi>d</mi><mtext>near</mtext></msub></math></mjx-assistive-mml></mjx-container>), el vértice utiliza su altura a resolución completa; cuando alcanza el siguiente anillo (<mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.357ex;" xmlns="http://www.w3.org/2000/svg" width="7.474ex" height="1.927ex" role="img" focusable="false" viewBox="0 -694 3303.7 851.8" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mi"><path data-c="1D451" d="M366 683Q367 683 438 688T511 694Q523 694 523 686Q523 679 450 384T375 83T374 68Q374 26 402 26Q411 27 422 35Q443 55 463 131Q469 151 473 152Q475 153 483 153H487H491Q506 153 506 145Q506 140 503 129Q490 79 473 48T445 8T417 -8Q409 -10 393 -10Q359 -10 336 5T306 36L300 51Q299 52 296 50Q294 48 292 46Q233 -10 172 -10Q117 -10 75 30T33 157Q33 205 53 255T101 341Q148 398 195 420T280 442Q336 442 364 400Q369 394 369 396Q370 400 396 505T424 616Q424 629 417 632T378 637H357Q351 643 351 645T353 664Q358 683 366 683ZM352 326Q329 405 277 405Q242 405 210 374T160 293Q131 214 119 129Q119 126 119 118T118 106Q118 61 136 44T179 26Q233 26 290 98L298 109L352 326Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(797.8,0)"><path data-c="2265" d="M83 616Q83 624 89 630T99 636Q107 636 253 568T543 431T687 361Q694 356 694 346T687 331Q685 329 395 192L107 56H101Q83 58 83 76Q83 77 83 79Q82 86 98 95Q117 105 248 167Q326 204 378 228L626 346L360 472Q291 505 200 548Q112 589 98 597T83 616ZM84 -118Q84 -108 99 -98H678Q694 -104 694 -118Q694 -130 679 -138H98Q84 -131 84 -118Z" style="stroke-width: 3;"/></g><g data-mml-node="msub" transform="translate(1853.6,0)"><g data-mml-node="mi"><path data-c="1D451" d="M366 683Q367 683 438 688T511 694Q523 694 523 686Q523 679 450 384T375 83T374 68Q374 26 402 26Q411 27 422 35Q443 55 463 131Q469 151 473 152Q475 153 483 153H487H491Q506 153 506 145Q506 140 503 129Q490 79 473 48T445 8T417 -8Q409 -10 393 -10Q359 -10 336 5T306 36L300 51Q299 52 296 50Q294 48 292 46Q233 -10 172 -10Q117 -10 75 30T33 157Q33 205 53 255T101 341Q148 398 195 420T280 442Q336 442 364 400Q369 394 369 396Q370 400 396 505T424 616Q424 629 417 632T378 637H357Q351 643 351 645T353 664Q358 683 366 683ZM352 326Q329 405 277 405Q242 405 210 374T160 293Q131 214 119 129Q119 126 119 118T118 106Q118 61 136 44T179 26Q233 26 290 98L298 109L352 326Z" style="stroke-width: 3;"/></g><g data-mml-node="mtext" transform="translate(553,-150) scale(0.707)"><path data-c="66" d="M273 0Q255 3 146 3Q43 3 34 0H26V46H42Q70 46 91 49Q99 52 103 60Q104 62 104 224V385H33V431H104V497L105 564L107 574Q126 639 171 668T266 704Q267 704 275 704T289 705Q330 702 351 679T372 627Q372 604 358 590T321 576T284 590T270 627Q270 647 288 667H284Q280 668 273 668Q245 668 223 647T189 592Q183 572 182 497V431H293V385H185V225Q185 63 186 61T189 57T194 54T199 51T206 49T213 48T222 47T231 47T241 46T251 46H282V0H273Z" style="stroke-width: 3;"/><path data-c="61" d="M137 305T115 305T78 320T63 359Q63 394 97 421T218 448Q291 448 336 416T396 340Q401 326 401 309T402 194V124Q402 76 407 58T428 40Q443 40 448 56T453 109V145H493V106Q492 66 490 59Q481 29 455 12T400 -6T353 12T329 54V58L327 55Q325 52 322 49T314 40T302 29T287 17T269 6T247 -2T221 -8T190 -11Q130 -11 82 20T34 107Q34 128 41 147T68 188T116 225T194 253T304 268H318V290Q318 324 312 340Q290 411 215 411Q197 411 181 410T156 406T148 403Q170 388 170 359Q170 334 154 320ZM126 106Q126 75 150 51T209 26Q247 26 276 49T315 109Q317 116 318 175Q318 233 317 233Q309 233 296 232T251 223T193 203T147 166T126 106Z" transform="translate(306,0)" style="stroke-width: 3;"/><path data-c="72" d="M36 46H50Q89 46 97 60V68Q97 77 97 91T98 122T98 161T98 203Q98 234 98 269T98 328L97 351Q94 370 83 376T38 385H20V408Q20 431 22 431L32 432Q42 433 60 434T96 436Q112 437 131 438T160 441T171 442H174V373Q213 441 271 441H277Q322 441 343 419T364 373Q364 352 351 337T313 322Q288 322 276 338T263 372Q263 381 265 388T270 400T273 405Q271 407 250 401Q234 393 226 386Q179 341 179 207V154Q179 141 179 127T179 101T180 81T180 66V61Q181 59 183 57T188 54T193 51T200 49T207 48T216 47T225 47T235 46T245 46H276V0H267Q249 3 140 3Q37 3 28 0H20V46H36Z" transform="translate(806,0)" style="stroke-width: 3;"/></g></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mi>d</mi><mo>≥</mo><msub><mi>d</mi><mtext>far</mtext></msub></math></mjx-assistive-mml></mjx-container>), ya ha migrado a la altura de baja resolución que utilizará ese anillo, por lo que no queda ningún salto por producirse.</p>
<p>Una lección sutil surgió durante las pruebas de movimiento de la cámara. Es fácil evaluar los clipmaps en capturas estáticas y pasar por alto los artefactos de transición. Dedicamos tiempo a realizar recorridos a velocidad constante a través de los límites de los anillos y a observar si aparecía ruido temporal. Las capturas mentían. El movimiento decía la verdad.</p>
<p>Este spike también nos proporcionó un límite arquitectónico claro. Con el tiempo, el terreno del campo cercano podía volverse dinámico y costoso, con edición volumétrica, materiales más complejos e interacción física. El terreno del campo lejano podía seguir siendo estable, predecible y barato. Esa separación se convirtió en la columna vertebral de todas las decisiones arquitectónicas a partir de ese momento.</p>
<p>Si estás evaluando los clipmaps para tu propio proyecto, prueba bucles de estrés, no escenas bonitas. Los recorridos largos, los cambios de altitud de la cámara y los cruces repetidos de límites son los que revelan los problemas reales.</p>
<p>En la parte 7 añadimos mallado volumétrico y pasamos de «el terreno como superficie» a «el terreno como volumen editable». Fue entonces cuando este proyecto dejó de ser un renderizador y empezó a convertirse en un editor de mundos.</p>
<h2 id="tecnologia-mencionada-en-este-capitulo" tabindex="-1">Tecnología mencionada en este capítulo <a class="header-anchor" href="#tecnologia-mencionada-en-este-capitulo" aria-label="Permalink to &quot;Tecnología mencionada en este capítulo&quot;"></a></h2>
<p><strong>Clipmaps de geometría.</strong> Presentados por Losasso y Hoppe en SIGGRAPH 2004 (<a href="https://hhoppe.com/geomclipmap.pdf" target="_blank" rel="noreferrer">artículo</a>), los clipmaps de geometría renderizan el terreno como anillos cuadrados concéntricos centrados en la cámara. Cada anillo cubre el doble de área que el anterior con la mitad de resolución de vértices. El número total de vértices es constante: aproximadamente <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: 0;" xmlns="http://www.w3.org/2000/svg" width="6.295ex" height="1.887ex" role="img" focusable="false" viewBox="0 -833.9 2782.2 833.9" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="msup"><g data-mml-node="mi"><path data-c="1D441" d="M234 637Q231 637 226 637Q201 637 196 638T191 649Q191 676 202 682Q204 683 299 683Q376 683 387 683T401 677Q612 181 616 168L670 381Q723 592 723 606Q723 633 659 637Q635 637 635 648Q635 650 637 660Q641 676 643 679T653 683Q656 683 684 682T767 680Q817 680 843 681T873 682Q888 682 888 672Q888 650 880 642Q878 637 858 637Q787 633 769 597L620 7Q618 0 599 0Q585 0 582 2Q579 5 453 305L326 604L261 344Q196 88 196 79Q201 46 268 46H278Q284 41 284 38T282 19Q278 6 272 0H259Q228 2 151 2Q123 2 100 2T63 2T46 1Q31 1 31 10Q31 14 34 26T39 40Q41 46 62 46Q130 49 150 85Q154 91 221 362L289 634Q287 635 234 637Z" style="stroke-width: 3;"/></g><g data-mml-node="mn" transform="translate(975.3,363) scale(0.707)"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"/></g></g><g data-mml-node="mo" transform="translate(1601,0)"><path data-c="22C5" d="M78 250Q78 274 95 292T138 310Q162 310 180 294T199 251Q199 226 182 208T139 190T96 207T78 250Z" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(2101.2,0)"><path data-c="1D43F" d="M228 637Q194 637 192 641Q191 643 191 649Q191 673 202 682Q204 683 217 683Q271 680 344 680Q485 680 506 683H518Q524 677 524 674T522 656Q517 641 513 637H475Q406 636 394 628Q387 624 380 600T313 336Q297 271 279 198T252 88L243 52Q243 48 252 48T311 46H328Q360 46 379 47T428 54T478 72T522 106T564 161Q580 191 594 228T611 270Q616 273 628 273H641Q647 264 647 262T627 203T583 83T557 9Q555 4 553 3T537 0T494 -1Q483 -1 418 -1T294 0H116Q32 0 32 10Q32 17 34 24Q39 43 44 45Q48 46 59 46H65Q92 46 125 49Q139 52 144 61Q147 65 216 339T285 628Q285 635 228 637Z" style="stroke-width: 3;"/></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><msup><mi>N</mi><mn>2</mn></msup><mo>⋅</mo><mi>L</mi></math></mjx-assistive-mml></mjx-container>. Con <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.186ex;" xmlns="http://www.w3.org/2000/svg" width="8.42ex" height="1.731ex" role="img" focusable="false" viewBox="0 -683 3721.6 765" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mi"><path data-c="1D441" d="M234 637Q231 637 226 637Q201 637 196 638T191 649Q191 676 202 682Q204 683 299 683Q376 683 387 683T401 677Q612 181 616 168L670 381Q723 592 723 606Q723 633 659 637Q635 637 635 648Q635 650 637 660Q641 676 643 679T653 683Q656 683 684 682T767 680Q817 680 843 681T873 682Q888 682 888 672Q888 650 880 642Q878 637 858 637Q787 633 769 597L620 7Q618 0 599 0Q585 0 582 2Q579 5 453 305L326 604L261 344Q196 88 196 79Q201 46 268 46H278Q284 41 284 38T282 19Q278 6 272 0H259Q228 2 151 2Q123 2 100 2T63 2T46 1Q31 1 31 10Q31 14 34 26T39 40Q41 46 62 46Q130 49 150 85Q154 91 221 362L289 634Q287 635 234 637Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(1165.8,0)"><path data-c="3D" d="M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z" style="stroke-width: 3;"/></g><g data-mml-node="mn" transform="translate(2221.6,0)"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"/><path data-c="35" d="M164 157Q164 133 148 117T109 101H102Q148 22 224 22Q294 22 326 82Q345 115 345 210Q345 313 318 349Q292 382 260 382H254Q176 382 136 314Q132 307 129 306T114 304Q97 304 95 310Q93 314 93 485V614Q93 664 98 664Q100 666 102 666Q103 666 123 658T178 642T253 634Q324 634 389 662Q397 666 402 666Q410 666 410 648V635Q328 538 205 538Q174 538 149 544L139 546V374Q158 388 169 396T205 412T256 420Q337 420 393 355T449 201Q449 109 385 44T229 -22Q148 -22 99 32T50 154Q50 178 61 192T84 210T107 214Q132 214 148 197T164 157Z" transform="translate(500,0)" style="stroke-width: 3;"/><path data-c="36" d="M42 313Q42 476 123 571T303 666Q372 666 402 630T432 550Q432 525 418 510T379 495Q356 495 341 509T326 548Q326 592 373 601Q351 623 311 626Q240 626 194 566Q147 500 147 364L148 360Q153 366 156 373Q197 433 263 433H267Q313 433 348 414Q372 400 396 374T435 317Q456 268 456 210V192Q456 169 451 149Q440 90 387 34T253 -22Q225 -22 199 -14T143 16T92 75T56 172T42 313ZM257 397Q227 397 205 380T171 335T154 278T148 216Q148 133 160 97T198 39Q222 21 251 21Q302 21 329 59Q342 77 347 104T352 209Q352 289 347 316T329 361Q302 397 257 397Z" transform="translate(1000,0)" style="stroke-width: 3;"/></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mi>N</mi><mo>=</mo><mn>256</mn></math></mjx-assistive-mml></mjx-container> y <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.186ex;" xmlns="http://www.w3.org/2000/svg" width="5.689ex" height="1.731ex" role="img" focusable="false" viewBox="0 -683 2514.6 765" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mi"><path data-c="1D43F" d="M228 637Q194 637 192 641Q191 643 191 649Q191 673 202 682Q204 683 217 683Q271 680 344 680Q485 680 506 683H518Q524 677 524 674T522 656Q517 641 513 637H475Q406 636 394 628Q387 624 380 600T313 336Q297 271 279 198T252 88L243 52Q243 48 252 48T311 46H328Q360 46 379 47T428 54T478 72T522 106T564 161Q580 191 594 228T611 270Q616 273 628 273H641Q647 264 647 262T627 203T583 83T557 9Q555 4 553 3T537 0T494 -1Q483 -1 418 -1T294 0H116Q32 0 32 10Q32 17 34 24Q39 43 44 45Q48 46 59 46H65Q92 46 125 49Q139 52 144 61Q147 65 216 339T285 628Q285 635 228 637Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(958.8,0)"><path data-c="3D" d="M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z" style="stroke-width: 3;"/></g><g data-mml-node="mn" transform="translate(2014.6,0)"><path data-c="38" d="M70 417T70 494T124 618T248 666Q319 666 374 624T429 515Q429 485 418 459T392 417T361 389T335 371T324 363L338 354Q352 344 366 334T382 323Q457 264 457 174Q457 95 399 37T249 -22Q159 -22 101 29T43 155Q43 263 172 335L154 348Q133 361 127 368Q70 417 70 494ZM286 386L292 390Q298 394 301 396T311 403T323 413T334 425T345 438T355 454T364 471T369 491T371 513Q371 556 342 586T275 624Q268 625 242 625Q201 625 165 599T128 534Q128 511 141 492T167 463T217 431Q224 426 228 424L286 386ZM250 21Q308 21 350 55T392 137Q392 154 387 169T375 194T353 216T330 234T301 253T274 270Q260 279 244 289T218 306L210 311Q204 311 181 294T133 239T107 157Q107 98 150 60T250 21Z" style="stroke-width: 3;"/></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mi>L</mi><mo>=</mo><mn>8</mn></math></mjx-assistive-mml></mjx-container> niveles, eso equivale a <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.439ex;" xmlns="http://www.w3.org/2000/svg" width="18.712ex" height="2.394ex" role="img" focusable="false" viewBox="0 -864 8270.6 1058" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="msup"><g data-mml-node="mn"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"/><path data-c="35" d="M164 157Q164 133 148 117T109 101H102Q148 22 224 22Q294 22 326 82Q345 115 345 210Q345 313 318 349Q292 382 260 382H254Q176 382 136 314Q132 307 129 306T114 304Q97 304 95 310Q93 314 93 485V614Q93 664 98 664Q100 666 102 666Q103 666 123 658T178 642T253 634Q324 634 389 662Q397 666 402 666Q410 666 410 648V635Q328 538 205 538Q174 538 149 544L139 546V374Q158 388 169 396T205 412T256 420Q337 420 393 355T449 201Q449 109 385 44T229 -22Q148 -22 99 32T50 154Q50 178 61 192T84 210T107 214Q132 214 148 197T164 157Z" transform="translate(500,0)" style="stroke-width: 3;"/><path data-c="36" d="M42 313Q42 476 123 571T303 666Q372 666 402 630T432 550Q432 525 418 510T379 495Q356 495 341 509T326 548Q326 592 373 601Q351 623 311 626Q240 626 194 566Q147 500 147 364L148 360Q153 366 156 373Q197 433 263 433H267Q313 433 348 414Q372 400 396 374T435 317Q456 268 456 210V192Q456 169 451 149Q440 90 387 34T253 -22Q225 -22 199 -14T143 16T92 75T56 172T42 313ZM257 397Q227 397 205 380T171 335T154 278T148 216Q148 133 160 97T198 39Q222 21 251 21Q302 21 329 59Q342 77 347 104T352 209Q352 289 347 316T329 361Q302 397 257 397Z" transform="translate(1000,0)" style="stroke-width: 3;"/></g><g data-mml-node="mn" transform="translate(1533,393.1) scale(0.707)"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"/></g></g><g data-mml-node="mo" transform="translate(2158.8,0)"><path data-c="D7" d="M630 29Q630 9 609 9Q604 9 587 25T493 118L389 222L284 117Q178 13 175 11Q171 9 168 9Q160 9 154 15T147 29Q147 36 161 51T255 146L359 250L255 354Q174 435 161 449T147 471Q147 480 153 485T168 490Q173 490 175 489Q178 487 284 383L389 278L493 382Q570 459 587 475T609 491Q630 491 630 471Q630 464 620 453T522 355L418 250L522 145Q606 61 618 48T630 29Z" style="stroke-width: 3;"/></g><g data-mml-node="mn" transform="translate(3159,0)"><path data-c="38" d="M70 417T70 494T124 618T248 666Q319 666 374 624T429 515Q429 485 418 459T392 417T361 389T335 371T324 363L338 354Q352 344 366 334T382 323Q457 264 457 174Q457 95 399 37T249 -22Q159 -22 101 29T43 155Q43 263 172 335L154 348Q133 361 127 368Q70 417 70 494ZM286 386L292 390Q298 394 301 396T311 403T323 413T334 425T345 438T355 454T364 471T369 491T371 513Q371 556 342 586T275 624Q268 625 242 625Q201 625 165 599T128 534Q128 511 141 492T167 463T217 431Q224 426 228 424L286 386ZM250 21Q308 21 350 55T392 137Q392 154 387 169T375 194T353 216T330 234T301 253T274 270Q260 279 244 289T218 306L210 311Q204 311 181 294T133 239T107 157Q107 98 150 60T250 21Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(3936.8,0)"><path data-c="2248" d="M55 319Q55 360 72 393T114 444T163 472T205 482Q207 482 213 482T223 483Q262 483 296 468T393 413L443 381Q502 346 553 346Q609 346 649 375T694 454Q694 465 698 474T708 483Q722 483 722 452Q722 386 675 338T555 289Q514 289 468 310T388 357T308 404T224 426Q164 426 125 393T83 318Q81 289 69 289Q55 289 55 319ZM55 85Q55 126 72 159T114 210T163 238T205 248Q207 248 213 248T223 249Q262 249 296 234T393 179L443 147Q502 112 553 112Q609 112 649 141T694 220Q694 249 708 249T722 217Q722 153 675 104T555 55Q514 55 468 76T388 123T308 170T224 192Q164 192 125 159T83 84Q80 55 69 55Q55 55 55 85Z" style="stroke-width: 3;"/></g><g data-mml-node="mn" transform="translate(4992.6,0)"><path data-c="35" d="M164 157Q164 133 148 117T109 101H102Q148 22 224 22Q294 22 326 82Q345 115 345 210Q345 313 318 349Q292 382 260 382H254Q176 382 136 314Q132 307 129 306T114 304Q97 304 95 310Q93 314 93 485V614Q93 664 98 664Q100 666 102 666Q103 666 123 658T178 642T253 634Q324 634 389 662Q397 666 402 666Q410 666 410 648V635Q328 538 205 538Q174 538 149 544L139 546V374Q158 388 169 396T205 412T256 420Q337 420 393 355T449 201Q449 109 385 44T229 -22Q148 -22 99 32T50 154Q50 178 61 192T84 210T107 214Q132 214 148 197T164 157Z" style="stroke-width: 3;"/><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" transform="translate(500,0)" style="stroke-width: 3;"/><path data-c="34" d="M462 0Q444 3 333 3Q217 3 199 0H190V46H221Q241 46 248 46T265 48T279 53T286 61Q287 63 287 115V165H28V211L179 442Q332 674 334 675Q336 677 355 677H373L379 671V211H471V165H379V114Q379 73 379 66T385 54Q393 47 442 46H471V0H462ZM293 211V545L74 212L183 211H293Z" transform="translate(1000,0)" style="stroke-width: 3;"/><path data-c="2C" d="M78 35T78 60T94 103T137 121Q165 121 187 96T210 8Q210 -27 201 -60T180 -117T154 -158T130 -185T117 -194Q113 -194 104 -185T95 -172Q95 -168 106 -156T131 -126T157 -76T173 -3V9L172 8Q170 7 167 6T161 3T152 1T140 0Q113 0 96 17Z" transform="translate(1500,0)" style="stroke-width: 3;"/><path data-c="30" d="M96 585Q152 666 249 666Q297 666 345 640T423 548Q460 465 460 320Q460 165 417 83Q397 41 362 16T301 -15T250 -22Q224 -22 198 -16T137 16T82 83Q39 165 39 320Q39 494 96 585ZM321 597Q291 629 250 629Q208 629 178 597Q153 571 145 525T137 333Q137 175 145 125T181 46Q209 16 250 16Q290 16 318 46Q347 76 354 130T362 333Q362 478 354 524T321 597Z" transform="translate(1778,0)" style="stroke-width: 3;"/><path data-c="30" d="M96 585Q152 666 249 666Q297 666 345 640T423 548Q460 465 460 320Q460 165 417 83Q397 41 362 16T301 -15T250 -22Q224 -22 198 -16T137 16T82 83Q39 165 39 320Q39 494 96 585ZM321 597Q291 629 250 629Q208 629 178 597Q153 571 145 525T137 333Q137 175 145 125T181 46Q209 16 250 16Q290 16 318 46Q347 76 354 130T362 333Q362 478 354 524T321 597Z" transform="translate(2278,0)" style="stroke-width: 3;"/><path data-c="30" d="M96 585Q152 666 249 666Q297 666 345 640T423 548Q460 465 460 320Q460 165 417 83Q397 41 362 16T301 -15T250 -22Q224 -22 198 -16T137 16T82 83Q39 165 39 320Q39 494 96 585ZM321 597Q291 629 250 629Q208 629 178 597Q153 571 145 525T137 333Q137 175 145 125T181 46Q209 16 250 16Q290 16 318 46Q347 76 354 130T362 333Q362 478 354 524T321 597Z" transform="translate(2778,0)" style="stroke-width: 3;"/></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><msup><mn>256</mn><mn>2</mn></msup><mo>×</mo><mn>8</mn><mo>≈</mo><mn>524,000</mn></math></mjx-assistive-mml></mjx-container> vértices, independientemente del tamaño del mundo. La CPU actualiza los datos del mapa de alturas de cada anillo a medida que se mueve la cámara. El shader de vértices lee la altura de una textura y desplaza la cuadrícula plana. Consulta nuestra <a href="/es/guides/landscape-generation-browser.html#geometry-clipmaps">guía de paisajes sobre clipmaps de geometría</a> y <a href="https://developer.nvidia.com/gpugems/gpugems2/part-i-geometric-complexity/chapter-2-terrain-rendering-using-gpu-based-geometry" target="_blank" rel="noreferrer">GPU Gems 2, capítulo 2</a>.</p>
<p><strong>Geomorfismo.</strong> El mayor artefacto visual del LOD de terreno son los saltos: los vértices cambian bruscamente cuando una sección pasa a otro nivel de LOD. El geomorfismo los elimina mezclando las posiciones de los vértices entre niveles de LOD a lo largo de una zona de transición. Cada vértice almacena tanto su altura del LOD actual como su altura del LOD de menor resolución. Un factor de transformación basado en la distancia a la cámara interpola suavemente entre ambas: <code>morphedHeight = mix(fineLodHeight, coarseLodHeight, smoothstep(lodNear, lodFar, distance))</code>. La zona de transición suele ocupar el 20 % exterior de cada anillo. A velocidades normales de cámara, la transición es invisible. Consulta los <a href="/es/guides/landscape-generation-browser.html#geomorphing-pop-free-lod-transitions">detalles sobre el geomorfismo</a>.</p>
<p><strong>CDLOD (clipmaps adaptativos con quadtree).</strong> Una mejora de los clipmaps de anillos fijos propuesta por Strugar (2014, <a href="https://www.vertexasylum.com/CDLOD/cdlod_latest.pdf" target="_blank" rel="noreferrer">artículo</a>). En lugar de usar anillos concéntricos con resolución uniforme, CDLOD utiliza un quadtree que se adapta a la complejidad del terreno. Las zonas planas utilizan nodos de baja resolución, mientras que las zonas con mucho detalle —acantilados o crestas— reciben subdivisiones más finas. Esto es importante para los mundos creados por usuarios, donde la complejidad puede variar enormemente entre distintos chunks. Consulta <a href="/es/guides/landscape-generation-browser.html#cdlod-quadtree-adaptive-clipmaps">CDLOD en nuestra guía de paisajes</a>.</p>
<hr>
<p>Parte 6 de 12.<br>
Anterior: <a href="/es/blog/2026-02-25-open-world-browser-part-05-budgeting-the-pretty.html">Parte 5: Presupuestando los elementos vistosos</a><br>
Siguiente: <a href="/es/blog/2026-02-25-open-world-browser-part-07-marching-cubes.html">Parte 7: Marching cubes y las primeras cuevas de verdad</a><br>
Guía de la serie: <a href="/es/blog/2026-02-25-open-world-browser-series-guide.html">/es/blog/2026-02-25-open-world-browser-series-guide</a></p>
]]></content:encoded>
            <enclosure url="https://cdn.cinevva.com/blog/why-webgpu-engine-hero.jpg" length="0" type="image/jpg"/>
        </item>
        <item>
            <title><![CDATA[Construir un mundo abierto en el navegador, parte 7: Marching cubes y las primeras cuevas de verdad]]></title>
            <link>https://app.cinevva.com/es/blog/2026-02-25-open-world-browser-part-07-marching-cubes</link>
            <guid>https://app.cinevva.com/es/blog/2026-02-25-open-world-browser-part-07-marching-cubes</guid>
            <pubDate>Wed, 25 Feb 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[El Spike 12 incorporó al proyecto marching cubes en tiempo real mediante WebGPU y cambió lo que el terreno podía llegar a ser.]]></description>
            <content:encoded><![CDATA[<h1 id="construir-un-mundo-abierto-en-el-navegador-parte-7-marching-cubes-y-las-primeras-cuevas-de-verdad" tabindex="-1">Construir un mundo abierto en el navegador, parte 7: Marching cubes y las primeras cuevas de verdad <a class="header-anchor" href="#construir-un-mundo-abierto-en-el-navegador-parte-7-marching-cubes-y-las-primeras-cuevas-de-verdad" aria-label="Permalink to &quot;Construir un mundo abierto en el navegador, parte 7: Marching cubes y las primeras cuevas de verdad&quot;"></a></h1>
<p><em>Por <a href="/es/about.html">Oleg Sidorkin</a>, CTO y cofundador de Cinevva</em></p>
<p>¿Acabas de llegar? Consulta la <a href="/es/blog/2026-02-25-open-world-browser-series-guide.html">guía de la serie</a>. Explica qué es un spike y enlaza todas las partes.</p>
<p>Los mapas de altura son estupendos hasta que necesitas voladizos.</p>
<p>En cuanto quieres túneles excavados, salientes rocosos flotantes o techos de cuevas, una pipeline basada exclusivamente en campos de altura empieza a limitarte. Un mapa de altura almacena un valor Y por cada coordenada XZ. Es físicamente incapaz de representar cualquier superficie que se pliegue sobre sí misma. Necesitábamos una representación volumétrica.</p>
<p>El Spike 12 implementó marching cubes en la GPU mediante shaders de cómputo de WebGPU. El algoritmo evalúa un campo de distancia con signo (SDF) sobre una cuadrícula 3D y extrae una malla de triángulos en la superficie donde se cruza el valor cero. Cada celda tiene 8 vértices, y cada uno está dentro o fuera de la superficie, lo que da <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.186ex;" xmlns="http://www.w3.org/2000/svg" width="8.53ex" height="2.072ex" role="img" focusable="false" viewBox="0 -833.9 3770.1 915.9" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="msup"><g data-mml-node="mn"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"/></g><g data-mml-node="mn" transform="translate(533,363) scale(0.707)"><path data-c="38" d="M70 417T70 494T124 618T248 666Q319 666 374 624T429 515Q429 485 418 459T392 417T361 389T335 371T324 363L338 354Q352 344 366 334T382 323Q457 264 457 174Q457 95 399 37T249 -22Q159 -22 101 29T43 155Q43 263 172 335L154 348Q133 361 127 368Q70 417 70 494ZM286 386L292 390Q298 394 301 396T311 403T323 413T334 425T345 438T355 454T364 471T369 491T371 513Q371 556 342 586T275 624Q268 625 242 625Q201 625 165 599T128 534Q128 511 141 492T167 463T217 431Q224 426 228 424L286 386ZM250 21Q308 21 350 55T392 137Q392 154 387 169T375 194T353 216T330 234T301 253T274 270Q260 279 244 289T218 306L210 311Q204 311 181 294T133 239T107 157Q107 98 150 60T250 21Z" style="stroke-width: 3;"/></g></g><g data-mml-node="mo" transform="translate(1214.3,0)"><path data-c="3D" d="M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z" style="stroke-width: 3;"/></g><g data-mml-node="mn" transform="translate(2270.1,0)"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"/><path data-c="35" d="M164 157Q164 133 148 117T109 101H102Q148 22 224 22Q294 22 326 82Q345 115 345 210Q345 313 318 349Q292 382 260 382H254Q176 382 136 314Q132 307 129 306T114 304Q97 304 95 310Q93 314 93 485V614Q93 664 98 664Q100 666 102 666Q103 666 123 658T178 642T253 634Q324 634 389 662Q397 666 402 666Q410 666 410 648V635Q328 538 205 538Q174 538 149 544L139 546V374Q158 388 169 396T205 412T256 420Q337 420 393 355T449 201Q449 109 385 44T229 -22Q148 -22 99 32T50 154Q50 178 61 192T84 210T107 214Q132 214 148 197T164 157Z" transform="translate(500,0)" style="stroke-width: 3;"/><path data-c="36" d="M42 313Q42 476 123 571T303 666Q372 666 402 630T432 550Q432 525 418 510T379 495Q356 495 341 509T326 548Q326 592 373 601Q351 623 311 626Q240 626 194 566Q147 500 147 364L148 360Q153 366 156 373Q197 433 263 433H267Q313 433 348 414Q372 400 396 374T435 317Q456 268 456 210V192Q456 169 451 149Q440 90 387 34T253 -22Q225 -22 199 -14T143 16T92 75T56 172T42 313ZM257 397Q227 397 205 380T171 335T154 278T148 216Q148 133 160 97T198 39Q222 21 251 21Q302 21 329 59Q342 77 347 104T352 209Q352 289 347 316T329 361Q302 397 257 397Z" transform="translate(1000,0)" style="stroke-width: 3;"/></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><msup><mn>2</mn><mn>8</mn></msup><mo>=</mo><mn>256</mn></math></mjx-assistive-mml></mjx-container> patrones de signos posibles. Una tabla de consulta asigna cada patrón a un conjunto de triángulos. Los vértices se sitúan sobre las aristas de la celda en el punto donde el campo cruza el cero. Para una arista entre los vértices <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.023ex;" xmlns="http://www.w3.org/2000/svg" width="1.197ex" height="1.02ex" role="img" focusable="false" viewBox="0 -441 529 451" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mi"><path data-c="1D44E" d="M33 157Q33 258 109 349T280 441Q331 441 370 392Q386 422 416 422Q429 422 439 414T449 394Q449 381 412 234T374 68Q374 43 381 35T402 26Q411 27 422 35Q443 55 463 131Q469 151 473 152Q475 153 483 153H487Q506 153 506 144Q506 138 501 117T481 63T449 13Q436 0 417 -8Q409 -10 393 -10Q359 -10 336 5T306 36L300 51Q299 52 296 50Q294 48 292 46Q233 -10 172 -10Q117 -10 75 30T33 157ZM351 328Q351 334 346 350T323 385T277 405Q242 405 210 374T160 293Q131 214 119 129Q119 126 119 118T118 106Q118 61 136 44T179 26Q217 26 254 59T298 110Q300 114 325 217T351 328Z" style="stroke-width: 3;"/></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mi>a</mi></math></mjx-assistive-mml></mjx-container> y <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.025ex;" xmlns="http://www.w3.org/2000/svg" width="0.971ex" height="1.595ex" role="img" focusable="false" viewBox="0 -694 429 705" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mi"><path data-c="1D44F" d="M73 647Q73 657 77 670T89 683Q90 683 161 688T234 694Q246 694 246 685T212 542Q204 508 195 472T180 418L176 399Q176 396 182 402Q231 442 283 442Q345 442 383 396T422 280Q422 169 343 79T173 -11Q123 -11 82 27T40 150V159Q40 180 48 217T97 414Q147 611 147 623T109 637Q104 637 101 637H96Q86 637 83 637T76 640T73 647ZM336 325V331Q336 405 275 405Q258 405 240 397T207 376T181 352T163 330L157 322L136 236Q114 150 114 114Q114 66 138 42Q154 26 178 26Q211 26 245 58Q270 81 285 114T318 219Q336 291 336 325Z" style="stroke-width: 3;"/></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mi>b</mi></math></mjx-assistive-mml></mjx-container>, con valores de campo <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.464ex;" xmlns="http://www.w3.org/2000/svg" width="2.143ex" height="2.059ex" role="img" focusable="false" viewBox="0 -705 947.1 910" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="msub"><g data-mml-node="mi"><path data-c="1D453" d="M118 -162Q120 -162 124 -164T135 -167T147 -168Q160 -168 171 -155T187 -126Q197 -99 221 27T267 267T289 382V385H242Q195 385 192 387Q188 390 188 397L195 425Q197 430 203 430T250 431Q298 431 298 432Q298 434 307 482T319 540Q356 705 465 705Q502 703 526 683T550 630Q550 594 529 578T487 561Q443 561 443 603Q443 622 454 636T478 657L487 662Q471 668 457 668Q445 668 434 658T419 630Q412 601 403 552T387 469T380 433Q380 431 435 431Q480 431 487 430T498 424Q499 420 496 407T491 391Q489 386 482 386T428 385H372L349 263Q301 15 282 -47Q255 -132 212 -173Q175 -205 139 -205Q107 -205 81 -186T55 -132Q55 -95 76 -78T118 -61Q162 -61 162 -103Q162 -122 151 -136T127 -157L118 -162Z" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(523,-150) scale(0.707)"><path data-c="1D44E" d="M33 157Q33 258 109 349T280 441Q331 441 370 392Q386 422 416 422Q429 422 439 414T449 394Q449 381 412 234T374 68Q374 43 381 35T402 26Q411 27 422 35Q443 55 463 131Q469 151 473 152Q475 153 483 153H487Q506 153 506 144Q506 138 501 117T481 63T449 13Q436 0 417 -8Q409 -10 393 -10Q359 -10 336 5T306 36L300 51Q299 52 296 50Q294 48 292 46Q233 -10 172 -10Q117 -10 75 30T33 157ZM351 328Q351 334 346 350T323 385T277 405Q242 405 210 374T160 293Q131 214 119 129Q119 126 119 118T118 106Q118 61 136 44T179 26Q217 26 254 59T298 110Q300 114 325 217T351 328Z" style="stroke-width: 3;"/></g></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><msub><mi>f</mi><mi>a</mi></msub></math></mjx-assistive-mml></mjx-container> y <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.464ex;" xmlns="http://www.w3.org/2000/svg" width="1.983ex" height="2.059ex" role="img" focusable="false" viewBox="0 -705 876.3 910" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="msub"><g data-mml-node="mi"><path data-c="1D453" d="M118 -162Q120 -162 124 -164T135 -167T147 -168Q160 -168 171 -155T187 -126Q197 -99 221 27T267 267T289 382V385H242Q195 385 192 387Q188 390 188 397L195 425Q197 430 203 430T250 431Q298 431 298 432Q298 434 307 482T319 540Q356 705 465 705Q502 703 526 683T550 630Q550 594 529 578T487 561Q443 561 443 603Q443 622 454 636T478 657L487 662Q471 668 457 668Q445 668 434 658T419 630Q412 601 403 552T387 469T380 433Q380 431 435 431Q480 431 487 430T498 424Q499 420 496 407T491 391Q489 386 482 386T428 385H372L349 263Q301 15 282 -47Q255 -132 212 -173Q175 -205 139 -205Q107 -205 81 -186T55 -132Q55 -95 76 -78T118 -61Q162 -61 162 -103Q162 -122 151 -136T127 -157L118 -162Z" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(523,-150) scale(0.707)"><path data-c="1D44F" d="M73 647Q73 657 77 670T89 683Q90 683 161 688T234 694Q246 694 246 685T212 542Q204 508 195 472T180 418L176 399Q176 396 182 402Q231 442 283 442Q345 442 383 396T422 280Q422 169 343 79T173 -11Q123 -11 82 27T40 150V159Q40 180 48 217T97 414Q147 611 147 623T109 637Q104 637 101 637H96Q86 637 83 637T76 640T73 647ZM336 325V331Q336 405 275 405Q258 405 240 397T207 376T181 352T163 330L157 322L136 236Q114 150 114 114Q114 66 138 42Q154 26 178 26Q211 26 245 58Q270 81 285 114T318 219Q336 291 336 325Z" style="stroke-width: 3;"/></g></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><msub><mi>f</mi><mi>b</mi></msub></math></mjx-assistive-mml></mjx-container>, la interpolación lineal coloca el vértice en</p>
<mjx-container tabindex="0" class="MathJax" jax="SVG" display="true" style="direction: ltr; display: block; text-align: center; margin: 1em 0; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -2.016ex;" xmlns="http://www.w3.org/2000/svg" width="37.407ex" height="5.14ex" role="img" focusable="false" viewBox="0 -1381 16534 2272" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="TeXAtom" data-mjx-texclass="ORD"><g data-mml-node="mi"><path data-c="1D42F" d="M401 444Q413 441 495 441Q568 441 574 444H580V382H510L409 156Q348 18 339 6Q331 -4 320 -4Q318 -4 313 -4T303 -3H288Q273 -3 264 12T221 102Q206 135 197 156L96 382H26V444H34Q49 441 145 441Q252 441 270 444H279V382H231L284 264Q335 149 338 149Q338 150 389 264T442 381Q442 382 418 382H394V444H401Z" style="stroke-width: 3;"/></g></g><g data-mml-node="mo" transform="translate(884.8,0)"><path data-c="3D" d="M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z" style="stroke-width: 3;"/></g><g data-mml-node="msub" transform="translate(1940.6,0)"><g data-mml-node="TeXAtom" data-mjx-texclass="ORD"><g data-mml-node="mi"><path data-c="1D429" d="M32 442L123 446Q214 450 215 450H221V409Q222 409 229 413T251 423T284 436T328 446T382 450Q480 450 540 388T600 223Q600 128 539 61T361 -6H354Q292 -6 236 28L227 34V-132H296V-194H287Q269 -191 163 -191Q56 -191 38 -194H29V-132H98V113V284Q98 330 97 348T93 370T83 376Q69 380 42 380H29V442H32ZM457 224Q457 303 427 349T350 395Q282 395 235 352L227 345V104L233 97Q274 45 337 45Q383 45 420 86T457 224Z" style="stroke-width: 3;"/></g></g><g data-mml-node="mi" transform="translate(672,-150) scale(0.707)"><path data-c="1D44E" d="M33 157Q33 258 109 349T280 441Q331 441 370 392Q386 422 416 422Q429 422 439 414T449 394Q449 381 412 234T374 68Q374 43 381 35T402 26Q411 27 422 35Q443 55 463 131Q469 151 473 152Q475 153 483 153H487Q506 153 506 144Q506 138 501 117T481 63T449 13Q436 0 417 -8Q409 -10 393 -10Q359 -10 336 5T306 36L300 51Q299 52 296 50Q294 48 292 46Q233 -10 172 -10Q117 -10 75 30T33 157ZM351 328Q351 334 346 350T323 385T277 405Q242 405 210 374T160 293Q131 214 119 129Q119 126 119 118T118 106Q118 61 136 44T179 26Q217 26 254 59T298 110Q300 114 325 217T351 328Z" style="stroke-width: 3;"/></g></g><g data-mml-node="mo" transform="translate(3258.8,0)"><path data-c="2B" d="M56 237T56 250T70 270H369V420L370 570Q380 583 389 583Q402 583 409 568V270H707Q722 262 722 250T707 230H409V-68Q401 -82 391 -82H389H387Q375 -82 369 -68V230H70Q56 237 56 250Z" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(4259.1,0)"><path data-c="1D461" d="M26 385Q19 392 19 395Q19 399 22 411T27 425Q29 430 36 430T87 431H140L159 511Q162 522 166 540T173 566T179 586T187 603T197 615T211 624T229 626Q247 625 254 615T261 596Q261 589 252 549T232 470L222 433Q222 431 272 431H323Q330 424 330 420Q330 398 317 385H210L174 240Q135 80 135 68Q135 26 162 26Q197 26 230 60T283 144Q285 150 288 151T303 153H307Q322 153 322 145Q322 142 319 133Q314 117 301 95T267 48T216 6T155 -11Q125 -11 98 4T59 56Q57 64 57 83V101L92 241Q127 382 128 383Q128 385 77 385H26Z" style="stroke-width: 3;"/></g><g data-mml-node="mstyle" transform="translate(4620.1,0)"><g data-mml-node="mspace"/></g><g data-mml-node="mo" transform="translate(4787.1,0)"><path data-c="28" d="M94 250Q94 319 104 381T127 488T164 576T202 643T244 695T277 729T302 750H315H319Q333 750 333 741Q333 738 316 720T275 667T226 581T184 443T167 250T184 58T225 -81T274 -167T316 -220T333 -241Q333 -250 318 -250H315H302L274 -226Q180 -141 137 -14T94 250Z" style="stroke-width: 3;"/></g><g data-mml-node="msub" transform="translate(5176.1,0)"><g data-mml-node="TeXAtom" data-mjx-texclass="ORD"><g data-mml-node="mi"><path data-c="1D429" d="M32 442L123 446Q214 450 215 450H221V409Q222 409 229 413T251 423T284 436T328 446T382 450Q480 450 540 388T600 223Q600 128 539 61T361 -6H354Q292 -6 236 28L227 34V-132H296V-194H287Q269 -191 163 -191Q56 -191 38 -194H29V-132H98V113V284Q98 330 97 348T93 370T83 376Q69 380 42 380H29V442H32ZM457 224Q457 303 427 349T350 395Q282 395 235 352L227 345V104L233 97Q274 45 337 45Q383 45 420 86T457 224Z" style="stroke-width: 3;"/></g></g><g data-mml-node="mi" transform="translate(672,-150) scale(0.707)"><path data-c="1D44F" d="M73 647Q73 657 77 670T89 683Q90 683 161 688T234 694Q246 694 246 685T212 542Q204 508 195 472T180 418L176 399Q176 396 182 402Q231 442 283 442Q345 442 383 396T422 280Q422 169 343 79T173 -11Q123 -11 82 27T40 150V159Q40 180 48 217T97 414Q147 611 147 623T109 637Q104 637 101 637H96Q86 637 83 637T76 640T73 647ZM336 325V331Q336 405 275 405Q258 405 240 397T207 376T181 352T163 330L157 322L136 236Q114 150 114 114Q114 66 138 42Q154 26 178 26Q211 26 245 58Q270 81 285 114T318 219Q336 291 336 325Z" style="stroke-width: 3;"/></g></g><g data-mml-node="mo" transform="translate(6423.6,0)"><path data-c="2212" d="M84 237T84 250T98 270H679Q694 262 694 250T679 230H98Q84 237 84 250Z" style="stroke-width: 3;"/></g><g data-mml-node="msub" transform="translate(7423.9,0)"><g data-mml-node="TeXAtom" data-mjx-texclass="ORD"><g data-mml-node="mi"><path data-c="1D429" d="M32 442L123 446Q214 450 215 450H221V409Q222 409 229 413T251 423T284 436T328 446T382 450Q480 450 540 388T600 223Q600 128 539 61T361 -6H354Q292 -6 236 28L227 34V-132H296V-194H287Q269 -191 163 -191Q56 -191 38 -194H29V-132H98V113V284Q98 330 97 348T93 370T83 376Q69 380 42 380H29V442H32ZM457 224Q457 303 427 349T350 395Q282 395 235 352L227 345V104L233 97Q274 45 337 45Q383 45 420 86T457 224Z" style="stroke-width: 3;"/></g></g><g data-mml-node="mi" transform="translate(672,-150) scale(0.707)"><path data-c="1D44E" d="M33 157Q33 258 109 349T280 441Q331 441 370 392Q386 422 416 422Q429 422 439 414T449 394Q449 381 412 234T374 68Q374 43 381 35T402 26Q411 27 422 35Q443 55 463 131Q469 151 473 152Q475 153 483 153H487Q506 153 506 144Q506 138 501 117T481 63T449 13Q436 0 417 -8Q409 -10 393 -10Q359 -10 336 5T306 36L300 51Q299 52 296 50Q294 48 292 46Q233 -10 172 -10Q117 -10 75 30T33 157ZM351 328Q351 334 346 350T323 385T277 405Q242 405 210 374T160 293Q131 214 119 129Q119 126 119 118T118 106Q118 61 136 44T179 26Q217 26 254 59T298 110Q300 114 325 217T351 328Z" style="stroke-width: 3;"/></g></g><g data-mml-node="mo" transform="translate(8519.9,0)"><path data-c="29" d="M60 749L64 750Q69 750 74 750H86L114 726Q208 641 251 514T294 250Q294 182 284 119T261 12T224 -76T186 -143T145 -194T113 -227T90 -246Q87 -249 86 -250H74Q66 -250 63 -250T58 -247T55 -238Q56 -237 66 -225Q221 -64 221 250T66 725Q56 737 55 738Q55 746 60 749Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(8908.9,0)"><path data-c="2C" d="M78 35T78 60T94 103T137 121Q165 121 187 96T210 8Q210 -27 201 -60T180 -117T154 -158T130 -185T117 -194Q113 -194 104 -185T95 -172Q95 -168 106 -156T131 -126T157 -76T173 -3V9L172 8Q170 7 167 6T161 3T152 1T140 0Q113 0 96 17Z" style="stroke-width: 3;"/></g><g data-mml-node="mstyle" transform="translate(9186.9,0)"><g data-mml-node="mspace"/></g><g data-mml-node="mi" transform="translate(11353.6,0)"><path data-c="1D461" d="M26 385Q19 392 19 395Q19 399 22 411T27 425Q29 430 36 430T87 431H140L159 511Q162 522 166 540T173 566T179 586T187 603T197 615T211 624T229 626Q247 625 254 615T261 596Q261 589 252 549T232 470L222 433Q222 431 272 431H323Q330 424 330 420Q330 398 317 385H210L174 240Q135 80 135 68Q135 26 162 26Q197 26 230 60T283 144Q285 150 288 151T303 153H307Q322 153 322 145Q322 142 319 133Q314 117 301 95T267 48T216 6T155 -11Q125 -11 98 4T59 56Q57 64 57 83V101L92 241Q127 382 128 383Q128 385 77 385H26Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(11992.4,0)"><path data-c="3D" d="M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z" style="stroke-width: 3;"/></g><g data-mml-node="mfrac" transform="translate(13048.1,0)"><g data-mml-node="mrow" transform="translate(880.4,676)"><g data-mml-node="mo"><path data-c="2212" d="M84 237T84 250T98 270H679Q694 262 694 250T679 230H98Q84 237 84 250Z" style="stroke-width: 3;"/></g><g data-mml-node="msub" transform="translate(778,0)"><g data-mml-node="mi"><path data-c="1D453" d="M118 -162Q120 -162 124 -164T135 -167T147 -168Q160 -168 171 -155T187 -126Q197 -99 221 27T267 267T289 382V385H242Q195 385 192 387Q188 390 188 397L195 425Q197 430 203 430T250 431Q298 431 298 432Q298 434 307 482T319 540Q356 705 465 705Q502 703 526 683T550 630Q550 594 529 578T487 561Q443 561 443 603Q443 622 454 636T478 657L487 662Q471 668 457 668Q445 668 434 658T419 630Q412 601 403 552T387 469T380 433Q380 431 435 431Q480 431 487 430T498 424Q499 420 496 407T491 391Q489 386 482 386T428 385H372L349 263Q301 15 282 -47Q255 -132 212 -173Q175 -205 139 -205Q107 -205 81 -186T55 -132Q55 -95 76 -78T118 -61Q162 -61 162 -103Q162 -122 151 -136T127 -157L118 -162Z" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(523,-150) scale(0.707)"><path data-c="1D44E" d="M33 157Q33 258 109 349T280 441Q331 441 370 392Q386 422 416 422Q429 422 439 414T449 394Q449 381 412 234T374 68Q374 43 381 35T402 26Q411 27 422 35Q443 55 463 131Q469 151 473 152Q475 153 483 153H487Q506 153 506 144Q506 138 501 117T481 63T449 13Q436 0 417 -8Q409 -10 393 -10Q359 -10 336 5T306 36L300 51Q299 52 296 50Q294 48 292 46Q233 -10 172 -10Q117 -10 75 30T33 157ZM351 328Q351 334 346 350T323 385T277 405Q242 405 210 374T160 293Q131 214 119 129Q119 126 119 118T118 106Q118 61 136 44T179 26Q217 26 254 59T298 110Q300 114 325 217T351 328Z" style="stroke-width: 3;"/></g></g></g><g data-mml-node="mrow" transform="translate(220,-686)"><g data-mml-node="msub"><g data-mml-node="mi"><path data-c="1D453" d="M118 -162Q120 -162 124 -164T135 -167T147 -168Q160 -168 171 -155T187 -126Q197 -99 221 27T267 267T289 382V385H242Q195 385 192 387Q188 390 188 397L195 425Q197 430 203 430T250 431Q298 431 298 432Q298 434 307 482T319 540Q356 705 465 705Q502 703 526 683T550 630Q550 594 529 578T487 561Q443 561 443 603Q443 622 454 636T478 657L487 662Q471 668 457 668Q445 668 434 658T419 630Q412 601 403 552T387 469T380 433Q380 431 435 431Q480 431 487 430T498 424Q499 420 496 407T491 391Q489 386 482 386T428 385H372L349 263Q301 15 282 -47Q255 -132 212 -173Q175 -205 139 -205Q107 -205 81 -186T55 -132Q55 -95 76 -78T118 -61Q162 -61 162 -103Q162 -122 151 -136T127 -157L118 -162Z" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(523,-150) scale(0.707)"><path data-c="1D44F" d="M73 647Q73 657 77 670T89 683Q90 683 161 688T234 694Q246 694 246 685T212 542Q204 508 195 472T180 418L176 399Q176 396 182 402Q231 442 283 442Q345 442 383 396T422 280Q422 169 343 79T173 -11Q123 -11 82 27T40 150V159Q40 180 48 217T97 414Q147 611 147 623T109 637Q104 637 101 637H96Q86 637 83 637T76 640T73 647ZM336 325V331Q336 405 275 405Q258 405 240 397T207 376T181 352T163 330L157 322L136 236Q114 150 114 114Q114 66 138 42Q154 26 178 26Q211 26 245 58Q270 81 285 114T318 219Q336 291 336 325Z" style="stroke-width: 3;"/></g></g><g data-mml-node="mo" transform="translate(1098.6,0)"><path data-c="2212" d="M84 237T84 250T98 270H679Q694 262 694 250T679 230H98Q84 237 84 250Z" style="stroke-width: 3;"/></g><g data-mml-node="msub" transform="translate(2098.8,0)"><g data-mml-node="mi"><path data-c="1D453" d="M118 -162Q120 -162 124 -164T135 -167T147 -168Q160 -168 171 -155T187 -126Q197 -99 221 27T267 267T289 382V385H242Q195 385 192 387Q188 390 188 397L195 425Q197 430 203 430T250 431Q298 431 298 432Q298 434 307 482T319 540Q356 705 465 705Q502 703 526 683T550 630Q550 594 529 578T487 561Q443 561 443 603Q443 622 454 636T478 657L487 662Q471 668 457 668Q445 668 434 658T419 630Q412 601 403 552T387 469T380 433Q380 431 435 431Q480 431 487 430T498 424Q499 420 496 407T491 391Q489 386 482 386T428 385H372L349 263Q301 15 282 -47Q255 -132 212 -173Q175 -205 139 -205Q107 -205 81 -186T55 -132Q55 -95 76 -78T118 -61Q162 -61 162 -103Q162 -122 151 -136T127 -157L118 -162Z" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(523,-150) scale(0.707)"><path data-c="1D44E" d="M33 157Q33 258 109 349T280 441Q331 441 370 392Q386 422 416 422Q429 422 439 414T449 394Q449 381 412 234T374 68Q374 43 381 35T402 26Q411 27 422 35Q443 55 463 131Q469 151 473 152Q475 153 483 153H487Q506 153 506 144Q506 138 501 117T481 63T449 13Q436 0 417 -8Q409 -10 393 -10Q359 -10 336 5T306 36L300 51Q299 52 296 50Q294 48 292 46Q233 -10 172 -10Q117 -10 75 30T33 157ZM351 328Q351 334 346 350T323 385T277 405Q242 405 210 374T160 293Q131 214 119 129Q119 126 119 118T118 106Q118 61 136 44T179 26Q217 26 254 59T298 110Q300 114 325 217T351 328Z" style="stroke-width: 3;"/></g></g></g><rect width="3245.9" height="60" x="120" y="220"/></g></g></g></svg><mjx-assistive-mml unselectable="on" display="block" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; overflow: hidden; width: 100%;"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><mrow data-mjx-texclass="ORD"><mi mathvariant="bold">v</mi></mrow><mo>=</mo><msub><mrow data-mjx-texclass="ORD"><mi mathvariant="bold">p</mi></mrow><mi>a</mi></msub><mo>+</mo><mi>t</mi><mstyle scriptlevel="0"><mspace width="0.167em"/></mstyle><mo stretchy="false">(</mo><msub><mrow data-mjx-texclass="ORD"><mi mathvariant="bold">p</mi></mrow><mi>b</mi></msub><mo>−</mo><msub><mrow data-mjx-texclass="ORD"><mi mathvariant="bold">p</mi></mrow><mi>a</mi></msub><mo stretchy="false">)</mo><mo>,</mo><mstyle scriptlevel="0"><mspace width="2em"/></mstyle><mi>t</mi><mo>=</mo><mfrac><mrow><mo>−</mo><msub><mi>f</mi><mi>a</mi></msub></mrow><mrow><msub><mi>f</mi><mi>b</mi></msub><mo>−</mo><msub><mi>f</mi><mi>a</mi></msub></mrow></mfrac></math></mjx-assistive-mml></mjx-container><p>que es la fracción del recorrido a lo largo de la arista donde el campo alcanza el valor cero. Como <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.464ex;" xmlns="http://www.w3.org/2000/svg" width="2.143ex" height="2.059ex" role="img" focusable="false" viewBox="0 -705 947.1 910" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="msub"><g data-mml-node="mi"><path data-c="1D453" d="M118 -162Q120 -162 124 -164T135 -167T147 -168Q160 -168 171 -155T187 -126Q197 -99 221 27T267 267T289 382V385H242Q195 385 192 387Q188 390 188 397L195 425Q197 430 203 430T250 431Q298 431 298 432Q298 434 307 482T319 540Q356 705 465 705Q502 703 526 683T550 630Q550 594 529 578T487 561Q443 561 443 603Q443 622 454 636T478 657L487 662Q471 668 457 668Q445 668 434 658T419 630Q412 601 403 552T387 469T380 433Q380 431 435 431Q480 431 487 430T498 424Q499 420 496 407T491 391Q489 386 482 386T428 385H372L349 263Q301 15 282 -47Q255 -132 212 -173Q175 -205 139 -205Q107 -205 81 -186T55 -132Q55 -95 76 -78T118 -61Q162 -61 162 -103Q162 -122 151 -136T127 -157L118 -162Z" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(523,-150) scale(0.707)"><path data-c="1D44E" d="M33 157Q33 258 109 349T280 441Q331 441 370 392Q386 422 416 422Q429 422 439 414T449 394Q449 381 412 234T374 68Q374 43 381 35T402 26Q411 27 422 35Q443 55 463 131Q469 151 473 152Q475 153 483 153H487Q506 153 506 144Q506 138 501 117T481 63T449 13Q436 0 417 -8Q409 -10 393 -10Q359 -10 336 5T306 36L300 51Q299 52 296 50Q294 48 292 46Q233 -10 172 -10Q117 -10 75 30T33 157ZM351 328Q351 334 346 350T323 385T277 405Q242 405 210 374T160 293Q131 214 119 129Q119 126 119 118T118 106Q118 61 136 44T179 26Q217 26 254 59T298 110Q300 114 325 217T351 328Z" style="stroke-width: 3;"/></g></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><msub><mi>f</mi><mi>a</mi></msub></math></mjx-assistive-mml></mjx-container> y <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.464ex;" xmlns="http://www.w3.org/2000/svg" width="1.983ex" height="2.059ex" role="img" focusable="false" viewBox="0 -705 876.3 910" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="msub"><g data-mml-node="mi"><path data-c="1D453" d="M118 -162Q120 -162 124 -164T135 -167T147 -168Q160 -168 171 -155T187 -126Q197 -99 221 27T267 267T289 382V385H242Q195 385 192 387Q188 390 188 397L195 425Q197 430 203 430T250 431Q298 431 298 432Q298 434 307 482T319 540Q356 705 465 705Q502 703 526 683T550 630Q550 594 529 578T487 561Q443 561 443 603Q443 622 454 636T478 657L487 662Q471 668 457 668Q445 668 434 658T419 630Q412 601 403 552T387 469T380 433Q380 431 435 431Q480 431 487 430T498 424Q499 420 496 407T491 391Q489 386 482 386T428 385H372L349 263Q301 15 282 -47Q255 -132 212 -173Q175 -205 139 -205Q107 -205 81 -186T55 -132Q55 -95 76 -78T118 -61Q162 -61 162 -103Q162 -122 151 -136T127 -157L118 -162Z" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(523,-150) scale(0.707)"><path data-c="1D44F" d="M73 647Q73 657 77 670T89 683Q90 683 161 688T234 694Q246 694 246 685T212 542Q204 508 195 472T180 418L176 399Q176 396 182 402Q231 442 283 442Q345 442 383 396T422 280Q422 169 343 79T173 -11Q123 -11 82 27T40 150V159Q40 180 48 217T97 414Q147 611 147 623T109 637Q104 637 101 637H96Q86 637 83 637T76 640T73 647ZM336 325V331Q336 405 275 405Q258 405 240 397T207 376T181 352T163 330L157 322L136 236Q114 150 114 114Q114 66 138 42Q154 26 178 26Q211 26 245 58Q270 81 285 114T318 219Q336 291 336 325Z" style="stroke-width: 3;"/></g></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><msub><mi>f</mi><mi>b</mi></msub></math></mjx-assistive-mml></mjx-container> tienen signos opuestos en una arista que cruza la superficie, <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.025ex;" xmlns="http://www.w3.org/2000/svg" width="0.817ex" height="1.441ex" role="img" focusable="false" viewBox="0 -626 361 637" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mi"><path data-c="1D461" d="M26 385Q19 392 19 395Q19 399 22 411T27 425Q29 430 36 430T87 431H140L159 511Q162 522 166 540T173 566T179 586T187 603T197 615T211 624T229 626Q247 625 254 615T261 596Q261 589 252 549T232 470L222 433Q222 431 272 431H323Q330 424 330 420Q330 398 317 385H210L174 240Q135 80 135 68Q135 26 162 26Q197 26 230 60T283 144Q285 150 288 151T303 153H307Q322 153 322 145Q322 142 319 133Q314 117 301 95T267 48T216 6T155 -11Q125 -11 98 4T59 56Q57 64 57 83V101L92 241Q127 382 128 383Q128 385 77 385H26Z" style="stroke-width: 3;"/></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mi>t</mi></math></mjx-assistive-mml></mjx-container> siempre se encuentra en <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.566ex;" xmlns="http://www.w3.org/2000/svg" width="4.526ex" height="2.262ex" role="img" focusable="false" viewBox="0 -750 2000.7 1000" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mo"><path data-c="5B" d="M118 -250V750H255V710H158V-210H255V-250H118Z" style="stroke-width: 3;"/></g><g data-mml-node="mn" transform="translate(278,0)"><path data-c="30" d="M96 585Q152 666 249 666Q297 666 345 640T423 548Q460 465 460 320Q460 165 417 83Q397 41 362 16T301 -15T250 -22Q224 -22 198 -16T137 16T82 83Q39 165 39 320Q39 494 96 585ZM321 597Q291 629 250 629Q208 629 178 597Q153 571 145 525T137 333Q137 175 145 125T181 46Q209 16 250 16Q290 16 318 46Q347 76 354 130T362 333Q362 478 354 524T321 597Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(778,0)"><path data-c="2C" d="M78 35T78 60T94 103T137 121Q165 121 187 96T210 8Q210 -27 201 -60T180 -117T154 -158T130 -185T117 -194Q113 -194 104 -185T95 -172Q95 -168 106 -156T131 -126T157 -76T173 -3V9L172 8Q170 7 167 6T161 3T152 1T140 0Q113 0 96 17Z" style="stroke-width: 3;"/></g><g data-mml-node="mn" transform="translate(1222.7,0)"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(1722.7,0)"><path data-c="5D" d="M22 710V750H159V-250H22V-210H119V710H22Z" style="stroke-width: 3;"/></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mo stretchy="false">[</mo><mn>0</mn><mo>,</mo><mn>1</mn><mo stretchy="false">]</mo></math></mjx-assistive-mml></mjx-container>. Ejecutamos este proceso simultáneamente en cuatro chunks activos de <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.05ex;" xmlns="http://www.w3.org/2000/svg" width="3.25ex" height="2.028ex" role="img" focusable="false" viewBox="0 -874.3 1436.6 896.3" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="msup"><g data-mml-node="mn"><path data-c="36" d="M42 313Q42 476 123 571T303 666Q372 666 402 630T432 550Q432 525 418 510T379 495Q356 495 341 509T326 548Q326 592 373 601Q351 623 311 626Q240 626 194 566Q147 500 147 364L148 360Q153 366 156 373Q197 433 263 433H267Q313 433 348 414Q372 400 396 374T435 317Q456 268 456 210V192Q456 169 451 149Q440 90 387 34T253 -22Q225 -22 199 -14T143 16T92 75T56 172T42 313ZM257 397Q227 397 205 380T171 335T154 278T148 216Q148 133 160 97T198 39Q222 21 251 21Q302 21 329 59Q342 77 347 104T352 209Q352 289 347 316T329 361Q302 397 257 397Z" style="stroke-width: 3;"/><path data-c="34" d="M462 0Q444 3 333 3Q217 3 199 0H190V46H221Q241 46 248 46T265 48T279 53T286 61Q287 63 287 115V165H28V211L179 442Q332 674 334 675Q336 677 355 677H373L379 671V211H471V165H379V114Q379 73 379 66T385 54Q393 47 442 46H471V0H462ZM293 211V545L74 212L183 211H293Z" transform="translate(500,0)" style="stroke-width: 3;"/></g><g data-mml-node="mn" transform="translate(1033,404.1) scale(0.707)"><path data-c="33" d="M127 463Q100 463 85 480T69 524Q69 579 117 622T233 665Q268 665 277 664Q351 652 390 611T430 522Q430 470 396 421T302 350L299 348Q299 347 308 345T337 336T375 315Q457 262 457 175Q457 96 395 37T238 -22Q158 -22 100 21T42 130Q42 158 60 175T105 193Q133 193 151 175T169 130Q169 119 166 110T159 94T148 82T136 74T126 70T118 67L114 66Q165 21 238 21Q293 21 321 74Q338 107 338 175V195Q338 290 274 322Q259 328 213 329L171 330L168 332Q166 335 166 348Q166 366 174 366Q202 366 232 371Q266 376 294 413T322 525V533Q322 590 287 612Q265 626 240 626Q208 626 181 615T143 592T132 580H135Q138 579 143 578T153 573T165 566T175 555T183 540T186 520Q186 498 172 481T127 463Z" style="stroke-width: 3;"/></g></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><msup><mn>64</mn><mn>3</mn></msup></math></mjx-assistive-mml></mjx-container> y probamos ediciones animadas del SDF con regeneración de la malla en cada fotograma.</p>
<div style="position:relative;padding-bottom:56.25%;height:0;overflow:hidden;border-radius:8px;margin:1.5rem 0;border:1px solid rgba(255,255,255,0.12)">
<iframe src="/es/spikes/12-webgpu-marching-cubes/" title="Spike 12: Marching Cubes con WebGPU" style="position:absolute;top:0;left:0;width:100%;height:100%;border:0;background:#000" loading="lazy" allowfullscreen></iframe>
</div>
<p><a href="/es/spikes/12-webgpu-marching-cubes/" target="_blank">Abrir el Spike 12 en una pestaña nueva ↗</a> · <a href="/es/blog/spike-source?spike=12-webgpu-marching-cubes">Ver el código fuente</a></p>
<p>El primer logro fue ganar confianza en la propia pipeline de cómputo. Una sola llamada podía evaluar el SDF, clasificar las celdas y emitir vértices en un búfer de la GPU sin ninguna lectura de vuelta por parte de la CPU. El segundo logro fue descubrir lo rápido que «funciona» se convierte en una búsqueda de artefactos. Los triángulos ausentes rara vez se debían a un problema teórico de marching cubes. Solían deberse a discrepancias en los índices de la tabla, rangos de dibujo incorrectos que leían más allá del número de vértices activos o interacciones en casos límite cerca de las fronteras de los chunks, donde no estaban disponibles las muestras del SDF vecino.</p>
<p>Este spike nos obligó a pensar en zonas. Cerca de la cámara, quieres libertad volumétrica para que los jugadores puedan tallar, excavar y ver cuevas. Lejos de la cámara, quieres la eficiencia de los clipmaps, donde un mapa de altura plano resulta más barato y perfectamente adecuado. Esa dualidad se convirtió en la columna vertebral de la arquitectura que seguimos perfeccionando a partir del Spike 13.</p>
<p>Uno de mis momentos favoritos durante la depuración fue activar la vista de estructura alámbrica mientras se ejecutaban las ediciones. Ver cómo la topología se formaba y se disolvía en tiempo real hacía que las concesiones de calidad fueran evidentes de inmediato. Podías ver dónde la densidad de vértices era suficiente, dónde se volvía demasiado baja y exactamente dónde las transiciones de LOD acabarían necesitando compatibilidad con Transvoxel para evitar grietas.</p>
<p>En la parte 8 abordamos el reto de la integración. Mantener las mallas generadas directamente mediante cómputo y la lógica del grafo de escena de Three.js dentro de una única pipeline de renderizado estable fue más difícil de lo que sugería la demo aislada.</p>
<h2 id="tecnologia-mencionada-en-este-capitulo" tabindex="-1">Tecnología mencionada en este capítulo <a class="header-anchor" href="#tecnologia-mencionada-en-este-capitulo" aria-label="Permalink to &quot;Tecnología mencionada en este capítulo&quot;"></a></h2>
<p><strong>Marching cubes.</strong> Un algoritmo para extraer una malla de triángulos de un campo escalar 3D (Lorensen y Cline, 1987). Cada celda de una cuadrícula 3D regular se clasifica muestreando el campo en sus 8 vértices. El patrón de signos produce un índice de caso (0-255), y una tabla de consulta asigna cada caso a un conjunto de triángulos. Los vértices se colocan sobre las aristas de la cuadrícula interpolando entre sus dos extremos. El algoritmo es altamente paralelizable, ya que cada celda se procesa de forma independiente, lo que lo hace ideal para el cómputo en la GPU. Consulta nuestra <a href="/es/guides/landscape-generation-browser.html#signed-distance-fields-sdfs">guía sobre paisajes acerca de los SDF y marching cubes</a>.</p>
<p><strong>Campos de distancia con signo (SDF).</strong> Una representación volumétrica que almacena, en cada punto del espacio 3D, la distancia con signo hasta la superficie más cercana. Los valores positivos están fuera, los negativos están dentro y el cruce por cero constituye la superficie. Los SDF pueden representar formas 3D arbitrarias: cuevas, arcos, voladizos y geometría flotante que los mapas de altura no pueden expresar. La edición se realiza de forma natural mediante operaciones de conjuntos sobre el campo. Añadir material (la unión de dos formas) se expresa como <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.566ex;" xmlns="http://www.w3.org/2000/svg" width="15.06ex" height="2.262ex" role="img" focusable="false" viewBox="0 -750 6656.3 1000" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mi"><path data-c="1D451" d="M366 683Q367 683 438 688T511 694Q523 694 523 686Q523 679 450 384T375 83T374 68Q374 26 402 26Q411 27 422 35Q443 55 463 131Q469 151 473 152Q475 153 483 153H487H491Q506 153 506 145Q506 140 503 129Q490 79 473 48T445 8T417 -8Q409 -10 393 -10Q359 -10 336 5T306 36L300 51Q299 52 296 50Q294 48 292 46Q233 -10 172 -10Q117 -10 75 30T33 157Q33 205 53 255T101 341Q148 398 195 420T280 442Q336 442 364 400Q369 394 369 396Q370 400 396 505T424 616Q424 629 417 632T378 637H357Q351 643 351 645T353 664Q358 683 366 683ZM352 326Q329 405 277 405Q242 405 210 374T160 293Q131 214 119 129Q119 126 119 118T118 106Q118 61 136 44T179 26Q233 26 290 98L298 109L352 326Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(797.8,0)"><path data-c="3D" d="M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(1853.6,0)"><path data-c="6D" d="M41 46H55Q94 46 102 60V68Q102 77 102 91T102 122T103 161T103 203Q103 234 103 269T102 328V351Q99 370 88 376T43 385H25V408Q25 431 27 431L37 432Q47 433 65 434T102 436Q119 437 138 438T167 441T178 442H181V402Q181 364 182 364T187 369T199 384T218 402T247 421T285 437Q305 442 336 442Q351 442 364 440T387 434T406 426T421 417T432 406T441 395T448 384T452 374T455 366L457 361L460 365Q463 369 466 373T475 384T488 397T503 410T523 422T546 432T572 439T603 442Q729 442 740 329Q741 322 741 190V104Q741 66 743 59T754 49Q775 46 803 46H819V0H811L788 1Q764 2 737 2T699 3Q596 3 587 0H579V46H595Q656 46 656 62Q657 64 657 200Q656 335 655 343Q649 371 635 385T611 402T585 404Q540 404 506 370Q479 343 472 315T464 232V168V108Q464 78 465 68T468 55T477 49Q498 46 526 46H542V0H534L510 1Q487 2 460 2T422 3Q319 3 310 0H302V46H318Q379 46 379 62Q380 64 380 200Q379 335 378 343Q372 371 358 385T334 402T308 404Q263 404 229 370Q202 343 195 315T187 232V168V108Q187 78 188 68T191 55T200 49Q221 46 249 46H265V0H257L234 1Q210 2 183 2T145 3Q42 3 33 0H25V46H41Z" style="stroke-width: 3;"/><path data-c="69" d="M69 609Q69 637 87 653T131 669Q154 667 171 652T188 609Q188 579 171 564T129 549Q104 549 87 564T69 609ZM247 0Q232 3 143 3Q132 3 106 3T56 1L34 0H26V46H42Q70 46 91 49Q100 53 102 60T104 102V205V293Q104 345 102 359T88 378Q74 385 41 385H30V408Q30 431 32 431L42 432Q52 433 70 434T106 436Q123 437 142 438T171 441T182 442H185V62Q190 52 197 50T232 46H255V0H247Z" transform="translate(833,0)" style="stroke-width: 3;"/><path data-c="6E" d="M41 46H55Q94 46 102 60V68Q102 77 102 91T102 122T103 161T103 203Q103 234 103 269T102 328V351Q99 370 88 376T43 385H25V408Q25 431 27 431L37 432Q47 433 65 434T102 436Q119 437 138 438T167 441T178 442H181V402Q181 364 182 364T187 369T199 384T218 402T247 421T285 437Q305 442 336 442Q450 438 463 329Q464 322 464 190V104Q464 66 466 59T477 49Q498 46 526 46H542V0H534L510 1Q487 2 460 2T422 3Q319 3 310 0H302V46H318Q379 46 379 62Q380 64 380 200Q379 335 378 343Q372 371 358 385T334 402T308 404Q263 404 229 370Q202 343 195 315T187 232V168V108Q187 78 188 68T191 55T200 49Q221 46 249 46H265V0H257L234 1Q210 2 183 2T145 3Q42 3 33 0H25V46H41Z" transform="translate(1111,0)" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(3520.6,0)"><path data-c="28" d="M94 250Q94 319 104 381T127 488T164 576T202 643T244 695T277 729T302 750H315H319Q333 750 333 741Q333 738 316 720T275 667T226 581T184 443T167 250T184 58T225 -81T274 -167T316 -220T333 -241Q333 -250 318 -250H315H302L274 -226Q180 -141 137 -14T94 250Z" style="stroke-width: 3;"/></g><g data-mml-node="msub" transform="translate(3909.6,0)"><g data-mml-node="mi"><path data-c="1D451" d="M366 683Q367 683 438 688T511 694Q523 694 523 686Q523 679 450 384T375 83T374 68Q374 26 402 26Q411 27 422 35Q443 55 463 131Q469 151 473 152Q475 153 483 153H487H491Q506 153 506 145Q506 140 503 129Q490 79 473 48T445 8T417 -8Q409 -10 393 -10Q359 -10 336 5T306 36L300 51Q299 52 296 50Q294 48 292 46Q233 -10 172 -10Q117 -10 75 30T33 157Q33 205 53 255T101 341Q148 398 195 420T280 442Q336 442 364 400Q369 394 369 396Q370 400 396 505T424 616Q424 629 417 632T378 637H357Q351 643 351 645T353 664Q358 683 366 683ZM352 326Q329 405 277 405Q242 405 210 374T160 293Q131 214 119 129Q119 126 119 118T118 106Q118 61 136 44T179 26Q233 26 290 98L298 109L352 326Z" style="stroke-width: 3;"/></g><g data-mml-node="mn" transform="translate(553,-150) scale(0.707)"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" style="stroke-width: 3;"/></g></g><g data-mml-node="mo" transform="translate(4866.1,0)"><path data-c="2C" d="M78 35T78 60T94 103T137 121Q165 121 187 96T210 8Q210 -27 201 -60T180 -117T154 -158T130 -185T117 -194Q113 -194 104 -185T95 -172Q95 -168 106 -156T131 -126T157 -76T173 -3V9L172 8Q170 7 167 6T161 3T152 1T140 0Q113 0 96 17Z" style="stroke-width: 3;"/></g><g data-mml-node="msub" transform="translate(5310.8,0)"><g data-mml-node="mi"><path data-c="1D451" d="M366 683Q367 683 438 688T511 694Q523 694 523 686Q523 679 450 384T375 83T374 68Q374 26 402 26Q411 27 422 35Q443 55 463 131Q469 151 473 152Q475 153 483 153H487H491Q506 153 506 145Q506 140 503 129Q490 79 473 48T445 8T417 -8Q409 -10 393 -10Q359 -10 336 5T306 36L300 51Q299 52 296 50Q294 48 292 46Q233 -10 172 -10Q117 -10 75 30T33 157Q33 205 53 255T101 341Q148 398 195 420T280 442Q336 442 364 400Q369 394 369 396Q370 400 396 505T424 616Q424 629 417 632T378 637H357Q351 643 351 645T353 664Q358 683 366 683ZM352 326Q329 405 277 405Q242 405 210 374T160 293Q131 214 119 129Q119 126 119 118T118 106Q118 61 136 44T179 26Q233 26 290 98L298 109L352 326Z" style="stroke-width: 3;"/></g><g data-mml-node="mn" transform="translate(553,-150) scale(0.707)"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"/></g></g><g data-mml-node="mo" transform="translate(6267.3,0)"><path data-c="29" d="M60 749L64 750Q69 750 74 750H86L114 726Q208 641 251 514T294 250Q294 182 284 119T261 12T224 -76T186 -143T145 -194T113 -227T90 -246Q87 -249 86 -250H74Q66 -250 63 -250T58 -247T55 -238Q56 -237 66 -225Q221 -64 221 250T66 725Q56 737 55 738Q55 746 60 749Z" style="stroke-width: 3;"/></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mi>d</mi><mo>=</mo><mo data-mjx-texclass="OP" movablelimits="true">min</mo><mo stretchy="false">(</mo><msub><mi>d</mi><mn>1</mn></msub><mo>,</mo><msub><mi>d</mi><mn>2</mn></msub><mo stretchy="false">)</mo></math></mjx-assistive-mml></mjx-container>; eliminarlo (excavar), como <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.566ex;" xmlns="http://www.w3.org/2000/svg" width="17.259ex" height="2.262ex" role="img" focusable="false" viewBox="0 -750 7628.3 1000" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mi"><path data-c="1D451" d="M366 683Q367 683 438 688T511 694Q523 694 523 686Q523 679 450 384T375 83T374 68Q374 26 402 26Q411 27 422 35Q443 55 463 131Q469 151 473 152Q475 153 483 153H487H491Q506 153 506 145Q506 140 503 129Q490 79 473 48T445 8T417 -8Q409 -10 393 -10Q359 -10 336 5T306 36L300 51Q299 52 296 50Q294 48 292 46Q233 -10 172 -10Q117 -10 75 30T33 157Q33 205 53 255T101 341Q148 398 195 420T280 442Q336 442 364 400Q369 394 369 396Q370 400 396 505T424 616Q424 629 417 632T378 637H357Q351 643 351 645T353 664Q358 683 366 683ZM352 326Q329 405 277 405Q242 405 210 374T160 293Q131 214 119 129Q119 126 119 118T118 106Q118 61 136 44T179 26Q233 26 290 98L298 109L352 326Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(797.8,0)"><path data-c="3D" d="M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(1853.6,0)"><path data-c="6D" d="M41 46H55Q94 46 102 60V68Q102 77 102 91T102 122T103 161T103 203Q103 234 103 269T102 328V351Q99 370 88 376T43 385H25V408Q25 431 27 431L37 432Q47 433 65 434T102 436Q119 437 138 438T167 441T178 442H181V402Q181 364 182 364T187 369T199 384T218 402T247 421T285 437Q305 442 336 442Q351 442 364 440T387 434T406 426T421 417T432 406T441 395T448 384T452 374T455 366L457 361L460 365Q463 369 466 373T475 384T488 397T503 410T523 422T546 432T572 439T603 442Q729 442 740 329Q741 322 741 190V104Q741 66 743 59T754 49Q775 46 803 46H819V0H811L788 1Q764 2 737 2T699 3Q596 3 587 0H579V46H595Q656 46 656 62Q657 64 657 200Q656 335 655 343Q649 371 635 385T611 402T585 404Q540 404 506 370Q479 343 472 315T464 232V168V108Q464 78 465 68T468 55T477 49Q498 46 526 46H542V0H534L510 1Q487 2 460 2T422 3Q319 3 310 0H302V46H318Q379 46 379 62Q380 64 380 200Q379 335 378 343Q372 371 358 385T334 402T308 404Q263 404 229 370Q202 343 195 315T187 232V168V108Q187 78 188 68T191 55T200 49Q221 46 249 46H265V0H257L234 1Q210 2 183 2T145 3Q42 3 33 0H25V46H41Z" style="stroke-width: 3;"/><path data-c="61" d="M137 305T115 305T78 320T63 359Q63 394 97 421T218 448Q291 448 336 416T396 340Q401 326 401 309T402 194V124Q402 76 407 58T428 40Q443 40 448 56T453 109V145H493V106Q492 66 490 59Q481 29 455 12T400 -6T353 12T329 54V58L327 55Q325 52 322 49T314 40T302 29T287 17T269 6T247 -2T221 -8T190 -11Q130 -11 82 20T34 107Q34 128 41 147T68 188T116 225T194 253T304 268H318V290Q318 324 312 340Q290 411 215 411Q197 411 181 410T156 406T148 403Q170 388 170 359Q170 334 154 320ZM126 106Q126 75 150 51T209 26Q247 26 276 49T315 109Q317 116 318 175Q318 233 317 233Q309 233 296 232T251 223T193 203T147 166T126 106Z" transform="translate(833,0)" style="stroke-width: 3;"/><path data-c="78" d="M201 0Q189 3 102 3Q26 3 17 0H11V46H25Q48 47 67 52T96 61T121 78T139 96T160 122T180 150L226 210L168 288Q159 301 149 315T133 336T122 351T113 363T107 370T100 376T94 379T88 381T80 383Q74 383 44 385H16V431H23Q59 429 126 429Q219 429 229 431H237V385Q201 381 201 369Q201 367 211 353T239 315T268 274L272 270L297 304Q329 345 329 358Q329 364 327 369T322 376T317 380T310 384L307 385H302V431H309Q324 428 408 428Q487 428 493 431H499V385H492Q443 385 411 368Q394 360 377 341T312 257L296 236L358 151Q424 61 429 57T446 50Q464 46 499 46H516V0H510H502Q494 1 482 1T457 2T432 2T414 3Q403 3 377 3T327 1L304 0H295V46H298Q309 46 320 51T331 63Q331 65 291 120L250 175Q249 174 219 133T185 88Q181 83 181 74Q181 63 188 55T206 46Q208 46 208 23V0H201Z" transform="translate(1333,0)" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(3714.6,0)"><path data-c="28" d="M94 250Q94 319 104 381T127 488T164 576T202 643T244 695T277 729T302 750H315H319Q333 750 333 741Q333 738 316 720T275 667T226 581T184 443T167 250T184 58T225 -81T274 -167T316 -220T333 -241Q333 -250 318 -250H315H302L274 -226Q180 -141 137 -14T94 250Z" style="stroke-width: 3;"/></g><g data-mml-node="msub" transform="translate(4103.6,0)"><g data-mml-node="mi"><path data-c="1D451" d="M366 683Q367 683 438 688T511 694Q523 694 523 686Q523 679 450 384T375 83T374 68Q374 26 402 26Q411 27 422 35Q443 55 463 131Q469 151 473 152Q475 153 483 153H487H491Q506 153 506 145Q506 140 503 129Q490 79 473 48T445 8T417 -8Q409 -10 393 -10Q359 -10 336 5T306 36L300 51Q299 52 296 50Q294 48 292 46Q233 -10 172 -10Q117 -10 75 30T33 157Q33 205 53 255T101 341Q148 398 195 420T280 442Q336 442 364 400Q369 394 369 396Q370 400 396 505T424 616Q424 629 417 632T378 637H357Q351 643 351 645T353 664Q358 683 366 683ZM352 326Q329 405 277 405Q242 405 210 374T160 293Q131 214 119 129Q119 126 119 118T118 106Q118 61 136 44T179 26Q233 26 290 98L298 109L352 326Z" style="stroke-width: 3;"/></g><g data-mml-node="mn" transform="translate(553,-150) scale(0.707)"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" style="stroke-width: 3;"/></g></g><g data-mml-node="mo" transform="translate(5060.1,0)"><path data-c="2C" d="M78 35T78 60T94 103T137 121Q165 121 187 96T210 8Q210 -27 201 -60T180 -117T154 -158T130 -185T117 -194Q113 -194 104 -185T95 -172Q95 -168 106 -156T131 -126T157 -76T173 -3V9L172 8Q170 7 167 6T161 3T152 1T140 0Q113 0 96 17Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(5504.8,0)"><path data-c="2212" d="M84 237T84 250T98 270H679Q694 262 694 250T679 230H98Q84 237 84 250Z" style="stroke-width: 3;"/></g><g data-mml-node="msub" transform="translate(6282.8,0)"><g data-mml-node="mi"><path data-c="1D451" d="M366 683Q367 683 438 688T511 694Q523 694 523 686Q523 679 450 384T375 83T374 68Q374 26 402 26Q411 27 422 35Q443 55 463 131Q469 151 473 152Q475 153 483 153H487H491Q506 153 506 145Q506 140 503 129Q490 79 473 48T445 8T417 -8Q409 -10 393 -10Q359 -10 336 5T306 36L300 51Q299 52 296 50Q294 48 292 46Q233 -10 172 -10Q117 -10 75 30T33 157Q33 205 53 255T101 341Q148 398 195 420T280 442Q336 442 364 400Q369 394 369 396Q370 400 396 505T424 616Q424 629 417 632T378 637H357Q351 643 351 645T353 664Q358 683 366 683ZM352 326Q329 405 277 405Q242 405 210 374T160 293Q131 214 119 129Q119 126 119 118T118 106Q118 61 136 44T179 26Q233 26 290 98L298 109L352 326Z" style="stroke-width: 3;"/></g><g data-mml-node="mn" transform="translate(553,-150) scale(0.707)"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"/></g></g><g data-mml-node="mo" transform="translate(7239.3,0)"><path data-c="29" d="M60 749L64 750Q69 750 74 750H86L114 726Q208 641 251 514T294 250Q294 182 284 119T261 12T224 -76T186 -143T145 -194T113 -227T90 -246Q87 -249 86 -250H74Q66 -250 63 -250T58 -247T55 -238Q56 -237 66 -225Q221 -64 221 250T66 725Q56 737 55 738Q55 746 60 749Z" style="stroke-width: 3;"/></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mi>d</mi><mo>=</mo><mo data-mjx-texclass="OP" movablelimits="true">max</mo><mo stretchy="false">(</mo><msub><mi>d</mi><mn>1</mn></msub><mo>,</mo><mo>−</mo><msub><mi>d</mi><mn>2</mn></msub><mo stretchy="false">)</mo></math></mjx-assistive-mml></mjx-container>, con la forma de sustracción negada; y una mezcla suave utiliza un mínimo suavizado como</p>
<mjx-container tabindex="0" class="MathJax" jax="SVG" display="true" style="direction: ltr; display: block; text-align: center; margin: 1em 0; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -1.577ex;" xmlns="http://www.w3.org/2000/svg" width="64.842ex" height="4.993ex" role="img" focusable="false" viewBox="0 -1509.9 28660.1 2206.9" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mi"><path data-c="73" d="M295 316Q295 356 268 385T190 414Q154 414 128 401Q98 382 98 349Q97 344 98 336T114 312T157 287Q175 282 201 278T245 269T277 256Q294 248 310 236T342 195T359 133Q359 71 321 31T198 -10H190Q138 -10 94 26L86 19L77 10Q71 4 65 -1L54 -11H46H42Q39 -11 33 -5V74V132Q33 153 35 157T45 162H54Q66 162 70 158T75 146T82 119T101 77Q136 26 198 26Q295 26 295 104Q295 133 277 151Q257 175 194 187T111 210Q75 227 54 256T33 318Q33 357 50 384T93 424T143 442T187 447H198Q238 447 268 432L283 424L292 431Q302 440 314 448H322H326Q329 448 335 442V310L329 304H301Q295 310 295 316Z" style="stroke-width: 3;"/><path data-c="6D" d="M41 46H55Q94 46 102 60V68Q102 77 102 91T102 122T103 161T103 203Q103 234 103 269T102 328V351Q99 370 88 376T43 385H25V408Q25 431 27 431L37 432Q47 433 65 434T102 436Q119 437 138 438T167 441T178 442H181V402Q181 364 182 364T187 369T199 384T218 402T247 421T285 437Q305 442 336 442Q351 442 364 440T387 434T406 426T421 417T432 406T441 395T448 384T452 374T455 366L457 361L460 365Q463 369 466 373T475 384T488 397T503 410T523 422T546 432T572 439T603 442Q729 442 740 329Q741 322 741 190V104Q741 66 743 59T754 49Q775 46 803 46H819V0H811L788 1Q764 2 737 2T699 3Q596 3 587 0H579V46H595Q656 46 656 62Q657 64 657 200Q656 335 655 343Q649 371 635 385T611 402T585 404Q540 404 506 370Q479 343 472 315T464 232V168V108Q464 78 465 68T468 55T477 49Q498 46 526 46H542V0H534L510 1Q487 2 460 2T422 3Q319 3 310 0H302V46H318Q379 46 379 62Q380 64 380 200Q379 335 378 343Q372 371 358 385T334 402T308 404Q263 404 229 370Q202 343 195 315T187 232V168V108Q187 78 188 68T191 55T200 49Q221 46 249 46H265V0H257L234 1Q210 2 183 2T145 3Q42 3 33 0H25V46H41Z" transform="translate(394,0)" style="stroke-width: 3;"/><path data-c="69" d="M69 609Q69 637 87 653T131 669Q154 667 171 652T188 609Q188 579 171 564T129 549Q104 549 87 564T69 609ZM247 0Q232 3 143 3Q132 3 106 3T56 1L34 0H26V46H42Q70 46 91 49Q100 53 102 60T104 102V205V293Q104 345 102 359T88 378Q74 385 41 385H30V408Q30 431 32 431L42 432Q52 433 70 434T106 436Q123 437 142 438T171 441T182 442H185V62Q190 52 197 50T232 46H255V0H247Z" transform="translate(1227,0)" style="stroke-width: 3;"/><path data-c="6E" d="M41 46H55Q94 46 102 60V68Q102 77 102 91T102 122T103 161T103 203Q103 234 103 269T102 328V351Q99 370 88 376T43 385H25V408Q25 431 27 431L37 432Q47 433 65 434T102 436Q119 437 138 438T167 441T178 442H181V402Q181 364 182 364T187 369T199 384T218 402T247 421T285 437Q305 442 336 442Q450 438 463 329Q464 322 464 190V104Q464 66 466 59T477 49Q498 46 526 46H542V0H534L510 1Q487 2 460 2T422 3Q319 3 310 0H302V46H318Q379 46 379 62Q380 64 380 200Q379 335 378 343Q372 371 358 385T334 402T308 404Q263 404 229 370Q202 343 195 315T187 232V168V108Q187 78 188 68T191 55T200 49Q221 46 249 46H265V0H257L234 1Q210 2 183 2T145 3Q42 3 33 0H25V46H41Z" transform="translate(1505,0)" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(2061,0)"><path data-c="28" d="M94 250Q94 319 104 381T127 488T164 576T202 643T244 695T277 729T302 750H315H319Q333 750 333 741Q333 738 316 720T275 667T226 581T184 443T167 250T184 58T225 -81T274 -167T316 -220T333 -241Q333 -250 318 -250H315H302L274 -226Q180 -141 137 -14T94 250Z" style="stroke-width: 3;"/></g><g data-mml-node="msub" transform="translate(2450,0)"><g data-mml-node="mi"><path data-c="1D451" d="M366 683Q367 683 438 688T511 694Q523 694 523 686Q523 679 450 384T375 83T374 68Q374 26 402 26Q411 27 422 35Q443 55 463 131Q469 151 473 152Q475 153 483 153H487H491Q506 153 506 145Q506 140 503 129Q490 79 473 48T445 8T417 -8Q409 -10 393 -10Q359 -10 336 5T306 36L300 51Q299 52 296 50Q294 48 292 46Q233 -10 172 -10Q117 -10 75 30T33 157Q33 205 53 255T101 341Q148 398 195 420T280 442Q336 442 364 400Q369 394 369 396Q370 400 396 505T424 616Q424 629 417 632T378 637H357Q351 643 351 645T353 664Q358 683 366 683ZM352 326Q329 405 277 405Q242 405 210 374T160 293Q131 214 119 129Q119 126 119 118T118 106Q118 61 136 44T179 26Q233 26 290 98L298 109L352 326Z" style="stroke-width: 3;"/></g><g data-mml-node="mn" transform="translate(553,-150) scale(0.707)"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" style="stroke-width: 3;"/></g></g><g data-mml-node="mo" transform="translate(3406.6,0)"><path data-c="2C" d="M78 35T78 60T94 103T137 121Q165 121 187 96T210 8Q210 -27 201 -60T180 -117T154 -158T130 -185T117 -194Q113 -194 104 -185T95 -172Q95 -168 106 -156T131 -126T157 -76T173 -3V9L172 8Q170 7 167 6T161 3T152 1T140 0Q113 0 96 17Z" style="stroke-width: 3;"/></g><g data-mml-node="msub" transform="translate(3851.2,0)"><g data-mml-node="mi"><path data-c="1D451" d="M366 683Q367 683 438 688T511 694Q523 694 523 686Q523 679 450 384T375 83T374 68Q374 26 402 26Q411 27 422 35Q443 55 463 131Q469 151 473 152Q475 153 483 153H487H491Q506 153 506 145Q506 140 503 129Q490 79 473 48T445 8T417 -8Q409 -10 393 -10Q359 -10 336 5T306 36L300 51Q299 52 296 50Q294 48 292 46Q233 -10 172 -10Q117 -10 75 30T33 157Q33 205 53 255T101 341Q148 398 195 420T280 442Q336 442 364 400Q369 394 369 396Q370 400 396 505T424 616Q424 629 417 632T378 637H357Q351 643 351 645T353 664Q358 683 366 683ZM352 326Q329 405 277 405Q242 405 210 374T160 293Q131 214 119 129Q119 126 119 118T118 106Q118 61 136 44T179 26Q233 26 290 98L298 109L352 326Z" style="stroke-width: 3;"/></g><g data-mml-node="mn" transform="translate(553,-150) scale(0.707)"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"/></g></g><g data-mml-node="mo" transform="translate(4807.8,0)"><path data-c="2C" d="M78 35T78 60T94 103T137 121Q165 121 187 96T210 8Q210 -27 201 -60T180 -117T154 -158T130 -185T117 -194Q113 -194 104 -185T95 -172Q95 -168 106 -156T131 -126T157 -76T173 -3V9L172 8Q170 7 167 6T161 3T152 1T140 0Q113 0 96 17Z" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(5252.4,0)"><path data-c="1D458" d="M121 647Q121 657 125 670T137 683Q138 683 209 688T282 694Q294 694 294 686Q294 679 244 477Q194 279 194 272Q213 282 223 291Q247 309 292 354T362 415Q402 442 438 442Q468 442 485 423T503 369Q503 344 496 327T477 302T456 291T438 288Q418 288 406 299T394 328Q394 353 410 369T442 390L458 393Q446 405 434 405H430Q398 402 367 380T294 316T228 255Q230 254 243 252T267 246T293 238T320 224T342 206T359 180T365 147Q365 130 360 106T354 66Q354 26 381 26Q429 26 459 145Q461 153 479 153H483Q499 153 499 144Q499 139 496 130Q455 -11 378 -11Q333 -11 305 15T277 90Q277 108 280 121T283 145Q283 167 269 183T234 206T200 217T182 220H180Q168 178 159 139T145 81T136 44T129 20T122 7T111 -2Q98 -11 83 -11Q66 -11 57 -1T48 16Q48 26 85 176T158 471L195 616Q196 629 188 632T149 637H144Q134 637 131 637T124 640T121 647Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(5773.4,0)"><path data-c="29" d="M60 749L64 750Q69 750 74 750H86L114 726Q208 641 251 514T294 250Q294 182 284 119T261 12T224 -76T186 -143T145 -194T113 -227T90 -246Q87 -249 86 -250H74Q66 -250 63 -250T58 -247T55 -238Q56 -237 66 -225Q221 -64 221 250T66 725Q56 737 55 738Q55 746 60 749Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(6440.2,0)"><path data-c="3D" d="M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(7496,0)"><path data-c="6D" d="M41 46H55Q94 46 102 60V68Q102 77 102 91T102 122T103 161T103 203Q103 234 103 269T102 328V351Q99 370 88 376T43 385H25V408Q25 431 27 431L37 432Q47 433 65 434T102 436Q119 437 138 438T167 441T178 442H181V402Q181 364 182 364T187 369T199 384T218 402T247 421T285 437Q305 442 336 442Q351 442 364 440T387 434T406 426T421 417T432 406T441 395T448 384T452 374T455 366L457 361L460 365Q463 369 466 373T475 384T488 397T503 410T523 422T546 432T572 439T603 442Q729 442 740 329Q741 322 741 190V104Q741 66 743 59T754 49Q775 46 803 46H819V0H811L788 1Q764 2 737 2T699 3Q596 3 587 0H579V46H595Q656 46 656 62Q657 64 657 200Q656 335 655 343Q649 371 635 385T611 402T585 404Q540 404 506 370Q479 343 472 315T464 232V168V108Q464 78 465 68T468 55T477 49Q498 46 526 46H542V0H534L510 1Q487 2 460 2T422 3Q319 3 310 0H302V46H318Q379 46 379 62Q380 64 380 200Q379 335 378 343Q372 371 358 385T334 402T308 404Q263 404 229 370Q202 343 195 315T187 232V168V108Q187 78 188 68T191 55T200 49Q221 46 249 46H265V0H257L234 1Q210 2 183 2T145 3Q42 3 33 0H25V46H41Z" style="stroke-width: 3;"/><path data-c="69" d="M69 609Q69 637 87 653T131 669Q154 667 171 652T188 609Q188 579 171 564T129 549Q104 549 87 564T69 609ZM247 0Q232 3 143 3Q132 3 106 3T56 1L34 0H26V46H42Q70 46 91 49Q100 53 102 60T104 102V205V293Q104 345 102 359T88 378Q74 385 41 385H30V408Q30 431 32 431L42 432Q52 433 70 434T106 436Q123 437 142 438T171 441T182 442H185V62Q190 52 197 50T232 46H255V0H247Z" transform="translate(833,0)" style="stroke-width: 3;"/><path data-c="6E" d="M41 46H55Q94 46 102 60V68Q102 77 102 91T102 122T103 161T103 203Q103 234 103 269T102 328V351Q99 370 88 376T43 385H25V408Q25 431 27 431L37 432Q47 433 65 434T102 436Q119 437 138 438T167 441T178 442H181V402Q181 364 182 364T187 369T199 384T218 402T247 421T285 437Q305 442 336 442Q450 438 463 329Q464 322 464 190V104Q464 66 466 59T477 49Q498 46 526 46H542V0H534L510 1Q487 2 460 2T422 3Q319 3 310 0H302V46H318Q379 46 379 62Q380 64 380 200Q379 335 378 343Q372 371 358 385T334 402T308 404Q263 404 229 370Q202 343 195 315T187 232V168V108Q187 78 188 68T191 55T200 49Q221 46 249 46H265V0H257L234 1Q210 2 183 2T145 3Q42 3 33 0H25V46H41Z" transform="translate(1111,0)" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(9163,0)"><path data-c="28" d="M94 250Q94 319 104 381T127 488T164 576T202 643T244 695T277 729T302 750H315H319Q333 750 333 741Q333 738 316 720T275 667T226 581T184 443T167 250T184 58T225 -81T274 -167T316 -220T333 -241Q333 -250 318 -250H315H302L274 -226Q180 -141 137 -14T94 250Z" style="stroke-width: 3;"/></g><g data-mml-node="msub" transform="translate(9552,0)"><g data-mml-node="mi"><path data-c="1D451" d="M366 683Q367 683 438 688T511 694Q523 694 523 686Q523 679 450 384T375 83T374 68Q374 26 402 26Q411 27 422 35Q443 55 463 131Q469 151 473 152Q475 153 483 153H487H491Q506 153 506 145Q506 140 503 129Q490 79 473 48T445 8T417 -8Q409 -10 393 -10Q359 -10 336 5T306 36L300 51Q299 52 296 50Q294 48 292 46Q233 -10 172 -10Q117 -10 75 30T33 157Q33 205 53 255T101 341Q148 398 195 420T280 442Q336 442 364 400Q369 394 369 396Q370 400 396 505T424 616Q424 629 417 632T378 637H357Q351 643 351 645T353 664Q358 683 366 683ZM352 326Q329 405 277 405Q242 405 210 374T160 293Q131 214 119 129Q119 126 119 118T118 106Q118 61 136 44T179 26Q233 26 290 98L298 109L352 326Z" style="stroke-width: 3;"/></g><g data-mml-node="mn" transform="translate(553,-150) scale(0.707)"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" style="stroke-width: 3;"/></g></g><g data-mml-node="mo" transform="translate(10508.5,0)"><path data-c="2C" d="M78 35T78 60T94 103T137 121Q165 121 187 96T210 8Q210 -27 201 -60T180 -117T154 -158T130 -185T117 -194Q113 -194 104 -185T95 -172Q95 -168 106 -156T131 -126T157 -76T173 -3V9L172 8Q170 7 167 6T161 3T152 1T140 0Q113 0 96 17Z" style="stroke-width: 3;"/></g><g data-mml-node="msub" transform="translate(10953.2,0)"><g data-mml-node="mi"><path data-c="1D451" d="M366 683Q367 683 438 688T511 694Q523 694 523 686Q523 679 450 384T375 83T374 68Q374 26 402 26Q411 27 422 35Q443 55 463 131Q469 151 473 152Q475 153 483 153H487H491Q506 153 506 145Q506 140 503 129Q490 79 473 48T445 8T417 -8Q409 -10 393 -10Q359 -10 336 5T306 36L300 51Q299 52 296 50Q294 48 292 46Q233 -10 172 -10Q117 -10 75 30T33 157Q33 205 53 255T101 341Q148 398 195 420T280 442Q336 442 364 400Q369 394 369 396Q370 400 396 505T424 616Q424 629 417 632T378 637H357Q351 643 351 645T353 664Q358 683 366 683ZM352 326Q329 405 277 405Q242 405 210 374T160 293Q131 214 119 129Q119 126 119 118T118 106Q118 61 136 44T179 26Q233 26 290 98L298 109L352 326Z" style="stroke-width: 3;"/></g><g data-mml-node="mn" transform="translate(553,-150) scale(0.707)"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"/></g></g><g data-mml-node="mo" transform="translate(11909.8,0)"><path data-c="29" d="M60 749L64 750Q69 750 74 750H86L114 726Q208 641 251 514T294 250Q294 182 284 119T261 12T224 -76T186 -143T145 -194T113 -227T90 -246Q87 -249 86 -250H74Q66 -250 63 -250T58 -247T55 -238Q56 -237 66 -225Q221 -64 221 250T66 725Q56 737 55 738Q55 746 60 749Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(12521,0)"><path data-c="2212" d="M84 237T84 250T98 270H679Q694 262 694 250T679 230H98Q84 237 84 250Z" style="stroke-width: 3;"/></g><g data-mml-node="mfrac" transform="translate(13521.2,0)"><g data-mml-node="msup" transform="translate(224.2,676)"><g data-mml-node="mi"><path data-c="210E" d="M137 683Q138 683 209 688T282 694Q294 694 294 685Q294 674 258 534Q220 386 220 383Q220 381 227 388Q288 442 357 442Q411 442 444 415T478 336Q478 285 440 178T402 50Q403 36 407 31T422 26Q450 26 474 56T513 138Q516 149 519 151T535 153Q555 153 555 145Q555 144 551 130Q535 71 500 33Q466 -10 419 -10H414Q367 -10 346 17T325 74Q325 90 361 192T398 345Q398 404 354 404H349Q266 404 205 306L198 293L164 158Q132 28 127 16Q114 -11 83 -11Q69 -11 59 -2T48 16Q48 30 121 320L195 616Q195 629 188 632T149 637H128Q122 643 122 645T124 664Q129 683 137 683Z" style="stroke-width: 3;"/></g><g data-mml-node="mn" transform="translate(609,363) scale(0.707)"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"/></g></g><g data-mml-node="mrow" transform="translate(220,-686)"><g data-mml-node="mn"><path data-c="34" d="M462 0Q444 3 333 3Q217 3 199 0H190V46H221Q241 46 248 46T265 48T279 53T286 61Q287 63 287 115V165H28V211L179 442Q332 674 334 675Q336 677 355 677H373L379 671V211H471V165H379V114Q379 73 379 66T385 54Q393 47 442 46H471V0H462ZM293 211V545L74 212L183 211H293Z" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(500,0)"><path data-c="1D458" d="M121 647Q121 657 125 670T137 683Q138 683 209 688T282 694Q294 694 294 686Q294 679 244 477Q194 279 194 272Q213 282 223 291Q247 309 292 354T362 415Q402 442 438 442Q468 442 485 423T503 369Q503 344 496 327T477 302T456 291T438 288Q418 288 406 299T394 328Q394 353 410 369T442 390L458 393Q446 405 434 405H430Q398 402 367 380T294 316T228 255Q230 254 243 252T267 246T293 238T320 224T342 206T359 180T365 147Q365 130 360 106T354 66Q354 26 381 26Q429 26 459 145Q461 153 479 153H483Q499 153 499 144Q499 139 496 130Q455 -11 378 -11Q333 -11 305 15T277 90Q277 108 280 121T283 145Q283 167 269 183T234 206T200 217T182 220H180Q168 178 159 139T145 81T136 44T129 20T122 7T111 -2Q98 -11 83 -11Q66 -11 57 -1T48 16Q48 26 85 176T158 471L195 616Q196 629 188 632T149 637H144Q134 637 131 637T124 640T121 647Z" style="stroke-width: 3;"/></g></g><rect width="1221" height="60" x="120" y="220"/></g><g data-mml-node="mo" transform="translate(14982.2,0)"><path data-c="2C" d="M78 35T78 60T94 103T137 121Q165 121 187 96T210 8Q210 -27 201 -60T180 -117T154 -158T130 -185T117 -194Q113 -194 104 -185T95 -172Q95 -168 106 -156T131 -126T157 -76T173 -3V9L172 8Q170 7 167 6T161 3T152 1T140 0Q113 0 96 17Z" style="stroke-width: 3;"/></g><g data-mml-node="mstyle" transform="translate(15260.2,0)"><g data-mml-node="mspace"/></g><g data-mml-node="mi" transform="translate(17426.9,0)"><path data-c="210E" d="M137 683Q138 683 209 688T282 694Q294 694 294 685Q294 674 258 534Q220 386 220 383Q220 381 227 388Q288 442 357 442Q411 442 444 415T478 336Q478 285 440 178T402 50Q403 36 407 31T422 26Q450 26 474 56T513 138Q516 149 519 151T535 153Q555 153 555 145Q555 144 551 130Q535 71 500 33Q466 -10 419 -10H414Q367 -10 346 17T325 74Q325 90 361 192T398 345Q398 404 354 404H349Q266 404 205 306L198 293L164 158Q132 28 127 16Q114 -11 83 -11Q69 -11 59 -2T48 16Q48 30 121 320L195 616Q195 629 188 632T149 637H128Q122 643 122 645T124 664Q129 683 137 683Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(18280.7,0)"><path data-c="3D" d="M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(19336.4,0)"><path data-c="6D" d="M41 46H55Q94 46 102 60V68Q102 77 102 91T102 122T103 161T103 203Q103 234 103 269T102 328V351Q99 370 88 376T43 385H25V408Q25 431 27 431L37 432Q47 433 65 434T102 436Q119 437 138 438T167 441T178 442H181V402Q181 364 182 364T187 369T199 384T218 402T247 421T285 437Q305 442 336 442Q351 442 364 440T387 434T406 426T421 417T432 406T441 395T448 384T452 374T455 366L457 361L460 365Q463 369 466 373T475 384T488 397T503 410T523 422T546 432T572 439T603 442Q729 442 740 329Q741 322 741 190V104Q741 66 743 59T754 49Q775 46 803 46H819V0H811L788 1Q764 2 737 2T699 3Q596 3 587 0H579V46H595Q656 46 656 62Q657 64 657 200Q656 335 655 343Q649 371 635 385T611 402T585 404Q540 404 506 370Q479 343 472 315T464 232V168V108Q464 78 465 68T468 55T477 49Q498 46 526 46H542V0H534L510 1Q487 2 460 2T422 3Q319 3 310 0H302V46H318Q379 46 379 62Q380 64 380 200Q379 335 378 343Q372 371 358 385T334 402T308 404Q263 404 229 370Q202 343 195 315T187 232V168V108Q187 78 188 68T191 55T200 49Q221 46 249 46H265V0H257L234 1Q210 2 183 2T145 3Q42 3 33 0H25V46H41Z" style="stroke-width: 3;"/><path data-c="61" d="M137 305T115 305T78 320T63 359Q63 394 97 421T218 448Q291 448 336 416T396 340Q401 326 401 309T402 194V124Q402 76 407 58T428 40Q443 40 448 56T453 109V145H493V106Q492 66 490 59Q481 29 455 12T400 -6T353 12T329 54V58L327 55Q325 52 322 49T314 40T302 29T287 17T269 6T247 -2T221 -8T190 -11Q130 -11 82 20T34 107Q34 128 41 147T68 188T116 225T194 253T304 268H318V290Q318 324 312 340Q290 411 215 411Q197 411 181 410T156 406T148 403Q170 388 170 359Q170 334 154 320ZM126 106Q126 75 150 51T209 26Q247 26 276 49T315 109Q317 116 318 175Q318 233 317 233Q309 233 296 232T251 223T193 203T147 166T126 106Z" transform="translate(833,0)" style="stroke-width: 3;"/><path data-c="78" d="M201 0Q189 3 102 3Q26 3 17 0H11V46H25Q48 47 67 52T96 61T121 78T139 96T160 122T180 150L226 210L168 288Q159 301 149 315T133 336T122 351T113 363T107 370T100 376T94 379T88 381T80 383Q74 383 44 385H16V431H23Q59 429 126 429Q219 429 229 431H237V385Q201 381 201 369Q201 367 211 353T239 315T268 274L272 270L297 304Q329 345 329 358Q329 364 327 369T322 376T317 380T310 384L307 385H302V431H309Q324 428 408 428Q487 428 493 431H499V385H492Q443 385 411 368Q394 360 377 341T312 257L296 236L358 151Q424 61 429 57T446 50Q464 46 499 46H516V0H510H502Q494 1 482 1T457 2T432 2T414 3Q403 3 377 3T327 1L304 0H295V46H298Q309 46 320 51T331 63Q331 65 291 120L250 175Q249 174 219 133T185 88Q181 83 181 74Q181 63 188 55T206 46Q208 46 208 23V0H201Z" transform="translate(1333,0)" style="stroke-width: 3;"/></g><g data-mml-node="TeXAtom" data-mjx-texclass="OPEN" transform="translate(21197.4,0)"><g data-mml-node="mo" transform="translate(0 -0.5)"><path data-c="28" d="M152 251Q152 646 388 850H416Q422 844 422 841Q422 837 403 816T357 753T302 649T255 482T236 250Q236 124 255 19T301 -147T356 -251T403 -315T422 -340Q422 -343 416 -349H388Q359 -325 332 -296T271 -213T212 -97T170 56T152 251Z" style="stroke-width: 3;"/></g></g><g data-mml-node="mi" transform="translate(21655.4,0)"><path data-c="1D458" d="M121 647Q121 657 125 670T137 683Q138 683 209 688T282 694Q294 694 294 686Q294 679 244 477Q194 279 194 272Q213 282 223 291Q247 309 292 354T362 415Q402 442 438 442Q468 442 485 423T503 369Q503 344 496 327T477 302T456 291T438 288Q418 288 406 299T394 328Q394 353 410 369T442 390L458 393Q446 405 434 405H430Q398 402 367 380T294 316T228 255Q230 254 243 252T267 246T293 238T320 224T342 206T359 180T365 147Q365 130 360 106T354 66Q354 26 381 26Q429 26 459 145Q461 153 479 153H483Q499 153 499 144Q499 139 496 130Q455 -11 378 -11Q333 -11 305 15T277 90Q277 108 280 121T283 145Q283 167 269 183T234 206T200 217T182 220H180Q168 178 159 139T145 81T136 44T129 20T122 7T111 -2Q98 -11 83 -11Q66 -11 57 -1T48 16Q48 26 85 176T158 471L195 616Q196 629 188 632T149 637H144Q134 637 131 637T124 640T121 647Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(22398.7,0)"><path data-c="2212" d="M84 237T84 250T98 270H679Q694 262 694 250T679 230H98Q84 237 84 250Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(23398.9,0) translate(0 -0.5)"><path data-c="7C" d="M139 -249H137Q125 -249 119 -235V251L120 737Q130 750 139 750Q152 750 159 735V-235Q151 -249 141 -249H139Z" style="stroke-width: 3;"/></g><g data-mml-node="msub" transform="translate(23676.9,0)"><g data-mml-node="mi"><path data-c="1D451" d="M366 683Q367 683 438 688T511 694Q523 694 523 686Q523 679 450 384T375 83T374 68Q374 26 402 26Q411 27 422 35Q443 55 463 131Q469 151 473 152Q475 153 483 153H487H491Q506 153 506 145Q506 140 503 129Q490 79 473 48T445 8T417 -8Q409 -10 393 -10Q359 -10 336 5T306 36L300 51Q299 52 296 50Q294 48 292 46Q233 -10 172 -10Q117 -10 75 30T33 157Q33 205 53 255T101 341Q148 398 195 420T280 442Q336 442 364 400Q369 394 369 396Q370 400 396 505T424 616Q424 629 417 632T378 637H357Q351 643 351 645T353 664Q358 683 366 683ZM352 326Q329 405 277 405Q242 405 210 374T160 293Q131 214 119 129Q119 126 119 118T118 106Q118 61 136 44T179 26Q233 26 290 98L298 109L352 326Z" style="stroke-width: 3;"/></g><g data-mml-node="mn" transform="translate(553,-150) scale(0.707)"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" style="stroke-width: 3;"/></g></g><g data-mml-node="mo" transform="translate(24855.7,0)"><path data-c="2212" d="M84 237T84 250T98 270H679Q694 262 694 250T679 230H98Q84 237 84 250Z" style="stroke-width: 3;"/></g><g data-mml-node="msub" transform="translate(25855.9,0)"><g data-mml-node="mi"><path data-c="1D451" d="M366 683Q367 683 438 688T511 694Q523 694 523 686Q523 679 450 384T375 83T374 68Q374 26 402 26Q411 27 422 35Q443 55 463 131Q469 151 473 152Q475 153 483 153H487H491Q506 153 506 145Q506 140 503 129Q490 79 473 48T445 8T417 -8Q409 -10 393 -10Q359 -10 336 5T306 36L300 51Q299 52 296 50Q294 48 292 46Q233 -10 172 -10Q117 -10 75 30T33 157Q33 205 53 255T101 341Q148 398 195 420T280 442Q336 442 364 400Q369 394 369 396Q370 400 396 505T424 616Q424 629 417 632T378 637H357Q351 643 351 645T353 664Q358 683 366 683ZM352 326Q329 405 277 405Q242 405 210 374T160 293Q131 214 119 129Q119 126 119 118T118 106Q118 61 136 44T179 26Q233 26 290 98L298 109L352 326Z" style="stroke-width: 3;"/></g><g data-mml-node="mn" transform="translate(553,-150) scale(0.707)"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"/></g></g><g data-mml-node="mo" transform="translate(26812.4,0) translate(0 -0.5)"><path data-c="7C" d="M139 -249H137Q125 -249 119 -235V251L120 737Q130 750 139 750Q152 750 159 735V-235Q151 -249 141 -249H139Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(27090.4,0)"><path data-c="2C" d="M78 35T78 60T94 103T137 121Q165 121 187 96T210 8Q210 -27 201 -60T180 -117T154 -158T130 -185T117 -194Q113 -194 104 -185T95 -172Q95 -168 106 -156T131 -126T157 -76T173 -3V9L172 8Q170 7 167 6T161 3T152 1T140 0Q113 0 96 17Z" style="stroke-width: 3;"/></g><g data-mml-node="mstyle" transform="translate(27368.4,0)"><g data-mml-node="mspace"/></g><g data-mml-node="mn" transform="translate(27702.1,0)"><path data-c="30" d="M96 585Q152 666 249 666Q297 666 345 640T423 548Q460 465 460 320Q460 165 417 83Q397 41 362 16T301 -15T250 -22Q224 -22 198 -16T137 16T82 83Q39 165 39 320Q39 494 96 585ZM321 597Q291 629 250 629Q208 629 178 597Q153 571 145 525T137 333Q137 175 145 125T181 46Q209 16 250 16Q290 16 318 46Q347 76 354 130T362 333Q362 478 354 524T321 597Z" style="stroke-width: 3;"/></g><g data-mml-node="TeXAtom" data-mjx-texclass="CLOSE" transform="translate(28202.1,0)"><g data-mml-node="mo" transform="translate(0 -0.5)"><path data-c="29" d="M305 251Q305 -145 69 -349H56Q43 -349 39 -347T35 -338Q37 -333 60 -307T108 -239T160 -136T204 27T221 250T204 473T160 636T108 740T60 807T35 839Q35 850 50 850H56H69Q197 743 256 566Q305 425 305 251Z" style="stroke-width: 3;"/></g></g></g></g></svg><mjx-assistive-mml unselectable="on" display="block" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; overflow: hidden; width: 100%;"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><mi>smin</mi><mo stretchy="false">(</mo><msub><mi>d</mi><mn>1</mn></msub><mo>,</mo><msub><mi>d</mi><mn>2</mn></msub><mo>,</mo><mi>k</mi><mo stretchy="false">)</mo><mo>=</mo><mo data-mjx-texclass="OP" movablelimits="true">min</mo><mo stretchy="false">(</mo><msub><mi>d</mi><mn>1</mn></msub><mo>,</mo><msub><mi>d</mi><mn>2</mn></msub><mo stretchy="false">)</mo><mo>−</mo><mfrac><msup><mi>h</mi><mn>2</mn></msup><mrow><mn>4</mn><mi>k</mi></mrow></mfrac><mo>,</mo><mstyle scriptlevel="0"><mspace width="2em"/></mstyle><mi>h</mi><mo>=</mo><mo data-mjx-texclass="OP" movablelimits="true">max</mo><mrow data-mjx-texclass="OPEN"><mo minsize="1.2em" maxsize="1.2em">(</mo></mrow><mi>k</mi><mo>−</mo><mo data-mjx-texclass="ORD" stretchy="false">|</mo><msub><mi>d</mi><mn>1</mn></msub><mo>−</mo><msub><mi>d</mi><mn>2</mn></msub><mo data-mjx-texclass="ORD" stretchy="false">|</mo><mo>,</mo><mstyle scriptlevel="0"><mspace width="0.167em"/></mstyle><mn>0</mn><mrow data-mjx-texclass="CLOSE"><mo minsize="1.2em" maxsize="1.2em">)</mo></mrow></math></mjx-assistive-mml></mjx-container><p>donde <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.025ex;" xmlns="http://www.w3.org/2000/svg" width="1.179ex" height="1.595ex" role="img" focusable="false" viewBox="0 -694 521 705" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mi"><path data-c="1D458" d="M121 647Q121 657 125 670T137 683Q138 683 209 688T282 694Q294 694 294 686Q294 679 244 477Q194 279 194 272Q213 282 223 291Q247 309 292 354T362 415Q402 442 438 442Q468 442 485 423T503 369Q503 344 496 327T477 302T456 291T438 288Q418 288 406 299T394 328Q394 353 410 369T442 390L458 393Q446 405 434 405H430Q398 402 367 380T294 316T228 255Q230 254 243 252T267 246T293 238T320 224T342 206T359 180T365 147Q365 130 360 106T354 66Q354 26 381 26Q429 26 459 145Q461 153 479 153H483Q499 153 499 144Q499 139 496 130Q455 -11 378 -11Q333 -11 305 15T277 90Q277 108 280 121T283 145Q283 167 269 183T234 206T200 217T182 220H180Q168 178 159 139T145 81T136 44T129 20T122 7T111 -2Q98 -11 83 -11Q66 -11 57 -1T48 16Q48 26 85 176T158 471L195 616Q196 629 188 632T149 637H144Q134 637 131 637T124 640T121 647Z" style="stroke-width: 3;"/></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mi>k</mi></math></mjx-assistive-mml></mjx-container> controla el radio de mezcla. Cuando <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.05ex;" xmlns="http://www.w3.org/2000/svg" width="5.829ex" height="1.62ex" role="img" focusable="false" viewBox="0 -694 2576.6 716" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mi"><path data-c="1D458" d="M121 647Q121 657 125 670T137 683Q138 683 209 688T282 694Q294 694 294 686Q294 679 244 477Q194 279 194 272Q213 282 223 291Q247 309 292 354T362 415Q402 442 438 442Q468 442 485 423T503 369Q503 344 496 327T477 302T456 291T438 288Q418 288 406 299T394 328Q394 353 410 369T442 390L458 393Q446 405 434 405H430Q398 402 367 380T294 316T228 255Q230 254 243 252T267 246T293 238T320 224T342 206T359 180T365 147Q365 130 360 106T354 66Q354 26 381 26Q429 26 459 145Q461 153 479 153H483Q499 153 499 144Q499 139 496 130Q455 -11 378 -11Q333 -11 305 15T277 90Q277 108 280 121T283 145Q283 167 269 183T234 206T200 217T182 220H180Q168 178 159 139T145 81T136 44T129 20T122 7T111 -2Q98 -11 83 -11Q66 -11 57 -1T48 16Q48 26 85 176T158 471L195 616Q196 629 188 632T149 637H144Q134 637 131 637T124 640T121 647Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(798.8,0)"><path data-c="2192" d="M56 237T56 250T70 270H835Q719 357 692 493Q692 494 692 496T691 499Q691 511 708 511H711Q720 511 723 510T729 506T732 497T735 481T743 456Q765 389 816 336T935 261Q944 258 944 250Q944 244 939 241T915 231T877 212Q836 186 806 152T761 85T740 35T732 4Q730 -6 727 -8T711 -11Q691 -11 691 0Q691 7 696 25Q728 151 835 230H70Q56 237 56 250Z" style="stroke-width: 3;"/></g><g data-mml-node="mn" transform="translate(2076.6,0)"><path data-c="30" d="M96 585Q152 666 249 666Q297 666 345 640T423 548Q460 465 460 320Q460 165 417 83Q397 41 362 16T301 -15T250 -22Q224 -22 198 -16T137 16T82 83Q39 165 39 320Q39 494 96 585ZM321 597Q291 629 250 629Q208 629 178 597Q153 571 145 525T137 333Q137 175 145 125T181 46Q209 16 250 16Q290 16 318 46Q347 76 354 130T362 333Q362 478 354 524T321 597Z" style="stroke-width: 3;"/></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mi>k</mi><mo accent="false" stretchy="false">→</mo><mn>0</mn></math></mjx-assistive-mml></mjx-container>, la expresión vuelve a convertirse en un <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: 0;" xmlns="http://www.w3.org/2000/svg" width="3.771ex" height="1.514ex" role="img" focusable="false" viewBox="0 -669 1667 669" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mo"><path data-c="6D" d="M41 46H55Q94 46 102 60V68Q102 77 102 91T102 122T103 161T103 203Q103 234 103 269T102 328V351Q99 370 88 376T43 385H25V408Q25 431 27 431L37 432Q47 433 65 434T102 436Q119 437 138 438T167 441T178 442H181V402Q181 364 182 364T187 369T199 384T218 402T247 421T285 437Q305 442 336 442Q351 442 364 440T387 434T406 426T421 417T432 406T441 395T448 384T452 374T455 366L457 361L460 365Q463 369 466 373T475 384T488 397T503 410T523 422T546 432T572 439T603 442Q729 442 740 329Q741 322 741 190V104Q741 66 743 59T754 49Q775 46 803 46H819V0H811L788 1Q764 2 737 2T699 3Q596 3 587 0H579V46H595Q656 46 656 62Q657 64 657 200Q656 335 655 343Q649 371 635 385T611 402T585 404Q540 404 506 370Q479 343 472 315T464 232V168V108Q464 78 465 68T468 55T477 49Q498 46 526 46H542V0H534L510 1Q487 2 460 2T422 3Q319 3 310 0H302V46H318Q379 46 379 62Q380 64 380 200Q379 335 378 343Q372 371 358 385T334 402T308 404Q263 404 229 370Q202 343 195 315T187 232V168V108Q187 78 188 68T191 55T200 49Q221 46 249 46H265V0H257L234 1Q210 2 183 2T145 3Q42 3 33 0H25V46H41Z" style="stroke-width: 3;"/><path data-c="69" d="M69 609Q69 637 87 653T131 669Q154 667 171 652T188 609Q188 579 171 564T129 549Q104 549 87 564T69 609ZM247 0Q232 3 143 3Q132 3 106 3T56 1L34 0H26V46H42Q70 46 91 49Q100 53 102 60T104 102V205V293Q104 345 102 359T88 378Q74 385 41 385H30V408Q30 431 32 431L42 432Q52 433 70 434T106 436Q123 437 142 438T171 441T182 442H185V62Q190 52 197 50T232 46H255V0H247Z" transform="translate(833,0)" style="stroke-width: 3;"/><path data-c="6E" d="M41 46H55Q94 46 102 60V68Q102 77 102 91T102 122T103 161T103 203Q103 234 103 269T102 328V351Q99 370 88 376T43 385H25V408Q25 431 27 431L37 432Q47 433 65 434T102 436Q119 437 138 438T167 441T178 442H181V402Q181 364 182 364T187 369T199 384T218 402T247 421T285 437Q305 442 336 442Q450 438 463 329Q464 322 464 190V104Q464 66 466 59T477 49Q498 46 526 46H542V0H534L510 1Q487 2 460 2T422 3Q319 3 310 0H302V46H318Q379 46 379 62Q380 64 380 200Q379 335 378 343Q372 371 358 385T334 402T308 404Q263 404 229 370Q202 343 195 315T187 232V168V108Q187 78 188 68T191 55T200 49Q221 46 249 46H265V0H257L234 1Q210 2 183 2T145 3Q42 3 33 0H25V46H41Z" transform="translate(1111,0)" style="stroke-width: 3;"/></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mo data-mjx-texclass="OP" movablelimits="true">min</mo></math></mjx-assistive-mml></mjx-container> estricto. Consulta <a href="/es/guides/landscape-generation-browser.html#signed-distance-fields-sdfs">la representación de terrenos mediante SDF</a>.</p>
<p><strong>Shaders de cómputo de WebGPU.</strong> Programas de GPU que ejecutan cálculos de propósito general sin estar ligados a la pipeline de rasterización. Un shader de cómputo lanza grupos de trabajo compuestos por hilos que se ejecutan en paralelo. Para marching cubes, cada hilo procesa una celda de la cuadrícula: muestrea el SDF, clasifica la celda, consulta la triangulación, interpola los vértices de las aristas y los añade a un búfer de malla mediante contadores atómicos. No se necesita ninguna lectura de vuelta por parte de la CPU, porque el búfer de salida se utiliza directamente como datos de vértices para el renderizado. El proyecto <a href="https://www.willusher.io/webgpu-marching-cubes/" target="_blank" rel="noreferrer">webgpu-marching-cubes</a> de Will Usher demuestra el procesamiento en tiempo real de una cuadrícula de 256^3 en el navegador. Consulta nuestra <a href="/es/guides/landscape-generation-browser.html#gpu-driven-lod-with-webgpu">guía sobre paisajes acerca del LOD controlado mediante WebGPU</a>.</p>
<p><strong>Arquitectura híbrida de mapa de altura + SDF.</strong> El enfoque práctico para crear terrenos en el navegador: los mapas de altura cubren todo el mundo (son baratos y compactos), mientras que los volúmenes SDF solo existen en los chunks que necesitan cuevas, voladizos o elementos tallados por el creador (entre el 5 y el 10 % de los chunks). Cerca de la cámara, la libertad volumétrica permite tallar y crear cuevas. A lo lejos, los mapas de altura proporcionan un terreno plano eficiente. Consulta <a href="/es/guides/landscape-generation-browser.html#hybrid-heightmap-base--volumetric-overlays">la representación híbrida del terreno</a>.</p>
<hr>
<p>Parte 7 de 12.<br>
Anterior: <a href="/es/blog/2026-02-25-open-world-browser-part-06-clipmaps.html">Parte 6 - Los clipmaps cambiaron el rumbo</a><br>
Siguiente: <a href="/es/blog/2026-02-25-open-world-browser-part-08-webgpu-integration.html">Parte 8 - Integración sin perder nuestra base de referencia</a><br>
Guía de la serie: <a href="/es/blog/2026-02-25-open-world-browser-series-guide.html">/es/blog/2026-02-25-open-world-browser-series-guide</a></p>
]]></content:encoded>
            <enclosure url="https://cdn.cinevva.com/blog/why-webgpu-engine-hero.jpg" length="0" type="image/jpg"/>
        </item>
        <item>
            <title><![CDATA[Construir un mundo abierto en el navegador, parte 8: Integración sin perder nuestra base de referencia]]></title>
            <link>https://app.cinevva.com/es/blog/2026-02-25-open-world-browser-part-08-webgpu-integration</link>
            <guid>https://app.cinevva.com/es/blog/2026-02-25-open-world-browser-part-08-webgpu-integration</guid>
            <pubDate>Wed, 25 Feb 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Los spikes 13 y 14 tuvieron menos que ver con funcionalidades y más con la disciplina del proceso. Congelamos una base limpia y después reforzamos una capa cada vez.]]></description>
            <content:encoded><![CDATA[<h1 id="construir-un-mundo-abierto-en-el-navegador-parte-8-integracion-sin-perder-nuestra-base-de-referencia" tabindex="-1">Construir un mundo abierto en el navegador, parte 8: Integración sin perder nuestra base de referencia <a class="header-anchor" href="#construir-un-mundo-abierto-en-el-navegador-parte-8-integracion-sin-perder-nuestra-base-de-referencia" aria-label="Permalink to &quot;Construir un mundo abierto en el navegador, parte 8: Integración sin perder nuestra base de referencia&quot;"></a></h1>
<p><em>Por <a href="/es/about.html">Oleg Sidorkin</a>, CTO y cofundador de Cinevva</em></p>
<p>¿Es tu primera vez aquí? Consulta la <a href="/es/blog/2026-02-25-open-world-browser-series-guide.html">guía de la serie</a>. Explica qué es un spike y contiene enlaces a todas las partes.</p>
<p>La integración es el momento en que los proyectos se vuelven caóticos. Tienes piezas que funcionan de forma aislada. Las conectas y, de repente, parece que cada error podría estar en cualquier parte.</p>
<p>Los spikes 13 y 14 fueron nuestra respuesta a esa trampa. El spike 13 estableció una base limpia de Three.js con WebGPU. Solo un renderizador, una escena, una cámara y una malla sencilla. Sin terreno, sin cómputo y sin efectos. Confirmamos que el backend WebGPU de Three.js se inicializaba correctamente, que el bucle de renderizado era estable y que los materiales de nodos de TSL (Three.js Shading Language) funcionaban como esperábamos. Solo después de superar ese punto de control empezamos a añadir capas.</p>
<div style="position:relative;padding-bottom:56.25%;height:0;overflow:hidden;border-radius:8px;margin:1.5rem 0;border:1px solid rgba(255,255,255,0.12)">
<iframe src="/es/spikes/13-threejs-webgpu/" title="Spike 13: base de Three.js con WebGPU" style="position:absolute;top:0;left:0;width:100%;height:100%;border:0;background:#000" loading="lazy" allowfullscreen></iframe>
</div>
<p><a href="/es/spikes/13-threejs-webgpu/" target="_blank">Abrir el spike 13 en una pestaña nueva ↗</a> · <a href="/es/blog/spike-source?spike=13-threejs-webgpu">Ver el código fuente</a></p>
<p>El spike 14 consistió en un refuerzo incremental. Añadimos una capacidad cada vez: primero los controles de cámara, después la iluminación, luego la malla generada por cómputo mediante el pipeline de marching cubes y, por último, las conexiones de búfer necesarias para enviar la salida de la GPU directamente a los atributos de geometría de Three.js. Después de cada incorporación, verificamos que la capa anterior siguiera comportándose correctamente.</p>
<div style="position:relative;padding-bottom:56.25%;height:0;overflow:hidden;border-radius:8px;margin:1.5rem 0;border:1px solid rgba(255,255,255,0.12)">
<iframe src="/es/spikes/14-threejs-webgpu-incremental/" title="Spike 14: refuerzo incremental" style="position:absolute;top:0;left:0;width:100%;height:100%;border:0;background:#000" loading="lazy" allowfullscreen></iframe>
</div>
<p><a href="/es/spikes/14-threejs-webgpu-incremental/" target="_blank">Abrir el spike 14 en una pestaña nueva ↗</a> · <a href="/es/blog/spike-source?spike=14-threejs-webgpu-incremental">Ver el código fuente</a></p>
<p>Eso suena lento. Lo fue durante exactamente un día, y poco después nos ahorró varios días cuando la lógica de costuras y el cambio de políticas se complicaron.</p>
<p>La categoría concreta de error que justificó esta disciplina fueron los artefactos finísimos. Eran fragmentos delgados que parecían indicar una geometría dañada, pero que en realidad se debían a datos obsoletos. El shader de cómputo escribía N vértices en un búfer, pero la llamada de dibujado seguía configurada para renderizar N+M vértices del fotograma anterior. Esos vértices adicionales contenían basura de la ejecución anterior. El resultado visual eran triángulos parpadeantes y finos como cuchillas que aparecían y desaparecían de forma impredecible.</p>
<p>Ese tipo de error no se vence con intuición. Se vence mediante cambios controlados que permiten saber exactamente qué ha cambiado entre el último estado funcional y el estado actual con errores.</p>
<p>La integración de WebGPU también nos enseñó mucho sobre el ciclo de vida de los búferes. Los búferes de GPU en WebGPU son inmutables una vez asignados para un uso específico. Si necesitas cambiar el tamaño de un búfer de vértices porque ha crecido la salida de marching cubes, tienes que crear uno nuevo y actualizar el enlace. No existe <code>realloc</code>. Gestionar correctamente ese ciclo de vida y destruir los búferes antiguos sin entrar en conflicto con el trabajo de la GPU aún en curso requirió una gestión explícita de fences que no existe en WebGL.</p>
<p>En la parte 9 pasamos al trabajo con costuras de Transvoxel. Ese capítulo comienza deliberadamente con un armazón básico. Para entonces ya habíamos interiorizado por completo la lección: precipitar la integración genera misterios, mientras que una preparación controlada genera problemas que se pueden depurar.</p>
<h2 id="tecnologia-mencionada-en-este-capitulo" tabindex="-1">Tecnología mencionada en este capítulo <a class="header-anchor" href="#tecnologia-mencionada-en-este-capitulo" aria-label="Permalink to &quot;Tecnología mencionada en este capítulo&quot;"></a></h2>
<p><strong>WebGPU.</strong> El sucesor de WebGL, que ofrece acceso de bajo nivel a la GPU desde el navegador mediante shaders de cómputo y renderizado indirecto. Las dos funciones esenciales de WebGPU para los mundos abiertos son las siguientes: los shaders de cómputo permiten generar terreno, colocar vegetación y realizar el descarte desde la GPU; el renderizado indirecto permite que la GPU decida qué dibujar a partir de la salida del cómputo, eliminando los cuellos de botella de la CPU en escenas densas. Está disponible en Chrome, Edge y Firefox para equipos de escritorio. Consulta <a href="/es/guides/browser-3d-open-world-tech.html#webgpu-the-performance-unlock">WebGPU como clave para mejorar el rendimiento</a>.</p>
<p><strong>Three.js Shading Language (TSL).</strong> El sistema de shaders basado en nodos de Three.js, que sustituye el código GLSL/WGSL sin procesar por expresiones de JavaScript componibles. Los nodos de TSL como <code>texture()</code>, <code>positionWorld</code>, <code>smoothstep()</code> y <code>fog()</code> crean en tiempo de ejecución un grafo de shaders que se compila para el backend correspondiente (GLSL de WebGL o WGSL de WebGPU). TSL permite escribir una vez la lógica de los materiales y utilizarla con ambos renderizadores. El grafo de nodos se evalúa en cada fotograma, por lo que los uniformes dinámicos y las bifurcaciones condicionales funcionan de manera natural.</p>
<p><strong>Ciclo de vida de los búferes de GPU en WebGPU.</strong> Los búferes de WebGPU se crean con indicadores de uso específicos (<code>VERTEX</code>, <code>STORAGE</code>, <code>COPY_DST</code>, etc.) y no se puede cambiar su tamaño después de crearlos. Si una ejecución de marching cubes produce más vértices de los que caben en el búfer, debes crear uno nuevo, actualizar el enlace y destruir el anterior. Destruir un búfer al que todavía hace referencia un comando de GPU en curso provoca errores. La gestión explícita de fences (mediante <code>device.queue.onSubmittedWorkDone()</code>) garantiza que el búfer antiguo no se destruya hasta que la GPU haya terminado de utilizarlo. Esta disciplina del ciclo de vida no existe en WebGL, donde el controlador gestiona la memoria de forma implícita.</p>
<p><strong>Refuerzo incremental.</strong> Una disciplina de integración que consiste en establecer una base de referencia cuyo correcto funcionamiento esté confirmado, añadir una capacidad cada vez y verificar que la capa anterior siga funcionando después de cada incorporación. Este enfoque es más lento durante un día, pero ahorra días en la depuración posterior, porque cada regresión puede rastrearse hasta un cambio concreto y controlado. El patrón de establecer primero una base y después avanzar de forma incremental es habitual en el <a href="/es/guides/browser-3d-open-world-tech.html#what-we-d-build-first">desarrollo de mundos abiertos AAA</a>, donde los sistemas se integran en un orden específico para gestionar el riesgo.</p>
<hr>
<p>Parte 8 de 12.<br>
Anterior: <a href="/es/blog/2026-02-25-open-world-browser-part-07-marching-cubes.html">Parte 7: Marching cubes y las primeras cuevas reales</a><br>
Siguiente: <a href="/es/blog/2026-02-25-open-world-browser-part-09-transvoxel-first-cut.html">Parte 9: Transvoxel comenzó con un armazón básico</a><br>
Guía de la serie: <a href="/es/blog/2026-02-25-open-world-browser-series-guide.html">/es/blog/2026-02-25-open-world-browser-series-guide</a></p>
]]></content:encoded>
            <enclosure url="https://cdn.cinevva.com/blog/why-webgpu-engine-hero.jpg" length="0" type="image/jpg"/>
        </item>
        <item>
            <title><![CDATA[Construir un mundo abierto en el navegador, parte 9: Transvoxel comenzó con un andamiaje]]></title>
            <link>https://app.cinevva.com/es/blog/2026-02-25-open-world-browser-part-09-transvoxel-first-cut</link>
            <guid>https://app.cinevva.com/es/blog/2026-02-25-open-world-browser-part-09-transvoxel-first-cut</guid>
            <pubDate>Wed, 25 Feb 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[No nos lanzamos directamente a cubrir todas las uniones. Primero construimos un banco de pruebas para ellas y después validamos una cara con datos de referencia.]]></description>
            <content:encoded><![CDATA[<h1 id="construir-un-mundo-abierto-en-el-navegador-parte-9-transvoxel-comenzo-con-un-andamiaje" tabindex="-1">Construir un mundo abierto en el navegador, parte 9: Transvoxel comenzó con un andamiaje <a class="header-anchor" href="#construir-un-mundo-abierto-en-el-navegador-parte-9-transvoxel-comenzo-con-un-andamiaje" aria-label="Permalink to &quot;Construir un mundo abierto en el navegador, parte 9: Transvoxel comenzó con un andamiaje&quot;"></a></h1>
<p><em>Por <a href="/es/about.html">Oleg Sidorkin</a>, CTO y cofundador de Cinevva</em></p>
<p>¿Acabas de llegar? Consulta la <a href="/es/blog/2026-02-25-open-world-browser-series-guide.html">guía de la serie</a>. Explica qué es un spike y enlaza todas las partes.</p>
<p>Las uniones son donde la confianza va a morir.</p>
<p>Todo puede parecer estable hasta que se encuentran dos resoluciones. Un chunk con LOD 0 está junto a otro con LOD 1. Sus mallas se generan de forma independiente. En el límite compartido, las posiciones de los vértices no coinciden porque el chunk de menor resolución tiene la mitad de densidad de cuadrícula. El resultado son grietas visibles, uniones en T y bordes que parpadean.</p>
<p>El algoritmo Transvoxel resuelve este problema generando celdas de transición especiales a lo largo de la cara limítrofe entre dos chunks con resoluciones diferentes. Estas celdas toman muestras simultáneamente de las cuadrículas de alta y baja resolución y producen triángulos que cosen ambas superficies. El algoritmo utiliza sus propias tablas de consulta, independientes de las tablas normales de marching cubes, con 512 casos de celdas de transición.</p>
<p>A esas alturas ya acumulábamos suficientes cicatrices de integración como para saber que no debíamos apresurar la implementación.</p>
<p>El Spike 15 tenía una sola misión: construir un banco de pruebas de uniones en el que pudiéramos confiar antes de tocar el algoritmo completo. Preparamos un entorno controlado donde dos chunks con datos SDF conocidos estaban uno junto al otro a distintas resoluciones, con controles de visualización para activar o desactivar de forma independiente la malla principal, la malla de unión, la vista alámbrica y las normales.</p>
<div style="position:relative;padding-bottom:56.25%;height:0;overflow:hidden;border-radius:8px;margin:1.5rem 0;border:1px solid rgba(255,255,255,0.12)">
<iframe src="/es/spikes/15-transvoxel-seam/" title="Andamiaje de uniones Transvoxel del Spike 15" style="position:absolute;top:0;left:0;width:100%;height:100%;border:0;background:#000" loading="lazy" allowfullscreen></iframe>
</div>
<p><a href="/es/spikes/15-transvoxel-seam/" target="_blank">Abrir el Spike 15 en una pestaña nueva ↗</a> · <a href="/es/blog/spike-source?spike=15-transvoxel-seam">Ver código fuente</a></p>
<p>Una vez estabilizado el banco de pruebas, el Spike 16 validó la generación de celdas de transición basada en tablas sobre una sola cara. Elegimos una cara alineada con un eje (el límite +X), implementamos la evaluación de celdas de transición únicamente para esa cara y comparamos el resultado con los datos de referencia del artículo de Transvoxel.</p>
<p><a href="/es/spikes/16-transvoxel-face/" target="_blank">Abrir el Spike 16 en una pestaña nueva ↗</a> · <a href="/es/blog/spike-source?spike=16-transvoxel-face">Ver código fuente</a></p>
<p>Probamos una cara cada vez de forma deliberada, porque el cableado de las tablas de transición presenta muchos modos de fallo independientes. El cálculo del índice de caso depende de tomar muestras de los vértices correctos de ambas cuadrículas. La indexación de vértices dentro de una celda de transición utiliza un esquema de numeración distinto al de las celdas normales de marching cubes. El orden de orientación debe ser coherente con el de la malla principal o el descarte de caras posteriores se comerá los triángulos de unión. Si pruebas las seis caras a la vez, todos los síntomas parecen aleatorios. Si pruebas exhaustivamente una sola cara, obtienes fallos significativos que puedes depurar.</p>
<p>Otro logro sutil de esta fase fue la inversión en herramientas. Desde el principio creamos controles de visibilidad, renderizado exclusivo de las uniones e indicadores LOD codificados por colores. En aquel momento, esos controles parecían trabajo adicional. Más adelante, cuando los casos extremos se complicaron, amortizaron con creces la inversión porque podíamos aislar exactamente qué celdas de unión se estaban comportando mal.</p>
<p>Al final de este capítulo no habíamos «terminado con las uniones». Estábamos en una posición desde la que podíamos razonar sobre sus errores en lugar de temerlos.</p>
<p>En la parte 10 comienza la verdadera montaña rusa. Esquinas con niveles LOD mezclados, inversiones de orientación, fantasmas por sobredibujado parcial y esos momentos en los que estás seguro de que el algoritmo es incorrecto, hasta que descubres que el error está en un rango de dibujo que lee más allá del número de vértices activos.</p>
<h2 id="tecnologia-mencionada-en-este-capitulo" tabindex="-1">Tecnología mencionada en este capítulo <a class="header-anchor" href="#tecnologia-mencionada-en-este-capitulo" aria-label="Permalink to &quot;Tecnología mencionada en este capítulo&quot;"></a></h2>
<p><strong>El algoritmo Transvoxel.</strong> Diseñado por Eric Lengyel (<a href="https://transvoxel.org/" target="_blank" rel="noreferrer">transvoxel.org</a>), Transvoxel resuelve el problema más difícil del LOD en terrenos volumétricos: las uniones entre chunks con distintas resoluciones. Cuando un chunk de alta resolución está junto a otro de baja resolución, las mallas de marching cubes no se alinean en el límite y producen grietas visibles. Transvoxel inserta celdas de transición especiales a lo largo de las caras limítrofes que salvan la diferencia de resolución mediante triángulos adicionales que coinciden con ambos lados. El algoritmo utiliza sus propias tablas de consulta, independientes de las de marching cubes normal, con 512 casos de celdas de transición reducidos a 73 clases de equivalencia. Está libre de patentes y se ha utilizado en juegos publicados (Space Engineers, Astroneer). Consulta nuestra <a href="/es/guides/landscape-generation-browser.html#the-transvoxel-algorithm">guía sobre paisajes dedicada a Transvoxel</a>.</p>
<p><strong>Celdas de transición.</strong> Celdas especiales generadas en la cara situada entre dos niveles LOD. A diferencia de las celdas normales de marching cubes, que toman muestras de 8 esquinas de una sola cuadrícula, las celdas de transición toman muestras simultáneamente de las cuadrículas de alta y baja resolución. La cara de alta resolución tiene <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.186ex;" xmlns="http://www.w3.org/2000/svg" width="9.176ex" height="1.692ex" role="img" focusable="false" viewBox="0 -666 4056 748" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mn"><path data-c="33" d="M127 463Q100 463 85 480T69 524Q69 579 117 622T233 665Q268 665 277 664Q351 652 390 611T430 522Q430 470 396 421T302 350L299 348Q299 347 308 345T337 336T375 315Q457 262 457 175Q457 96 395 37T238 -22Q158 -22 100 21T42 130Q42 158 60 175T105 193Q133 193 151 175T169 130Q169 119 166 110T159 94T148 82T136 74T126 70T118 67L114 66Q165 21 238 21Q293 21 321 74Q338 107 338 175V195Q338 290 274 322Q259 328 213 329L171 330L168 332Q166 335 166 348Q166 366 174 366Q202 366 232 371Q266 376 294 413T322 525V533Q322 590 287 612Q265 626 240 626Q208 626 181 615T143 592T132 580H135Q138 579 143 578T153 573T165 566T175 555T183 540T186 520Q186 498 172 481T127 463Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(722.2,0)"><path data-c="D7" d="M630 29Q630 9 609 9Q604 9 587 25T493 118L389 222L284 117Q178 13 175 11Q171 9 168 9Q160 9 154 15T147 29Q147 36 161 51T255 146L359 250L255 354Q174 435 161 449T147 471Q147 480 153 485T168 490Q173 490 175 489Q178 487 284 383L389 278L493 382Q570 459 587 475T609 491Q630 491 630 471Q630 464 620 453T522 355L418 250L522 145Q606 61 618 48T630 29Z" style="stroke-width: 3;"/></g><g data-mml-node="mn" transform="translate(1722.4,0)"><path data-c="33" d="M127 463Q100 463 85 480T69 524Q69 579 117 622T233 665Q268 665 277 664Q351 652 390 611T430 522Q430 470 396 421T302 350L299 348Q299 347 308 345T337 336T375 315Q457 262 457 175Q457 96 395 37T238 -22Q158 -22 100 21T42 130Q42 158 60 175T105 193Q133 193 151 175T169 130Q169 119 166 110T159 94T148 82T136 74T126 70T118 67L114 66Q165 21 238 21Q293 21 321 74Q338 107 338 175V195Q338 290 274 322Q259 328 213 329L171 330L168 332Q166 335 166 348Q166 366 174 366Q202 366 232 371Q266 376 294 413T322 525V533Q322 590 287 612Q265 626 240 626Q208 626 181 615T143 592T132 580H135Q138 579 143 578T153 573T165 566T175 555T183 540T186 520Q186 498 172 481T127 463Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(2500.2,0)"><path data-c="3D" d="M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z" style="stroke-width: 3;"/></g><g data-mml-node="mn" transform="translate(3556,0)"><path data-c="39" d="M352 287Q304 211 232 211Q154 211 104 270T44 396Q42 412 42 436V444Q42 537 111 606Q171 666 243 666Q245 666 249 666T257 665H261Q273 665 286 663T323 651T370 619T413 560Q456 472 456 334Q456 194 396 97Q361 41 312 10T208 -22Q147 -22 108 7T68 93T121 149Q143 149 158 135T173 96Q173 78 164 65T148 49T135 44L131 43Q131 41 138 37T164 27T206 22H212Q272 22 313 86Q352 142 352 280V287ZM244 248Q292 248 321 297T351 430Q351 508 343 542Q341 552 337 562T323 588T293 615T246 625Q208 625 181 598Q160 576 154 546T147 441Q147 358 152 329T172 282Q197 248 244 248Z" style="stroke-width: 3;"/></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mn>3</mn><mo>×</mo><mn>3</mn><mo>=</mo><mn>9</mn></math></mjx-assistive-mml></mjx-container> puntos de muestra, mientras que la de baja resolución tiene <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.186ex;" xmlns="http://www.w3.org/2000/svg" width="9.176ex" height="1.717ex" role="img" focusable="false" viewBox="0 -677 4056 759" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mn"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(722.2,0)"><path data-c="D7" d="M630 29Q630 9 609 9Q604 9 587 25T493 118L389 222L284 117Q178 13 175 11Q171 9 168 9Q160 9 154 15T147 29Q147 36 161 51T255 146L359 250L255 354Q174 435 161 449T147 471Q147 480 153 485T168 490Q173 490 175 489Q178 487 284 383L389 278L493 382Q570 459 587 475T609 491Q630 491 630 471Q630 464 620 453T522 355L418 250L522 145Q606 61 618 48T630 29Z" style="stroke-width: 3;"/></g><g data-mml-node="mn" transform="translate(1722.4,0)"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(2500.2,0)"><path data-c="3D" d="M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z" style="stroke-width: 3;"/></g><g data-mml-node="mn" transform="translate(3556,0)"><path data-c="34" d="M462 0Q444 3 333 3Q217 3 199 0H190V46H221Q241 46 248 46T265 48T279 53T286 61Q287 63 287 115V165H28V211L179 442Q332 674 334 675Q336 677 355 677H373L379 671V211H471V165H379V114Q379 73 379 66T385 54Q393 47 442 46H471V0H462ZM293 211V545L74 212L183 211H293Z" style="stroke-width: 3;"/></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mn>2</mn><mo>×</mo><mn>2</mn><mo>=</mo><mn>4</mn></math></mjx-assistive-mml></mjx-container>. Esas 9 muestras son las que dan al algoritmo sus <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.186ex;" xmlns="http://www.w3.org/2000/svg" width="8.53ex" height="2.072ex" role="img" focusable="false" viewBox="0 -833.9 3770.1 915.9" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="msup"><g data-mml-node="mn"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"/></g><g data-mml-node="mn" transform="translate(533,363) scale(0.707)"><path data-c="39" d="M352 287Q304 211 232 211Q154 211 104 270T44 396Q42 412 42 436V444Q42 537 111 606Q171 666 243 666Q245 666 249 666T257 665H261Q273 665 286 663T323 651T370 619T413 560Q456 472 456 334Q456 194 396 97Q361 41 312 10T208 -22Q147 -22 108 7T68 93T121 149Q143 149 158 135T173 96Q173 78 164 65T148 49T135 44L131 43Q131 41 138 37T164 27T206 22H212Q272 22 313 86Q352 142 352 280V287ZM244 248Q292 248 321 297T351 430Q351 508 343 542Q341 552 337 562T323 588T293 615T246 625Q208 625 181 598Q160 576 154 546T147 441Q147 358 152 329T172 282Q197 248 244 248Z" style="stroke-width: 3;"/></g></g><g data-mml-node="mo" transform="translate(1214.3,0)"><path data-c="3D" d="M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z" style="stroke-width: 3;"/></g><g data-mml-node="mn" transform="translate(2270.1,0)"><path data-c="35" d="M164 157Q164 133 148 117T109 101H102Q148 22 224 22Q294 22 326 82Q345 115 345 210Q345 313 318 349Q292 382 260 382H254Q176 382 136 314Q132 307 129 306T114 304Q97 304 95 310Q93 314 93 485V614Q93 664 98 664Q100 666 102 666Q103 666 123 658T178 642T253 634Q324 634 389 662Q397 666 402 666Q410 666 410 648V635Q328 538 205 538Q174 538 149 544L139 546V374Q158 388 169 396T205 412T256 420Q337 420 393 355T449 201Q449 109 385 44T229 -22Q148 -22 99 32T50 154Q50 178 61 192T84 210T107 214Q132 214 148 197T164 157Z" style="stroke-width: 3;"/><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" transform="translate(500,0)" style="stroke-width: 3;"/><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" transform="translate(1000,0)" style="stroke-width: 3;"/></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><msup><mn>2</mn><mn>9</mn></msup><mo>=</mo><mn>512</mn></math></mjx-assistive-mml></mjx-container> casos brutos, que se reducen a 73 triangulaciones distintas al eliminar rotaciones y reflexiones equivalentes. La clasificación y triangulación de las celdas utiliza tablas específicas que producen triángulos conectando vértices de ambas resoluciones. El esquema de numeración de vértices es distinto al de las celdas normales de MC, lo que constituye una fuente habitual de errores de implementación.</p>
<p><strong>Uniones de transición LOD.</strong> El límite entre dos resoluciones de malla donde la falta de correspondencia topológica causa artefactos visuales. Sin cosido, un chunk con LOD 0 (cuadrícula de 1 m) junto a otro con LOD 1 (cuadrícula de 2 m) produce uniones en T: la malla fina tiene vértices a lo largo del límite que la malla gruesa no comparte, lo que provoca grietas por las que se filtra la luz. Transvoxel, el geomorphing y la geometría de faldón son tres enfoques para corregir estas uniones. Para terrenos volumétricos, Transvoxel es la solución estándar porque el geomorphing solo funciona con mapas de alturas. Consulta <a href="/es/guides/landscape-generation-browser.html#lod-for-volumetric-terrain">LOD para terrenos volumétricos</a>.</p>
<hr>
<p>Parte 9 de 12.<br>
Anterior: <a href="/es/blog/2026-02-25-open-world-browser-part-08-webgpu-integration.html">Parte 8 - Integración sin perder nuestra base de referencia</a><br>
Siguiente: <a href="/es/blog/2026-02-25-open-world-browser-part-10-seam-chaos.html">Parte 10 - Caos en las uniones y el combate final contra las esquinas</a><br>
Guía de la serie: <a href="/es/blog/2026-02-25-open-world-browser-series-guide.html">/es/blog/2026-02-25-open-world-browser-series-guide</a></p>
]]></content:encoded>
            <enclosure url="https://cdn.cinevva.com/blog/why-webgpu-engine-hero.jpg" length="0" type="image/jpg"/>
        </item>
        <item>
            <title><![CDATA[Construir un mundo abierto en el navegador, parte 10: Caos en las costuras y el combate contra el jefe de las esquinas]]></title>
            <link>https://app.cinevva.com/es/blog/2026-02-25-open-world-browser-part-10-seam-chaos</link>
            <guid>https://app.cinevva.com/es/blog/2026-02-25-open-world-browser-part-10-seam-chaos</guid>
            <pubDate>Wed, 25 Feb 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Los spikes del 17 al 22 fueron el punto donde la teoría se enfrentó a los casos límite. Perseguimos errores de orientación de vértices, triángulos ausentes, fantasmas de sobredibujado y lógica híbrida de respaldo.]]></description>
            <content:encoded><![CDATA[<h1 id="construir-un-mundo-abierto-en-el-navegador-parte-10-caos-en-las-costuras-y-el-combate-contra-el-jefe-de-las-esquinas" tabindex="-1">Construir un mundo abierto en el navegador, parte 10: Caos en las costuras y el combate contra el jefe de las esquinas <a class="header-anchor" href="#construir-un-mundo-abierto-en-el-navegador-parte-10-caos-en-las-costuras-y-el-combate-contra-el-jefe-de-las-esquinas" aria-label="Permalink to &quot;Construir un mundo abierto en el navegador, parte 10: Caos en las costuras y el combate contra el jefe de las esquinas&quot;"></a></h1>
<p><em>Por <a href="/es/about.html">Oleg Sidorkin</a>, CTO y cofundador de Cinevva</em></p>
<p>¿Acabas de llegar? Consulta la <a href="/es/blog/2026-02-25-open-world-browser-series-guide.html">guía de la serie</a>. Explica qué es un spike y enlaza todas las partes.</p>
<p>Si las partes anteriores parecían metódicas, este capítulo se sintió como un combate.</p>
<p>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.</p>
<p>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.</p>
<div style="position:relative;padding-bottom:56.25%;height:0;overflow:hidden;border-radius:8px;margin:1.5rem 0;border:1px solid rgba(255,255,255,0.12)">
<iframe src="/es/spikes/19-transvoxel-corner-grid/" title="Spike 19: cuadrícula de esquina Transvoxel" style="position:absolute;top:0;left:0;width:100%;height:100%;border:0;background:#000" loading="lazy" allowfullscreen></iframe>
</div>
<p><a href="/es/spikes/19-transvoxel-corner-grid/" target="_blank">Abrir el spike 19 en una pestaña nueva ↗</a> · <a href="/es/blog/spike-source?spike=19-transvoxel-corner-grid">Ver código fuente</a></p>
<p>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.</p>
<p>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.</p>
<p>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ó.</p>
<p>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.</p>
<p>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.</p>
<div style="position:relative;padding-bottom:56.25%;height:0;overflow:hidden;border-radius:8px;margin:1.5rem 0;border:1px solid rgba(255,255,255,0.12)">
<iframe src="/es/spikes/22-gpu-mc-heightmap-fallback/" title="Spike 22: respaldo de MC con mapa de alturas" style="position:absolute;top:0;left:0;width:100%;height:100%;border:0;background:#000" loading="lazy" allowfullscreen></iframe>
</div>
<p><a href="/es/spikes/22-gpu-mc-heightmap-fallback/" target="_blank">Abrir el spike 22 en una pestaña nueva ↗</a> · <a href="/es/blog/spike-source?spike=22-gpu-mc-heightmap-fallback">Ver código fuente</a></p>
<p>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.</p>
<p>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.</p>
<h2 id="tecnologia-mencionada-en-este-capitulo" tabindex="-1">Tecnología mencionada en este capítulo <a class="header-anchor" href="#tecnologia-mencionada-en-este-capitulo" aria-label="Permalink to &quot;Tecnología mencionada en este capítulo&quot;"></a></h2>
<p><strong>Marching cubes con LOD dual.</strong> 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.</p>
<p><strong>Orden de orientación de los vértices.</strong> 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 <code>side: THREE.DoubleSide</code> en el material para confirmar si los artefactos se deben a problemas de orientación o a huecos topológicos reales.</p>
<p><strong>Respaldo de mapa de alturas a MC.</strong> 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 <a href="/es/guides/landscape-generation-browser.html#hybrid-heightmap-base--volumetric-overlays">mapa de alturas híbrido + capas volumétricas</a>.</p>
<p><strong>Rango de dibujado y contadores atómicos.</strong> 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.</p>
<hr>
<p>Parte 10 de 12.<br>
Anterior: <a href="/es/blog/2026-02-25-open-world-browser-part-09-transvoxel-first-cut.html">Parte 9 - Transvoxel comenzó con una estructura básica</a><br>
Siguiente: <a href="/es/blog/2026-02-25-open-world-browser-part-11-policy-modes.html">Parte 11 - Modo basado en políticas, no un modo codificado de forma rígida</a><br>
Guía de la serie: <a href="/es/blog/2026-02-25-open-world-browser-series-guide.html">/es/blog/2026-02-25-open-world-browser-series-guide</a></p>
]]></content:encoded>
            <enclosure url="https://cdn.cinevva.com/blog/why-webgpu-engine-hero.jpg" length="0" type="image/jpg"/>
        </item>
        <item>
            <title><![CDATA[Construir un mundo abierto en el navegador, parte 11: modo basado en políticas, no modo codificado]]></title>
            <link>https://app.cinevva.com/es/blog/2026-02-25-open-world-browser-part-11-policy-modes</link>
            <guid>https://app.cinevva.com/es/blog/2026-02-25-open-world-browser-part-11-policy-modes</guid>
            <pubDate>Wed, 25 Feb 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[El Spike 23 nos hizo pasar de las correcciones reactivas a políticas explícitas. LOD basado en la distancia, cambio entre HM y MC según las ediciones y mejores controles para depurar las uniones.]]></description>
            <content:encoded><![CDATA[<h1 id="construir-un-mundo-abierto-en-el-navegador-parte-11-modo-basado-en-politicas-no-modo-codificado" tabindex="-1">Construir un mundo abierto en el navegador, parte 11: modo basado en políticas, no modo codificado <a class="header-anchor" href="#construir-un-mundo-abierto-en-el-navegador-parte-11-modo-basado-en-politicas-no-modo-codificado" aria-label="Permalink to &quot;Construir un mundo abierto en el navegador, parte 11: modo basado en políticas, no modo codificado&quot;"></a></h1>
<p><em>Por <a href="/es/about.html">Oleg Sidorkin</a>, director de tecnología y cofundador de Cinevva</em></p>
<p>¿Acabas de llegar? Consulta la <a href="/es/blog/2026-02-25-open-world-browser-series-guide.html">guía de la serie</a>. Explica qué es un spike y contiene enlaces a todas las partes.</p>
<p>Después del capítulo sobre el caos de las uniones, teníamos que dejar de reaccionar y empezar a establecer reglas.</p>
<p>El Spike 23 sustituyó el comportamiento improvisado por reglas de política explícitas. En lugar de que los chunks hicieran lo que indicara su estado local, ahora un sistema central de políticas tomaba las decisiones. ¿Qué nivel de LOD recibe este chunk? ¿Se renderiza como mapa de alturas o mediante marching cubes? ¿Necesita celdas de transición y, de ser así, en qué caras? Las respuestas procedían de una función de políticas que evaluaba la distancia a la cámara, el historial de ediciones y los estados de resolución de los chunks vecinos.</p>
<div style="position:relative;padding-bottom:56.25%;height:0;overflow:hidden;border-radius:8px;margin:1.5rem 0;border:1px solid rgba(255,255,255,0.12)">
<iframe src="/es/spikes/23-policy-chunk-modes/" title="Spike 23: políticas para los modos de los chunks" style="position:absolute;top:0;left:0;width:100%;height:100%;border:0;background:#000" loading="lazy" allowfullscreen></iframe>
</div>
<p><a href="/es/spikes/23-policy-chunk-modes/" target="_blank">Abrir el Spike 23 en una pestaña nueva ↗</a> · <a href="/es/blog/spike-source?spike=23-policy-chunk-modes">Ver el código fuente</a></p>
<p>La asignación de LOD basada en la distancia utilizaba anillos concéntricos alrededor de la cámara, de forma similar al concepto de clipmap, pero aplicado a la cuadrícula de chunks. Los chunks del anillo 0 reciben MC a resolución completa. Los del anillo 1 reciben MC a media resolución. Los del anillo 2 y posteriores usan el modo de mapa de alturas. La restricción de adyacencia era fundamental: para dos chunks vecinos cualesquiera exigimos que <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.666ex;" xmlns="http://www.w3.org/2000/svg" width="12.84ex" height="2.361ex" role="img" focusable="false" viewBox="0 -749.5 5675.3 1043.7" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mo" transform="translate(0 -0.5)"><path data-c="7C" d="M139 -249H137Q125 -249 119 -235V251L120 737Q130 750 139 750Q152 750 159 735V-235Q151 -249 141 -249H139Z" style="stroke-width: 3;"/></g><g data-mml-node="msub" transform="translate(278,0)"><g data-mml-node="mi"><path data-c="1D43F" d="M228 637Q194 637 192 641Q191 643 191 649Q191 673 202 682Q204 683 217 683Q271 680 344 680Q485 680 506 683H518Q524 677 524 674T522 656Q517 641 513 637H475Q406 636 394 628Q387 624 380 600T313 336Q297 271 279 198T252 88L243 52Q243 48 252 48T311 46H328Q360 46 379 47T428 54T478 72T522 106T564 161Q580 191 594 228T611 270Q616 273 628 273H641Q647 264 647 262T627 203T583 83T557 9Q555 4 553 3T537 0T494 -1Q483 -1 418 -1T294 0H116Q32 0 32 10Q32 17 34 24Q39 43 44 45Q48 46 59 46H65Q92 46 125 49Q139 52 144 61Q147 65 216 339T285 628Q285 635 228 637Z" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(714,-150) scale(0.707)"><path data-c="1D456" d="M184 600Q184 624 203 642T247 661Q265 661 277 649T290 619Q290 596 270 577T226 557Q211 557 198 567T184 600ZM21 287Q21 295 30 318T54 369T98 420T158 442Q197 442 223 419T250 357Q250 340 236 301T196 196T154 83Q149 61 149 51Q149 26 166 26Q175 26 185 29T208 43T235 78T260 137Q263 149 265 151T282 153Q302 153 302 143Q302 135 293 112T268 61T223 11T161 -11Q129 -11 102 10T74 74Q74 91 79 106T122 220Q160 321 166 341T173 380Q173 404 156 404H154Q124 404 99 371T61 287Q60 286 59 284T58 281T56 279T53 278T49 278T41 278H27Q21 284 21 287Z" style="stroke-width: 3;"/></g></g><g data-mml-node="mo" transform="translate(1508.2,0)"><path data-c="2212" d="M84 237T84 250T98 270H679Q694 262 694 250T679 230H98Q84 237 84 250Z" style="stroke-width: 3;"/></g><g data-mml-node="msub" transform="translate(2508.4,0)"><g data-mml-node="mi"><path data-c="1D43F" d="M228 637Q194 637 192 641Q191 643 191 649Q191 673 202 682Q204 683 217 683Q271 680 344 680Q485 680 506 683H518Q524 677 524 674T522 656Q517 641 513 637H475Q406 636 394 628Q387 624 380 600T313 336Q297 271 279 198T252 88L243 52Q243 48 252 48T311 46H328Q360 46 379 47T428 54T478 72T522 106T564 161Q580 191 594 228T611 270Q616 273 628 273H641Q647 264 647 262T627 203T583 83T557 9Q555 4 553 3T537 0T494 -1Q483 -1 418 -1T294 0H116Q32 0 32 10Q32 17 34 24Q39 43 44 45Q48 46 59 46H65Q92 46 125 49Q139 52 144 61Q147 65 216 339T285 628Q285 635 228 637Z" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(714,-150) scale(0.707)"><path data-c="1D457" d="M297 596Q297 627 318 644T361 661Q378 661 389 651T403 623Q403 595 384 576T340 557Q322 557 310 567T297 596ZM288 376Q288 405 262 405Q240 405 220 393T185 362T161 325T144 293L137 279Q135 278 121 278H107Q101 284 101 286T105 299Q126 348 164 391T252 441Q253 441 260 441T272 442Q296 441 316 432Q341 418 354 401T367 348V332L318 133Q267 -67 264 -75Q246 -125 194 -164T75 -204Q25 -204 7 -183T-12 -137Q-12 -110 7 -91T53 -71Q70 -71 82 -81T95 -112Q95 -148 63 -167Q69 -168 77 -168Q111 -168 139 -140T182 -74L193 -32Q204 11 219 72T251 197T278 308T289 365Q289 372 288 376Z" style="stroke-width: 3;"/></g></g><g data-mml-node="mo" transform="translate(3563.7,0) translate(0 -0.5)"><path data-c="7C" d="M139 -249H137Q125 -249 119 -235V251L120 737Q130 750 139 750Q152 750 159 735V-235Q151 -249 141 -249H139Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(4119.5,0)"><path data-c="2264" d="M674 636Q682 636 688 630T694 615T687 601Q686 600 417 472L151 346L399 228Q687 92 691 87Q694 81 694 76Q694 58 676 56H670L382 192Q92 329 90 331Q83 336 83 348Q84 359 96 365Q104 369 382 500T665 634Q669 636 674 636ZM84 -118Q84 -108 99 -98H678Q694 -104 694 -118Q694 -130 679 -138H98Q84 -131 84 -118Z" style="stroke-width: 3;"/></g><g data-mml-node="mn" transform="translate(5175.3,0)"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" style="stroke-width: 3;"/></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mo data-mjx-texclass="ORD" stretchy="false">|</mo><msub><mi>L</mi><mi>i</mi></msub><mo>−</mo><msub><mi>L</mi><mi>j</mi></msub><mo data-mjx-texclass="ORD" stretchy="false">|</mo><mo>≤</mo><mn>1</mn></math></mjx-assistive-mml></mjx-container>. La relación de resolución a través de una cara es <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: 0;" xmlns="http://www.w3.org/2000/svg" width="6.754ex" height="2.02ex" role="img" focusable="false" viewBox="0 -893 2985.2 893" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="msup"><g data-mml-node="mn"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"/></g><g data-mml-node="TeXAtom" transform="translate(533,363) scale(0.707)" data-mjx-texclass="ORD"><g data-mml-node="mo" transform="translate(0 -0.5)"><path data-c="7C" d="M139 -249H137Q125 -249 119 -235V251L120 737Q130 750 139 750Q152 750 159 735V-235Q151 -249 141 -249H139Z" style="stroke-width: 3;"/></g><g data-mml-node="msub" transform="translate(278,0)"><g data-mml-node="mi"><path data-c="1D43F" d="M228 637Q194 637 192 641Q191 643 191 649Q191 673 202 682Q204 683 217 683Q271 680 344 680Q485 680 506 683H518Q524 677 524 674T522 656Q517 641 513 637H475Q406 636 394 628Q387 624 380 600T313 336Q297 271 279 198T252 88L243 52Q243 48 252 48T311 46H328Q360 46 379 47T428 54T478 72T522 106T564 161Q580 191 594 228T611 270Q616 273 628 273H641Q647 264 647 262T627 203T583 83T557 9Q555 4 553 3T537 0T494 -1Q483 -1 418 -1T294 0H116Q32 0 32 10Q32 17 34 24Q39 43 44 45Q48 46 59 46H65Q92 46 125 49Q139 52 144 61Q147 65 216 339T285 628Q285 635 228 637Z" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(714,-150) scale(0.707)"><path data-c="1D456" d="M184 600Q184 624 203 642T247 661Q265 661 277 649T290 619Q290 596 270 577T226 557Q211 557 198 567T184 600ZM21 287Q21 295 30 318T54 369T98 420T158 442Q197 442 223 419T250 357Q250 340 236 301T196 196T154 83Q149 61 149 51Q149 26 166 26Q175 26 185 29T208 43T235 78T260 137Q263 149 265 151T282 153Q302 153 302 143Q302 135 293 112T268 61T223 11T161 -11Q129 -11 102 10T74 74Q74 91 79 106T122 220Q160 321 166 341T173 380Q173 404 156 404H154Q124 404 99 371T61 287Q60 286 59 284T58 281T56 279T53 278T49 278T41 278H27Q21 284 21 287Z" style="stroke-width: 3;"/></g></g><g data-mml-node="mo" transform="translate(1286,0)"><path data-c="2212" d="M84 237T84 250T98 270H679Q694 262 694 250T679 230H98Q84 237 84 250Z" style="stroke-width: 3;"/></g><g data-mml-node="msub" transform="translate(2064,0)"><g data-mml-node="mi"><path data-c="1D43F" d="M228 637Q194 637 192 641Q191 643 191 649Q191 673 202 682Q204 683 217 683Q271 680 344 680Q485 680 506 683H518Q524 677 524 674T522 656Q517 641 513 637H475Q406 636 394 628Q387 624 380 600T313 336Q297 271 279 198T252 88L243 52Q243 48 252 48T311 46H328Q360 46 379 47T428 54T478 72T522 106T564 161Q580 191 594 228T611 270Q616 273 628 273H641Q647 264 647 262T627 203T583 83T557 9Q555 4 553 3T537 0T494 -1Q483 -1 418 -1T294 0H116Q32 0 32 10Q32 17 34 24Q39 43 44 45Q48 46 59 46H65Q92 46 125 49Q139 52 144 61Q147 65 216 339T285 628Q285 635 228 637Z" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(714,-150) scale(0.707)"><path data-c="1D457" d="M297 596Q297 627 318 644T361 661Q378 661 389 651T403 623Q403 595 384 576T340 557Q322 557 310 567T297 596ZM288 376Q288 405 262 405Q240 405 220 393T185 362T161 325T144 293L137 279Q135 278 121 278H107Q101 284 101 286T105 299Q126 348 164 391T252 441Q253 441 260 441T272 442Q296 441 316 432Q341 418 354 401T367 348V332L318 133Q267 -67 264 -75Q246 -125 194 -164T75 -204Q25 -204 7 -183T-12 -137Q-12 -110 7 -91T53 -71Q70 -71 82 -81T95 -112Q95 -148 63 -167Q69 -168 77 -168Q111 -168 139 -140T182 -74L193 -32Q204 11 219 72T251 197T278 308T289 365Q289 372 288 376Z" style="stroke-width: 3;"/></g></g><g data-mml-node="mo" transform="translate(3119.3,0) translate(0 -0.5)"><path data-c="7C" d="M139 -249H137Q125 -249 119 -235V251L120 737Q130 750 139 750Q152 750 159 735V-235Q151 -249 141 -249H139Z" style="stroke-width: 3;"/></g></g></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><msup><mn>2</mn><mrow data-mjx-texclass="ORD"><mo data-mjx-texclass="ORD" stretchy="false">|</mo><msub><mi>L</mi><mi>i</mi></msub><mo>−</mo><msub><mi>L</mi><mi>j</mi></msub><mo data-mjx-texclass="ORD" stretchy="false">|</mo></mrow></msup></math></mjx-assistive-mml></mjx-container>, y las tablas de transición de Transvoxel solo están definidas para el caso 2:1 (<mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.666ex;" xmlns="http://www.w3.org/2000/svg" width="12.84ex" height="2.361ex" role="img" focusable="false" viewBox="0 -749.5 5675.3 1043.7" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mo" transform="translate(0 -0.5)"><path data-c="7C" d="M139 -249H137Q125 -249 119 -235V251L120 737Q130 750 139 750Q152 750 159 735V-235Q151 -249 141 -249H139Z" style="stroke-width: 3;"/></g><g data-mml-node="msub" transform="translate(278,0)"><g data-mml-node="mi"><path data-c="1D43F" d="M228 637Q194 637 192 641Q191 643 191 649Q191 673 202 682Q204 683 217 683Q271 680 344 680Q485 680 506 683H518Q524 677 524 674T522 656Q517 641 513 637H475Q406 636 394 628Q387 624 380 600T313 336Q297 271 279 198T252 88L243 52Q243 48 252 48T311 46H328Q360 46 379 47T428 54T478 72T522 106T564 161Q580 191 594 228T611 270Q616 273 628 273H641Q647 264 647 262T627 203T583 83T557 9Q555 4 553 3T537 0T494 -1Q483 -1 418 -1T294 0H116Q32 0 32 10Q32 17 34 24Q39 43 44 45Q48 46 59 46H65Q92 46 125 49Q139 52 144 61Q147 65 216 339T285 628Q285 635 228 637Z" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(714,-150) scale(0.707)"><path data-c="1D456" d="M184 600Q184 624 203 642T247 661Q265 661 277 649T290 619Q290 596 270 577T226 557Q211 557 198 567T184 600ZM21 287Q21 295 30 318T54 369T98 420T158 442Q197 442 223 419T250 357Q250 340 236 301T196 196T154 83Q149 61 149 51Q149 26 166 26Q175 26 185 29T208 43T235 78T260 137Q263 149 265 151T282 153Q302 153 302 143Q302 135 293 112T268 61T223 11T161 -11Q129 -11 102 10T74 74Q74 91 79 106T122 220Q160 321 166 341T173 380Q173 404 156 404H154Q124 404 99 371T61 287Q60 286 59 284T58 281T56 279T53 278T49 278T41 278H27Q21 284 21 287Z" style="stroke-width: 3;"/></g></g><g data-mml-node="mo" transform="translate(1508.2,0)"><path data-c="2212" d="M84 237T84 250T98 270H679Q694 262 694 250T679 230H98Q84 237 84 250Z" style="stroke-width: 3;"/></g><g data-mml-node="msub" transform="translate(2508.4,0)"><g data-mml-node="mi"><path data-c="1D43F" d="M228 637Q194 637 192 641Q191 643 191 649Q191 673 202 682Q204 683 217 683Q271 680 344 680Q485 680 506 683H518Q524 677 524 674T522 656Q517 641 513 637H475Q406 636 394 628Q387 624 380 600T313 336Q297 271 279 198T252 88L243 52Q243 48 252 48T311 46H328Q360 46 379 47T428 54T478 72T522 106T564 161Q580 191 594 228T611 270Q616 273 628 273H641Q647 264 647 262T627 203T583 83T557 9Q555 4 553 3T537 0T494 -1Q483 -1 418 -1T294 0H116Q32 0 32 10Q32 17 34 24Q39 43 44 45Q48 46 59 46H65Q92 46 125 49Q139 52 144 61Q147 65 216 339T285 628Q285 635 228 637Z" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(714,-150) scale(0.707)"><path data-c="1D457" d="M297 596Q297 627 318 644T361 661Q378 661 389 651T403 623Q403 595 384 576T340 557Q322 557 310 567T297 596ZM288 376Q288 405 262 405Q240 405 220 393T185 362T161 325T144 293L137 279Q135 278 121 278H107Q101 284 101 286T105 299Q126 348 164 391T252 441Q253 441 260 441T272 442Q296 441 316 432Q341 418 354 401T367 348V332L318 133Q267 -67 264 -75Q246 -125 194 -164T75 -204Q25 -204 7 -183T-12 -137Q-12 -110 7 -91T53 -71Q70 -71 82 -81T95 -112Q95 -148 63 -167Q69 -168 77 -168Q111 -168 139 -140T182 -74L193 -32Q204 11 219 72T251 197T278 308T289 365Q289 372 288 376Z" style="stroke-width: 3;"/></g></g><g data-mml-node="mo" transform="translate(3563.7,0) translate(0 -0.5)"><path data-c="7C" d="M139 -249H137Q125 -249 119 -235V251L120 737Q130 750 139 750Q152 750 159 735V-235Q151 -249 141 -249H139Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(4119.5,0)"><path data-c="3D" d="M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z" style="stroke-width: 3;"/></g><g data-mml-node="mn" transform="translate(5175.3,0)"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" style="stroke-width: 3;"/></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mo data-mjx-texclass="ORD" stretchy="false">|</mo><msub><mi>L</mi><mi>i</mi></msub><mo>−</mo><msub><mi>L</mi><mi>j</mi></msub><mo data-mjx-texclass="ORD" stretchy="false">|</mo><mo>=</mo><mn>1</mn></math></mjx-assistive-mml></mjx-container>). Un salto de 2 niveles requeriría una transición 4:1 que las tablas no pueden representar, por lo que la política obliga al chunk con menor nivel de detalle a aumentar su resolución hasta que se cumpla la restricción.</p>
<p>La lógica de cambio entre HM y MC comprobaba el mapa de bits de ediciones de cada chunk. Si un chunk tenía alguna edición volumétrica —cuevas, túneles o esculpidos del terreno—, permanecía en modo MC independientemente de la distancia. Los chunks sin editar podían pasar al modo de mapa de alturas cuando se alejaban lo suficiente. Este enfoque híbrido nos proporcionaba libertad volumétrica donde importaba y eficiencia donde no.</p>
<p>Desde fuera, este spike parecía más pequeño que algunos de los anteriores. En la práctica, supuso una mejora importante en la calidad de vida durante el desarrollo.</p>
<p>Cuando el sistema puede explicar por qué un chunk ha cambiado de modo, se pierde menos tiempo haciendo conjeturas. Añadimos superposiciones codificadas por colores: verde para los chunks de mapa de alturas, azul para los chunks MC y naranja para las caras con transiciones activas. Cuando la visibilidad de las uniones dispone de controles de renderizado específicos, disminuye la ambigüedad de la depuración visual. Cuando los rangos de dibujo están vinculados explícitamente a los recuentos de vértices activos del sistema de políticas, los fantasmas de geometría obsoleta dejan de hacerte perder toda la tarde.</p>
<p>También rediseñamos el comportamiento de la cámara en este spike. Los spikes anteriores tenían controles de órbita sencillos, adecuados para capturas de pantalla pero inútiles para reproducir errores. El Spike 23 añadió una cámara de vuelo con WASD, velocidad configurable, opción para bloquear la altitud y lectura de la posición. Parece algo menor. Pero marcaba la diferencia entre «vi un error en algún lugar cerca de esa cresta» y «el error aparece en la posición (142, 12, -67), mirando hacia el noroeste».</p>
<p>La idea clave de este capítulo es que las políticas no redujeron la complejidad, sino que la organizaron. Seguía existiendo el mismo número de casos límite. Pero ahora cada caso límite tenía un nombre, una condición de activación y un lugar en el código donde se podía establecer un punto de interrupción. Es otro tipo de victoria, y es lo que determina si un sistema puede seguir evolucionando o si se derrumba bajo su propio peso.</p>
<p>Al terminar el Spike 23, teníamos una capa de comportamiento para el campo cercano lo bastante predecible como para conectarla a una estrategia de anillos de clipmap para el campo lejano sin temer constantemente errores derivados de su interacción.</p>
<p>En la parte 12 abordamos el Spike 24, donde las transiciones entre anillos, la niebla del skybox y la integración de shaders específica de cada versión de Three.js cierran este capítulo del proyecto.</p>
<h2 id="tecnologias-mencionadas-en-este-capitulo" tabindex="-1">Tecnologías mencionadas en este capítulo <a class="header-anchor" href="#tecnologias-mencionadas-en-este-capitulo" aria-label="Permalink to &quot;Tecnologías mencionadas en este capítulo&quot;"></a></h2>
<p><strong>Política de LOD basada en la distancia.</strong> Una función central que asigna a cada chunk un nivel de LOD y un modo de renderizado según su distancia a la cámara, el historial de ediciones y los estados de sus vecinos. Los anillos concéntricos de distancia determinan el LOD base: anillo 0 = MC a resolución completa, anillo 1 = MC a media resolución, anillo 2 o superior = modo de mapa de alturas. La función de políticas se ejecuta en cada fotograma a medida que se mueve la cámara y activa las transiciones de los chunks. Esto sustituye las decisiones improvisadas de cada chunk por un sistema de reglas predecible y fácil de depurar. Consulta la <a href="/es/guides/landscape-generation-browser.html#gpu-driven-lod-with-webgpu">selección de LOD controlada por la GPU</a> para ver el equivalente con shaders de cómputo.</p>
<p><strong>Restricciones de adyacencia.</strong> El algoritmo Transvoxel solo admite relaciones de resolución 2:1. Si dos chunks vecinos difieren en más de un nivel de LOD —por ejemplo, LOD 0 junto a LOD 2—, las tablas de transición no pueden producir una geometría de unión válida. El sistema de políticas lo impide aumentando la resolución del chunk con menor nivel de detalle cuando la diferencia de LOD supera 1. Esta propagación de restricciones puede producirse en cascada: aumentar la resolución de un chunk puede obligar a hacer lo mismo con sus vecinos. La implementación consiste en una sencilla pasada iterativa que converge en 2 o 3 iteraciones para las configuraciones de cuadrícula habituales.</p>
<p><strong>Mapa de bits de ediciones para seleccionar el modo.</strong> Cada chunk mantiene un mapa de bits que registra si contiene ediciones SDF volumétricas —cuevas, túneles o esculpidos—. Los chunks con alguna edición permanecen en modo marching cubes independientemente de la distancia, lo que conserva las modificaciones del creador. Los chunks sin editar pasan al modo de mapa de alturas cuando están lo bastante lejos de la cámara, lo que ahorra recursos de cómputo y memoria. El mapa de bits es un único indicador por chunk, pero puede ampliarse para registrar la densidad de las ediciones y tomar decisiones de modo más detalladas.</p>
<p><strong>Superposiciones de visualización para depuración.</strong> Renderizado de chunks codificado por colores, donde verde = modo de mapa de alturas, azul = modo MC y naranja = caras con transiciones activas. Superposiciones por chunk con números de nivel de LOD, etiquetas de modo y controles para activar la visualización de la malla alámbrica. Son herramientas de desarrollo, no funcionalidades incluidas en el producto final, pero compensan su coste una y otra vez al depurar transiciones de LOD y artefactos en las uniones. Combinadas con una cámara de vuelo controlada mediante WASD que muestra la posición exacta en el mundo, convierten «vi un error en algún sitio» en «el error aparece en (142, 12, -67) con esta configuración de LOD».</p>
<hr>
<p>Parte 11 de 12.<br>
Anterior: <a href="/es/blog/2026-02-25-open-world-browser-part-10-seam-chaos.html">Parte 10 - El caos de las uniones y el jefe final de las esquinas</a><br>
Siguiente: <a href="/es/blog/2026-02-25-open-world-browser-part-12-lessons.html">Parte 12 - Anillos, niebla del cielo y lo que volveríamos a hacer</a><br>
Guía de la serie: <a href="/es/blog/2026-02-25-open-world-browser-series-guide.html">/es/blog/2026-02-25-open-world-browser-series-guide</a></p>
]]></content:encoded>
            <enclosure url="https://cdn.cinevva.com/blog/why-webgpu-engine-hero.jpg" length="0" type="image/jpg"/>
        </item>
        <item>
            <title><![CDATA[Cómo crear un mundo abierto en el navegador, parte 12: Anillos, niebla del cielo y qué volveríamos a hacer]]></title>
            <link>https://app.cinevva.com/es/blog/2026-02-25-open-world-browser-part-12-lessons</link>
            <guid>https://app.cinevva.com/es/blog/2026-02-25-open-world-browser-part-12-lessons</guid>
            <pubDate>Wed, 25 Feb 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[El prototipo 24 cerró este capítulo con transiciones entre anillos de clipmap, integración de la niebla con el skybox y una larga lista de lecciones aprendidas por las malas.]]></description>
            <content:encoded><![CDATA[<h1 id="como-crear-un-mundo-abierto-en-el-navegador-parte-12-anillos-niebla-del-cielo-y-que-volveriamos-a-hacer" tabindex="-1">Cómo crear un mundo abierto en el navegador, parte 12: Anillos, niebla del cielo y qué volveríamos a hacer <a class="header-anchor" href="#como-crear-un-mundo-abierto-en-el-navegador-parte-12-anillos-niebla-del-cielo-y-que-volveriamos-a-hacer" aria-label="Permalink to &quot;Cómo crear un mundo abierto en el navegador, parte 12: Anillos, niebla del cielo y qué volveríamos a hacer&quot;"></a></h1>
<p><em>Por <a href="/es/about.html">Oleg Sidorkin</a>, CTO y cofundador de Cinevva</em></p>
<p>¿Acabas de llegar? Consulta la <a href="/es/blog/2026-02-25-open-world-browser-series-guide.html">guía de la serie</a>. Explica qué es un prototipo y enlaza todas las partes.</p>
<p>Se suponía que el prototipo 24 consistiría en «añadir anillos de clipmap al terreno». Acabó convirtiéndose en un gran final que abordó a la vez el renderizado, los shaders, la infraestructura de módulos y la integración visual.</p>
<p>La tarea principal del terreno era generar anillos concéntricos de clipmap en el shader de vértices. Cada anillo es una malla de cuadrícula plana centrada en la cámara, cuyos vértices se desplazan según las muestras del mapa de alturas. El anillo interior utiliza la resolución completa. Cada anillo posterior duplica el espaciado entre vértices y cubre un área mayor. La parte complicada es el límite entre anillos: cuando un anillo de alta resolución se encuentra con otro de baja resolución, los vértices del borde de la malla más detallada deben ajustarse al punto medio del borde de la malla más gruesa. Implementamos un morphing de bordes 2:1 detectando los vértices del límite —aquellos cuya coordenada de cuadrícula es impar a lo largo del borde del anillo— y ajustando su altura al punto medio de sus dos vecinos pares, <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.781ex;" xmlns="http://www.w3.org/2000/svg" width="19.274ex" height="2.737ex" role="img" focusable="false" viewBox="0 -864.9 8519.1 1209.9" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mi"><path data-c="210E" d="M137 683Q138 683 209 688T282 694Q294 694 294 685Q294 674 258 534Q220 386 220 383Q220 381 227 388Q288 442 357 442Q411 442 444 415T478 336Q478 285 440 178T402 50Q403 36 407 31T422 26Q450 26 474 56T513 138Q516 149 519 151T535 153Q555 153 555 145Q555 144 551 130Q535 71 500 33Q466 -10 419 -10H414Q367 -10 346 17T325 74Q325 90 361 192T398 345Q398 404 354 404H349Q266 404 205 306L198 293L164 158Q132 28 127 16Q114 -11 83 -11Q69 -11 59 -2T48 16Q48 30 121 320L195 616Q195 629 188 632T149 637H128Q122 643 122 645T124 664Q129 683 137 683Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(853.8,0)"><path data-c="3D" d="M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z" style="stroke-width: 3;"/></g><g data-mml-node="mstyle" transform="translate(1909.6,0)"><g data-mml-node="mfrac"><g data-mml-node="mn" transform="translate(220,394) scale(0.707)"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" style="stroke-width: 3;"/></g><g data-mml-node="mn" transform="translate(220,-345) scale(0.707)"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"/></g><rect width="553.6" height="60" x="120" y="220"/></g></g><g data-mml-node="mo" transform="translate(2703.1,0)"><path data-c="28" d="M94 250Q94 319 104 381T127 488T164 576T202 643T244 695T277 729T302 750H315H319Q333 750 333 741Q333 738 316 720T275 667T226 581T184 443T167 250T184 58T225 -81T274 -167T316 -220T333 -241Q333 -250 318 -250H315H302L274 -226Q180 -141 137 -14T94 250Z" style="stroke-width: 3;"/></g><g data-mml-node="msub" transform="translate(3092.1,0)"><g data-mml-node="mi"><path data-c="210E" d="M137 683Q138 683 209 688T282 694Q294 694 294 685Q294 674 258 534Q220 386 220 383Q220 381 227 388Q288 442 357 442Q411 442 444 415T478 336Q478 285 440 178T402 50Q403 36 407 31T422 26Q450 26 474 56T513 138Q516 149 519 151T535 153Q555 153 555 145Q555 144 551 130Q535 71 500 33Q466 -10 419 -10H414Q367 -10 346 17T325 74Q325 90 361 192T398 345Q398 404 354 404H349Q266 404 205 306L198 293L164 158Q132 28 127 16Q114 -11 83 -11Q69 -11 59 -2T48 16Q48 30 121 320L195 616Q195 629 188 632T149 637H128Q122 643 122 645T124 664Q129 683 137 683Z" style="stroke-width: 3;"/></g><g data-mml-node="mtext" transform="translate(609,-150) scale(0.707)"><path data-c="6C" d="M42 46H56Q95 46 103 60V68Q103 77 103 91T103 124T104 167T104 217T104 272T104 329Q104 366 104 407T104 482T104 542T103 586T103 603Q100 622 89 628T44 637H26V660Q26 683 28 683L38 684Q48 685 67 686T104 688Q121 689 141 690T171 693T182 694H185V379Q185 62 186 60Q190 52 198 49Q219 46 247 46H263V0H255L232 1Q209 2 183 2T145 3T107 3T57 1L34 0H26V46H42Z" style="stroke-width: 3;"/><path data-c="65" d="M28 218Q28 273 48 318T98 391T163 433T229 448Q282 448 320 430T378 380T406 316T415 245Q415 238 408 231H126V216Q126 68 226 36Q246 30 270 30Q312 30 342 62Q359 79 369 104L379 128Q382 131 395 131H398Q415 131 415 121Q415 117 412 108Q393 53 349 21T250 -11Q155 -11 92 58T28 218ZM333 275Q322 403 238 411H236Q228 411 220 410T195 402T166 381T143 340T127 274V267H333V275Z" transform="translate(278,0)" style="stroke-width: 3;"/><path data-c="66" d="M273 0Q255 3 146 3Q43 3 34 0H26V46H42Q70 46 91 49Q99 52 103 60Q104 62 104 224V385H33V431H104V497L105 564L107 574Q126 639 171 668T266 704Q267 704 275 704T289 705Q330 702 351 679T372 627Q372 604 358 590T321 576T284 590T270 627Q270 647 288 667H284Q280 668 273 668Q245 668 223 647T189 592Q183 572 182 497V431H293V385H185V225Q185 63 186 61T189 57T194 54T199 51T206 49T213 48T222 47T231 47T241 46T251 46H282V0H273Z" transform="translate(722,0)" style="stroke-width: 3;"/><path data-c="74" d="M27 422Q80 426 109 478T141 600V615H181V431H316V385H181V241Q182 116 182 100T189 68Q203 29 238 29Q282 29 292 100Q293 108 293 146V181H333V146V134Q333 57 291 17Q264 -10 221 -10Q187 -10 162 2T124 33T105 68T98 100Q97 107 97 248V385H18V422H27Z" transform="translate(1028,0)" style="stroke-width: 3;"/></g></g><g data-mml-node="mo" transform="translate(4975.3,0)"><path data-c="2B" d="M56 237T56 250T70 270H369V420L370 570Q380 583 389 583Q402 583 409 568V270H707Q722 262 722 250T707 230H409V-68Q401 -82 391 -82H389H387Q375 -82 369 -68V230H70Q56 237 56 250Z" style="stroke-width: 3;"/></g><g data-mml-node="msub" transform="translate(5975.5,0)"><g data-mml-node="mi"><path data-c="210E" d="M137 683Q138 683 209 688T282 694Q294 694 294 685Q294 674 258 534Q220 386 220 383Q220 381 227 388Q288 442 357 442Q411 442 444 415T478 336Q478 285 440 178T402 50Q403 36 407 31T422 26Q450 26 474 56T513 138Q516 149 519 151T535 153Q555 153 555 145Q555 144 551 130Q535 71 500 33Q466 -10 419 -10H414Q367 -10 346 17T325 74Q325 90 361 192T398 345Q398 404 354 404H349Q266 404 205 306L198 293L164 158Q132 28 127 16Q114 -11 83 -11Q69 -11 59 -2T48 16Q48 30 121 320L195 616Q195 629 188 632T149 637H128Q122 643 122 645T124 664Q129 683 137 683Z" style="stroke-width: 3;"/></g><g data-mml-node="mtext" transform="translate(609,-150) scale(0.707)"><path data-c="72" d="M36 46H50Q89 46 97 60V68Q97 77 97 91T98 122T98 161T98 203Q98 234 98 269T98 328L97 351Q94 370 83 376T38 385H20V408Q20 431 22 431L32 432Q42 433 60 434T96 436Q112 437 131 438T160 441T171 442H174V373Q213 441 271 441H277Q322 441 343 419T364 373Q364 352 351 337T313 322Q288 322 276 338T263 372Q263 381 265 388T270 400T273 405Q271 407 250 401Q234 393 226 386Q179 341 179 207V154Q179 141 179 127T179 101T180 81T180 66V61Q181 59 183 57T188 54T193 51T200 49T207 48T216 47T225 47T235 46T245 46H276V0H267Q249 3 140 3Q37 3 28 0H20V46H36Z" style="stroke-width: 3;"/><path data-c="69" d="M69 609Q69 637 87 653T131 669Q154 667 171 652T188 609Q188 579 171 564T129 549Q104 549 87 564T69 609ZM247 0Q232 3 143 3Q132 3 106 3T56 1L34 0H26V46H42Q70 46 91 49Q100 53 102 60T104 102V205V293Q104 345 102 359T88 378Q74 385 41 385H30V408Q30 431 32 431L42 432Q52 433 70 434T106 436Q123 437 142 438T171 441T182 442H185V62Q190 52 197 50T232 46H255V0H247Z" transform="translate(392,0)" style="stroke-width: 3;"/><path data-c="67" d="M329 409Q373 453 429 453Q459 453 472 434T485 396Q485 382 476 371T449 360Q416 360 412 390Q410 404 415 411Q415 412 416 414V415Q388 412 363 393Q355 388 355 386Q355 385 359 381T368 369T379 351T388 325T392 292Q392 230 343 187T222 143Q172 143 123 171Q112 153 112 133Q112 98 138 81Q147 75 155 75T227 73Q311 72 335 67Q396 58 431 26Q470 -13 470 -72Q470 -139 392 -175Q332 -206 250 -206Q167 -206 107 -175Q29 -140 29 -75Q29 -39 50 -15T92 18L103 24Q67 55 67 108Q67 155 96 193Q52 237 52 292Q52 355 102 398T223 442Q274 442 318 416L329 409ZM299 343Q294 371 273 387T221 404Q192 404 171 388T145 343Q142 326 142 292Q142 248 149 227T179 192Q196 182 222 182Q244 182 260 189T283 207T294 227T299 242Q302 258 302 292T299 343ZM403 -75Q403 -50 389 -34T348 -11T299 -2T245 0H218Q151 0 138 -6Q118 -15 107 -34T95 -74Q95 -84 101 -97T122 -127T170 -155T250 -167Q319 -167 361 -139T403 -75Z" transform="translate(670,0)" style="stroke-width: 3;"/><path data-c="68" d="M41 46H55Q94 46 102 60V68Q102 77 102 91T102 124T102 167T103 217T103 272T103 329Q103 366 103 407T103 482T102 542T102 586T102 603Q99 622 88 628T43 637H25V660Q25 683 27 683L37 684Q47 685 66 686T103 688Q120 689 140 690T170 693T181 694H184V367Q244 442 328 442Q451 442 463 329Q464 322 464 190V104Q464 66 466 59T477 49Q498 46 526 46H542V0H534L510 1Q487 2 460 2T422 3Q319 3 310 0H302V46H318Q379 46 379 62Q380 64 380 200Q379 335 378 343Q372 371 358 385T334 402T308 404Q263 404 229 370Q202 343 195 315T187 232V168V108Q187 78 188 68T191 55T200 49Q221 46 249 46H265V0H257L234 1Q210 2 183 2T145 3Q42 3 33 0H25V46H41Z" transform="translate(1170,0)" style="stroke-width: 3;"/><path data-c="74" d="M27 422Q80 426 109 478T141 600V615H181V431H316V385H181V241Q182 116 182 100T189 68Q203 29 238 29Q282 29 292 100Q293 108 293 146V181H333V146V134Q333 57 291 17Q264 -10 221 -10Q187 -10 162 2T124 33T105 68T98 100Q97 107 97 248V385H18V422H27Z" transform="translate(1726,0)" style="stroke-width: 3;"/></g></g><g data-mml-node="mo" transform="translate(8130.1,0)"><path data-c="29" d="M60 749L64 750Q69 750 74 750H86L114 726Q208 641 251 514T294 250Q294 182 284 119T261 12T224 -76T186 -143T145 -194T113 -227T90 -246Q87 -249 86 -250H74Q66 -250 63 -250T58 -247T55 -238Q56 -237 66 -225Q221 -64 221 250T66 725Q56 737 55 738Q55 746 60 749Z" style="stroke-width: 3;"/></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mi>h</mi><mo>=</mo><mstyle displaystyle="false" scriptlevel="0"><mfrac><mn>1</mn><mn>2</mn></mfrac></mstyle><mo stretchy="false">(</mo><msub><mi>h</mi><mtext>left</mtext></msub><mo>+</mo><msub><mi>h</mi><mtext>right</mtext></msub><mo stretchy="false">)</mo></math></mjx-assistive-mml></mjx-container>. Ese es exactamente el punto en el que se situaría el único borde del anillo grueso, de modo que los bordes fino y grueso describen la misma línea. Esto produce uniones estancas sin geometría de transición.</p>
<div style="position:relative;padding-bottom:56.25%;height:0;overflow:hidden;border-radius:8px;margin:1.5rem 0;border:1px solid rgba(255,255,255,0.12)">
<iframe src="/es/spikes/24-gpu-clipmap-rings/" title="Prototipo 24: anillos de clipmap y niebla del cielo" style="position:absolute;top:0;left:0;width:100%;height:100%;border:0;background:#000" loading="lazy" allowfullscreen></iframe>
</div>
<p><a href="/es/spikes/24-gpu-clipmap-rings/" target="_blank">Abrir el prototipo 24 en una pestaña nueva ↗</a> · <a href="/es/blog/spike-source?spike=24-gpu-clipmap-rings">Ver el código fuente</a></p>
<p>Después llegó la integración de la niebla y el cielo. Queríamos que el terreno lejano se fundiera con el color real del cielo, no con una constante plana. Eso implicaba que el shader de niebla debía saber qué color tendría el cielo en la dirección de cada fragmento. Cargamos una textura HDR equirectangular para el skybox y la muestreamos en el shader de fragmentos mediante la dirección de visión desde la cámara hasta el fragmento, convertida a coordenadas UV equirectangulares a través del nodo <code>equirectUV</code> de TSL. El factor de niebla se basaba en la distancia y utilizaba <code>positionView.z.negate()</code> para obtener la profundidad en el espacio de la cámara, interpolada con <code>smoothstep</code> entre una distancia cercana y otra lejana.</p>
<p>El cableado de los módulos resultó ser más molesto que cualquier aspecto de la geometría. Actualizamos a Three.js 0.183.1, que había reorganizado las salidas de compilación. La importación <code>three/tsl</code> debía resolverse como <code>three.tsl.js</code>, y TSL importaba internamente <code>three/webgpu</code> como un especificador simple. Ambas correspondencias debían indicarse de forma explícita en el mapa de importaciones del HTML. Si faltaba cualquiera de ellas, aparecían errores crípticos como «does not provide an export» o «failed to resolve module specifier», sin ninguna indicación sobre qué correspondencia era incorrecta. Una vez añadidas las dos al mapa de importaciones, el grafo de shaders se cargó correctamente.</p>
<p>También tuvimos un problema de orientación del skybox: la textura se renderizaba al revés. La solución fue establecer <code>flipY = true</code> en la textura equirectangular, que es el valor predeterminado de Three.js para las texturas cargadas, pero que en nuestro código inicial estaba establecido como <code>false</code>.</p>
<p>La implementación original de la niebla muestreaba el cielo en una dirección casi constante, lo que producía una fina franja del color del horizonte en lugar de un gradiente natural. La solución fue calcular por píxel la dirección real en el espacio del mundo desde la cámara hasta el fragmento mediante <code>positionWorld.sub(cameraPosition).normalize()</code> y pasarla a <code>equirectUV</code> para consultar el color de la niebla. Así, los fragmentos del terreno se funden con el color del cielo que realmente tienen detrás, lo que se ve correctamente desde cualquier ángulo de cámara.</p>
<p>Por debajo de todas las correcciones individuales, el resultado principal se mantuvo. Ahora tenemos un sistema de terreno que combina edición volumétrica en el campo cercano —marching cubes con uniones Transvoxel—, fragmentos de mapas de alturas en el campo medio y anillos de clipmap en el campo lejano, todo ello gobernado por una capa de políticas que decide el modo, el LOD y el comportamiento de las transiciones.</p>
<p>Si tuviera que nombrar los patrones que repetiría en el próximo proyecto, serían estos:</p>
<p>Empezar con prototipos de riesgo antes de trabajar en funcionalidades. El prototipo 1 resolvió la pregunta «¿podemos renderizar siquiera con suficiente rapidez?» antes de que invirtiéramos en flujos de contenido.</p>
<p>Congelar líneas base que sepamos que funcionan antes de dar grandes saltos de integración. Los prototipos 13 y 14 nos ahorraron días de búsqueda por bisección de regresiones.</p>
<p>Imponer políticas y observabilidad antes de embarcarse en maratones de optimización. El prototipo 23 convirtió errores misteriosos en condiciones con nombre y reglas de activación.</p>
<p>Probar en movimiento, no mediante capturas de pantalla. Los saltos de los clipmaps, el parpadeo de las uniones y los tirones del streaming se ocultan en los fotogramas estáticos.</p>
<p>Medir el coste en tiempo de fotograma de cada funcionalidad, no los FPS medios. Los promedios ocultan los picos que los usuarios perciben de verdad.</p>
<p>Y publicar las partes caóticas. Los caminos equivocados, la búsqueda de fantasmas en búferes obsoletos, los dos días culpando a la lógica de transición cuando el rango de dibujo era incorrecto. Esas son las partes de las que la gente realmente puede aprender.</p>
<h2 id="comprobacion-con-la-realidad-externa-los-diarios-de-desarrollo-de-vuntra-city" tabindex="-1">Comprobación con la realidad externa: los diarios de desarrollo de Vuntra City <a class="header-anchor" href="#comprobacion-con-la-realidad-externa-los-diarios-de-desarrollo-de-vuntra-city" aria-label="Permalink to &quot;Comprobación con la realidad externa: los diarios de desarrollo de Vuntra City&quot;"></a></h2>
<p>Después de terminar esta serie, revisamos los diarios de desarrollo de <code>@VuntraCity</code> como comprobación de una implementación externa frente a nuestras propias suposiciones sobre los mundos abiertos. Es un proyecto nativo de UE5, no una plataforma para navegador, pero los patrones de sus sistemas se corresponden lo bastante bien como para que la comparación resulte útil.</p>
<p>La primera señal es que la velocidad de desplazamiento debe tratarse como un control del streaming, no solo como una cuestión de jugabilidad. En Vuntra City, el transporte de alta velocidad se encauza de forma intencionada por encima de la mayoría de los interiores, y el alcance del detalle se adapta a la velocidad de movimiento para evitar la creación y destrucción constante de elementos y los bloqueos (<a href="https://www.youtube.com/watch?v=KKeBElJS6-M" target="_blank" rel="noreferrer">sistema de transporte</a>, <a href="https://www.youtube.com/watch?v=aPuYXyJet38" target="_blank" rel="noreferrer">técnicas de rendimiento</a>). Esto coincide con la dirección de nuestra capa de políticas: el modo de movimiento debe influir directamente en el radio de los fragmentos, la activación de interiores y el trabajo permitido por fotograma.</p>
<p>La segunda señal es la arquitectura. Sus mapas y su sistema de direcciones exigieron separar la topología del mundo de los objetos renderizados para poder ejecutar consultas globales sobre regiones no cargadas (<a href="https://www.youtube.com/watch?v=6dLn1GQpu2c" target="_blank" rel="noreferrer">mapas y direcciones</a>). Es la misma separación que necesitamos en el navegador para la búsqueda en el mundo, el trazado de rutas de misiones, los análisis de moderación y la indexación de puntos de interés sin obligarnos a usar rutas de datos ligadas al renderizado.</p>
<p>La tercera señal es la división de la simulación por niveles. Su diseño para un millón de PNJ mantiene barato y global el estado aproximado de sus horarios, y solo destina el costoso presupuesto de comportamiento a los PNJ cercanos al jugador (<a href="https://www.youtube.com/watch?v=nBV0yAAJUf0" target="_blank" rel="noreferrer">resumen del millón de PNJ</a>, <a href="https://www.youtube.com/watch?v=eUi7DB1ar3s" target="_blank" rel="noreferrer">análisis detallado del sistema</a>). Esto refuerza nuestro propio modelo de simulación centrado en el área de interés, donde la fidelidad en el campo cercano y el determinismo en el campo lejano son aspectos independientes con presupuestos distintos.</p>
<p>Y la cuarta señal es la calidad del diseño, no la escala bruta. Sus mejores momentos de exploración surgen de distribuciones ponderadas, valores atípicos poco frecuentes y pistas diegéticas de navegación, en lugar de superposiciones constantes de la interfaz (<a href="https://www.youtube.com/watch?v=4MZ5-KQW3pc" target="_blank" rel="noreferrer">notas sobre entornos procedurales</a>, <a href="https://www.youtube.com/watch?v=ixR1hqZJlv4" target="_blank" rel="noreferrer">bucle sin minimapa</a>). Para nosotros, esto recuerda que los sistemas técnicos deben ajustarse para producir variaciones que inviten al descubrimiento, no solo para maximizar el rendimiento.</p>
<h2 id="tecnologias-mencionadas-en-este-capitulo" tabindex="-1">Tecnologías mencionadas en este capítulo <a class="header-anchor" href="#tecnologias-mencionadas-en-este-capitulo" aria-label="Permalink to &quot;Tecnologías mencionadas en este capítulo&quot;"></a></h2>
<p><strong>Geometría de anillos de clipmap.</strong> Cada anillo es una malla de cuadrícula plana centrada en la cámara, cuyos vértices se desplazan según las muestras del mapa de alturas. El anillo interior utiliza la resolución completa. Cada anillo posterior duplica el espaciado entre vértices y cubre un área mayor. La parte complicada es el límite: cuando un anillo de alta resolución se encuentra con otro de baja resolución, los vértices del borde de la malla más detallada se ajustan al punto medio del borde de la malla más gruesa. La técnica tiene su origen en el artículo de Losasso y Hoppe para SIGGRAPH 2004 (<a href="https://hhoppe.com/geomclipmap.pdf" target="_blank" rel="noreferrer">PDF</a>) y se explica con detalle en <a href="https://developer.nvidia.com/gpugems/gpugems2/part-i-geometric-complexity/chapter-2-terrain-rendering-using-gpu-based-geometry" target="_blank" rel="noreferrer">GPU Gems 2, capítulo 2</a>. Consulta nuestra <a href="/es/guides/landscape-generation-browser.html#geometry-clipmaps">guía de paisajes sobre clipmaps geométricos</a>.</p>
<p><strong>Morphing de bordes 2:1.</strong> En el límite entre dos anillos de clipmap, el anillo más detallado tiene vértices en posiciones que el anillo más grueso no comparte. Se detectan los vértices del límite cuya coordenada de cuadrícula es impar a lo largo del borde del anillo y se interpola su altura entre los dos vértices pares vecinos. Esto produce uniones estancas sin necesidad de geometría de transición específica. La interpolación se ejecuta en el shader de vértices: <code>morphedHeight = mix(heightLeft, heightRight, 0.5)</code> para los vértices del límite, utilizando el mismo sistema de geomorphing descrito en <a href="/es/guides/landscape-generation-browser.html#geomorphing-pop-free-lod-transitions">nuestra guía</a>.</p>
<p><strong>Mapeo equirectangular del skybox.</strong> Una única imagen 2D que representa la esfera completa de direcciones del cielo mediante una proyección de longitud y latitud. El eje horizontal abarca de 0 a 360 grados y el vertical, de 0 a 180 grados. Una dirección de visión normalizada <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.667ex;" xmlns="http://www.w3.org/2000/svg" width="14.501ex" height="3.07ex" role="img" focusable="false" viewBox="0 -1062 6409.6 1357" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="TeXAtom" data-mjx-texclass="ORD"><g data-mml-node="mover"><g data-mml-node="mi"><path data-c="1D451" d="M366 683Q367 683 438 688T511 694Q523 694 523 686Q523 679 450 384T375 83T374 68Q374 26 402 26Q411 27 422 35Q443 55 463 131Q469 151 473 152Q475 153 483 153H487H491Q506 153 506 145Q506 140 503 129Q490 79 473 48T445 8T417 -8Q409 -10 393 -10Q359 -10 336 5T306 36L300 51Q299 52 296 50Q294 48 292 46Q233 -10 172 -10Q117 -10 75 30T33 157Q33 205 53 255T101 341Q148 398 195 420T280 442Q336 442 364 400Q369 394 369 396Q370 400 396 505T424 616Q424 629 417 632T378 637H357Q351 643 351 645T353 664Q358 683 366 683ZM352 326Q329 405 277 405Q242 405 210 374T160 293Q131 214 119 129Q119 126 119 118T118 106Q118 61 136 44T179 26Q233 26 290 98L298 109L352 326Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(427,268) translate(-250 0)"><path data-c="5E" d="M112 560L249 694L257 686Q387 562 387 560L361 531Q359 532 303 581L250 627L195 580Q182 569 169 557T148 538L140 532Q138 530 125 546L112 560Z" style="stroke-width: 3;"/></g></g></g><g data-mml-node="mo" transform="translate(797.8,0)"><path data-c="3D" d="M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(1853.6,0)"><path data-c="28" d="M94 250Q94 319 104 381T127 488T164 576T202 643T244 695T277 729T302 750H315H319Q333 750 333 741Q333 738 316 720T275 667T226 581T184 443T167 250T184 58T225 -81T274 -167T316 -220T333 -241Q333 -250 318 -250H315H302L274 -226Q180 -141 137 -14T94 250Z" style="stroke-width: 3;"/></g><g data-mml-node="msub" transform="translate(2242.6,0)"><g data-mml-node="mi"><path data-c="1D451" d="M366 683Q367 683 438 688T511 694Q523 694 523 686Q523 679 450 384T375 83T374 68Q374 26 402 26Q411 27 422 35Q443 55 463 131Q469 151 473 152Q475 153 483 153H487H491Q506 153 506 145Q506 140 503 129Q490 79 473 48T445 8T417 -8Q409 -10 393 -10Q359 -10 336 5T306 36L300 51Q299 52 296 50Q294 48 292 46Q233 -10 172 -10Q117 -10 75 30T33 157Q33 205 53 255T101 341Q148 398 195 420T280 442Q336 442 364 400Q369 394 369 396Q370 400 396 505T424 616Q424 629 417 632T378 637H357Q351 643 351 645T353 664Q358 683 366 683ZM352 326Q329 405 277 405Q242 405 210 374T160 293Q131 214 119 129Q119 126 119 118T118 106Q118 61 136 44T179 26Q233 26 290 98L298 109L352 326Z" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(553,-150) scale(0.707)"><path data-c="1D465" d="M52 289Q59 331 106 386T222 442Q257 442 286 424T329 379Q371 442 430 442Q467 442 494 420T522 361Q522 332 508 314T481 292T458 288Q439 288 427 299T415 328Q415 374 465 391Q454 404 425 404Q412 404 406 402Q368 386 350 336Q290 115 290 78Q290 50 306 38T341 26Q378 26 414 59T463 140Q466 150 469 151T485 153H489Q504 153 504 145Q504 144 502 134Q486 77 440 33T333 -11Q263 -11 227 52Q186 -10 133 -10H127Q78 -10 57 16T35 71Q35 103 54 123T99 143Q142 143 142 101Q142 81 130 66T107 46T94 41L91 40Q91 39 97 36T113 29T132 26Q168 26 194 71Q203 87 217 139T245 247T261 313Q266 340 266 352Q266 380 251 392T217 404Q177 404 142 372T93 290Q91 281 88 280T72 278H58Q52 284 52 289Z" style="stroke-width: 3;"/></g></g><g data-mml-node="mo" transform="translate(3250,0)"><path data-c="2C" d="M78 35T78 60T94 103T137 121Q165 121 187 96T210 8Q210 -27 201 -60T180 -117T154 -158T130 -185T117 -194Q113 -194 104 -185T95 -172Q95 -168 106 -156T131 -126T157 -76T173 -3V9L172 8Q170 7 167 6T161 3T152 1T140 0Q113 0 96 17Z" style="stroke-width: 3;"/></g><g data-mml-node="msub" transform="translate(3694.7,0)"><g data-mml-node="mi"><path data-c="1D451" d="M366 683Q367 683 438 688T511 694Q523 694 523 686Q523 679 450 384T375 83T374 68Q374 26 402 26Q411 27 422 35Q443 55 463 131Q469 151 473 152Q475 153 483 153H487H491Q506 153 506 145Q506 140 503 129Q490 79 473 48T445 8T417 -8Q409 -10 393 -10Q359 -10 336 5T306 36L300 51Q299 52 296 50Q294 48 292 46Q233 -10 172 -10Q117 -10 75 30T33 157Q33 205 53 255T101 341Q148 398 195 420T280 442Q336 442 364 400Q369 394 369 396Q370 400 396 505T424 616Q424 629 417 632T378 637H357Q351 643 351 645T353 664Q358 683 366 683ZM352 326Q329 405 277 405Q242 405 210 374T160 293Q131 214 119 129Q119 126 119 118T118 106Q118 61 136 44T179 26Q233 26 290 98L298 109L352 326Z" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(553,-150) scale(0.707)"><path data-c="1D466" d="M21 287Q21 301 36 335T84 406T158 442Q199 442 224 419T250 355Q248 336 247 334Q247 331 231 288T198 191T182 105Q182 62 196 45T238 27Q261 27 281 38T312 61T339 94Q339 95 344 114T358 173T377 247Q415 397 419 404Q432 431 462 431Q475 431 483 424T494 412T496 403Q496 390 447 193T391 -23Q363 -106 294 -155T156 -205Q111 -205 77 -183T43 -117Q43 -95 50 -80T69 -58T89 -48T106 -45Q150 -45 150 -87Q150 -107 138 -122T115 -142T102 -147L99 -148Q101 -153 118 -160T152 -167H160Q177 -167 186 -165Q219 -156 247 -127T290 -65T313 -9T321 21L315 17Q309 13 296 6T270 -6Q250 -11 231 -11Q185 -11 150 11T104 82Q103 89 103 113Q103 170 138 262T173 379Q173 380 173 381Q173 390 173 393T169 400T158 404H154Q131 404 112 385T82 344T65 302T57 280Q55 278 41 278H27Q21 284 21 287Z" style="stroke-width: 3;"/></g></g><g data-mml-node="mo" transform="translate(4644.2,0)"><path data-c="2C" d="M78 35T78 60T94 103T137 121Q165 121 187 96T210 8Q210 -27 201 -60T180 -117T154 -158T130 -185T117 -194Q113 -194 104 -185T95 -172Q95 -168 106 -156T131 -126T157 -76T173 -3V9L172 8Q170 7 167 6T161 3T152 1T140 0Q113 0 96 17Z" style="stroke-width: 3;"/></g><g data-mml-node="msub" transform="translate(5088.8,0)"><g data-mml-node="mi"><path data-c="1D451" d="M366 683Q367 683 438 688T511 694Q523 694 523 686Q523 679 450 384T375 83T374 68Q374 26 402 26Q411 27 422 35Q443 55 463 131Q469 151 473 152Q475 153 483 153H487H491Q506 153 506 145Q506 140 503 129Q490 79 473 48T445 8T417 -8Q409 -10 393 -10Q359 -10 336 5T306 36L300 51Q299 52 296 50Q294 48 292 46Q233 -10 172 -10Q117 -10 75 30T33 157Q33 205 53 255T101 341Q148 398 195 420T280 442Q336 442 364 400Q369 394 369 396Q370 400 396 505T424 616Q424 629 417 632T378 637H357Q351 643 351 645T353 664Q358 683 366 683ZM352 326Q329 405 277 405Q242 405 210 374T160 293Q131 214 119 129Q119 126 119 118T118 106Q118 61 136 44T179 26Q233 26 290 98L298 109L352 326Z" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(553,-150) scale(0.707)"><path data-c="1D467" d="M347 338Q337 338 294 349T231 360Q211 360 197 356T174 346T162 335T155 324L153 320Q150 317 138 317Q117 317 117 325Q117 330 120 339Q133 378 163 406T229 440Q241 442 246 442Q271 442 291 425T329 392T367 375Q389 375 411 408T434 441Q435 442 449 442H462Q468 436 468 434Q468 430 463 420T449 399T432 377T418 358L411 349Q368 298 275 214T160 106L148 94L163 93Q185 93 227 82T290 71Q328 71 360 90T402 140Q406 149 409 151T424 153Q443 153 443 143Q443 138 442 134Q425 72 376 31T278 -11Q252 -11 232 6T193 40T155 57Q111 57 76 -3Q70 -11 59 -11H54H41Q35 -5 35 -2Q35 13 93 84Q132 129 225 214T340 322Q352 338 347 338Z" style="stroke-width: 3;"/></g></g><g data-mml-node="mo" transform="translate(6020.6,0)"><path data-c="29" d="M60 749L64 750Q69 750 74 750H86L114 726Q208 641 251 514T294 250Q294 182 284 119T261 12T224 -76T186 -143T145 -194T113 -227T90 -246Q87 -249 86 -250H74Q66 -250 63 -250T58 -247T55 -238Q56 -237 66 -225Q221 -64 221 250T66 725Q56 737 55 738Q55 746 60 749Z" style="stroke-width: 3;"/></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mrow data-mjx-texclass="ORD"><mover><mi>d</mi><mo stretchy="false">^</mo></mover></mrow><mo>=</mo><mo stretchy="false">(</mo><msub><mi>d</mi><mi>x</mi></msub><mo>,</mo><msub><mi>d</mi><mi>y</mi></msub><mo>,</mo><msub><mi>d</mi><mi>z</mi></msub><mo stretchy="false">)</mo></math></mjx-assistive-mml></mjx-container> se convierte en coordenadas UV a partir de su longitud y latitud:</p>
<mjx-container tabindex="0" class="MathJax" jax="SVG" display="true" style="direction: ltr; display: block; text-align: center; margin: 1em 0; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -1.577ex;" xmlns="http://www.w3.org/2000/svg" width="48.882ex" height="4.982ex" role="img" focusable="false" viewBox="0 -1505 21605.8 2202" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mi"><path data-c="1D462" d="M21 287Q21 295 30 318T55 370T99 420T158 442Q204 442 227 417T250 358Q250 340 216 246T182 105Q182 62 196 45T238 27T291 44T328 78L339 95Q341 99 377 247Q407 367 413 387T427 416Q444 431 463 431Q480 431 488 421T496 402L420 84Q419 79 419 68Q419 43 426 35T447 26Q469 29 482 57T512 145Q514 153 532 153Q551 153 551 144Q550 139 549 130T540 98T523 55T498 17T462 -8Q454 -10 438 -10Q372 -10 347 46Q345 45 336 36T318 21T296 6T267 -6T233 -11Q189 -11 155 7Q103 38 103 113Q103 170 138 262T173 379Q173 380 173 381Q173 390 173 393T169 400T158 404H154Q131 404 112 385T82 344T65 302T57 280Q55 278 41 278H27Q21 284 21 287Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(849.8,0)"><path data-c="3D" d="M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z" style="stroke-width: 3;"/></g><g data-mml-node="mfrac" transform="translate(1905.6,0)"><g data-mml-node="mn" transform="translate(220,676)"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" style="stroke-width: 3;"/></g><g data-mml-node="mn" transform="translate(220,-686)"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"/></g><rect width="700" height="60" x="120" y="220"/></g><g data-mml-node="mo" transform="translate(3067.8,0)"><path data-c="2B" d="M56 237T56 250T70 270H369V420L370 570Q380 583 389 583Q402 583 409 568V270H707Q722 262 722 250T707 230H409V-68Q401 -82 391 -82H389H387Q375 -82 369 -68V230H70Q56 237 56 250Z" style="stroke-width: 3;"/></g><g data-mml-node="mfrac" transform="translate(4068,0)"><g data-mml-node="mrow" transform="translate(220,710)"><g data-mml-node="TeXAtom" data-mjx-texclass="OP"><g data-mml-node="mi"><path data-c="61" d="M137 305T115 305T78 320T63 359Q63 394 97 421T218 448Q291 448 336 416T396 340Q401 326 401 309T402 194V124Q402 76 407 58T428 40Q443 40 448 56T453 109V145H493V106Q492 66 490 59Q481 29 455 12T400 -6T353 12T329 54V58L327 55Q325 52 322 49T314 40T302 29T287 17T269 6T247 -2T221 -8T190 -11Q130 -11 82 20T34 107Q34 128 41 147T68 188T116 225T194 253T304 268H318V290Q318 324 312 340Q290 411 215 411Q197 411 181 410T156 406T148 403Q170 388 170 359Q170 334 154 320ZM126 106Q126 75 150 51T209 26Q247 26 276 49T315 109Q317 116 318 175Q318 233 317 233Q309 233 296 232T251 223T193 203T147 166T126 106Z" style="stroke-width: 3;"/><path data-c="74" d="M27 422Q80 426 109 478T141 600V615H181V431H316V385H181V241Q182 116 182 100T189 68Q203 29 238 29Q282 29 292 100Q293 108 293 146V181H333V146V134Q333 57 291 17Q264 -10 221 -10Q187 -10 162 2T124 33T105 68T98 100Q97 107 97 248V385H18V422H27Z" transform="translate(500,0)" style="stroke-width: 3;"/><path data-c="61" d="M137 305T115 305T78 320T63 359Q63 394 97 421T218 448Q291 448 336 416T396 340Q401 326 401 309T402 194V124Q402 76 407 58T428 40Q443 40 448 56T453 109V145H493V106Q492 66 490 59Q481 29 455 12T400 -6T353 12T329 54V58L327 55Q325 52 322 49T314 40T302 29T287 17T269 6T247 -2T221 -8T190 -11Q130 -11 82 20T34 107Q34 128 41 147T68 188T116 225T194 253T304 268H318V290Q318 324 312 340Q290 411 215 411Q197 411 181 410T156 406T148 403Q170 388 170 359Q170 334 154 320ZM126 106Q126 75 150 51T209 26Q247 26 276 49T315 109Q317 116 318 175Q318 233 317 233Q309 233 296 232T251 223T193 203T147 166T126 106Z" transform="translate(889,0)" style="stroke-width: 3;"/><path data-c="6E" d="M41 46H55Q94 46 102 60V68Q102 77 102 91T102 122T103 161T103 203Q103 234 103 269T102 328V351Q99 370 88 376T43 385H25V408Q25 431 27 431L37 432Q47 433 65 434T102 436Q119 437 138 438T167 441T178 442H181V402Q181 364 182 364T187 369T199 384T218 402T247 421T285 437Q305 442 336 442Q450 438 463 329Q464 322 464 190V104Q464 66 466 59T477 49Q498 46 526 46H542V0H534L510 1Q487 2 460 2T422 3Q319 3 310 0H302V46H318Q379 46 379 62Q380 64 380 200Q379 335 378 343Q372 371 358 385T334 402T308 404Q263 404 229 370Q202 343 195 315T187 232V168V108Q187 78 188 68T191 55T200 49Q221 46 249 46H265V0H257L234 1Q210 2 183 2T145 3Q42 3 33 0H25V46H41Z" transform="translate(1389,0)" style="stroke-width: 3;"/></g><g data-mml-node="mn" transform="translate(2111.7,0)"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"/></g></g><g data-mml-node="mo" transform="translate(2611.7,0)"><path data-c="28" d="M94 250Q94 319 104 381T127 488T164 576T202 643T244 695T277 729T302 750H315H319Q333 750 333 741Q333 738 316 720T275 667T226 581T184 443T167 250T184 58T225 -81T274 -167T316 -220T333 -241Q333 -250 318 -250H315H302L274 -226Q180 -141 137 -14T94 250Z" style="stroke-width: 3;"/></g><g data-mml-node="msub" transform="translate(3000.7,0)"><g data-mml-node="mi"><path data-c="1D451" d="M366 683Q367 683 438 688T511 694Q523 694 523 686Q523 679 450 384T375 83T374 68Q374 26 402 26Q411 27 422 35Q443 55 463 131Q469 151 473 152Q475 153 483 153H487H491Q506 153 506 145Q506 140 503 129Q490 79 473 48T445 8T417 -8Q409 -10 393 -10Q359 -10 336 5T306 36L300 51Q299 52 296 50Q294 48 292 46Q233 -10 172 -10Q117 -10 75 30T33 157Q33 205 53 255T101 341Q148 398 195 420T280 442Q336 442 364 400Q369 394 369 396Q370 400 396 505T424 616Q424 629 417 632T378 637H357Q351 643 351 645T353 664Q358 683 366 683ZM352 326Q329 405 277 405Q242 405 210 374T160 293Q131 214 119 129Q119 126 119 118T118 106Q118 61 136 44T179 26Q233 26 290 98L298 109L352 326Z" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(553,-150) scale(0.707)"><path data-c="1D467" d="M347 338Q337 338 294 349T231 360Q211 360 197 356T174 346T162 335T155 324L153 320Q150 317 138 317Q117 317 117 325Q117 330 120 339Q133 378 163 406T229 440Q241 442 246 442Q271 442 291 425T329 392T367 375Q389 375 411 408T434 441Q435 442 449 442H462Q468 436 468 434Q468 430 463 420T449 399T432 377T418 358L411 349Q368 298 275 214T160 106L148 94L163 93Q185 93 227 82T290 71Q328 71 360 90T402 140Q406 149 409 151T424 153Q443 153 443 143Q443 138 442 134Q425 72 376 31T278 -11Q252 -11 232 6T193 40T155 57Q111 57 76 -3Q70 -11 59 -11H54H41Q35 -5 35 -2Q35 13 93 84Q132 129 225 214T340 322Q352 338 347 338Z" style="stroke-width: 3;"/></g></g><g data-mml-node="mo" transform="translate(3932.5,0)"><path data-c="2C" d="M78 35T78 60T94 103T137 121Q165 121 187 96T210 8Q210 -27 201 -60T180 -117T154 -158T130 -185T117 -194Q113 -194 104 -185T95 -172Q95 -168 106 -156T131 -126T157 -76T173 -3V9L172 8Q170 7 167 6T161 3T152 1T140 0Q113 0 96 17Z" style="stroke-width: 3;"/></g><g data-mml-node="mstyle" transform="translate(4210.5,0)"><g data-mml-node="mspace"/></g><g data-mml-node="msub" transform="translate(4544.1,0)"><g data-mml-node="mi"><path data-c="1D451" d="M366 683Q367 683 438 688T511 694Q523 694 523 686Q523 679 450 384T375 83T374 68Q374 26 402 26Q411 27 422 35Q443 55 463 131Q469 151 473 152Q475 153 483 153H487H491Q506 153 506 145Q506 140 503 129Q490 79 473 48T445 8T417 -8Q409 -10 393 -10Q359 -10 336 5T306 36L300 51Q299 52 296 50Q294 48 292 46Q233 -10 172 -10Q117 -10 75 30T33 157Q33 205 53 255T101 341Q148 398 195 420T280 442Q336 442 364 400Q369 394 369 396Q370 400 396 505T424 616Q424 629 417 632T378 637H357Q351 643 351 645T353 664Q358 683 366 683ZM352 326Q329 405 277 405Q242 405 210 374T160 293Q131 214 119 129Q119 126 119 118T118 106Q118 61 136 44T179 26Q233 26 290 98L298 109L352 326Z" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(553,-150) scale(0.707)"><path data-c="1D465" d="M52 289Q59 331 106 386T222 442Q257 442 286 424T329 379Q371 442 430 442Q467 442 494 420T522 361Q522 332 508 314T481 292T458 288Q439 288 427 299T415 328Q415 374 465 391Q454 404 425 404Q412 404 406 402Q368 386 350 336Q290 115 290 78Q290 50 306 38T341 26Q378 26 414 59T463 140Q466 150 469 151T485 153H489Q504 153 504 145Q504 144 502 134Q486 77 440 33T333 -11Q263 -11 227 52Q186 -10 133 -10H127Q78 -10 57 16T35 71Q35 103 54 123T99 143Q142 143 142 101Q142 81 130 66T107 46T94 41L91 40Q91 39 97 36T113 29T132 26Q168 26 194 71Q203 87 217 139T245 247T261 313Q266 340 266 352Q266 380 251 392T217 404Q177 404 142 372T93 290Q91 281 88 280T72 278H58Q52 284 52 289Z" style="stroke-width: 3;"/></g></g><g data-mml-node="mo" transform="translate(5551.6,0)"><path data-c="29" d="M60 749L64 750Q69 750 74 750H86L114 726Q208 641 251 514T294 250Q294 182 284 119T261 12T224 -76T186 -143T145 -194T113 -227T90 -246Q87 -249 86 -250H74Q66 -250 63 -250T58 -247T55 -238Q56 -237 66 -225Q221 -64 221 250T66 725Q56 737 55 738Q55 746 60 749Z" style="stroke-width: 3;"/></g></g><g data-mml-node="mrow" transform="translate(2655.3,-686)"><g data-mml-node="mn"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(500,0)"><path data-c="1D70B" d="M132 -11Q98 -11 98 22V33L111 61Q186 219 220 334L228 358H196Q158 358 142 355T103 336Q92 329 81 318T62 297T53 285Q51 284 38 284Q19 284 19 294Q19 300 38 329T93 391T164 429Q171 431 389 431Q549 431 553 430Q573 423 573 402Q573 371 541 360Q535 358 472 358H408L405 341Q393 269 393 222Q393 170 402 129T421 65T431 37Q431 20 417 5T381 -10Q370 -10 363 -7T347 17T331 77Q330 86 330 121Q330 170 339 226T357 318T367 358H269L268 354Q268 351 249 275T206 114T175 17Q164 -11 132 -11Z" style="stroke-width: 3;"/></g></g><rect width="6140.6" height="60" x="120" y="220"/></g><g data-mml-node="mo" transform="translate(10448.6,0)"><path data-c="2C" d="M78 35T78 60T94 103T137 121Q165 121 187 96T210 8Q210 -27 201 -60T180 -117T154 -158T130 -185T117 -194Q113 -194 104 -185T95 -172Q95 -168 106 -156T131 -126T157 -76T173 -3V9L172 8Q170 7 167 6T161 3T152 1T140 0Q113 0 96 17Z" style="stroke-width: 3;"/></g><g data-mml-node="mstyle" transform="translate(10726.6,0)"><g data-mml-node="mspace"/></g><g data-mml-node="mi" transform="translate(12893.3,0)"><path data-c="1D463" d="M173 380Q173 405 154 405Q130 405 104 376T61 287Q60 286 59 284T58 281T56 279T53 278T49 278T41 278H27Q21 284 21 287Q21 294 29 316T53 368T97 419T160 441Q202 441 225 417T249 361Q249 344 246 335Q246 329 231 291T200 202T182 113Q182 86 187 69Q200 26 250 26Q287 26 319 60T369 139T398 222T409 277Q409 300 401 317T383 343T365 361T357 383Q357 405 376 424T417 443Q436 443 451 425T467 367Q467 340 455 284T418 159T347 40T241 -11Q177 -11 139 22Q102 54 102 117Q102 148 110 181T151 298Q173 362 173 380Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(13656,0)"><path data-c="3D" d="M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z" style="stroke-width: 3;"/></g><g data-mml-node="mfrac" transform="translate(14711.8,0)"><g data-mml-node="mn" transform="translate(220,676)"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" style="stroke-width: 3;"/></g><g data-mml-node="mn" transform="translate(220,-686)"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"/></g><rect width="700" height="60" x="120" y="220"/></g><g data-mml-node="mo" transform="translate(15874,0)"><path data-c="2212" d="M84 237T84 250T98 270H679Q694 262 694 250T679 230H98Q84 237 84 250Z" style="stroke-width: 3;"/></g><g data-mml-node="mfrac" transform="translate(16874.3,0)"><g data-mml-node="mrow" transform="translate(220,755)"><g data-mml-node="mi"><path data-c="61" d="M137 305T115 305T78 320T63 359Q63 394 97 421T218 448Q291 448 336 416T396 340Q401 326 401 309T402 194V124Q402 76 407 58T428 40Q443 40 448 56T453 109V145H493V106Q492 66 490 59Q481 29 455 12T400 -6T353 12T329 54V58L327 55Q325 52 322 49T314 40T302 29T287 17T269 6T247 -2T221 -8T190 -11Q130 -11 82 20T34 107Q34 128 41 147T68 188T116 225T194 253T304 268H318V290Q318 324 312 340Q290 411 215 411Q197 411 181 410T156 406T148 403Q170 388 170 359Q170 334 154 320ZM126 106Q126 75 150 51T209 26Q247 26 276 49T315 109Q317 116 318 175Q318 233 317 233Q309 233 296 232T251 223T193 203T147 166T126 106Z" style="stroke-width: 3;"/><path data-c="72" d="M36 46H50Q89 46 97 60V68Q97 77 97 91T98 122T98 161T98 203Q98 234 98 269T98 328L97 351Q94 370 83 376T38 385H20V408Q20 431 22 431L32 432Q42 433 60 434T96 436Q112 437 131 438T160 441T171 442H174V373Q213 441 271 441H277Q322 441 343 419T364 373Q364 352 351 337T313 322Q288 322 276 338T263 372Q263 381 265 388T270 400T273 405Q271 407 250 401Q234 393 226 386Q179 341 179 207V154Q179 141 179 127T179 101T180 81T180 66V61Q181 59 183 57T188 54T193 51T200 49T207 48T216 47T225 47T235 46T245 46H276V0H267Q249 3 140 3Q37 3 28 0H20V46H36Z" transform="translate(500,0)" style="stroke-width: 3;"/><path data-c="63" d="M370 305T349 305T313 320T297 358Q297 381 312 396Q317 401 317 402T307 404Q281 408 258 408Q209 408 178 376Q131 329 131 219Q131 137 162 90Q203 29 272 29Q313 29 338 55T374 117Q376 125 379 127T395 129H409Q415 123 415 120Q415 116 411 104T395 71T366 33T318 2T249 -11Q163 -11 99 53T34 214Q34 318 99 383T250 448T370 421T404 357Q404 334 387 320Z" transform="translate(892,0)" style="stroke-width: 3;"/><path data-c="73" d="M295 316Q295 356 268 385T190 414Q154 414 128 401Q98 382 98 349Q97 344 98 336T114 312T157 287Q175 282 201 278T245 269T277 256Q294 248 310 236T342 195T359 133Q359 71 321 31T198 -10H190Q138 -10 94 26L86 19L77 10Q71 4 65 -1L54 -11H46H42Q39 -11 33 -5V74V132Q33 153 35 157T45 162H54Q66 162 70 158T75 146T82 119T101 77Q136 26 198 26Q295 26 295 104Q295 133 277 151Q257 175 194 187T111 210Q75 227 54 256T33 318Q33 357 50 384T93 424T143 442T187 447H198Q238 447 268 432L283 424L292 431Q302 440 314 448H322H326Q329 448 335 442V310L329 304H301Q295 310 295 316Z" transform="translate(1336,0)" style="stroke-width: 3;"/><path data-c="69" d="M69 609Q69 637 87 653T131 669Q154 667 171 652T188 609Q188 579 171 564T129 549Q104 549 87 564T69 609ZM247 0Q232 3 143 3Q132 3 106 3T56 1L34 0H26V46H42Q70 46 91 49Q100 53 102 60T104 102V205V293Q104 345 102 359T88 378Q74 385 41 385H30V408Q30 431 32 431L42 432Q52 433 70 434T106 436Q123 437 142 438T171 441T182 442H185V62Q190 52 197 50T232 46H255V0H247Z" transform="translate(1730,0)" style="stroke-width: 3;"/><path data-c="6E" d="M41 46H55Q94 46 102 60V68Q102 77 102 91T102 122T103 161T103 203Q103 234 103 269T102 328V351Q99 370 88 376T43 385H25V408Q25 431 27 431L37 432Q47 433 65 434T102 436Q119 437 138 438T167 441T178 442H181V402Q181 364 182 364T187 369T199 384T218 402T247 421T285 437Q305 442 336 442Q450 438 463 329Q464 322 464 190V104Q464 66 466 59T477 49Q498 46 526 46H542V0H534L510 1Q487 2 460 2T422 3Q319 3 310 0H302V46H318Q379 46 379 62Q380 64 380 200Q379 335 378 343Q372 371 358 385T334 402T308 404Q263 404 229 370Q202 343 195 315T187 232V168V108Q187 78 188 68T191 55T200 49Q221 46 249 46H265V0H257L234 1Q210 2 183 2T145 3Q42 3 33 0H25V46H41Z" transform="translate(2008,0)" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(2564,0)"><path data-c="2061" d="" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(2564,0)"><path data-c="28" d="M94 250Q94 319 104 381T127 488T164 576T202 643T244 695T277 729T302 750H315H319Q333 750 333 741Q333 738 316 720T275 667T226 581T184 443T167 250T184 58T225 -81T274 -167T316 -220T333 -241Q333 -250 318 -250H315H302L274 -226Q180 -141 137 -14T94 250Z" style="stroke-width: 3;"/></g><g data-mml-node="msub" transform="translate(2953,0)"><g data-mml-node="mi"><path data-c="1D451" d="M366 683Q367 683 438 688T511 694Q523 694 523 686Q523 679 450 384T375 83T374 68Q374 26 402 26Q411 27 422 35Q443 55 463 131Q469 151 473 152Q475 153 483 153H487H491Q506 153 506 145Q506 140 503 129Q490 79 473 48T445 8T417 -8Q409 -10 393 -10Q359 -10 336 5T306 36L300 51Q299 52 296 50Q294 48 292 46Q233 -10 172 -10Q117 -10 75 30T33 157Q33 205 53 255T101 341Q148 398 195 420T280 442Q336 442 364 400Q369 394 369 396Q370 400 396 505T424 616Q424 629 417 632T378 637H357Q351 643 351 645T353 664Q358 683 366 683ZM352 326Q329 405 277 405Q242 405 210 374T160 293Q131 214 119 129Q119 126 119 118T118 106Q118 61 136 44T179 26Q233 26 290 98L298 109L352 326Z" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(553,-150) scale(0.707)"><path data-c="1D466" d="M21 287Q21 301 36 335T84 406T158 442Q199 442 224 419T250 355Q248 336 247 334Q247 331 231 288T198 191T182 105Q182 62 196 45T238 27Q261 27 281 38T312 61T339 94Q339 95 344 114T358 173T377 247Q415 397 419 404Q432 431 462 431Q475 431 483 424T494 412T496 403Q496 390 447 193T391 -23Q363 -106 294 -155T156 -205Q111 -205 77 -183T43 -117Q43 -95 50 -80T69 -58T89 -48T106 -45Q150 -45 150 -87Q150 -107 138 -122T115 -142T102 -147L99 -148Q101 -153 118 -160T152 -167H160Q177 -167 186 -165Q219 -156 247 -127T290 -65T313 -9T321 21L315 17Q309 13 296 6T270 -6Q250 -11 231 -11Q185 -11 150 11T104 82Q103 89 103 113Q103 170 138 262T173 379Q173 380 173 381Q173 390 173 393T169 400T158 404H154Q131 404 112 385T82 344T65 302T57 280Q55 278 41 278H27Q21 284 21 287Z" style="stroke-width: 3;"/></g></g><g data-mml-node="mo" transform="translate(3902.5,0)"><path data-c="29" d="M60 749L64 750Q69 750 74 750H86L114 726Q208 641 251 514T294 250Q294 182 284 119T261 12T224 -76T186 -143T145 -194T113 -227T90 -246Q87 -249 86 -250H74Q66 -250 63 -250T58 -247T55 -238Q56 -237 66 -225Q221 -64 221 250T66 725Q56 737 55 738Q55 746 60 749Z" style="stroke-width: 3;"/></g></g><g data-mml-node="mi" transform="translate(2080.7,-686)"><path data-c="1D70B" d="M132 -11Q98 -11 98 22V33L111 61Q186 219 220 334L228 358H196Q158 358 142 355T103 336Q92 329 81 318T62 297T53 285Q51 284 38 284Q19 284 19 294Q19 300 38 329T93 391T164 429Q171 431 389 431Q549 431 553 430Q573 423 573 402Q573 371 541 360Q535 358 472 358H408L405 341Q393 269 393 222Q393 170 402 129T421 65T431 37Q431 20 417 5T381 -10Q370 -10 363 -7T347 17T331 77Q330 86 330 121Q330 170 339 226T357 318T367 358H269L268 354Q268 351 249 275T206 114T175 17Q164 -11 132 -11Z" style="stroke-width: 3;"/></g><rect width="4491.5" height="60" x="120" y="220"/></g></g></g></svg><mjx-assistive-mml unselectable="on" display="block" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; overflow: hidden; width: 100%;"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><mi>u</mi><mo>=</mo><mfrac><mn>1</mn><mn>2</mn></mfrac><mo>+</mo><mfrac><mrow><mrow data-mjx-texclass="OP"><mi>atan</mi><mn>2</mn></mrow><mo stretchy="false">(</mo><msub><mi>d</mi><mi>z</mi></msub><mo>,</mo><mstyle scriptlevel="0"><mspace width="0.167em"/></mstyle><msub><mi>d</mi><mi>x</mi></msub><mo stretchy="false">)</mo></mrow><mrow><mn>2</mn><mi>π</mi></mrow></mfrac><mo>,</mo><mstyle scriptlevel="0"><mspace width="2em"/></mstyle><mi>v</mi><mo>=</mo><mfrac><mn>1</mn><mn>2</mn></mfrac><mo>−</mo><mfrac><mrow><mi>arcsin</mi><mo data-mjx-texclass="NONE">⁡</mo><mo stretchy="false">(</mo><msub><mi>d</mi><mi>y</mi></msub><mo stretchy="false">)</mo></mrow><mi>π</mi></mfrac></math></mjx-assistive-mml></mjx-container><p>En Three.js, establecer <code>texture.mapping = EquirectangularReflectionMapping</code> con <code>SRGBColorSpace</code> permite utilizarla como fondo de la escena. En TSL, <code>equirectUV(direction)</code> aplica esa misma conversión y transforma una dirección de visión 3D en las coordenadas UV 2D necesarias para muestrear la textura.</p>
<p><strong>Color de niebla por fragmento obtenido del cielo.</strong> La niebla estándar mezcla los fragmentos con un único color constante. En una escena con un skybox detallado, esto resulta incorrecto porque el color del cielo varía según la dirección. La solución consiste en calcular por píxel la dirección en el espacio del mundo desde la cámara hasta el fragmento (<code>positionWorld.sub(cameraPosition).normalize()</code>) y muestrear el skybox en esa dirección para obtener el color de la niebla. Cada fragmento se desvanece hacia el color del cielo que realmente tiene detrás, lo que produce una mezcla correcta desde cualquier ángulo de cámara. El factor de niebla utiliza <code>smoothstep(nearDist, farDist, viewDepth)</code> con <code>positionView.z.negate()</code> para la profundidad en el espacio de la cámara.</p>
<p><strong>Mapas de importaciones para módulos ES.</strong> Un mecanismo nativo del navegador (<code>&lt;script type=&quot;importmap&quot;&gt;</code>) que asigna especificadores simples de módulos —como <code>three/tsl</code>— a URL reales. Cuando Three.js 0.183.1 reorganizó sus salidas de compilación, <code>three/tsl</code> tuvo que resolverse como <code>three.tsl.js</code>, y TSL importaba internamente <code>three/webgpu</code> como un especificador simple. Ambas correspondencias debían indicarse de forma explícita en el mapa de importaciones; de lo contrario, el navegador producía errores como «does not provide an export» o «failed to resolve module specifier».</p>
<h2 id="lecturas-adicionales" tabindex="-1">Lecturas adicionales <a class="header-anchor" href="#lecturas-adicionales" aria-label="Permalink to &quot;Lecturas adicionales&quot;"></a></h2>
<p>Para profundizar en las tecnologías utilizadas a lo largo de esta serie, consulta nuestras guías complementarias:</p>
<ul>
<li><a href="/es/guides/landscape-generation-browser.html">Generación de paisajes con LOD dinámico y streaming para mundos abiertos en el navegador</a> abarca mapas de alturas, SDF, marching cubes, Transvoxel, clipmaps geométricos, geomorphing, arquitectura de streaming, materiales de terreno y renderizado de vegetación.</li>
<li><a href="/es/guides/browser-3d-open-world-tech.html">Tecnología 3D de mundos abiertos en el navegador para mundos multijugador creados por usuarios</a> abarca plataformas de renderizado, WebGPU, físicas, redes, arquitectura multijugador y lecciones de Skyrim, The Witcher 3, Breath of the Wild y GTA V.</li>
</ul>
<p>Gracias por acompañarnos en este recorrido de doce partes.</p>
<p>Parte 1: <a href="/es/blog/2026-02-25-open-world-browser-part-01-risk-first.html">Empezamos intentando romperlo</a><br>
Parte 2: <a href="/es/blog/2026-02-25-open-world-browser-part-02-worker-physics.html">Físicas en workers y el temor al retardo de entrada</a><br>
Parte 3: <a href="/es/blog/2026-02-25-open-world-browser-part-03-the-unflashy-spikes.html">Los prototipos poco vistosos que nos salvaron</a><br>
Parte 4: <a href="/es/blog/2026-02-25-open-world-browser-part-04-streaming-before-fancy.html">Streaming antes que terrenos sofisticados</a><br>
Parte 5: <a href="/es/blog/2026-02-25-open-world-browser-part-05-budgeting-the-pretty.html">Presupuestar los elementos visuales</a><br>
Parte 6: <a href="/es/blog/2026-02-25-open-world-browser-part-06-clipmaps.html">Los clipmaps cambiaron el rumbo</a><br>
Parte 7: <a href="/es/blog/2026-02-25-open-world-browser-part-07-marching-cubes.html">Marching cubes y las primeras cuevas de verdad</a><br>
Parte 8: <a href="/es/blog/2026-02-25-open-world-browser-part-08-webgpu-integration.html">Integración sin perder nuestra línea base</a><br>
Parte 9: <a href="/es/blog/2026-02-25-open-world-browser-part-09-transvoxel-first-cut.html">Transvoxel comenzó con una estructura básica</a><br>
Parte 10: <a href="/es/blog/2026-02-25-open-world-browser-part-10-seam-chaos.html">El caos de las uniones y la batalla final de las esquinas</a><br>
Parte 11: <a href="/es/blog/2026-02-25-open-world-browser-part-11-policy-modes.html">Modo basado en políticas, no codificado de forma rígida</a></p>
<hr>
<p>Parte 12 de 14.<br>
Anterior: <a href="/es/blog/2026-02-25-open-world-browser-part-11-policy-modes.html">Parte 11 - Modo basado en políticas, no codificado de forma rígida</a><br>
Siguiente: <a href="/es/blog/2026-04-13-open-world-browser-part-13-terrain-sculpting.html">Parte 13 - Esculpido del terreno y la muerte de la función matemática</a><br>
Guía de la serie: <a href="/es/blog/2026-02-25-open-world-browser-series-guide.html">/es/blog/2026-02-25-open-world-browser-series-guide</a></p>
]]></content:encoded>
            <enclosure url="https://cdn.cinevva.com/blog/why-webgpu-engine-hero.jpg" length="0" type="image/jpg"/>
        </item>
        <item>
            <title><![CDATA[Guía de la serie sobre mundos abiertos en el navegador]]></title>
            <link>https://app.cinevva.com/es/blog/2026-02-25-open-world-browser-series-guide</link>
            <guid>https://app.cinevva.com/es/blog/2026-02-25-open-world-browser-series-guide</guid>
            <pubDate>Wed, 25 Feb 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Orden de lectura de la serie de 29 partes sobre mundos abiertos en el navegador, además de un glosario sencillo de prototipos técnicos y un mapa de demostraciones en vivo.]]></description>
            <content:encoded><![CDATA[<h1 id="guia-de-la-serie-sobre-mundos-abiertos-en-el-navegador" tabindex="-1">Guía de la serie sobre mundos abiertos en el navegador <a class="header-anchor" href="#guia-de-la-serie-sobre-mundos-abiertos-en-el-navegador" aria-label="Permalink to &quot;Guía de la serie sobre mundos abiertos en el navegador&quot;"></a></h1>
<p><em>Por <a href="/es/about.html">Oleg Sidorkin</a>, CTO y cofundador de Cinevva</em></p>
<p>Esta página es el centro de navegación de la serie completa.</p>
<p>Si has llegado desde una parte al azar, empieza aquí.</p>
<p>Actualización de marzo de 2026: añadimos una comprobación externa de la implementación basada en los diarios de desarrollo de Vuntra City en la <a href="/es/blog/2026-02-25-open-world-browser-part-12-lessons.html">Parte 12</a> y ampliamos la <a href="/es/guides/browser-3d-open-world-tech.html">guía técnica de mundos abiertos en el navegador</a> complementaria con los mismos hallazgos.</p>
<p>Actualización de abril de 2026: las partes 13 y 14 cubren el esculpido del terreno (prototipos 25-27) y la capa visual y de jugabilidad: texturizado multimaterial, vegetación instanciada y un controlador de personaje con colisiones HM+SDF (prototipos 28-30).</p>
<p>Actualización de mayo de 2026: la serie llegó a 29 partes. Las partes 15-29 cubren la larga fase intermedia del desarrollo, el terreno y el agua multijugador, una refactorización de la estructura del código, animaciones y distribución mediante IA, impostores y paralaje, el búfer de visibilidad que no dio resultado, nubes y descarte de meshlets, avatares procesados por lotes y voz por proximidad, persistencia del mundo y viento en la GPU, personajes universales, tres enfoques para el agua, una isla procedural, hierba y oclusión, y un controlador de personaje conectable que funciona con cualquier cuerpo (prototipos 31-60).</p>
<p>Actualización de junio de 2026: la Parte 30 añade una cámara consciente de las colisiones, un brazo de cámara con resorte, un contrato de colisionador conectable y una sonda de distancia con signo que impide que la vista atraviese salientes y techos de cuevas, no solo colinas.</p>
<h2 id="que-significa-«prototipo»-en-esta-serie" tabindex="-1">Qué significa «prototipo» en esta serie <a class="header-anchor" href="#que-significa-«prototipo»-en-esta-serie" aria-label="Permalink to &quot;Qué significa «prototipo» en esta serie&quot;"></a></h2>
<p>Un prototipo es un experimento breve y enfocado.</p>
<p>Cada prototipo pone a prueba una cuestión arriesgada. Mantenemos un alcance reducido, medimos lo que importa y decidimos qué hacer a continuación. Considéralo un instrumento de aprendizaje, no una funcionalidad pulida.</p>
<p>En este proyecto, los prototipos son principalmente páginas independientes bajo <code>/spikes/*</code> que puedes ejecutar en vivo.</p>
<h2 id="lee-la-serie-en-orden" tabindex="-1">Lee la serie en orden <a class="header-anchor" href="#lee-la-serie-en-orden" aria-label="Permalink to &quot;Lee la serie en orden&quot;"></a></h2>
<ol>
<li><a href="/es/blog/2026-02-25-open-world-browser-part-01-risk-first.html">Parte 1: Empezamos intentando romperlo</a></li>
<li><a href="/es/blog/2026-02-25-open-world-browser-part-02-worker-physics.html">Parte 2: Física en un worker y el temor al retardo de entrada</a></li>
<li><a href="/es/blog/2026-02-25-open-world-browser-part-03-the-unflashy-spikes.html">Parte 3: Los prototipos poco vistosos que nos salvaron</a></li>
<li><a href="/es/blog/2026-02-25-open-world-browser-part-04-streaming-before-fancy.html">Parte 4: Streaming antes que terrenos sofisticados</a></li>
<li><a href="/es/blog/2026-02-25-open-world-browser-part-05-budgeting-the-pretty.html">Parte 5: Presupuestar los elementos visuales</a></li>
<li><a href="/es/blog/2026-02-25-open-world-browser-part-06-clipmaps.html">Parte 6: Los clipmaps cambiaron la historia</a></li>
<li><a href="/es/blog/2026-02-25-open-world-browser-part-07-marching-cubes.html">Parte 7: Marching cubes y las primeras cuevas de verdad</a></li>
<li><a href="/es/blog/2026-02-25-open-world-browser-part-08-webgpu-integration.html">Parte 8: Integración sin perder nuestra referencia inicial</a></li>
<li><a href="/es/blog/2026-02-25-open-world-browser-part-09-transvoxel-first-cut.html">Parte 9: Transvoxel comenzó con una estructura base</a></li>
<li><a href="/es/blog/2026-02-25-open-world-browser-part-10-seam-chaos.html">Parte 10: Caos en las uniones y la batalla final de las esquinas</a></li>
<li><a href="/es/blog/2026-02-25-open-world-browser-part-11-policy-modes.html">Parte 11: Modo basado en políticas, no codificado de forma rígida</a></li>
<li><a href="/es/blog/2026-02-25-open-world-browser-part-12-lessons.html">Parte 12: Anillos, niebla del cielo y lo que volveríamos a hacer</a></li>
<li><a href="/es/blog/2026-04-13-open-world-browser-part-13-terrain-sculpting.html">Parte 13: El esculpido del terreno y la muerte de la función matemática</a></li>
<li><a href="/es/blog/2026-04-13-open-world-browser-part-14-world-comes-alive.html">Parte 14: El mundo cobra vida</a></li>
<li><a href="/es/blog/2026-04-13-open-world-browser-part-15-multiplayer-and-water.html">Parte 15: Sustituir la base y después sincronizarla</a></li>
<li><a href="/es/blog/2026-04-28-open-world-browser-part-16-structure-and-authoring.html">Parte 16: Una estructura para un mundo que no deja de crecer</a></li>
<li><a href="/es/blog/2026-05-01-open-world-browser-part-17-animations-and-search.html">Parte 17: Animaciones que no necesitaron retargeting y una búsqueda de recursos en vivo</a></li>
<li><a href="/es/blog/2026-05-02-open-world-browser-part-18-ai-scattering.html">Parte 18: Un pincel de distribución que parece controlado por IA</a></li>
<li><a href="/es/blog/2026-05-04-open-world-browser-part-19-imposters.html">Parte 19: El impostor que tiene que sobrevivir en un bosque</a></li>
<li><a href="/es/blog/2026-05-05-open-world-browser-part-20-parallax-occlusion.html">Parte 20: Simular profundidad en un plano</a></li>
<li><a href="/es/blog/2026-05-06-open-world-browser-part-21-visibility-buffer.html">Parte 21: Un renderizador más rápido que no era más rápido</a></li>
<li><a href="/es/blog/2026-05-07-open-world-browser-part-22-clouds-and-meshlets.html">Parte 22: Nubes que puedes iluminar y un sistema de descarte que hay que alimentar</a></li>
<li><a href="/es/blog/2026-05-08-open-world-browser-part-23-avatars-and-voice.html">Parte 23: Cincuenta avatares y una voz en la sala</a></li>
<li><a href="/es/blog/2026-05-09-open-world-browser-part-24-persistence-and-wind.html">Parte 24: Guardar un mundo y crear viento visible</a></li>
<li><a href="/es/blog/2026-05-10-open-world-browser-part-25-universal-characters.html">Parte 25: Un esqueleto para cualquier atuendo</a></li>
<li><a href="/es/blog/2026-05-12-open-world-browser-part-26-water.html">Parte 26: Tres formas de crear agua</a></li>
<li><a href="/es/blog/2026-05-13-open-world-browser-part-27-island-and-terrain.html">Parte 27: Una isla creada con ruido y un suelo que parece real</a></li>
<li><a href="/es/blog/2026-05-14-open-world-browser-part-28-grass-and-occlusion.html">Parte 28: Hierba hasta el horizonte y un terreno que se oculta a sí mismo</a></li>
<li><a href="/es/blog/2026-05-15-open-world-browser-part-29-pluggable-character.html">Parte 29: Un controlador para cualquier cuerpo</a></li>
<li><a href="/es/blog/2026-06-04-open-world-browser-part-30-collision-aware-camera.html">Parte 30: Una cámara que respeta las paredes</a></li>
</ol>
<h2 id="mapa-de-prototipos-en-vivo" tabindex="-1">Mapa de prototipos en vivo <a class="header-anchor" href="#mapa-de-prototipos-en-vivo" aria-label="Permalink to &quot;Mapa de prototipos en vivo&quot;"></a></h2>
<p>Empieza por estos si quieres recorrer directamente la cronología técnica.</p>
<p><a href="/es/spikes/01-terrain/" target="_blank">Prototipo 1</a> terreno e instanciación · <a href="/es/blog/spike-source?spike=01-terrain">código fuente</a><br>
<a href="/es/spikes/02-rapier-worker/" target="_blank">Prototipo 2</a> física en un worker · <a href="/es/blog/spike-source?spike=02-rapier-worker">código fuente</a><br>
El prototipo 3, una prueba de carga de difusión con Durable Objects, se ejecutó como un script de servicio, no como una página independiente<br>
El prototipo 4 probó las restricciones de calidad en móviles mediante un parámetro de consulta del prototipo 1<br>
El prototipo 5 probó la fiabilidad del comportamiento del LLM y se ejecutó como un script, no como una página independiente<br>
<a href="/es/spikes/06-chunk-streaming/" target="_blank">Prototipo 6</a> carga e intercambio de chunks · <a href="/es/blog/spike-source?spike=06-chunk-streaming">código fuente</a><br>
<a href="/es/spikes/07-gpu-vegetation/" target="_blank">Prototipo 7</a> vegetación a partir de mapas de densidad · <a href="/es/blog/spike-source?spike=07-gpu-vegetation">código fuente</a><br>
<a href="/es/spikes/08-terrain-material/" target="_blank">Prototipo 8</a> coste del material del terreno · <a href="/es/blog/spike-source?spike=08-terrain-material">código fuente</a><br>
<a href="/es/spikes/09-csm-shadows/" target="_blank">Prototipo 9</a> presupuesto de sombras en cascada · <a href="/es/blog/spike-source?spike=09-csm-shadows">código fuente</a><br>
<a href="/es/spikes/10-clipmap-geomorph/" target="_blank">Prototipo 10</a> clipmaps y geomorfismo · <a href="/es/blog/spike-source?spike=10-clipmap-geomorph">código fuente</a><br>
<a href="/es/spikes/11-chunk-streaming/" target="_blank">Prototipo 11</a> streaming de chunks de mapas de altura · <a href="/es/blog/spike-source?spike=11-chunk-streaming">código fuente</a><br>
<a href="/es/spikes/12-webgpu-marching-cubes/" target="_blank">Prototipo 12</a> marching cubes con WebGPU · <a href="/es/blog/spike-source?spike=12-webgpu-marching-cubes">código fuente</a><br>
<a href="/es/spikes/13-threejs-webgpu/" target="_blank">Prototipo 13</a> referencia inicial de integración con WebGPU · <a href="/es/blog/spike-source?spike=13-threejs-webgpu">código fuente</a><br>
<a href="/es/spikes/14-threejs-webgpu-incremental/" target="_blank">Prototipo 14</a> robustecimiento incremental · <a href="/es/blog/spike-source?spike=14-threejs-webgpu-incremental">código fuente</a><br>
<a href="/es/spikes/15-transvoxel-seam/" target="_blank">Prototipo 15</a> estructura base para uniones · <a href="/es/blog/spike-source?spike=15-transvoxel-seam">código fuente</a><br>
<a href="/es/spikes/16-transvoxel-face/" target="_blank">Prototipo 16</a> primera cara de Transvoxel · <a href="/es/blog/spike-source?spike=16-transvoxel-face">código fuente</a><br>
<a href="/es/spikes/17-dual-mc-lod/" target="_blank">Prototipo 17</a> LOD dual de MC · <a href="/es/blog/spike-source?spike=17-dual-mc-lod">código fuente</a><br>
<a href="/es/spikes/18-transvoxel-heightmap-seam/" target="_blank">Prototipo 18</a> unión de mapas de altura · <a href="/es/blog/spike-source?spike=18-transvoxel-heightmap-seam">código fuente</a><br>
<a href="/es/spikes/19-transvoxel-corner-grid/" target="_blank">Prototipo 19</a> esquina con resoluciones mixtas · <a href="/es/blog/spike-source?spike=19-transvoxel-corner-grid">código fuente</a><br>
<a href="/es/spikes/20-gpu-transvoxel-corner/" target="_blank">Prototipo 20</a> unión de esquina en la GPU · <a href="/es/blog/spike-source?spike=20-gpu-transvoxel-corner">código fuente</a><br>
<a href="/es/spikes/21-gpu-mc-transvoxel-corner/" target="_blank">Prototipo 21</a> unión de esquina MC en la GPU · <a href="/es/blog/spike-source?spike=21-gpu-mc-transvoxel-corner">código fuente</a><br>
<a href="/es/spikes/22-gpu-mc-heightmap-fallback/" target="_blank">Prototipo 22</a> alternativa de MC a HM · <a href="/es/blog/spike-source?spike=22-gpu-mc-heightmap-fallback">código fuente</a><br>
<a href="/es/spikes/23-policy-chunk-modes/" target="_blank">Prototipo 23</a> modos de chunks basados en políticas · <a href="/es/blog/spike-source?spike=23-policy-chunk-modes">código fuente</a><br>
<a href="/es/spikes/24-gpu-clipmap-rings/" target="_blank">Prototipo 24</a> anillos de clipmap y niebla del cielo · <a href="/es/blog/spike-source?spike=24-gpu-clipmap-rings">código fuente</a><br>
<a href="/es/spikes/25-heightmap-brush/" target="_blank">Prototipo 25</a> pincel de mapas de altura sobre datos muestreados · <a href="/es/blog/spike-source?spike=25-heightmap-brush">código fuente</a><br>
<a href="/es/spikes/26-sdf-brush/" target="_blank">Prototipo 26</a> pincel SDF mediante cómputo en la GPU · <a href="/es/blog/spike-source?spike=26-sdf-brush">código fuente</a><br>
<a href="/es/spikes/27-hm-mc-brush/" target="_blank">Prototipo 27</a> integración de HM + MC + pincel · <a href="/es/blog/spike-source?spike=27-hm-mc-brush">código fuente</a><br>
<a href="/es/spikes/28-multi-material/" target="_blank">Prototipo 28</a> texturizado multimaterial · <a href="/es/blog/spike-source?spike=28-multi-material">código fuente</a><br>
<a href="/es/spikes/29-vegetation/" target="_blank">Prototipo 29</a> vegetación y hierba mediante shaders · <a href="/es/blog/spike-source?spike=29-vegetation">código fuente</a><br>
<a href="/es/spikes/30-physics/" target="_blank">Prototipo 30</a> física del terreno y controlador de personaje · <a href="/es/blog/spike-source?spike=30-physics">código fuente</a><br>
<a href="/es/spikes/31-multiplayer-sync/" target="_blank">Prototipo 31</a> sincronización de terreno multijugador · <a href="/es/blog/spike-source?spike=31-multiplayer-sync">código fuente</a><br>
<a href="/es/spikes/32-water-swimming/" target="_blank">Prototipo 32</a> agua y natación · <a href="/es/blog/spike-source?spike=32-water-swimming">código fuente</a><br>
<a href="/es/spikes/33-code-structure/" target="_blank">Prototipo 33</a> refactorización de la estructura del código · <a href="/es/blog/spike-source?spike=33-code-structure">código fuente</a><br>
<a href="/es/spikes/34-world-authoring/" target="_blank">Prototipo 34</a> creación dentro del mundo · <a href="/es/blog/spike-source?spike=34-world-authoring">código fuente</a><br>
<a href="/es/spikes/35-combat-animations/" target="_blank">Prototipo 35</a> animaciones de combate y retargeting · <a href="/es/blog/spike-source?spike=35-combat-animations">código fuente</a><br>
<a href="/es/spikes/36-polyhaven-models/" target="_blank">Prototipo 36</a> búsqueda en vivo de recursos de Poly Haven · <a href="/es/blog/spike-source?spike=36-polyhaven-models">código fuente</a><br>
<a href="/es/spikes/37-ai-scattering/" target="_blank">Prototipo 37</a> distribución de objetos asistida por IA · <a href="/es/blog/spike-source?spike=37-ai-scattering">código fuente</a><br>
<a href="/es/spikes/38-imposters/" target="_blank">Prototipo 38</a> impostores octaédricos · <a href="/es/blog/spike-source?spike=38-imposters">código fuente</a><br>
<a href="/es/spikes/39-parallax-pom/" target="_blank">Prototipo 39</a> mapeado de oclusión por paralaje · <a href="/es/blog/spike-source?spike=39-parallax-pom">código fuente</a><br>
<a href="/es/spikes/40-visibility-buffer/" target="_blank">Prototipo 40</a> renderizador con búfer de visibilidad · <a href="/es/blog/spike-source?spike=40-visibility-buffer">código fuente</a><br>
<a href="/es/spikes/41-imposter-forest/" target="_blank">Prototipo 41</a> impostores en un bosque · <a href="/es/blog/spike-source?spike=41-imposter-forest">código fuente</a><br>
<a href="/es/spikes/42-imposter-flicker/" target="_blank">Prototipo 42</a> corrección del parpadeo de los impostores · <a href="/es/blog/spike-source?spike=42-imposter-flicker">código fuente</a><br>
<a href="/es/spikes/43-clouds-atmosphere/" target="_blank">Prototipo 43</a> atmósfera y nubes volumétricas · <a href="/es/blog/spike-source?spike=43-clouds-atmosphere">código fuente</a><br>
<a href="/es/spikes/44-meshlet-clusters/" target="_blank">Prototipo 44</a> descarte Hi-Z de meshlets · <a href="/es/blog/spike-source?spike=44-meshlet-clusters">código fuente</a><br>
<a href="/es/spikes/45-avatar-network-sync/" target="_blank">Prototipo 45</a> skinning de avatares por lotes y sincronización de red · <a href="/es/blog/spike-source?spike=45-avatar-network-sync">código fuente</a><br>
<a href="/es/spikes/46-proximity-voice/" target="_blank">Prototipo 46</a> chat de voz por proximidad · <a href="/es/blog/spike-source?spike=46-proximity-voice">código fuente</a><br>
<a href="/es/spikes/47-world-persistence/" target="_blank">Prototipo 47</a> persistencia del mundo con autoridad del servidor · <a href="/es/blog/spike-source?spike=47-world-persistence">código fuente</a><br>
La integración del rig de avatares del prototipo 48 se reutilizó como código compartido en prototipos posteriores (sin página independiente)<br>
<a href="/es/spikes/49-gpu-wind-props/" target="_blank">Prototipo 49</a> viento en la GPU aplicado a objetos y follaje · <a href="/es/blog/spike-source?spike=49-gpu-wind-props">código fuente</a><br>
<a href="/es/spikes/50-universal-characters/" target="_blank">Prototipo 50</a> personajes universales y accesorios equipables · <a href="/es/blog/spike-source?spike=50-universal-characters">código fuente</a><br>
<a href="/es/spikes/51-water-ssr-caustics/" target="_blank">Prototipo 51</a> agua con reflejos en espacio de pantalla · <a href="/es/blog/spike-source?spike=51-water-ssr-caustics">código fuente</a><br>
<a href="/es/spikes/52-water-planar/" target="_blank">Prototipo 52</a> agua con reflejos planares · <a href="/es/blog/spike-source?spike=52-water-planar">código fuente</a><br>
<a href="/es/spikes/53-water-pro/" target="_blank">Prototipo 53</a> biblioteca de agua para producción · <a href="/es/blog/spike-source?spike=53-water-pro">código fuente</a>
<a href="/es/spikes/54-procgen-island/" target="_blank">Spike 54</a> generación procedural de islas · <a href="/es/blog/spike-source?spike=54-procgen-island">código fuente</a><br>
<a href="/es/spikes/55-terrain-shading/" target="_blank">Spike 55</a> sombreado del terreno y disimulación del mosaico · <a href="/es/blog/spike-source?spike=55-terrain-shading">código fuente</a><br>
<a href="/es/spikes/56-grass/" target="_blank">Spike 56</a> césped de quads cruzados en la GPU · <a href="/es/blog/spike-source?spike=56-grass">código fuente</a><br>
<a href="/es/spikes/57-terrain-occlusion/" target="_blank">Spike 57</a> descarte por oclusión del terreno · <a href="/es/blog/spike-source?spike=57-terrain-occlusion">código fuente</a><br>
<a href="/es/spikes/58-pluggable-character/" target="_blank">Spike 58</a> controlador de personaje intercambiable · <a href="/es/blog/spike-source?spike=58-pluggable-character">código fuente</a><br>
<a href="/es/spikes/59-pluggable-with-avatar/" target="_blank">Spike 59</a> controlador con un avatar real · <a href="/es/blog/spike-source?spike=59-pluggable-with-avatar">código fuente</a><br>
<a href="/es/spikes/60-polygon-animations/" target="_blank">Spike 60</a> animaciones poligonales de Synty · <a href="/es/blog/spike-source?spike=60-polygon-animations">código fuente</a></p>
]]></content:encoded>
            <enclosure url="https://cdn.cinevva.com/blog/why-webgpu-engine-hero.jpg" length="0" type="image/jpg"/>
        </item>
        <item>
            <title><![CDATA[A Breaker Belt: Snake se encuentra con Arkanoid, creado con vibe coding en tres días]]></title>
            <link>https://app.cinevva.com/es/blog/2026-02-18-a-breaker-belt</link>
            <guid>https://app.cinevva.com/es/blog/2026-02-18-a-breaker-belt</guid>
            <pubDate>Wed, 18 Feb 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Una serpiente cósmica rompe ladrillos a lo largo de 50 oleadas, con música reactiva, narración por IA y 23 tipos de ladrillos. Dos personas. Tres días. Web, móvil y PC.]]></description>
            <content:encoded><![CDATA[<h1 id="a-breaker-belt-snake-se-encuentra-con-arkanoid-creado-con-vibe-coding-en-tres-dias" tabindex="-1">A Breaker Belt: Snake se encuentra con Arkanoid, creado con vibe coding en tres días <a class="header-anchor" href="#a-breaker-belt-snake-se-encuentra-con-arkanoid-creado-con-vibe-coding-en-tres-dias" aria-label="Permalink to &quot;A Breaker Belt: Snake se encuentra con Arkanoid, creado con vibe coding en tres días&quot;"></a></h1>
<p><em>Por <a href="/es/about.html">Mariana Muntean</a>, CEO de Cinevva</em></p>
<img src="https://cdn.cinevva.com/blog/breaker-belt-cover.webp" alt="Partida de A Breaker Belt: una serpiente cósmica de neón rompiendo ladrillos en el espacio" style="width:100%;border-radius:8px;margin:1.5rem 0" />
<p>Creamos un juego en el que tu serpiente es la pala y los ladrillos contraatacan. Se publicó para web, móvil y PC. Nos llevó unos tres días entre dos personas. A ratos, sin jornadas agotadoras. Y es realmente divertido de jugar.</p>
<p>Esa última parte es a la que merece la pena prestar atención.</p>
<div style="position:relative;padding-bottom:56.25%;height:0;overflow:hidden;border-radius:8px;margin:1.5rem 0">
<iframe src="https://www.youtube.com/embed/VaFkfCT3OuU" style="position:absolute;top:0;left:0;width:100%;height:100%;border:0" allow="accelerometer;autoplay;clipboard-write;encrypted-media;gyroscope;picture-in-picture" allowfullscreen></iframe>
</div>
<h2 id="la-mezcla-que-nadie-pidio" tabindex="-1">La mezcla que nadie pidió <a class="header-anchor" href="#la-mezcla-que-nadie-pidio" aria-label="Permalink to &quot;La mezcla que nadie pidió&quot;"></a></h2>
<p>Snake trata sobre crecer y tener conciencia espacial. Arkanoid trata sobre reflejos y predicción de ángulos. Provienen de filosofías de diseño completamente distintas, y mezclarlos suena como esa clase de propuesta que se rechaza amablemente.</p>
<p>Pero <a href="https://app.cinevva.com/engine" target="_blank" rel="noreferrer">A Breaker Belt</a> consigue que funcione. Eres una serpiente cósmica, un arco viviente de corriente de neón, ensamblado con vértebras de metal errante y seda de cometa, que se abre paso por un campo de asteroides formado por bloques rompibles. Tu cabeza es la pala. Tu cola, que no deja de crecer, es a la vez tu mejor arma y tu amenaza más constante. Los orbes rebotan contra tu cuerpo para destruir ladrillos, pero basta un giro equivocado hacia tu propia cola para que se acabe la partida.</p>
<p>Es la clase de experimento extraño entre géneros que normalmente muere antes de que nadie llegue a jugarlo, porque el coste de desarrollo necesario para averiguar si una idea peculiar funciona se ha medido tradicionalmente en meses. Aquí se midió en tardes.</p>
<h2 id="lo-que-realmente-publicamos" tabindex="-1">Lo que realmente publicamos <a class="header-anchor" href="#lo-que-realmente-publicamos" aria-label="Permalink to &quot;Lo que realmente publicamos&quot;"></a></h2>
<p>El alcance es lo que hace que esto resulte interesante. No es un prototipo de una game jam con rectángulos provisionales y sin sonido.</p>
<p>El juego cuenta con 50 oleadas. Y no son 50 variaciones del mismo muro de ladrillos. Las formaciones evolucionan desde suaves arcos introductorios hasta anillos fortificados que exigen tiros angulados a través de aberturas laterales, para después convertirse en laberintos diagonales por capas con huecos de una sola casilla que requieren un control preciso. Los ladrillos explosivos hacen saltar por los aires a sus vecinos. Los ladrillos fantasma aparecen y desaparecen. Los ladrillos regenerativos se reparan después de romperlos, lo que te obliga a priorizar objetivos en lugar de barrer la pantalla de izquierda a derecha. Los ladrillos portal teletransportan tus orbes por la arena. Los pozos gravitatorios desvían tus disparos y los convierten en himnos lentos y curvos. Los emisores láser dibujan líneas rojas en el vacío. Los ladrillos miméticos parecen inofensivos hasta que deciden dejar de serlo. Al llegar a la oleada 15, navegas por algo que se parece menos a un rompecabezas y más a un sistema vivo que está aprendiendo tus hábitos.</p>
<p>La música no es un bucle. Es una banda sonora reactiva que evoluciona con la partida. El sistema subyacente reproduce una línea de bajo, un sintetizador principal, un pad, un bombo, una caja y un hi-hat en mi menor a 140 BPM y, a medida que se intensifica la acción, aparecen gradualmente capas adicionales de percusión y sintetizador. Cuando todo se calma entre oleadas, los pads ambientales toman el protagonismo. La música respira contigo. Un compositor dedicado tardaría semanas en ajustar ese grado de respuesta. Aquí formó parte del propio flujo creativo.</p>
<p>Los efectos de sonido no son muestras sacadas de un paquete gratuito. Cada ladrillo que se rompe, cada potenciador recogido, cada rebote de un orbe y cada colisión se sintetizan en tiempo real. Los contactos con la cabeza tienen un tono diferente a los contactos con la cola. Una reverberación cálida aporta la sensación espacial. El filtrado de paso bajo mantiene el sonido satisfactorio sin volverlo estridente. Cuando encadenas un combo, el audio te lo comunica antes que la pantalla.</p>
<p>Y luego está la narrativa. Cada oleada comienza con un fragmento narrativo interpretado por una voz generada mediante IA. El texto tiene una personalidad auténtica. Oleada uno: «Lo llaman el Cinturón Quebrador: una cinta de escombros artificiales que rodea la vieja estrella como una advertencia». En la oleada 38: «El Cinturón deja de parecer un muro y empieza a parecer una mente. No pone a prueba tus reflejos, sino tus hábitos. Rompes el hábito. El Cinturón se da cuenta». Son 50 capítulos de mitología cósmica que hacen que te importe por qué eres una serpiente que rompe ladrillos en el espacio.</p>
<p>Los fondos también evolucionan. Las primeras oleadas muestran tranquilos campos de estrellas índigo con una suave lluvia de meteoros. Hacia la mitad del juego aparecen franjas de auroras y nubes de nebulosa. En las fases finales se desata una Tormenta Iónica en toda regla, con intensos trazos cian sobre un espacio casi negro. A partir de la oleada 15, entras en territorio de Horizonte de Sucesos: un vacío profundo salpicado de filamentos de nebulosa que se mueven lentamente y un tenue efecto de lente gravitacional producido por agujeros negros. El juego comunica la progresión tanto mediante la atmósfera como mediante la dificultad.</p>
<p>Todo esto funciona con teclado, mando o pantalla táctil. Publicado para web, móvil y PC desde una única base de código. Sin compilaciones independientes. Sin adaptaciones entre plataformas.</p>
<h2 id="el-equipo-que-no-hizo-falta" tabindex="-1">El equipo que no hizo falta <a class="header-anchor" href="#el-equipo-que-no-hizo-falta" aria-label="Permalink to &quot;El equipo que no hizo falta&quot;"></a></h2>
<p>Esta es la parte que debería hacer reflexionar a cualquier desarrollador de videojuegos.</p>
<p>Un juego con esta profundidad de contenido normalmente necesitaría un diseñador de juegos, un par de programadores, un artista 2D, un diseñador de sonido, un compositor musical, un diseñador de niveles, un guionista narrativo y control de calidad. Es decir, ocho o nueve personas. Incluso a un ritmo indie moderado, hablaríamos de entre tres y seis meses de trabajo coordinado. Reuniones diarias, tareas en Jira, procesos de recursos y depuración específica para cada plataforma.</p>
<p>Dos personas hicimos esto durante un fin de semana largo con <a href="https://app.cinevva.com/engine" target="_blank" rel="noreferrer">Cinevva Engine</a>.</p>
<p>El talento necesario no cambió. Lo que cambió fue la proporción entre la intención creativa y la sobrecarga de implementación. El tiempo se dedicó a decidir qué sensaciones debía transmitir el juego, no a pelearse con las herramientas para hacerlo realidad.</p>
<h2 id="por-que-importa-si-creas-cosas" tabindex="-1">Por qué importa si creas cosas <a class="header-anchor" href="#por-que-importa-si-creas-cosas" aria-label="Permalink to &quot;Por qué importa si creas cosas&quot;"></a></h2>
<p>La pregunta interesante no es si las herramientas de IA pueden ayudar a crear juegos más rápido. Eso ya está respondido. La pregunta interesante es qué ocurre con las ideas que antes eran demasiado arriesgadas como para intentarlas.</p>
<p>«Snake, pero tú eres la pala en una arena de Arkanoid» no es algo a lo que un productor dé luz verde. Algunos desarrolladores indie han probado variaciones de esta mezcla en itch.io (<a href="https://newdron.itch.io/breaksnake" target="_blank" rel="noreferrer">BreakSnake</a>, <a href="https://neop87.itch.io/snakeout" target="_blank" rel="noreferrer">SnakeOut</a>, <a href="https://merrak.itch.io/snake-break" target="_blank" rel="noreferrer">Snake Break</a>), pero todos son pequeños experimentos de game jam. Esta fusión de géneros nunca había recibido un verdadero tratamiento de producción con música reactiva, narración por IA, docenas de tipos de ladrillos y 50 oleadas con un diseño de niveles de dificultad creciente. En el desarrollo tradicional, ese grado de acabado aplicado a un concepto arriesgado se descarta en una reunión antes de que nadie escriba una sola línea de código.</p>
<p>Cuando probar algo extraño cuesta una tarde en lugar del presupuesto de un trimestre, las ideas peculiares llegan a construirse. Algunas resultan ser realmente buenas. A Breaker Belt es una de ellas.</p>
<h2 id="juegalo-o-crea-el-tuyo" tabindex="-1">Juégalo. O crea el tuyo. <a class="header-anchor" href="#juegalo-o-crea-el-tuyo" aria-label="Permalink to &quot;Juégalo. O crea el tuyo.&quot;"></a></h2>
<p>Puedes jugar a <a href="https://app.cinevva.com/engine" target="_blank" rel="noreferrer">A Breaker Belt</a> ahora mismo en web, móvil y PC. Si te inspira a crear algo, <a href="https://app.cinevva.com/engine" target="_blank" rel="noreferrer">Cinevva Engine</a> es gratuito. Describe lo que quieres, itera sobre el resultado y publícalo cuando esté listo. La <a href="https://app.cinevva.com/tools/music" target="_blank" rel="noreferrer">música</a>, los <a href="https://app.cinevva.com/tools/sfx" target="_blank" rel="noreferrer">efectos de sonido</a>, el <a href="https://app.cinevva.com/tools/flux" target="_blank" rel="noreferrer">arte</a> y los <a href="https://app.cinevva.com/tools/hunyuan3d" target="_blank" rel="noreferrer">modelos 3D</a> están integrados.</p>
<p>Puede que tu extraña idea para un juego esté a solo tres días de existir.</p>
<hr>
<p><em><a href="https://app.cinevva.com/engine" target="_blank" rel="noreferrer">Juega a A Breaker Belt</a> | <a href="https://app.cinevva.com/engine" target="_blank" rel="noreferrer">Crea tu propio juego</a> | <a href="https://cinevva.com/charts" target="_blank" rel="noreferrer">Explora los juegos de la comunidad</a></em></p>
<p><strong>Relacionado:</strong></p>
<ul>
<li><a href="/es/signals/2026-03-13-vibe-coding-new-game-jam.html">El vibe coding es la nueva game jam</a> — cómo las herramientas de IA acortan la distancia entre la idea y el prototipo</li>
<li><a href="/es/guides/game-jams-hackathons.html">Game jams y hackatones</a> — el formato de jam que hace posibles las mezclas más extrañas</li>
<li><a href="/es/guides/web-game-engines-comparison.html">Comparativa de motores de juegos web</a> — motores para publicar en web, móvil y PC</li>
</ul>
]]></content:encoded>
            <enclosure url="https://cdn.cinevva.com/blog/open-world-browser-series-cover.png" length="0" type="image/png"/>
        </item>
        <item>
            <title><![CDATA[No esperábamos acabar creando una emisora de radio]]></title>
            <link>https://app.cinevva.com/es/blog/2026-02-17-we-didnt-expect-a-radio-station</link>
            <guid>https://app.cinevva.com/es/blog/2026-02-17-we-didnt-expect-a-radio-station</guid>
            <pubDate>Tue, 17 Feb 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Cinevva cuenta con un generador de música para que los creadores de juegos puedan producir bandas sonoras. Pero la gente empezó a crear música simplemente porque podía. 362 pistas después, Cinevva Radio ya está en directo.]]></description>
            <content:encoded><![CDATA[<h1 id="no-esperabamos-acabar-creando-una-emisora-de-radio" tabindex="-1">No esperábamos acabar creando una emisora de radio <a class="header-anchor" href="#no-esperabamos-acabar-creando-una-emisora-de-radio" aria-label="Permalink to &quot;No esperábamos acabar creando una emisora de radio&quot;"></a></h1>
<p><em>Por <a href="/es/about.html">Mariana Muntean</a>, CEO de Cinevva</em></p>
<img src="https://cdn.cinevva.com/blog/cinevva-radio-lofi-cafe.png" alt="Cinevva Community Radio con 8 emisoras, entre ellas Soundstage, Voltage, Lo-Fi Cafe, Main Stage, Ivory Tower y Electric Dreams, reproduciendo actualmente Quiet Flute Drone" style="width:100%;border-radius:8px;margin:1.5rem 0" />
<p>La plataforma Cinevva cuenta con un <a href="https://app.cinevva.com/tools/music" target="_blank" rel="noreferrer">generador de música</a> para que los creadores de juegos puedan producir bandas sonoras y efectos de sonido sin quebraderos de cabeza con las licencias. Lo que ocurrió después no entraba en nuestros planes. La gente empezó a crear música porque quería crear música. No para juegos ni proyectos. Simplemente por hacer música.</p>
<h2 id="bella-bay-creo-mas-de-100-pistas-en-dos-semanas" tabindex="-1">Bella Bay creó más de 100 pistas en dos semanas <a class="header-anchor" href="#bella-bay-creo-mas-de-100-pistas-en-dos-semanas" aria-label="Permalink to &quot;Bella Bay creó más de 100 pistas en dos semanas&quot;"></a></h2>
<p>No exagero. Bella Bay, una de nuestras creadoras, generó más de 100 pistas en unas dos semanas. Al escucharlas en <a href="https://cinevva.com/radio" target="_blank" rel="noreferrer">Cinevva Radio</a>, se percibe la evolución. Las primeras pistas son experimentos. Las últimas suenan como el trabajo de alguien que ha encontrado su estilo. Ese tipo de aceleración creativa no ocurre cuando tienes que luchar contra tus herramientas. Ocurre cuando las herramientas dejan de interponerse.</p>
<p>Bella Bay no es una excepción por su motivación, sino por el volumen de su producción. En toda la plataforma, la gente empezó a tratar el generador de música no como una utilidad para crear recursos de juegos, sino como un instrumento creativo. Productores que experimentaban con géneros que nunca habían probado. Personas que refinaban un sonido una y otra vez hasta dar con el resultado que buscaban. Artistas que trabajaban desde su habitación y que nunca habían tenido acceso a un conjunto completo de herramientas de producción de repente lo tenían y se entregaron por completo.</p>
<h2 id="asi-que-creamos-una-radio" tabindex="-1">Así que creamos una radio <a class="header-anchor" href="#asi-que-creamos-una-radio" aria-label="Permalink to &quot;Así que creamos una radio&quot;"></a></h2>
<p>Había que hacerlo.</p>
<p>Teníamos todas esas pistas guardadas en las cuentas de la gente, sin un espacio común. No había forma de descubrir lo que creaban los demás. Ni de encontrarse por casualidad con una pista capaz de cambiarte la tarde.</p>
<p><a href="https://cinevva.com/radio" target="_blank" rel="noreferrer">Cinevva Radio</a> ya está en directo. Ocho emisoras. 362 pistas creadas por la comunidad, y la cifra aumenta cada día. Todas y cada una de las canciones fueron creadas por alguien de la plataforma. Entras y ya hay algo sonando. No tienes que buscar. No tienes que decidir. Solo tienes que escuchar.</p>
<p><strong><a href="https://cinevva.com/radio#cinematic" target="_blank" rel="noreferrer">Soundstage</a></strong> es nuestra emisora más grande. 111 pistas de música cinematográfica y épica. Sinceramente, no me lo esperaba. A la gente le encanta crear música dramática, al estilo de las bandas sonoras de cine.</p>
<p><strong><a href="https://cinevva.com/radio#mixed" target="_blank" rel="noreferrer">Discovery</a></strong> reúne todo lo que no encaja claramente en un género. 78 pistas. Ritmos latinos junto a afrobeats, country y otras cosas imposibles de describir. Esta emisora es una locura.</p>
<p><strong><a href="https://cinevva.com/radio#pop" target="_blank" rel="noreferrer">Main Stage</a></strong> está dedicada al pop y a las pistas vocales. 56 temas con voz y letras completas. La gente escribe canciones de amor, de rupturas, música de alabanza y baladas. Algunas son realmente pegadizas.</p>
<p><strong><a href="https://cinevva.com/radio#rock" target="_blank" rel="noreferrer">Voltage</a></strong> es rock y metal. 53 pistas. Riffs de guitarra, energía punk, grunge y hard rock. Suelo escucharla mientras trabajo.</p>
<p><strong><a href="https://cinevva.com/radio#lofi" target="_blank" rel="noreferrer">Lo-Fi Cafe</a></strong> es exactamente lo que parece. 25 pistas ambientales y relajadas para estudiar, trabajar o simplemente dejarse llevar.</p>
<p><strong><a href="https://cinevva.com/radio#electronic" target="_blank" rel="noreferrer">Electric Dreams</a></strong> cuenta con 22 pistas electrónicas y de sintetizador. Synthwave, techno, EDM y drum and bass.</p>
<p><strong><a href="https://cinevva.com/radio#classical" target="_blank" rel="noreferrer">Ivory Tower</a></strong> está dedicada a la música clásica y orquestal. 10 pistas. Piezas para piano, arreglos de cuerda y composiciones sinfónicas. Es pequeña, pero sigue creciendo.</p>
<p><strong><a href="https://cinevva.com/radio#hiphop" target="_blank" rel="noreferrer">The Cipher</a></strong> es hip-hop y rap. Por ahora tiene 7 pistas. Es la emisora más reciente y todavía está encontrando su voz.</p>
<h2 id="lo-que-ves-mientras-escuchas" tabindex="-1">Lo que ves mientras escuchas <a class="header-anchor" href="#lo-que-ves-mientras-escuchas" aria-label="Permalink to &quot;Lo que ves mientras escuchas&quot;"></a></h2>
<p>Cuando abres <a href="https://cinevva.com/radio" target="_blank" rel="noreferrer">Cinevva Radio</a>, accedes a una emisión en directo. No la veas tanto como una aplicación de listas de reproducción, sino como una emisora de radio de verdad. Las pistas suenan de forma continua. Puedes reaccionar en tiempo real, conversar con otros oyentes y ver quién creó cada pista.</p>
<p>Los creadores aparecen acreditados en pantalla mientras suena su pista: su nombre, su prompt y el género. Si escuchas algo que te gusta, sabes quién lo creó. Es contenido creado por la comunidad con una capa de descubrimiento por encima. No hay algoritmos que decidan qué merece la pena. No hay guardianes que controlen el acceso. Creas una pista, esta entra en la emisora correspondiente a su género y la gente la escucha.</p>
<h2 id="esto-es-mas-que-una-funcionalidad" tabindex="-1">Esto es más que una funcionalidad <a class="header-anchor" href="#esto-es-mas-que-una-funcionalidad" aria-label="Permalink to &quot;Esto es más que una funcionalidad&quot;"></a></h2>
<p>Durante décadas, producir música requería software caro, años de formación y acceso a equipos que la mayoría de la gente no podía permitirse. Lo que estamos viendo es un tipo diferente de creador: personas que piensan mediante descripciones y sentimientos, en lugar de notas y compases.</p>
<p>«Jazz para una noche lluviosa con un piano roto» es una dirección creativa. La persona que escribió ese prompt tomó una decisión artística. Dirigió el ambiente, la instrumentación y el registro emocional. Simplemente no toca el piano.</p>
<p>No creo que eso reste validez a su obra. Creo que significa que la definición de «músico» se está ampliando. Y ver a alguien como Bella Bay pasar de cero a cien pistas en dos semanas me demuestra que el impulso creativo siempre estuvo ahí. Lo que faltaban eran las herramientas.</p>
<h2 id="proximos-pasos" tabindex="-1">Próximos pasos <a class="header-anchor" href="#proximos-pasos" aria-label="Permalink to &quot;Próximos pasos&quot;"></a></h2>
<p>Estamos trabajando en perfiles de la comunidad donde los productores puedan mostrar su catálogo y conseguir seguidores. La <a href="https://cinevva.com/charts" target="_blank" rel="noreferrer">página de listas</a> ya muestra creaciones de la comunidad realizadas con todas las herramientas, y queremos llevar esa misma energía específicamente a la música.</p>
<p>Pero, por ahora, la radio ya está en directo. <a href="https://cinevva.com/radio" target="_blank" rel="noreferrer">Ve a escucharla</a>. Y si quieres crear tus propias pistas, puedes usar gratis el <a href="https://app.cinevva.com/tools/music" target="_blank" rel="noreferrer">generador de música</a>. Puede que tu pista acabe sonando en antena.</p>
<hr>
<p><em><a href="https://cinevva.com/radio" target="_blank" rel="noreferrer">Escucha Cinevva Radio</a> | <a href="https://app.cinevva.com/tools/music" target="_blank" rel="noreferrer">Crea música</a> | <a href="https://cinevva.com/charts" target="_blank" rel="noreferrer">Explora las creaciones de la comunidad</a></em></p>
<p><strong>Contenido relacionado:</strong></p>
<ul>
<li><a href="/es/guides/frontier-gen-ai-models.html">Modelos generativos de IA de código abierto de vanguardia</a> — los modelos de IA para música y audio que funcionan entre bastidores</li>
<li><a href="/es/tutorials/web-audio-api-games.html">Web Audio API para juegos</a> — cómo crear audio interactivo en el navegador</li>
<li><a href="/es/signals/2026-03-13-vibe-coding-new-game-jam.html">El vibe coding es la nueva game jam</a> — cómo describir una intención se convierte en la principal aportación creativa</li>
</ul>
]]></content:encoded>
            <enclosure url="https://cdn.cinevva.com/blog/cinevva-radio-lofi-cafe.png" length="0" type="image/png"/>
        </item>
        <item>
            <title><![CDATA[La mente intuitiva en la era de la IA]]></title>
            <link>https://app.cinevva.com/es/blog/2026-02-10-the-intuitive-mind</link>
            <guid>https://app.cinevva.com/es/blog/2026-02-10-the-intuitive-mind</guid>
            <pubDate>Tue, 10 Feb 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Jensen Huang afirma que las habilidades matemáticas puras se han convertido en algo básico. Estas son las razones por las que sus palabras conectan con alguien que suspendió el SAT, ignoró las reglas y creó algo que la gente realmente quería.]]></description>
            <content:encoded><![CDATA[<h1 id="la-mente-intuitiva-en-la-era-de-la-ia" tabindex="-1">La mente intuitiva en la era de la IA <a class="header-anchor" href="#la-mente-intuitiva-en-la-era-de-la-ia" aria-label="Permalink to &quot;La mente intuitiva en la era de la IA&quot;"></a></h1>
<p><em>Por <a href="/es/about.html">Mariana Muntean</a>, CEO de Cinevva</em></p>
<img src="https://cdn.cinevva.com/blog/game-jam-houston-2018.png" alt="Mariana Muntean con sus compañeros durante una game jam de 48 horas en Houston en 2018" style="width:100%;border-radius:8px;margin:1.5rem 0" />
<small>Con mis compañeros durante una game jam de 48 horas en Houston, 2018</small>
<p>La IA ha convertido la lógica pura y la capacidad de cálculo en algo prácticamente indiferenciado. Las habilidades que antes venerábamos —el cálculo mental, el reconocimiento de patrones, la capacidad de abrirse paso a través de algoritmos complejos— ahora las realiza la IA. Más rápido. Mejor. Sin cansarse. ¿Seguimos necesitando esos conocimientos? Por supuesto, pero las percepciones cambian. Ahora todos debemos adaptarnos a la nueva era: una era de interacción intuitiva y resultados.</p>
<p>Según <a href="https://business.columbia.edu/insights/digital-future/nvidia-ceo-jensen-huang-reveals-keys-ai-and-leadership" target="_blank" rel="noreferrer">Jensen Huang</a>, CEO de NVIDIA, lo que importa ahora es la capacidad de percibir una «vibra» y anticiparse antes de que aparezcan los datos. La intersección entre los conocimientos técnicos y una profunda empatía. Esa comprensión intuitiva que el silicio no puede alcanzar.</p>
<p>Nunca había oído a nadie con su credibilidad decir algo que validara de forma tan directa toda la trayectoria de mi vida.</p>
<h2 id="el-sat-y-el-sistema-que-no-estaba-hecho-para-mi" tabindex="-1">El SAT y el sistema que no estaba hecho para mí <a class="header-anchor" href="#el-sat-y-el-sistema-que-no-estaba-hecho-para-mi" aria-label="Permalink to &quot;El SAT y el sistema que no estaba hecho para mí&quot;"></a></h2>
<p>Hace unos años hice el SAT y suspendí. No me enorgullece, pero tampoco volví a intentarlo. Había algo fundamentalmente equivocado en todo aquello, y no lograba quitarme esa sensación por mucho que la gente me dijera que simplemente estudiara más y volviera a presentarme.</p>
<p>Visto en retrospectiva, creo que tenía razón.</p>
<p>El SAT está diseñado para el sistema educativo estadounidense. Parece obvio, pero sus implicaciones son profundas. Los institutos estadounidenses preparan a los estudiantes para patrones, tipos de preguntas y formas concretas de plantear problemas. Desde la escuela primaria, los alumnos crecen inmersos en ese estilo de exámenes estandarizados. Cuando llegan al SAT, ya han interiorizado su ritmo.</p>
<p>Los estudiantes internacionales no tenemos esa ventaja. Venimos de sistemas con filosofías educativas diferentes. Las escuelas europeas suelen priorizar la profundidad sobre la amplitud, los exámenes de desarrollo sobre los tests de opción múltiple y las defensas orales sobre las hojas de respuestas. Los sistemas asiáticos tienen sus propios exámenes estandarizados, pero miden cosas distintas de maneras diferentes. Las tradiciones educativas de Sudamérica, África y Oriente Medio tienen cada una su propia lógica.</p>
<p>Cuando pones a un estudiante internacional ante el SAT, no evalúas únicamente sus conocimientos. Evalúas la rapidez con la que puede adaptarse a una cultura de evaluación extranjera mientras demuestra simultáneamente su dominio de los contenidos. Evalúas tanto su fluidez cultural como su capacidad académica.</p>
<p>Esperaban que me preparara durante un verano y sacara una nota excelente. Que aprendiera toda una cultura de evaluación, desaprendiera mis propios instintos educativos y rindiera a un nivel que impresionara a los responsables de admisiones estadounidenses. Todo en unos pocos meses.</p>
<p>Decidí no hacerlo.</p>
<p>Cuando eres joven, eres inteligente de maneras diferentes. De maneras intuitivas. Yo estaba abriéndome mi propio camino, aunque en aquel momento no pudiera explicar exactamente por qué. Algo dentro de mí sabía que aquel sistema no era para mí.</p>
<h2 id="seguir-el-hilo-creativo-en-su-lugar" tabindex="-1">Seguir el hilo creativo en su lugar <a class="header-anchor" href="#seguir-el-hilo-creativo-en-su-lugar" aria-label="Permalink to &quot;Seguir el hilo creativo en su lugar&quot;"></a></h2>
<p>Estudié desarrollo y diseño de videojuegos porque me encantaba la idea de utilizar la creatividad y los efectos visuales para construir mundos virtuales en los que la gente pudiera jugar e interactuar. Me fascinaba la intersección entre el arte y la tecnología, entre la narrativa y la interactividad.</p>
<p>Lo que descubrí me sorprendió.</p>
<p>Los juegos requieren una gran profundidad técnica. Simulaciones físicas, detección de colisiones, matemáticas vectoriales, cálculos de iluminación, optimización. Lo sabía cuando empecé. Las matemáticas y la ingeniería no son obstáculos para el desarrollo de videojuegos. Son parte de lo que hace que funcionen.</p>
<p>El problema era la brecha entre la visión creativa y la implementación. Los motores y las herramientas que dominaban el sector habían sido diseñados por ingenieros para ingenieros. Todo funcionaba con «si» y «entonces» y con esquemas basados en nodos. ¿Querías un efecto de vórtice? Aprende a programar shaders. ¿Una ambientación lumínica concreta? Sumérgete en grafos de materiales. ¿Un movimiento de personajes que se sienta bien? Pasa horas depurando el controlador del personaje o los parámetros físicos.</p>
<p>Si eres una persona visual, si piensas en colores intensos e imágenes en movimiento, si las ideas te llegan como escenas totalmente formadas, con sonido, textura y peso emocional, tenías que traducir todo eso al lenguaje técnico antes de poder construirlo. Ves un mundo en tu mente, con su iluminación, su atmósfera y la forma en que los personajes se mueven por el espacio. Después te sientas frente al ordenador y pasas las seis horas siguientes intentando averiguar por qué tu personaje atraviesa el suelo.</p>
<p>La base técnica importa. Pero las herramientas obligaban a los creadores a vivir inmersos en los detalles de implementación, en lugar de abstraer toda esa complejidad. Crear un juego debería sentirse como contar una historia o dirigir una película en la que la gente puede participar. Esa es la magia del medio. En cambio, parecía que tenías que superar un examen de ingeniería antes siquiera de poder empezar.</p>
<p>Los directores de cine no pasan años aprendiendo a utilizar motores de física antes de poder expresar su visión. Reciben un presupuesto y cuentan con un equipo que se encarga de la ejecución técnica. Pero en el desarrollo de videojuegos independientes rara vez tienes presupuesto. Lo que tienes es tiempo y acceso a herramientas. Y si eres una persona técnica, puedes crear un juego increíble. Pero solo si lo eres.</p>
<p>Así surgieron títulos como Limbo, creado por un equipo pequeño con una visión artística única y los conocimientos técnicos necesarios para ejecutarla. O Undertale, creado en gran medida por una sola persona que casualmente reunía la combinación adecuada de instinto creativo y capacidad de programación. O Stardew Valley, para el que Eric Barone pasó años aprendiendo por su cuenta de todo, desde pixel art y composición musical hasta programación en C#.</p>
<p>Estos juegos triunfaron contra todo pronóstico. Pero por cada Limbo hay millones de visiones creativas que murieron porque las herramientas exigían una fluidez técnica que sus creadores no podían aportar. Menos del 3 % de los desarrolladores de videojuegos independientes llegan a alcanzar un éxito significativo. ¿Cuántos juegos brillantes nunca llegaron a crearse porque sus autores chocaron contra un muro de «si» y «entonces» y se rindieron?</p>
<p>La barrera de entrada no era la creatividad. Era la exclusión técnica incorporada en las propias herramientas.</p>
<h2 id="crear-lo-que-deberia-haber-existido" tabindex="-1">Crear lo que debería haber existido <a class="header-anchor" href="#crear-lo-que-deberia-haber-existido" aria-label="Permalink to &quot;Crear lo que debería haber existido&quot;"></a></h2>
<p>Por eso, hace 5 años, empecé a crear algo diferente.</p>
<p>La propuesta era sencilla: el desarrollo de videojuegos debería estar al alcance de cualquiera que tuviera una visión creativa. No deberías necesitar un título en informática para expresarte mediante medios interactivos. Las herramientas deberían adaptarse a cómo piensan realmente las personas creativas, y no al revés.</p>
<p>Inversores de capital riesgo de Sequoia, Pear, Draper y decenas de otras firmas me dijeron que no funcionaría. Es B2C. No existe mercado. Los desarrolladores independientes no pagan por nada. No se puede simplificar el desarrollo de videojuegos sin sacrificar capacidades. Los jugadores quieren juegos complejos, y los juegos complejos requieren herramientas complejas. Millones de excusas disfrazadas de análisis de mercado.</p>
<p>La gente me decía que estaba loca. Tal vez lo estaba. Pero siempre volvía a la misma pregunta: ¿por qué los presupuestos multimillonarios deberían ser un requisito previo para la expresión creativa? Los directores de cine y los productores de videojuegos famosos tienen equipos y recursos. Todos los demás reciben un editor de código y una plegaria. Yo quería crear aquello que cerrara esa brecha. Describes lo que quieres y ocurre ante tus ojos. Cada parte de mí sabía que aquello era lo correcto. Lo sentía en cada célula de mi cuerpo.</p>
<p>Hoy, miles de personas utilizan Cinevva a diario para crear recursos 3D para videojuegos, juegos, música, niveles y experiencias. Los proyectos creados hasta ahora acumulan millones de visualizaciones. Y crecemos cada día. Una presentación de dos minutos en Sand Hill Road no es precisamente el formato ideal para decir: «Suspendí el SAT, pero confíen en mi intuición».</p>
<h2 id="lo-que-significa-realmente-la-intuicion" tabindex="-1">Lo que significa realmente la intuición <a class="header-anchor" href="#lo-que-significa-realmente-la-intuicion" aria-label="Permalink to &quot;Lo que significa realmente la intuición&quot;"></a></h2>
<p><a href="https://singjupost.com/transcript-jensen-huangs-interview-cisco-ai-summit-2026/" target="_blank" rel="noreferrer">Huang</a> no estaba planteando únicamente una cuestión filosófica. Estaba describiendo un cambio real en lo que constituye una inteligencia valiosa.</p>
<p>Durante décadas optimizamos las cosas equivocadas. Construimos sistemas educativos que premiaban la memorización y el cálculo. Diseñamos exámenes estandarizados que medían la capacidad de reconocer patrones en problemas vistos anteriormente. Contratamos a personas basándonos en credenciales que demostraban que podían sobrevivir a cuatro años de filtros académicos. La IA acaba de hacer que todo eso sea menos especial.</p>
<p>Lo que la IA no puede hacer, al menos por ahora, es percibir lo que falta. Sentir cuándo algo no encaja. Intuir lo que la gente necesita antes de que pueda expresarlo por sí misma. Leer el ambiente. Comprender un contexto que no está recogido en ningún conjunto de datos.</p>
<p>Invertí mi tiempo, mi experiencia de vida internacional, mi dinero y mis conocimientos intuitivos en crear Cinevva. Es una combinación difícil de obtener en la universidad. Difícil de evaluar en el SAT. Difícil de reflejar en cualquier sistema de credenciales diseñado antes de que la IA hiciera abundante la potencia cognitiva pura.</p>
<p>Hace dieciséis o veinte años, los informáticos decidían qué aspecto debían tener las herramientas y cómo debían funcionar. Las creaban para sí mismos, para personas que pensaban como ellos. Se esperaba que el resto nos adaptáramos. Esa era está terminando. Quienes darán forma a lo que viene serán quienes entiendan lo que realmente quieren los seres humanos. Quienes puedan sentir cuándo algo está mal y cuándo está bien. Quienes creen para las personas en lugar de hacerlo para lograr elegancia técnica.</p>
<p>Confié en algo dentro de mí que el sistema consideraba inútil. Y tenía razón.</p>
<hr>
<p><strong>Relacionado:</strong></p>
<ul>
<li><a href="/es/blog/2026-01-18-skills-over-degrees.html">El mercado laboral se está transformando: de las credenciales a las habilidades</a></li>
<li><a href="/es/guides/game-dev-courses.html">Cursos de desarrollo de videojuegos en línea</a> — caminos centrados en las habilidades que eluden los filtros tradicionales</li>
<li><a href="/es/signals/2026-03-04-everyone-wants-ai-game-engine.html">Ahora todos quieren ser el motor de videojuegos con IA</a> — el cambio del sector hacia herramientas que se adaptan a la forma de pensar de las personas</li>
</ul>
]]></content:encoded>
            <enclosure url="https://cdn.cinevva.com/blog/game-jam-houston-2018.png" length="0" type="image/png"/>
        </item>
        <item>
            <title><![CDATA[Controversia sobre la IA, confianza y economía pos-IA en los videojuegos]]></title>
            <link>https://app.cinevva.com/es/blog/2026-01-18-ai-controversy-and-post-ai-economy</link>
            <guid>https://app.cinevva.com/es/blog/2026-01-18-ai-controversy-and-post-ai-economy</guid>
            <pubDate>Sun, 18 Jan 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Una perspectiva práctica: la IA no es lo importante, sino la confianza. Por qué el etiquetado, los filtros y una distribución justa importan más que los debates entre partidarios y detractores de la IA.]]></description>
            <content:encoded><![CDATA[<h1 id="controversia-sobre-la-ia-confianza-y-economia-pos-ia-en-los-videojuegos" tabindex="-1">Controversia sobre la IA, confianza y economía pos-IA en los videojuegos <a class="header-anchor" href="#controversia-sobre-la-ia-confianza-y-economia-pos-ia-en-los-videojuegos" aria-label="Permalink to &quot;Controversia sobre la IA, confianza y economía pos-IA en los videojuegos&quot;"></a></h1>
<p><em>Por <a href="/es/about.html">Oleg Sidorkin</a>, director de tecnología de Cinevva</em></p>
<p>La IA en los videojuegos se convirtió en un auténtico campo de minas hacia mediados de 2024. Puestos de trabajo que desaparecen. Personas convencidas de que serán las siguientes. Cuestiones de derechos de autor que ni siquiera los abogados pueden desenredar. Debates estéticos interminables que vuelven una y otra vez al punto de partida. Steam ahogándose en contenido que nadie pidió. Y, por debajo de todo, esa inquietud persistente que ahora tiene cada creador: «¿De verdad estoy creando algo o solo... escribiendo prompts?».</p>
<p>Gestionamos una plataforma. Y al hacerlo, hay algo que se aprende rápido.</p>
<p><strong>A nadie le gusta sentirse engañado.</strong></p>
<h2 id="estas-cifras-nos-sorprendieron" tabindex="-1">Estas cifras nos sorprendieron <a class="header-anchor" href="#estas-cifras-nos-sorprendieron" aria-label="Permalink to &quot;Estas cifras nos sorprendieron&quot;"></a></h2>
<p>Pensábamos que la adopción de la IA crecería. Pero no así. Esta era la situación a finales de 2025:</p>
<table tabindex="0">
<thead>
<tr>
<th>Lo que medimos</th>
<th>2024</th>
<th>2025</th>
<th>El cambio</th>
</tr>
</thead>
<tbody>
<tr>
<td>Juegos de Steam que declaran usar IA</td>
<td>~1.000</td>
<td>7.818</td>
<td>Aumento de 7 veces</td>
</tr>
<tr>
<td>Nuevos lanzamientos en Steam que usan IA</td>
<td>~3 %</td>
<td>~20 %</td>
<td>Uno de cada cinco</td>
</tr>
<tr>
<td>Desarrolladores que creen que la IA perjudica la calidad</td>
<td>34 %</td>
<td>47 %</td>
<td>Trece puntos más</td>
</tr>
<tr>
<td>Desarrolladores que creen que la IA mejora la calidad</td>
<td>—</td>
<td>11 %</td>
<td>No son muchos</td>
</tr>
<tr>
<td>Ingresos de juegos que declaran usar IA</td>
<td>—</td>
<td>660 M$</td>
<td>Doce juegos superaron las ocho cifras</td>
</tr>
</tbody>
</table>
<p>Fuentes: análisis de Tom's Hardware / Totally Human Media, encuesta de desarrolladores de GDC 2025 e informe Unity 2025 Gaming Report</p>
<h2 id="que-ocurrio-realmente-para-que-los-jugadores-se-volvieran-tan-escepticos" tabindex="-1">Qué ocurrió realmente para que los jugadores se volvieran tan escépticos <a class="header-anchor" href="#que-ocurrio-realmente-para-que-los-jugadores-se-volvieran-tan-escepticos" aria-label="Permalink to &quot;Qué ocurrió realmente para que los jugadores se volvieran tan escépticos&quot;"></a></h2>
<p>Esto no surgió de la nada. Hubo problemas reales. Y la gente los recuerda.</p>
<h3 id="los-actores-de-voz-descubrieron-que-los-habian-clonado-el-dia-del-lanzamiento" tabindex="-1">Los actores de voz descubrieron que los habían clonado el día del lanzamiento <a class="header-anchor" href="#los-actores-de-voz-descubrieron-que-los-habian-clonado-el-dia-del-lanzamiento" aria-label="Permalink to &quot;Los actores de voz descubrieron que los habían clonado el día del lanzamiento&quot;"></a></h3>
<p><em>Tomb Raider 4-6 Remastered</em> salió con versiones generadas por IA de las interpretaciones de voz originales. Los actores se enteraron al mismo tiempo que todos los demás: el día del lanzamiento. Al final, la distribuidora eliminó esas voces mediante un parche tras aumentar la presión legal. ¿Aquella huelga de SAG-AFTRA que duró once meses? Este era exactamente el tipo de situación que la impulsaba.</p>
<h3 id="«basura-de-ia»-se-convirtio-en-una-expresion-habitual" tabindex="-1">«Basura de IA» se convirtió en una expresión habitual <a class="header-anchor" href="#«basura-de-ia»-se-convirtio-en-una-expresion-habitual" aria-label="Permalink to &quot;«Basura de IA» se convirtió en una expresión habitual&quot;"></a></h3>
<p><em>Call of Duty: Black Ops 6</em> añadió discretamente una declaración sobre el uso de IA a su página de Steam. Después de que el juego ya hubiera salido. Los jugadores habían detectado cosas extrañas: fallos visuales dispersos por todas partes. Un personaje de una pantalla de carga tenía seis dedos. «Basura de IA» se convirtió en una forma abreviada de referirse a cualquier cosa que se ve... rara. Vacía. Como si a nadie le hubiera importado lo suficiente como para revisarla.</p>
<h3 id="desaparecio-una-nominacion-a-un-premio" tabindex="-1">Desapareció una nominación a un premio <a class="header-anchor" href="#desaparecio-una-nominacion-a-un-premio" aria-label="Permalink to &quot;Desapareció una nominación a un premio&quot;"></a></h3>
<p>A <em>Clair Obscur: Expedition 33</em> le retiraron su nominación a Juego del Año en los Indie Game Awards. Sin embargo, el juego publicado no usaba IA. El problema eran los recursos provisionales generados con IA durante el desarrollo: material interno que nunca llegó a los jugadores. Los recursos finales fueron creados íntegramente por personas. No importó. Siguieron semanas de discusiones sobre dónde debía trazarse exactamente la línea.</p>
<h3 id="equipos-que-nunca-usaron-ia-tuvieron-que-demostrarlo" tabindex="-1">Equipos que nunca usaron IA tuvieron que demostrarlo <a class="header-anchor" href="#equipos-que-nunca-usaron-ia-tuvieron-que-demostrarlo" aria-label="Permalink to &quot;Equipos que nunca usaron IA tuvieron que demostrarlo&quot;"></a></h3>
<p>Tanto <em>Chessplus</em> como <em>Peak</em> fueron acusados de usar IA. Ninguno la había utilizado. Ambos estaban nominados a premios. Los dos equipos de desarrollo terminaron rebuscando entre capturas antiguas y archivos con capas solo para demostrar que su trabajo estaba hecho a mano. El equipo de <em>Peak</em> lo expresó mejor que nadie: «Puede que seamos basura, pero somos basura artesanal, de origen local y hecha por personas».</p>
<h3 id="los-estudios-tomaron-direcciones-completamente-opuestas" tabindex="-1">Los estudios tomaron direcciones completamente opuestas <a class="header-anchor" href="#los-estudios-tomaron-direcciones-completamente-opuestas" aria-label="Permalink to &quot;Los estudios tomaron direcciones completamente opuestas&quot;"></a></h3>
<p><strong>SNK</strong> — Los moderadores de Discord abandonaron su puesto después de que aparecieran imágenes con aspecto de estar generadas por IA en un tráiler de <em>Fatal Fury: City of the Wolves</em>. <strong>Games Workshop</strong> — Prohibió por completo la IA en todas las propiedades de Warhammer. <strong>Larian Studios</strong> — Afirmó que solo usó IA para bocetos conceptuales muy preliminares de Baldur's Gate 3 y que no había nada generado con IA en el juego final. <strong>Tim Sweeney</strong> — Declaró que las etiquetas de IA de Steam no servían para nada y que debían eliminarse. <strong>Valve</strong> — Replicó que los desarrolladores que se quejan de las etiquetas de IA suelen temer que su trabajo parezca «hecho con poco esfuerzo».</p>
<h2 id="encontrar-juegos-se-convirtio-en-un-problema-de-confianza" tabindex="-1">Encontrar juegos se convirtió en un problema de confianza <a class="header-anchor" href="#encontrar-juegos-se-convirtio-en-un-problema-de-confianza" aria-label="Permalink to &quot;Encontrar juegos se convirtió en un problema de confianza&quot;"></a></h2>
<p>Ahora se produce contenido más rápido de lo que nadie puede evaluarlo adecuadamente. Las preguntas han cambiado:</p>
<p>¿Qué estoy viendo exactamente?
¿Quién ha hecho esto?
¿Me arrepentiré del tiempo que le dedique?
¿Se corresponde algo de esto con lo que prometía el tráiler?</p>
<p>Probablemente no habrá una gran resolución. Ningún veredicto definitivo sobre la IA frente al trabajo humano.</p>
<p>Lo más probable es que veamos <strong>filtros, transparencia real y estructuras de incentivos que fomenten la honestidad</strong>.</p>
<h2 id="los-pequenos-estudios-atrapados-en-medio-de-todo-esto" tabindex="-1">Los pequeños estudios, atrapados en medio de todo esto <a class="header-anchor" href="#los-pequenos-estudios-atrapados-en-medio-de-todo-esto" aria-label="Permalink to &quot;Los pequeños estudios, atrapados en medio de todo esto&quot;"></a></h2>
<p>Los desarrolladores independientes han quedado en una posición extraña.</p>
<p><strong>Las ventajas son realmente difíciles de ignorar:</strong>
Se puede iterar más rápido. Los costes bajan cuando cuatro personas tienen que hacerlo todo. Ahora los desarrolladores en solitario pueden llegar a terminar sus proyectos. La localización deja de comerse todo el presupuesto.</p>
<p><strong>Las desventajas son igual de reales:</strong>
Resultados que parecen genéricos. Preocupaciones sobre los datos de entrenamiento y la propiedad intelectual que los abogados todavía no quieren abordar. Publicar sistemas que no se comprenden del todo: algunos lo llaman deuda de comprensión. Quedar agrupado con la avalancha de lanzamientos hechos con poco esfuerzo. Casi la mitad de los desarrolladores encuestados cree que la IA empeora los videojuegos en general.</p>
<p>El informe de Unity de 2025 afirma que el 79 % de los desarrolladores ve con buenos ojos las herramientas de IA. Parece bastante concluyente. La realidad es más complicada. Los equipos que lo hacen bien suelen usar la IA para las partes aburridas: tareas pesadas, borradores iniciales y labores tediosas de control de calidad. ¿La dirección creativa? Esa sigue en manos humanas.</p>
<h2 id="la-postura-de-cinevva-neutral-ante-la-ia-estricta-con-la-honestidad" tabindex="-1">La postura de Cinevva: neutral ante la IA, estricta con la honestidad <a class="header-anchor" href="#la-postura-de-cinevva-neutral-ante-la-ia-estricta-con-la-honestidad" aria-label="Permalink to &quot;La postura de Cinevva: neutral ante la IA, estricta con la honestidad&quot;"></a></h2>
<p>No rechazamos juegos por usar IA. Tampoco les damos un trato especial.</p>
<p>La regla es sencilla: <strong>si intervino la IA, hay que decirlo.</strong> Los jugadores deciden qué les importa. Así los filtros funcionan de verdad.</p>
<ul>
<li><a href="/es/ai-content.html">Política sobre contenido generado por IA</a></li>
</ul>
<h2 id="los-filtros-funcionan-mejor-que-las-discusiones" tabindex="-1">Los filtros funcionan mejor que las discusiones <a class="header-anchor" href="#los-filtros-funcionan-mejor-que-las-discusiones" aria-label="Permalink to &quot;Los filtros funcionan mejor que las discusiones&quot;"></a></h2>
<p>El debate sobre la IA en los videojuegos no alcanzará un consenso pronto. Probablemente nunca. Pero ¿las preferencias individuales? Esas sí están bastante claras.</p>
<p>Algunos jugadores buscan específicamente arte dirigido por personas. Textos escritos por una persona. Un trabajo artesanal visible.</p>
<p>A otros, sinceramente, no les importa. Si es divertido, es divertido.</p>
<p>Los filtros permiten que ambos grupos encuentren lo que buscan. Nadie tiene que ganar.</p>
<h2 id="los-modelos-de-pago-importan-mas-que-la-opinion-de-cualquiera" tabindex="-1">Los modelos de pago importan más que la opinión de cualquiera <a class="header-anchor" href="#los-modelos-de-pago-importan-mas-que-la-opinion-de-cualquiera" aria-label="Permalink to &quot;Los modelos de pago importan más que la opinión de cualquiera&quot;"></a></h2>
<p>Cuando los ingresos dependen del <strong>tiempo de juego</strong> en lugar de las ventas por unidad, se gana dinero de esta forma:</p>
<p>Captando rápido a los jugadores. Manteniendo su atención. Ofreciendo lo que prometía el marketing.</p>
<p>La calidad se convierte en el camino evidente. Cómo se creó el juego importa menos.</p>
<p>¿El tráiler promete demasiado? Los jugadores se marchan de inmediato. La retención se desploma. ¿Les muestras exactamente lo que van a recibir? Se quedan. El tiempo de juego aumenta. Llegan los ingresos. La propia economía pone las cosas en su sitio.</p>
<h2 id="lo-que-probablemente-traera-2026" tabindex="-1">Lo que probablemente traerá 2026 <a class="header-anchor" href="#lo-que-probablemente-traera-2026" aria-label="Permalink to &quot;Lo que probablemente traerá 2026&quot;"></a></h2>
<p><strong>Más normas</strong> — La Ley de IA de la UE sigue ampliándose. Las protecciones de la voz y la imagen en Estados Unidos están creciendo, especialmente después de SAG-AFTRA.</p>
<p><strong>Herramientas especializadas</strong> — IA creada específicamente para equipos pequeños. Diseñada para que las personas mantengan el control.</p>
<p><strong>Etiquetas más precisas</strong> — «Hecho con IA» es demasiado impreciso. Cabe esperar distinciones entre flujos de trabajo asistidos por IA y recursos finales generados por IA.</p>
<p><strong>División del público</strong> — Algunos jugadores buscarán deliberadamente juegos creados mediante métodos tradicionales. Otros ni siquiera pensarán en ello. Ambos grupos son lo bastante grandes como para crear juegos para ellos.</p>
<p><strong>Competencia entre plataformas</strong> — La forma en que las tiendas gestionen la transparencia y el descubrimiento se convertirá en un verdadero factor diferenciador.</p>
<h2 id="lo-que-realmente-hace-avanzar-las-cosas" tabindex="-1">Lo que realmente hace avanzar las cosas <a class="header-anchor" href="#lo-que-realmente-hace-avanzar-las-cosas" aria-label="Permalink to &quot;Lo que realmente hace avanzar las cosas&quot;"></a></h2>
<p>Discutir no resolverá la cuestión de la IA. Lo que sí lo hará:</p>
<ol>
<li><strong>Los jugadores</strong>, eligiendo en función de lo que realmente les importa</li>
<li><strong>Los creadores</strong>, siendo honestos sobre cómo trabajan</li>
<li><strong>Las plataformas</strong>, creando herramientas que ayuden a ambos grupos a encontrarse</li>
</ol>
<p>Esa es la economía pos-IA. No bandos enfrentados. La confianza manteniéndolo todo unido.</p>
<hr>
<p><strong>Relacionado:</strong></p>
<ul>
<li><a href="/es/ai-content.html">Política sobre contenido generado por IA</a></li>
<li><a href="/es/creators.html">Para creadores de juegos</a></li>
<li><a href="/es/faq.html">Preguntas frecuentes</a></li>
<li><a href="/es/guides/frontier-gen-ai-models.html">Modelos frontera de IA generativa de código abierto</a> — los modelos concretos y cómo funcionan</li>
<li><a href="/es/signals/2026-03-06-open-source-ai-pollution.html">El código abierto tiene un problema de contaminación por IA</a> — qué ocurre cuando los resultados de la IA inundan los proyectos de código abierto</li>
</ul>
]]></content:encoded>
            <enclosure url="https://app.cinevva.com/img/blog/ai-controversy-trust.png" length="0" type="image/png"/>
        </item>
        <item>
            <title><![CDATA[El mercado laboral se está transformando: de los títulos a las habilidades]]></title>
            <link>https://app.cinevva.com/es/blog/2026-01-18-skills-over-degrees</link>
            <guid>https://app.cinevva.com/es/blog/2026-01-18-skills-over-degrees</guid>
            <pubDate>Sun, 18 Jan 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[El 90 % de las empresas ya prioriza las habilidades sobre los títulos universitarios. Esto es lo que significa para quienes acaban de graduarse y quieren entrar en el sector tecnológico y el desarrollo de videojuegos.]]></description>
            <content:encoded><![CDATA[<h1 id="el-mercado-laboral-se-esta-transformando-de-los-titulos-a-las-habilidades" tabindex="-1">El mercado laboral se está transformando: de los títulos a las habilidades <a class="header-anchor" href="#el-mercado-laboral-se-esta-transformando-de-los-titulos-a-las-habilidades" aria-label="Permalink to &quot;El mercado laboral se está transformando: de los títulos a las habilidades&quot;"></a></h1>
<p><em>Por <a href="/es/about.html">Oleg Sidorkin</a>, CTO de Cinevva</em></p>
<p>Vi a mi primo graduarse con honores en 2023. Tenía un grado en informática de una buena universidad pública y un expediente sólido. Pasó catorce meses solicitando empleos antes de conseguir uno. Mientras tanto, un amigo que dejó la universidad en segundo año para crear juegos independientes recibió tres ofertas en el plazo de un mes desde que decidió empezar a buscar.</p>
<p>Eso ya no es una anomalía. Es la norma.</p>
<h2 id="las-cifras-por-fin-confirman-lo-que-veniamos-percibiendo" tabindex="-1">Las cifras por fin confirman lo que veníamos percibiendo <a class="header-anchor" href="#las-cifras-por-fin-confirman-lo-que-veniamos-percibiendo" aria-label="Permalink to &quot;Las cifras por fin confirman lo que veníamos percibiendo&quot;"></a></h2>
<p>En 2025, el <strong>90 % de los responsables de RR. HH.</strong> afirmó contratar a personas sin el tradicional título universitario de cuatro años (<a href="https://fortune.com/2025/07/01/90-percent-hr-leaders-looking-to-hire-outside-of-traditional-college-degrees-as-they-prioritize-skills/" target="_blank" rel="noreferrer">Fortune</a>). Una cuarta parte de las empresas estadounidenses eliminó por completo el requisito de tener un grado universitario (<a href="https://www.hrdive.com/news/employer-eliminate-degree-requirements-2025/748998/" target="_blank" rel="noreferrer">HR Dive</a>). Y esta es la parte que duele si acabas de terminar de pagar tus préstamos estudiantiles: <strong>el 94 % de los empleadores afirma que las contrataciones basadas en habilidades rinden mejor que las basadas en títulos</strong> (<a href="https://www.forbes.com/sites/cynthiapong/2024/12/26/90-of-companies-make-better-hires-based-on-skills-over-degrees/" target="_blank" rel="noreferrer">Forbes</a>).</p>
<p>Verizon afirma ahora que el 99 % de sus puestos no requiere un título universitario. Sergey Brin admitió que Google contrata a «muchísimas» personas sin grado universitario. IBM hizo que la mitad de sus vacantes en Estados Unidos no exigieran titulación mediante su programa «New Collar».</p>
<p>No es que las empresas estén siendo caritativas. Se dieron cuenta de que los títulos no permitían predecir quién sería realmente bueno en el trabajo.</p>
<h2 id="por-que-se-rompio-el-antiguo-sistema" tabindex="-1">Por qué se rompió el antiguo sistema <a class="header-anchor" href="#por-que-se-rompio-el-antiguo-sistema" aria-label="Permalink to &quot;Por qué se rompió el antiguo sistema&quot;"></a></h2>
<p>¿La respuesta sincera? Los títulos se convirtieron en un filtro fácil.</p>
<p>Cuando estás contratando y tienes 400 solicitudes, exigir un grado universitario reduce la pila a la mitad. No te dice quién puede hacer realmente el trabajo. Te dice quién tuvo el dinero, el tiempo y la estabilidad familiar necesarios para pasar cuatro años en las aulas. Esa correlación con la capacidad siempre fue más débil de lo que fingíamos.</p>
<p>Y ahora han ocurrido tres cosas a la vez:</p>
<p><strong>Las habilidades evolucionaron demasiado rápido.</strong> Motores de videojuegos, herramientas de IA, frameworks web. Para cuando un comité académico aprueba un curso sobre algo, ese algo ya está obsoleto. Un grado de cuatro años te enseña teoría de hace cuatro años. En tecnología, eso es historia antigua.</p>
<p><strong>Los portafolios se volvieron irrefutables.</strong> ¿Por qué intentar adivinar si alguien sabe programar cuando puedes mirar su GitHub? ¿Por qué preguntarte si puede publicar un juego cuando su página de itch.io tiene cinco proyectos terminados con reseñas de jugadores?</p>
<p><strong>Las empresas se desesperaron.</strong> La escasez de talento es real. Excluir a todo el mundo que no tenga un título implica excluir a personas que podrían ser exactamente lo que necesitas. Algunos responsables de contratación lo descubrieron por las malas, tras ver cómo desarrolladores autodidactas superaban con creces a empleados con títulos.</p>
<h2 id="la-industria-de-los-videojuegos-lo-vio-venir" tabindex="-1">La industria de los videojuegos lo vio venir <a class="header-anchor" href="#la-industria-de-los-videojuegos-lo-vio-venir" aria-label="Permalink to &quot;La industria de los videojuegos lo vio venir&quot;"></a></h2>
<p>Creo que el sector de los videojuegos se ha adelantado a esta tendencia, y merece la pena entender por qué.</p>
<p>A los estudios nunca les importó demasiado dónde estudiaste. Les importaba lo que habías publicado. Un juego pulido creado durante una game jam de 48 horas le dice más a un responsable de contratación que cualquier grado de cuatro años en diseño de videojuegos. Demuestra que sabes terminar proyectos bajo presión. Demuestra que tomaste decisiones difíciles sobre el alcance. Demuestra que el juego es jugable, no solo teórico.</p>
<p>Si intentas abrirte camino en la industria de los videojuegos en 2026, esto es lo que realmente importa (<a href="https://www.dice.com/career-advice/aspiring-video-game-designers-in-2025-what-you-need-to-know" target="_blank" rel="noreferrer">Dice</a>, <a href="https://combinegr.com/2025-global-gaming-employment-outlook-trends-talent-strategy/" target="_blank" rel="noreferrer">CombineGR</a>): dos o tres demos pulidas y jugables. Estudios de caso que expliquen qué hiciste y por qué. Pruebas de que terminas los proyectos. Dominio de al menos un motor importante, demostrado mediante proyectos reales.</p>
<p>Los responsables de contratación no buscan potencial. Buscan pruebas.</p>
<h2 id="la-parte-incomoda-de-la-que-nadie-habla" tabindex="-1">La parte incómoda de la que nadie habla <a class="header-anchor" href="#la-parte-incomoda-de-la-que-nadie-habla" aria-label="Permalink to &quot;La parte incómoda de la que nadie habla&quot;"></a></h2>
<p>Hay algo que me frustró cuando profundicé en la investigación.</p>
<p>Un estudio de Harvard y Burning Glass descubrió que las empresas que eliminaban los requisitos de titulación a menudo no contrataban realmente a más candidatos sin título. El aumento fue de solo unos 3,5 puntos porcentuales (<a href="https://www.forbes.com/sites/jenamcgregor/2024/02/14/companies-are-dropping-diploma-requirements-for-more-jobs-but-hiring-few-non-degreed-workers-to-fill-them/" target="_blank" rel="noreferrer">Forbes</a>). La política cambió. Las prácticas de contratación se quedaron atrás.</p>
<p>Eso significa que, si sigues una vía no tradicional, todavía tienes que esforzarte más. La puerta está más abierta que antes, pero aún no entras en igualdad de condiciones. Tu portafolio tiene que ser irrefutable. Tus proyectos deben hablar más alto que los títulos de otra persona.</p>
<p>No es justo. Pero saberlo te ayuda a prepararte.</p>
<h2 id="lo-que-le-diria-a-alguien-que-empieza-ahora-mismo" tabindex="-1">Lo que le diría a alguien que empieza ahora mismo <a class="header-anchor" href="#lo-que-le-diria-a-alguien-que-empieza-ahora-mismo" aria-label="Permalink to &quot;Lo que le diría a alguien que empieza ahora mismo&quot;"></a></h2>
<p>Si estás estudiando, no lo dejes. Pero entiende que el título por sí solo ya no es suficiente. Crea proyectos en paralelo. Participa en game jams. Obtén un <a href="https://grow.google/certificates/" target="_blank" rel="noreferrer">Certificado Profesional de Google</a> o una certificación de Unity. Considera el título como una credencial más entre varias, no como la credencial definitiva.</p>
<p>Si no estás estudiando una carrera, tienes un camino diferente, pero no necesariamente más difícil. Crea proyectos sin parar. Publícalos. Documenta todo. Tu <a href="https://github.com" target="_blank" rel="noreferrer">GitHub</a>, tu página de <a href="https://itch.io" target="_blank" rel="noreferrer">itch.io</a>, tu sitio web personal. Esas son ahora tus credenciales.</p>
<p>En cualquier caso, practica cómo explicar tu trabajo. No solo qué creaste, sino por qué tomaste esas decisiones. Qué harías de otra manera. Qué aprendiste. Los entrevistadores recuerdan a quienes saben articular su forma de pensar.</p>
<h2 id="esto-va-mas-alla-de-la-contratacion" tabindex="-1">Esto va más allá de la contratación <a class="header-anchor" href="#esto-va-mas-alla-de-la-contratacion" aria-label="Permalink to &quot;Esto va más allá de la contratación&quot;"></a></h2>
<p>Lo que está ocurriendo no es solo un cambio en la forma en que las empresas cubren puestos. Es un cambio en lo que valoramos colectivamente.</p>
<p>Durante décadas, los títulos sirvieron como filtro. Caros y lentos de obtener, pero fáciles de interpretar. Si alguien tenía un título, podías dar ciertas cosas por sentadas. Era una señal, no una medida directa, pero era suficiente.</p>
<p>Esa señal se está desmoronando. La tecnología permite ver lo que alguien sabe hacer realmente. El trabajo remoto demostró que los resultados importan más que el lugar desde el que trabajas. La IA está haciendo que el conocimiento teórico sea menos valioso que la aplicación práctica.</p>
<p>Esto me parece realmente esperanzador, aunque la transición sea complicada. Antes la pregunta era: «¿Dónde estudiaste?». Ahora es: «¿Qué sabes crear?».</p>
<p>Esa es una pregunta mejor.</p>
<hr>
<h2 id="fuentes" tabindex="-1">Fuentes <a class="header-anchor" href="#fuentes" aria-label="Permalink to &quot;Fuentes&quot;"></a></h2>
<ul>
<li><a href="https://fortune.com/2025/07/01/90-percent-hr-leaders-looking-to-hire-outside-of-traditional-college-degrees-as-they-prioritize-skills/" target="_blank" rel="noreferrer">Fortune: El 90 % de los responsables de RR. HH. contrata a personas sin títulos tradicionales</a></li>
<li><a href="https://www.forbes.com/sites/cynthiapong/2024/12/26/90-of-companies-make-better-hires-based-on-skills-over-degrees/" target="_blank" rel="noreferrer">Forbes: El 90 % de las empresas realiza mejores contrataciones basándose en las habilidades</a></li>
<li><a href="https://www.forbes.com/sites/jenamcgregor/2024/02/14/companies-are-dropping-diploma-requirements-for-more-jobs-but-hiring-few-non-degreed-workers-to-fill-them/" target="_blank" rel="noreferrer">Forbes: Las empresas eliminan los requisitos de titulación, pero contratan a pocas personas sin título</a></li>
<li><a href="https://www.hrdive.com/news/employer-eliminate-degree-requirements-2025/748998/" target="_blank" rel="noreferrer">HR Dive: Los empleadores eliminan los requisitos de titulación</a></li>
<li><a href="https://www.computerworld.com/article/1623286/no-degree-no-problem-tech-firms-move-away-from-college-requirement-for-new-hires.html" target="_blank" rel="noreferrer">Computerworld: Las empresas tecnológicas se alejan del requisito de tener estudios universitarios</a></li>
<li><a href="https://www.dice.com/career-advice/aspiring-video-game-designers-in-2025-what-you-need-to-know" target="_blank" rel="noreferrer">Dice: Aspirantes a diseñadores de videojuegos en 2025</a></li>
<li><a href="https://combinegr.com/2025-global-gaming-employment-outlook-trends-talent-strategy/" target="_blank" rel="noreferrer">CombineGR: Perspectivas mundiales del empleo en videojuegos para 2025</a></li>
</ul>
<hr>
<p><strong>Relacionado:</strong></p>
<ul>
<li><a href="/es/guides/game-jams-hackathons.html">Cómo triunfar en las game jams</a></li>
<li><a href="/es/guides/game-dev-courses.html">Cursos en línea de desarrollo de videojuegos</a> — itinerarios de aprendizaje centrados en habilidades para todos los presupuestos</li>
<li><a href="/es/tutorials/agentic-code-tools.html">Herramientas de programación con IA agéntica</a> — las herramientas que están redefiniendo qué habilidades importan</li>
<li><a href="/es/blog/2026-02-10-the-intuitive-mind.html">La mente intuitiva</a> — por qué la intuición importa más que los títulos</li>
</ul>
]]></content:encoded>
            <enclosure url="https://app.cinevva.com/img/blog/skills-over-degrees.jpg" length="0" type="image/jpg"/>
        </item>
    </channel>
</rss>