Construindo um mundo aberto no navegador, parte 28: Grama até o horizonte e terreno que se oculta
Por Oleg Sidorkin, CTO e cofundador da Cinevva
Chegou agora? Consulte o guia da série. Ele explica o que é um spike e traz links para todas as partes.
A Parte 27 construiu a ilha e deu a ela um terreno que não parece repetitivo. Esta parte aborda as duas coisas que fazem o terreno parecer habitado, em vez de vazio. O Spike 56 trata da grama, o detalhe da superfície que transforma uma encosta texturizada em um lugar pelo qual você caminharia, e o problema é fazer um campo parecer um campo, em vez de riscos espalhados. O Spike 57 é o oposto de desenhar mais: trata-se de não desenhar o que uma colina já está ocultando, e o resultado interessante é que a forma rápida de fazer esse teste também se revelou a forma correta.
Grama que parece um campo, não confete
Abrir o Spike 56 em uma nova aba ↗ · Ver código-fonte
A decisão central é geométrica. Uma única lâmina fina e afilada ocupa menos de um pixel na maioria dos ângulos de câmera, então meio milhão de lâminas planas parecem confete verde esparso, em vez de um campo. A solução é um tufo de quads cruzados: três quads afilados girados em intervalos de sessenta graus ao redor do eixo vertical local, de modo que, em qualquer direção de visualização, pelo menos um quad fique quase perpendicular à câmera e cada instância cubra aproximadamente três larguras de lâmina de área real na tela. Essa é a diferença entre ver riscos verdes e ver grama.
Um kernel de computação WebGPU posiciona cada tufo uma única vez na inicialização. Ele transforma o índice da instância em cinco fluxos aleatórios descorrelacionados por meio de hash, escolhe uma posição XZ dentro da área, amostra a altura do terreno usando o mesmo FBM empregado pela malha de terreno da CPU (uma adaptação para TSL com mod que preserva o sinal, para que os valores coincidam exatamente e as lâminas fiquem sobre a superfície, em vez de flutuar acima dela), calcula uma normal por diferenças centrais e sorteia largura, altura e matiz para cada tufo. No lado da renderização, há um grafo de vértices TSL que ignora por completo a matriz de instância e escreve diretamente no espaço de recorte: ele redimensiona o quad cruzado unitário, gira o eixo vertical local até a normal do terreno usando a fórmula de Rodrigues e o translada para a posição do tufo. O LOD por distância vem de graça, sem uma etapa de descarte, porque o grafo de vértices multiplica a altura do tufo por
A receita de cores foi tomada emprestada do shader URP de Breath of the Wild criado por NedMakesGames: sombreamento plano, com a cor da lâmina interpolada de um tom da raiz para um tom da ponta ao longo da fração da altura; os tons da raiz e da ponta, por sua vez, são interpolados entre duas paletas pelo valor de matiz de cada tufo. Isso produz o aspecto salpicado em dois tons de um campo de grama real de BotW. A iluminação difusa usa a normal do terreno em relação ao sol, com um piso de luz ambiente, porque as normais individuais dos quads cruzados geram ruído demais para serem sombreadas separadamente em um visual estilizado. O campo inteiro usa uma única chamada de desenho e é posicionado e animado inteiramente na GPU.
Quatro maneiras de descartar o que uma colina está ocultando
Abrir o Spike 57 em uma nova aba ↗ · Ver código-fonte
O Spike 57 compara quatro caminhos de descarte no mesmo mundo procedural transmitido pelo cliente de produção, escalado verticalmente em 1,8 vez para que as colinas realmente ocultem a vegetação. O T0 usa apenas a distância, correspondendo ao que a visibilidade de chunks da versão atual já faz. O T1 acrescenta descarte pelo frustum, o maior ganho barato isolado, removendo tudo que está fora do cone de visão. O T2 acrescenta um teste de horizonte que leva o terreno em conta: ele percorre um raio do olho até cada instância e a rejeita se o mapa de alturas ultrapassar o raio em qualquer ponto do caminho. Assim, uma árvore atrás de uma crista é descartada mesmo que esteja dentro do frustum. O T3 mantém o mesmo teste de horizonte, mas o acelera com uma pirâmide de alturas máximas. Já o T4 transfere todo o teste de distância, frustum e horizonte para um kernel de computação TSL, que grava uma escala de visibilidade por instância, lida pelo material da vegetação para colapsar os vértices ocultos. Um contador que mantém a visibilidade por dois quadros suaviza a cintilação de um único quadro quando um ponto de amostragem cai logo dentro ou fora de um texel enquanto a câmera se move levemente. Ele é propositalmente curto, pois qualquer duração maior mascara erros algorítmicos em vez de corrigi-los.
É na pirâmide que o spike mostra seu valor, e a lição está em fazer o teste corresponder ao que realmente aparece na tela. O terreno renderizado é uma malha de triângulos com vértices em uma grade fixa de dois metros, e o rasterizador interpola linearmente entre os vértices. Portanto, a altura real renderizada dentro de qualquer retângulo é o máximo dos vértices contidos nele, nunca o pico do ruído contínuo entre eles. Se a pirâmide de oclusão amostrar o ruído em uma grade mais fina, ela encontrará picos fantasmas que a malha nunca exibe e começará a bloquear raios que a câmera claramente consegue atravessar. Por isso, os texels da base da pirâmide ficam exatamente sobre a grade de vértices, cada um armazenando o máximo de seus quatro vértices de canto, enquanto os níveis superiores usam reduções máximas 2x2 convencionais. Isso a torna exata em relação à malha renderizada. Para o teste de raio a cada passo, o código deliberadamente faz amostragem pontual da malha com interpolação bilinear, em vez de consultar a pirâmide, pois uma consulta AABB menor que um texel retorna o máximo do texel inteiro e aumenta a altura em vários metros nas cristas íngremes — exatamente o tipo de oclusão excessiva que ocultaria objetos visíveis.
O resultado surpreendente é que o T2, a referência de força bruta, é o que está errado. Como o T2 faz amostragem pontual diretamente no ruído contínuo, ele detecta picos entre vértices da malha que não são renderizados. Assim, ele causa uma pequena oclusão excessiva e oculta vegetação que o jogador realmente consegue ver. O caminho da pirâmide é mais rápido, graças à redução AABB de
Tecnologia mencionada neste capítulo
Grama de quads cruzados na GPU. Três quads afilados girados em intervalos de sessenta graus por tufo garantem um quad quase perpendicular a partir de qualquer ângulo. Assim, meio milhão de instâncias parecem um campo, em vez de confete menor que um pixel. Um kernel de computação posiciona cada tufo (altura do terreno FBM amostrada com o mesmo mod que preserva o sinal usado pela malha da CPU, normal por diferenças centrais, tamanho e matiz por tufo), e um grafo de vértices TSL ignora a matriz de instância para redimensionar, girar até a normal pela fórmula de Rodrigues, transladar e aplicar vento modulado pela altura. O LOD por distância é gratuito: os tufos colapsam até altura zero por
Descarte por oclusão no horizonte do terreno. Quatro caminhos comparados no mundo de produção: distância; distância mais frustum; mais um teste de raio no mapa de alturas que rejeita instâncias atrás de uma crista; mais uma pirâmide de alturas máximas que acelera o teste; e uma adaptação para computação TSL. A pirâmide faz amostragens exatamente na grade de vértices de dois metros usada para a tesselação da malha (texel da base = máximo dos quatro vértices de canto, seguido por reduções máximas 2x2 nos níveis superiores), de modo que ela retorna apenas alturas que o rasterizador realmente exibe.
Acelerado e correto, não uma troca. A amostragem pontual do ruído contínuo — o caminho T2 de força bruta — encontra picos entre vértices da malha que nunca são renderizados, causando oclusão excessiva de vegetação visível. A pirâmide baseada na grade de vértices é mais rápida — redução AABB de
Parte 28 de 29. Anterior: Parte 27 — Uma ilha criada com ruído e terreno que parece terreno Próxima: Parte 29 — Um controlador, qualquer corpo Guia da série: /pt-BR/blog/2026-02-25-open-world-browser-series-guide