Skip to content

Construindo um mundo aberto no navegador, parte 4: Streaming antes de terrenos sofisticados

Por Oleg Sidorkin, CTO e cofundador da Cinevva

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

É no streaming que projetos com “boa aparência” geralmente desmoronam.

É possível esconder muita coisa em um quadro estático. Mas não dá para esconder uma travada de 40 ms ao cruzar o limite de um chunk.

Testamos o streaming de propósito antes de criar uma representação avançada do terreno. Isso nos deu dados claros sobre o comportamento de carregamento e descarregamento.

O Spike 6 validou a rotatividade dos chunks vizinhos usando conteúdo simples.

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

Depois, no Spike 11, passamos para o pipeline real do terreno: streaming de chunks de altura, com decodificação em worker e refinamento progressivo de grades com 17, 33 e 65 amostras.

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

A sequência importou mais do que esperávamos. Se tivéssemos começado diretamente com chunks de altura comprimidos, a causa de cada travada seria ambígua: problema de decodificação, de upload de textura ou de atualização da geometria? O Spike 6 eliminou uma camada de incerteza antes que o Spike 11 adicionasse complexidade.

Uma lição prática deste capítulo foi aplicada nos spikes posteriores: as pausas causadas por uploads precisam ser medidas diretamente, não deduzidas a partir do FPS médio. O FPS médio esconde picos no tempo de quadro, e são esses picos que os usuários realmente sentem.

Na parte 5, entramos no capítulo sobre custos visuais, em que vegetação, shaders de terreno e sombras em cascata disputam o mesmo orçamento por quadro.

Tecnologias mencionadas neste capítulo

Streaming baseado em chunks. O mundo é dividido em uma grade de chunks independentes (normalmente de 64 × 64 metros). À medida que o jogador se move, os chunks da borda traseira são descarregados, enquanto os da borda dianteira entram por streaming. É assim que funciona o sistema de células de Skyrim: uma grade de 5 × 5 células carregada ao redor do jogador, com trocas conforme ele se move. A versão para navegador acrescenta latência de rede à equação, tornando essencial o pré-carregamento preditivo com base na velocidade do jogador. Consulte nosso guia de arquitetura de streaming.

Refinamento progressivo de mapas de altura. Primeiro, o terreno é enviado em baixa resolução e depois refinado. Os tamanhos das grades não são arbitrários: cada nível é uma grade de (2k+1)×(2k+1), portanto 17=24+1, 33=25+1 e 65=26+1. O +1 mantém uma amostra compartilhada em cada limite para que os chunks vizinhos se alinhem, e cada etapa praticamente quadruplica o número de amostras (n2 cresce à medida que o lado dobra). Uma grade de 17 × 17 (o mínimo para um chunk de 64 m com espaçamento de 4 m) tem cerca de 200 bytes quando comprimida e renderiza uma superfície visível instantaneamente. Depois, transmitimos o refinamento de 33 × 33 e, por fim, a resolução completa de 65 × 65. Cada nível adiciona amostras sem substituir os dados anteriores. Isso corresponde diretamente aos anéis de LOD de clipmaps de geometria, nos quais terrenos distantes usam dados de baixa resolução e terrenos próximos usam a resolução completa. Consulte carregamento progressivo de chunks.

Codificação delta e compressão. Dados de mapas de altura são bem comprimidos porque células adjacentes têm valores semelhantes. A codificação delta armazena a diferença entre cada célula e seu valor previsto (a média das vizinhas), concentrando os valores perto de zero. Combinado com zlib ou brotli, um chunk de 65 × 65 cai de 8,4 KB sem compressão para 1–2 KB comprimido. Com precisão reduzida para chunks distantes (8 bits em vez de 16 bits), o tamanho fica entre 0,5 e 1 KB. Consulte compressão de dados de terreno.

Pré-carregamento preditivo. Consiste em carregar chunks antes que o jogador chegue até eles. A distância de antecipação precisa cobrir o quanto o jogador percorre durante o carregamento de um chunk, dprefetch=vtload, portanto ela varia de acordo com a velocidade: ao caminhar (5 km/h), pré-carregue 2 chunks à frente (128 m); ao correr (15 km/h), pré-carregue 4. O anel de carregamento se desloca de acordo com a direção da velocidade. Uma fila de prioridade ordena as solicitações pendentes por urgência e cancela as de chunks dos quais o jogador se afastou. Consulte pré-carregamento preditivo.


Parte 4 de 12.
Anterior: Parte 3 — Os spikes pouco chamativos que nos salvaram
Próxima: Parte 5 — Definindo o orçamento dos elementos visuais
Guia da série: /pt-BR/blog/2026-02-25-open-world-browser-series-guide