Skip to content

Construindo um mundo aberto no navegador, parte 10: O caos das emendas e a batalha final dos cantos

Por Oleg Sidorkin, CTO e cofundador da Cinevva

Chegou agora? Consulte o guia da série. Ele explica o que é um spike e contém links para todas as partes.

Se as partes anteriores pareceram metódicas, este capítulo pareceu um combate.

Os spikes 17 a 22 marcaram nossa era dos casos extremos. Marching cubes com LOD duplo, emendas nas fronteiras entre mapas de altura e MC, chunks de canto com resoluções mistas onde três ou quatro níveis de LOD se encontram, geração de emendas na GPU e comportamento do modo de fallback. Cada spike tratou de um cenário de falha específico que havíamos encontrado ou previsto.

O Spike 17 testou marching cubes duplo com dois níveis de LOD ativos simultaneamente. O desafio era que os vizinhos de um único chunk podiam ter resoluções diferentes em faces distintas. A lógica das células de transição do Spike 16 funcionava em uma face por vez, mas, quando um chunk precisava de células de transição em várias faces, o gerenciamento do buffer de vértices ficava complicado. As células de transição de cada face precisavam ser geradas e anexadas sem sobrescrever as demais.

Abrir o Spike 19 em uma nova aba ↗ · Ver código-fonte

O primeiro vilão recorrente foi a ordem de orientação dos vértices. Várias vezes achamos que tínhamos problemas de topologia, mas acabamos descobrindo problemas de orientação. O descarte de faces traseiras estava eliminando triângulos válidos das emendas porque a orientação estava invertida em relação à malha principal. A mesma causa-raiz produzia sintomas visuais diferentes dependendo do ângulo da câmera. A correção foi impor uma convenção de orientação consistente no código de emissão das células de transição e verificá-la alternando para um material de duas faces.

O segundo vilão foi a falsa confiança trazida por algo parcialmente correto. Uma emenda podia parecer perfeita de um ângulo de câmera e quebrar quando os papéis de LOD eram trocados entre chunks de maior e menor resolução. A célula de transição é assimétrica. Ela coleta amostras de maneiras diferentes nos lados de alta e baixa resolução. Se a lógica que determina "qual lado tem alta resolução" estiver invertida em uma configuração, o bug só aparece quando a câmera se move para uma posição específica.

Então veio uma de nossas recuperações favoritas. Estávamos investigando um artefato de corte na emenda dos tiles de mapa de altura e culpando a lógica de transição. Perdemos dois dias nisso. O verdadeiro culpado era um sobredesenho residual. A geometria de maior resolução de um frame anterior continuava na cauda do buffer depois que o chunk era reduzido para um LOD mais baixo. O intervalo de desenho ainda estava definido com a contagem de vértices antiga e maior. Assim que limitamos o intervalo de desenho à contagem de vértices ativos informada pelo contador atômico do compute shader, o "misterioso problema de emenda" desapareceu.

Foi um ótimo lembrete de que bugs de renderização muitas vezes se disfarçam de bugs de geração de malha. A geometria estava correta o tempo todo. A chamada de desenho apenas estava lendo além do fim dos dados válidos.

No Spike 22, já estávamos testando um fallback híbrido no qual os chunks podiam alternar de marching cubes para o modo de mapa de altura sob condições específicas, como quando o chunk não contém edições volumétricas e está suficientemente distante da câmera. Isso nos deu um caminho mais prático do que uma política de tudo ou nada. Chunks editados no campo próximo usam MC para oferecer liberdade volumétrica. Chunks não editados no campo distante usam mapas de altura para ganhar eficiência.

Abrir o Spike 22 em uma nova aba ↗ · Ver código-fonte

Este capítulo foi a queda acentuada da montanha-russa. Frustrante e produtivo ao mesmo tempo. Muitas das correções individuais eram pequenas, às vezes uma única linha alterando um operador de comparação ou um deslocamento. Mas o entendimento que elas proporcionaram sobre como as transições de LOD, o gerenciamento de buffers e os intervalos de desenho interagem não foi nada pequeno.

Na parte 11, abordamos a camada de estabilização que veio depois do caos: modos de chunk baseados em políticas e a transição da correção reativa de bugs para regras explícitas do sistema.

Tecnologias mencionadas neste capítulo

Marching cubes com LOD duplo. Execução de marching cubes em dois níveis de resolução simultaneamente, com células de transição unindo a fronteira. O desafio é que os vizinhos de um único chunk podem ter resoluções diferentes em faces distintas, exigindo a geração independente de células de transição para cada face. As células de transição de cada face são anexadas ao buffer de vértices sem sobrescrever as demais. Contadores atômicos acompanham a contagem total de vértices ativos em todas as faces.

Ordem de orientação dos vértices. A ordem dos vértices em cada triângulo determina qual lado é a face "frontal". Uma orientação consistente — geralmente no sentido anti-horário quando vista de fora — é necessária para o descarte de faces traseiras. Quando as células de transição emitem triângulos, a orientação deve corresponder à convenção da malha principal. Invertê-la faz com que o descarte de faces traseiras elimine triângulos válidos das emendas, o que parece com superfícies ausentes em determinados ângulos de câmera. Uma técnica comum de depuração é alternar side: THREE.DoubleSide no material para confirmar se os artefatos são problemas de orientação ou lacunas reais na topologia.

Fallback de mapa de altura para MC. Um modo híbrido de chunks no qual chunks distantes ou não editados usam terreno baseado em mapa de altura — barato e com superfície plana — enquanto chunks próximos ou editados usam marching cubes — volumétrico e compatível com cavernas. A decisão de fallback depende da distância até a câmera e de o chunk conter ou não edições de SDF. A emenda entre um chunk de mapa de altura e um chunk de MC exige sua própria geometria de transição, semelhante ao Transvoxel, mas conectando duas representações diferentes em vez de dois níveis de LOD. Consulte mapa de altura híbrido + sobreposições volumétricas.

Intervalo de desenho e contadores atômicos. Na geração de malha orientada pela GPU, o compute shader grava vértices em um buffer e incrementa um contador atômico para acompanhar quantos vértices foram emitidos. A chamada de desenho deve usar esse contador como a contagem de vértices, e não a capacidade do buffer. Se o intervalo de desenho não for limitado à contagem ativa, vértices residuais de frames anteriores — ainda presentes na cauda do buffer — produzem geometria fantasma: lascas finas e triângulos tremeluzentes que parecem erros de topologia, mas na verdade são artefatos de renderização causados pela leitura além dos dados válidos.


Parte 10 de 12.
Anterior: Parte 9 — O Transvoxel começou com uma estrutura básica
Próxima: Parte 11 — Modo por política, não modo codificado diretamente
Guia da série: /pt-BR/blog/2026-02-25-open-world-browser-series-guide