Construindo um mundo aberto no navegador, parte 5: Orçando os recursos visuais
Por Oleg Sidorkin, Diretor de Tecnologia e Cofundador da Cinevva
Chegou agora? Consulte o guia da série. Ele explica o que é um spike e reúne links para todas as partes.
Este foi o capítulo em que a ambição visual encontrou a aritmética.
Dividimos o custo de renderização em spikes separados porque resultados agrupados são difíceis de diagnosticar. Se você ativa tudo de uma vez, só descobre que o frame está lento. Não descobre qual recurso consumiu o orçamento.
O Spike 7 teve como foco a densidade da vegetação e o custo da animação. A abordagem foi distribuir a vegetação em tempo de execução usando mapas de densidade de 32x32 para cada chunk do terreno, alimentando grandes conjuntos de InstancedMesh. Cada lâmina de grama e agrupamento de arbustos recebeu animação de vento no vertex shader, controlada por uma textura de ruído em movimento. O principal número que monitoramos não foi a quantidade de triângulos, mas o overhead das draw calls e o throughput de vértices em GPUs intermediárias. Descobrimos que agrupar as instâncias em menos meshes era mais importante do que reduzir a quantidade de polígonos de cada lâmina.
Abrir o Spike 7 em uma nova aba ↗ · Ver código-fonte
O Spike 8 aumentou a complexidade dos materiais do terreno. Mistura de múltiplas camadas ponderada pelo ângulo de inclinação e pela altitude, projeção triplanar opcional para faces de penhascos e normal maps por camada. O shader fazia splatting com base na inclinação usando quatro camadas de textura, cada uma exigindo uma amostra difusa e uma amostra de normal. Isso representa
Abrir o Spike 8 em uma nova aba ↗ · Ver código-fonte
O Spike 9 concentrou-se no custo dos mapas de sombras em cascata sob uma carga realista de terreno e objetos. CSM com três cascatas era a configuração de referência. Testamos especificamente com o sol em ângulos baixos, pois é quando a pressão sobre as cascatas é maior. A cascata distante cobre uma enorme fatia do frustum, e o detalhamento das sombras é determinado pela densidade de texels,
Abrir o Spike 9 em uma nova aba ↗ · Ver código-fonte
A parte difícil dessa fase foi manter a disciplina de produto. Alguns efeitos ficaram excelentes e, mesmo assim, precisaram ser limitados porque consumiam uma parcela grande demais do orçamento de frame em relação ao seu impacto visual.
Nossa regra ficou simples. Um recurso só avança se puder justificar seu custo com dados medidos de tempo de frame.
Parece óbvio. Não é algo comum em ciclos rápidos de prototipagem, nos quais todos estão empolgados com o próximo ganho visual. Manter essa regra desde o início tornou muito mais claras as decisões de arquitetura sobre clipmaps e zonas volumétricas mais adiante, pois já conhecíamos o custo individual de cada recurso que disputava os mesmos 16 ms.
Na parte 6, chegamos à primeira grande mudança de arquitetura do terreno com os geometry clipmaps.
Tecnologias mencionadas neste capítulo
InstancedMesh e vegetação na GPU. O InstancedMesh do Three.js renderiza N cópias da mesma geometria com uma única draw call. Para a vegetação, um mapa de densidade (32x32 por chunk) controla a distribuição, em tempo de execução, de lâminas de grama e agrupamentos de arbustos em buffers de instâncias. A animação do vento é executada no vertex shader usando uma textura de ruído em movimento. Em grande escala, o ComputeInstanceCulling do WebGPU elimina instâncias fora da tela e distantes antes da rasterização, enquanto o IndirectBatchedMesh reúne vários tipos de vegetação em um único buffer, desenhado com multi-draw indirect. Consulte nosso guia de paisagens sobre culling de vegetação na GPU.
Mapeamento triplanar. Texturas com mapeamento UV convencional ficam esticadas em encostas íngremes porque as coordenadas UV são comprimidas. O mapeamento triplanar projeta texturas ao longo dos três eixos (X, Y, Z) e faz a mistura com base na normal da superfície. Faces de penhascos recebem a projeção X ou Z (sem esticar), enquanto terrenos planos recebem a projeção Y. A mistura é suave e automática, sem exigir abertura de UV. Para terrenos PBR, os mesmos pesos de mistura são aplicados aos canais de albedo, normal, rugosidade e oclusão de ambiente. Consulte os detalhes do mapeamento triplanar.
Splatting de materiais baseado em inclinação e altitude. Em vez de splat maps pintados à mão, os materiais são atribuídos proceduralmente no fragment shader com base nas propriedades do terreno. Áreas planas em baixa altitude recebem grama, encostas íngremes recebem rocha, áreas de grande altitude recebem neve (apenas em superfícies planas o suficiente para permitir o acúmulo) e áreas próximas ao nível do mar recebem areia. As transições usam smoothstep para produzir uma mistura suave. Em nossa implementação, cada chunk do terreno avalia quatro camadas de textura, com amostras difusas e de normal por camada, totalizando oito leituras de textura por fragmento antes da iluminação. Consulte a atribuição de materiais por inclinação e altitude.
Mapas de Sombras em Cascata (CSM). O CSM divide o frustum de visão da câmera em 3 a 4 faixas de distância (cascatas). Cada cascata renderiza um mapa de sombras da perspectiva do sol com uma resolução adequada à sua distância. Cascatas próximas recebem sombras em alta resolução (sombras de contato detalhadas sob árvores e edifícios), enquanto cascatas distantes recebem resolução mais baixa (sombras amplas de montanhas). O shader do terreno amostra todas as cascatas e seleciona a adequada para cada fragmento. Custo de desempenho: 3 a 4 cascatas em 1024x1024 acrescentam cerca de 0,5 a 1 ms à renderização dos mapas de sombras, além de aproximadamente 0,2 a 0,3 ms para a amostragem. Consulte sombras para terrenos.
Parte 5 de 12.
Anterior: Parte 4 — Streaming antes de terrenos sofisticados
Próxima: Parte 6 — Os clipmaps mudaram o rumo da história
Guia da série: /pt-BR/blog/2026-02-25-open-world-browser-series-guide