Por que criamos nosso próprio motor WebGPU em vez de fazer um fork do PlayCanvas
Por Oleg Sidorkin, CTO e cofundador da Cinevva

Toda pessoa da área técnica que conhece o Cinevva World faz a mesma pergunta nos primeiros cinco minutos. Vocês são uma equipe pequena. Já existem motores 3D maduros para a web. Por que escreveram seu próprio renderizador, sua própria física de personagens e seu próprio sistema de animação, em vez de usar PlayCanvas ou Babylon como base e lançar mais rápido?
É uma pergunta justa, e “não foi inventado aqui” é a resposta errada. Fizemos a lição de casa. Testamos os motores existentes, lemos seu código-fonte e criamos protótipos sobre dois deles antes de decidir. Este post traz a versão honesta dessa decisão: no que as opções prontas são realmente boas, os quatro pontos em que nossas necessidades divergiram o bastante para justificar construir algo próprio e as situações em que você deveria escolher uma delas em vez de nos imitar. Documentamos o desenvolvimento em si em uma longa série de engenharia sobre um mundo aberto no navegador. Portanto, quando uma afirmação abaixo tiver um registro prático por trás dela, incluirei o link.
As opções que realmente avaliamos
Quatro coisas são chamadas de “motores de jogos para a web”, mas elas não são o mesmo tipo de ferramenta.
Three.js é uma biblioteca de renderização, não um motor de jogos. Ela oferece um grafo de cena, materiais, carregadores e um renderizador, e então sai do seu caminho. Não há editor, física, sistema de entidades nem uma opinião sobre como seu jogo deve ser estruturado. Esse é tanto o atrativo quanto o custo. Você constrói por conta própria tudo o que fica acima do renderizador, mas nada atrapalha. Ela usa a licença MIT, tem o maior ecossistema desse segmento e, quando você encontra um bug obscuro de shader às duas da manhã, há uma resposta no fórum esperando por você.
Babylon.js é um motor completo com grafo de cena, integração de física (Havok), pipeline de assets e editor web. Ele usa a licença MIT, conta com o apoio de uma equipe da Microsoft e seu trabalho com WebGPU tem avançado rapidamente. Se você quer uma solução completa e não se importa em trabalhar dentro da estrutura do motor, é uma ótima escolha padrão.
PlayCanvas é o que mais se aproxima de uma “Unity para a web”. No momento em que este texto foi escrito, o motor estava na versão v2.19.6, lançada em 5 de junho de 2026, e o motor em si é open source sob a licença MIT. Porém, o que a maioria das pessoas realmente usa é o editor visual hospedado, e esse editor é um produto comercial, não open source. O PlayCanvas usa um sistema de entidade-componente, permite criar scripts em TypeScript ou JavaScript, processa assets por meio de um pipeline GLB no servidor e já foi usado para lançar jogos comerciais reais (a Snap, por exemplo, usa o PlayCanvas em produção). Seu renderizador roda em WebGL2, com um caminho WebGPU que ainda está amadurecendo, em vez de ser o padrão. Esse último detalhe importa mais do que parece, e voltarei a ele.
Unity WebGL nem sequer é um motor web. É um destino de exportação. Você desenvolve no editor desktop da Unity e compila para um pacote WebGL. É a ferramenta certa quando você já tem um jogo na Unity e quer levá-lo ao navegador, e a ferramenta errada quando “carregar instantaneamente em uma aba de um celular intermediário” é um requisito obrigatório, porque o runtime e o peso do download vêm junto.
Qualquer uma dessas opções é uma base razoável para um jogo web comum. Nós não tínhamos um jogo web comum.
Primeira decisão: WebGPU é nosso ponto de partida, não nossa linha de chegada
A diferença que nos afasta de todas as soluções prontas é esta: para nós, WebGPU é um requisito, não um recurso que adotaremos no futuro.
Nosso terreno não é um heightmap estático. Ele é um híbrido entre um campo de heightmap transmitido sob demanda e chunks de marching cubes sustentados por um campo de distância com sinal, para que o mundo possa ter cavernas e saliências reais e os criadores possam esculpi-lo ao vivo. Os pincéis de escultura, a distribuição da vegetação e a geração da malha do terreno são executados como compute shaders. Sem computação, o mundo não perde apenas qualidade: ele simplesmente não roda.
Isso é o oposto de onde os motores de uso geral estão hoje. O suporte deles a WebGPU foi projetado como um aprimoramento progressivo sobre um renderizador centrado em WebGL2, com um caminho alternativo para navegadores que não oferecem suporte. O PlayCanvas, em particular, prioriza WebGL2, enquanto WebGPU ainda está em beta. Essa é a decisão correta para eles, porque sua função é executar a maior variedade possível de jogos na maior variedade possível de dispositivos. Nossa função é mais restrita e mais profunda, então tomamos a decisão oposta: passamos a usar apenas WebGPU no protótipo 13 e nunca olhamos para trás. Navegadores sem WebGPU não recebem uma versão reduzida; eles não são compatíveis, e acompanhamos isso como uma métrica de alcance em vez de fingir que um fallback para WebGL2 está a uma única opção de configuração de distância. Não está. Isso exigiria uma reescrita parcial dos nossos estágios de terreno e vegetação.
Construir sobre um motor centrado em WebGL2 significaria lutar contra as premissas de fallback em cada recurso de computação ou manter dois caminhos de renderização para sempre. Ter controle sobre o renderizador nos permitiu tratar a computação como base.
Segunda decisão: um solucionador de movimento para personagens, não um motor de física
A abordagem clássica é adicionar um motor de física. Nós tentamos. Um dos primeiros protótipos validou o Rapier rodando em um worker, e o resultado parecia bom.
Mesmo assim, escrevemos o nosso, e não há Rapier, Cannon nem Ammo em nenhuma parte da versão lançada. O motivo é o escopo. Não precisamos de corpos rígidos, articulações, ragdolls nem de um solucionador de restrições. Precisamos que uma única cápsula se mova corretamente sobre o terreno e que caminhar, deslizar, planar, escalar e nadar compartilhem uma única resposta para “estou no chão, em qual superfície e em que ângulo?”. Um motor de física de uso geral torna isso mais difícil, não mais fácil, porque esses modos acabam entrando em conflito com suas molas e amortecedores internos.
Por isso, nosso controlador de personagem é uma máquina de estados multicanal modular. Cada modo é uma pequena unidade que informa se quer assumir o controle naquele quadro e, se vencer, define a velocidade e a direção. Eles disputam por prioridade em três canais — recurso, depois postura e, por fim, locomoção — e todos consultam o mesmo terreno. A colisão é determinada por uma sondagem de cápsula contra o heightmap ou o campo de distância com sinal, dependendo do chunk.
O detalhe de que mais me orgulho não tem glamour algum. A detecção do chão examina todas as superfícies na coluna vertical abaixo dos seus pés e escolhe a mais alta que esteja na altura da cápsula ou abaixo dela, em vez de confiar no gradiente do SDF. Na borda de uma saliência, a superfície lateral mais próxima é a face do penhasco, então uma normal baseada em gradiente oscila entre “chão” e “parede”, causando deslizamentos fantasmas. A consulta por coluna torna ficar em pé em uma beirada algo sem graça, que é exatamente o que você quer. Um colisor de heightfield pronto não nos daria isso de graça, porque, para começo de conversa, ele não consegue enxergar nosso terreno. O terreno reside na GPU, em nosso próprio formato. Nenhum motor externo consegue detectar colisões contra ele sem que copiemos o campo inteiro para o formato de colisores desse motor a cada edição.
Terceira decisão: animações que funcionam em diferentes rigs
Os avatares usam o rig Synty POLYGON, e nossos clipes de movimento vêm de uma grande biblioteca aberta de animações. Como o rig e os clipes compartilham os nomes dos ossos, o caso comum não exige retargeting em runtime: as trilhas simplesmente são vinculadas pelo nome. Descrevemos todo o pipeline de personagens em personagens universais.
O trabalho interessante está nos casos em que eles não correspondem. Criamos uma etapa de retargeting que mapeia um esqueleto para outro, e fazê-la funcionar corretamente exigiu resolver três problemas específicos. Primeiro, é preciso alinhar as bind poses, porque combinar uma pose A com uma pose T acrescenta silenciosamente cerca de trinta graus por articulação. Depois, é preciso dimensionar o movimento da raiz e a passada usando duas proporções distintas: a distância do quadril ao chão para o eixo vertical e a proporção geral para o eixo horizontal. Por fim, é preciso testar os clipes adaptados contra os originais em uma taxa de amostragem fixa, para que as regressões apareçam antes que um jogador as encontre. Esse pipeline é o que nos permite adicionar novas fontes de animação e, no futuro, personagens enviados pelos criadores, sem corrigir manualmente cada clipe.
Acima disso, há uma máquina de estados de animação que escolhe a família correta de clipes a cada quadro com base no estado do movimento: variante de salto de acordo com a velocidade, intensidade da aterrissagem de acordo com o impacto, direção da inclinação pelo produto escalar da velocidade com o gradiente do terreno, paradas sincronizadas com a fase dos pés para que o personagem não deslize para interromper o movimento e um debounce de cem milissegundos para que esbarrar em uma parede não faça o personagem piscar entre os estados de caminhada e queda. Nada disso é exótico, mas é o tipo de coisa que você só consegue ao controlar essa camada.
Quarta decisão: a parte que nenhum motor oferece
As outras três decisões dizem respeito a como o mundo funciona. Esta diz respeito ao que o produto é, e é por isso que a comparação com o PlayCanvas é, no fim das contas, um erro de categoria.
PlayCanvas, Babylon, Unity e um aplicativo Three.js feito do zero partem todos da mesma premissa: você cria seu jogo em uma mesa, em um editor 2D, observando o mundo de fora, e depois aperta o botão de jogar e publica um runtime separado. Mesmo na edição dentro do próprio motor, você está em uma estação de trabalho manipulando uma cena que observa de fora.
O Cinevva World inverte essa lógica. Você cria de dentro do mundo, como um avatar no mesmo espaço em que seus jogadores estarão, descrevendo o que deseja e vendo isso aparecer. Criar e jogar fazem parte de uma única sessão contínua, não são uma etapa de desenvolvimento conectada a um runtime. As referências mais próximas são Roblox, Rec Room e Horizon Worlds, não motores 3D para a web, e até mesmo essas plataformas mantêm a maior parte da criação em uma mesa. O que torna isso viável sem um editor controlado por mouse é o construtor com IA, que transforma “coloque aqui um cais iluminado por lanternas” em geometria e posicionamento.
Não é possível simplesmente acoplar isso a um motor de uso geral, porque não se trata de um recurso de renderização. É a premissa de toda a stack, desde a maneira como o terreno pode ser editado em runtime até a forma como a rede trata cada objeto como algo que uma pessoa próxima acabou de criar.
Quando você não deve fazer o que fizemos
Esta é a parte que o gênero “criamos nosso próprio motor” geralmente ignora. Se você quer lançar um jogo para navegador neste trimestre, não nos imite. Use o PlayCanvas se quiser um editor no estilo da Unity e um pipeline gerenciado. Use o Babylon se quiser um motor completo, com física incluída, e estiver satisfeito em trabalhar dentro da estrutura dele. Use o Three.js se quiser o máximo de controle e o mínimo de imposições e tiver uma equipe capaz de construir as camadas acima dele. Faça a portabilidade a partir da Unity se já tiver um jogo feito nela.
Escrever seu próprio renderizador, sua própria física e suas próprias animações só é a decisão certa quando a premissa do seu produto é incompatível com as soluções prontas — quando o que você está construindo não é um jogo executado em um motor, mas um lugar que, por acaso, é feito de um. Esse era o nosso caso. Provavelmente não é o seu, e tudo bem. O objetivo de fazer uma avaliação honesta é saber em qual caso você se encontra antes de escrever a primeira linha.