Skip to content

Por qué creamos nuestro propio motor WebGPU en vez de bifurcar PlayCanvas

Por Oleg Sidorkin, CTO y cofundador de Cinevva

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

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?

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 serie de ingeniería sobre cómo crear un mundo abierto en el navegador, así que, cuando alguna afirmación de este artículo tenga detrás un registro práctico, incluiré un enlace.

Las opciones que evaluamos de verdad

Hay cuatro cosas a las que se suele llamar «motores de juegos web», pero no son el mismo tipo de herramienta.

Three.js 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.

Babylon.js 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.

PlayCanvas 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.

Unity WebGL 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.

Cualquiera de estas opciones es una base razonable para un juego web normal. Nosotros no teníamos un juego web normal.

Primera decisión: WebGPU es nuestro punto de partida, no nuestra meta

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.

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.

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.

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.

Segunda decisión: un solucionador para personajes, no un motor de física

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.

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.

Por eso, nuestro controlador de personajes es una máquina de estados multicanal conectable. 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.

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.

Tercera decisión: animaciones que pueden trasladarse entre rigs

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 personajes universales.

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.

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.

Cuarta decisión: la parte que ningún motor incluye

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.

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.

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.

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.

Cuándo no deberías hacer lo mismo que nosotros

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.

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.