1 pontos por GN⁺ 2024-09-06 | 1 comentários | Compartilhar no WhatsApp
  • Nanite WebGPU é um projeto que implementa renderização no estilo Nanite do UE5 dentro do navegador usando WebGPU, incluindo hierarquia de LOD por meshlets, rasterizador por software, billboard impostor e culling por instância/meshlet
  • A implementação tem como principais objetivos a simplicidade de pré-processar entradas OBJ no navegador e permitir experimentar mudanças de desempenho alterando configurações por checkboxes e sliders
  • A demo oferece cenas como Jinx com 640M triangles e Lucy/Dragons com até 1.7B triangles; os triângulos brancos em Jinx são o resultado da rasterização por software processada com compactação em 32 bits por causa das restrições do WebGPU
  • Como o WebGPU não tem atomic<u64>, é difícil implementar de forma direta um rasterizador por software eficiente baseado em visibility buffer; a implementação atual coloca depth u16 e octahedron normal 2*u8 em 32 bits, aceitando artefatos de precisão
  • Em uma implementação real no estilo Nanite, o desafio central não é a simples contagem de triângulos, mas mesh simplification e error metric; o autor deixa claro que sua implementação, diferentemente do UE5, não inclui simplificação, streaming, compressão, visibility buffer, 2-pass occlusion culling etc.

Visão geral do projeto

  • Nanite WebGPU é um projeto que implementa renderização no estilo Nanite em navegadores web usando WebGPU
  • Os principais elementos incluídos são meshlet LOD hierarchy, rasterizador por software, billboard impostor e culling por instância e por meshlet
  • Suporta modelos com textura e per-vertex normal, e oferece sliders ou checkboxes para cada configuração
  • WebGPU só pode ser usado no Chrome
  • O app inteiro pode ser executado offline usando Deno, e os testes unitários de shaders também foram escritos dessa forma

Cenas de demonstração e escala

  • A demo Jinx tem 120×120 instâncias, em uma escala de 640M triangles
    • Um único modelo Jinx é simplificado de 44k triangles para 3k triangles, com 59 root meshlets
    • Os triângulos brancos são triângulos rasterizados por software situados entre a área rasterizada por hardware e os impostors no fundo distante
  • Lucy and dragons posiciona os dois objetos em 70×70 instâncias cada, compondo 1.7B triangles
    • Na cena de exemplo, quase 98% dos triângulos são rasterizados por software, e o autor afirma que esse caminho é muito mais rápido do que o hardware
  • Lucy é uma cena com 110×110 instâncias e 1.2B triangles
    • Uma única estátua Lucy é simplificada de 100k triangles para um único root meshlet de 86 triangles
  • Dragons é uma cena com 70×70 instâncias e 1.2B triangles
    • Um único dragon é simplificado de 250k triangles para um único root meshlet de 102 triangles
  • Bunnies é uma cena com 500×500 instâncias e 1.2B triangles
    • Um único bunny é simplificado de 5k triangles para um único root meshlet de 96 triangles
    • Como os bunnies são pequenos, a maior parte sofre frustum culling

Funcionalidades implementadas

  • Meshlet LOD hierarchy

    • O mesh preprocessing é executado no navegador
    • Usa meshoptimizer e METIS via WebAssembly
    • Também oferece um exporter de arquivos para evitar esperar pelo pré-processamento entre recarregamentos da página
  • Software rasterizer

    • O WebGPU não tem atomic<u64>, necessário para uma implementação eficiente
    • A implementação atual empacota depth u16 e octahedron-encoded normals 2*u8 em 32 bits
    • Por causa da limitação de 32 bits, há uma grande perda de precisão, e o objetivo é mostrar que o rasterizador funciona
    • Essa limitação também afeta a depth pyramid usada em occlusion culling
  • Billboard impostors

    • Usa 12 imagens ao redor do eixo UP e faz blend com dithering conforme a posição da câmera
    • Não trata pontos de vista por cima/por baixo
    • Inclui tanto diffuse quanto normal para realizar shading em runtime
    • Impostors preview é uma demo com tamanho maior de textura dos impostors

Culling e caminhos de renderização

  • O culling é composto por várias etapas
    • Per-instance: frustum culling e occlusion culling
    • Per-meshlet: frustum culling e occlusion culling
    • Per-triangle: hardware backface culling e z-buffer
  • O WebGPU não tem early-z
  • O occlusion culling usa apenas uma depth pyramid criada a partir do depth buffer do frame anterior
    • Não há reprojection nem abordagem two-pass
    • O autor considera que a implementação atual já é suficiente para fazer culling de muitos triângulos e avaliar a melhoria de desempenho
  • É possível alternar entre GPU-driven rendering e uma implementação simples na CPU
    • A versão em CPU não tem muitas otimizações, mas permite execução passo a passo no debugger
  • O recurso “Freeze culling” permite mover a câmera e inspecionar apenas o que foi desenhado no último frame

Usabilidade e depuração

  • Para movimento, usa [W, S, A, D]; para subir/descer, [Z, SPACEBAR]; para movimento rápido, [Shift]
  • Se surgirem resultados estranhos, é possível verificar ligando e desligando as opções de culling
    • A implementação tem alguns pequenos bugs
  • Os triângulos brancos são triângulos rasterizados por software
    • Devido à ausência de atomic<u64> no WebGPU, depth e normal são compactados em 32 bits
    • O 16-bit depth pode gerar muitos artefatos, como z-fighting ou vazamentos
    • Desligar o rasterizador por software facilita ver os raw Nanite meshlets, mas pode causar uma grande queda de desempenho
  • O FPS pode oscilar por causa do VSync forçado do navegador; para verificar timings, use o botão “Profile”

Metas de design

  • O primeiro objetivo do projeto é a simplicidade
    • Começa a partir de um arquivo OBJ e realiza todo o processamento dentro do app
    • Não exige uma etapa separada de pré-processamento, como exportação pelo Blender
    • Busca um fluxo em que seja possível colocar um breakpoint em loadObjFile() e acompanhar até o fim do primeiro frame
  • O segundo objetivo é a experimentação
    • Como foi feito como uma página web, em vez de Rust e Vulkan, é possível clicar no link e alterar checkboxes ou sliders para ver as mudanças de desempenho
    • Dá para confirmar diretamente quais opções são importantes, por exemplo quando mudar uma única configuração faz o FPS cair bastante
  • Muito código poderia ser otimizado, mas considera-se que essa otimização não é importante até que o problema de simplification seja resolvido

Diferenças em relação ao UE5 Nanite

  • A error metric usa um projected simplification error simples
  • A meshlet simplification é feita de forma simples
  • Não há two-pass occlusion culling
    • Não é difícil adicionar, mas a depuração é trabalhosa e surgem interações com as configurações da GUI
    • Isso prejudica a legibilidade do código, então não combina com o objetivo
  • Não há visibility buffer
    • Não é possível implementar por causa da limitação de atomic<u64>
  • Não há built-in shadows nem multiview
  • Não há work queue dentro do shader
    • Para meshlet culling e LOD selection, é feito dispatch de uma thread por meshlet
  • Não há VRAM eviction nem streaming de LODs não usados
  • Não há compression
  • A escalabilidade é baixa para muitos objetos diferentes
    • O foco está no uso de memória previsível nos casos de demonstração
    • É preciso saber de antemão o limite superior de drawn meshlets para o buffer que armazena dados entre stages
  • Não há implementação de BVH ou hierarquia para instances
    • Frustum e occlusion culling são executados para todas as instances

Condições por trás da contagem de triângulos

  • É difícil julgar o desempenho apenas pelo número “dezenas de bilhões de triangles”; o desempenho depende de vários fatores
  • Dense meshes

    • Ter muitas dense meshes por perto pode prejudicar o desempenho
    • Porém, se estiverem perto o suficiente para cobrir boa parte da tela, o occlusion culling entra em ação
    • Dense geometry tem meshlets pequenos, ocupa pouco espaço na tela e tende a ser facilmente eliminada por occlusion/cone culling
  • Instance count

    • Cada instance possui uma transform matrix mat4x3, consumindo VRAM
    • Durante o frame, também é preciso armazenar a lista de itens a renderizar
    • No pior caso, cada instance renderiza os meshlets mais densos
    • Na implementação, são alocados instanceCount * bottomLevelMeshletsCount * sizeof(vec2u) bytes
    • O limite padrão do storage buffer do WebGPU no Chrome é 128 MB, e a cena de demonstração foi ajustada levando isso em conta
  • Scene arrangement

    • As cenas do app posicionam os objetos em um quadrado
    • Objetos distantes ficam apenas parcialmente visíveis, mas o LOD de meshlet coarse inclui uma área maior, gerando overdraw
    • Um posicionamento em dense grid renderiza mais triângulos próximos, mas, como a diferença de profundidade é pequena, é favorável ao occlusion culling
    • Objetos muito distantes podem contaminar a depth pyramid com pixels distantes arbitrários

Por que a cena da Jinx é difícil

  • A personagem Jinx é magra e tem espaços vazios entre os braços e o tronco, o que dificulta o occlusion culling
  • O modelo não simplifica bem, então até o LOD mais coarse tem 3k triangles
  • Surgem situações em que muitos triângulos do tamanho de 1 pixel se acumulam
  • O software rasterizer ajuda bastante, mas, por causa do layout da cena, a maioria das instances é renderizada como impostor
  • Nas áreas próximas, o hardware rasterizer assume o trabalho, e hardware rasterizer, software rasterizer e impostor têm pontos fortes diferentes

Pontos surpreendentes na implementação do Nanite

  • O objetivo do DAG não é simplesmente usar menos triângulos em objetos distantes, mas manter uma consistência próxima de 1 pixel == 1 triangle em toda a tela
  • Em uma discrete LOD mesh, cada LOD é uma geometry separada, o que dificulta lidar com níveis intermediários quando eles são necessários; por isso, continuous LOD é necessário
  • A meshlet hierarchy permite fazer sampling da geometry no nível de detalhe escolhido
  • Gasta-se mais tempo em culling e trabalho com meshlets do que no Nanite em si
  • Fazer a meshlet LOD hierarchy funcionar é fácil, mas torná-la eficiente é difícil
  • Se a mesh não simplifica de forma limpa, surgem situações como a da Jinx, com cerca de 3.000 triangles cobrindo um único pixel
  • Se você quer pixel-sized triangles, precisa de um software rasterizer, e billboard impostor também é útil como fallback focado em estabilidade

Problema de mesh simplification

  • Simplification não é um problema de “receber uma mesh e reduzi-la para X% dos triangles”, mas sim um problema realizado no contexto de meshlets e METIS
  • O UE5 usa seu próprio mesh simplification code como a primeira etapa do asset pipeline
    • O custo reduzido aqui gera ganhos em cascata por todo o sistema posteriormente
    • No material de Brian Karis para a SIGGRAPH, afirma-se que o LOD graph termina em um único root cluster e que qualquer modelo pode ser simplificado para 128 triangles
  • O modelo da Jinx tinha um problema em que a simplification parava em determinado ponto
    • Mesmo inserindo X triangles como entrada, os mesmos X triangles eram retornados
    • O algoritmo fazia crash com uma assertion
    • Depois, as partes da mesh que não eram reduzidas o suficiente foram alteradas para permitir múltiplos roots no DAG
  • O modelo bunny inicialmente foi simplificado para um único meshlet de 128 tris, mas, ao mudar as condições, surgiu o problema de ele não chegar a um único root
    • Muitos meshlets não conseguiam reduzir triangles o suficiente, e também havia muitos meshlets “não full” com menos de 128 triangles
  • Discussões relacionadas:

Métrica de erro

  • Ao renderizar uma malha de 20.000.000 de triângulos como uma hierarquia de meshlets, é preciso escolher qual meshlet é o “correto”
  • Esse problema de escolha é o núcleo do Nanite, e simplification, meshlet DAG e software rasterizer são quase pré-requisitos para lidar com ele
  • A implementação usa o projected simplification error fornecido pelo meshoptimizer
  • O autor considera que essa métrica não é boa para o Nanite, e que outros atributos de vértice também deveriam ser incluídos na função
    • Deveria ser possível atribuir pesos por atributo
    • As normals do rosto da Jinx foram um grande problema
  • Materiais de referência:

Por que o software rasterizer não gera texturas

  • No hardware rasterizer, é possível escrever depth texture, color e normal juntos conforme o resultado do depth test
  • No software rasterizer, se várias threads escreverem no mesmo pixel, ocorre uma race condition
  • A solução comum é um visibility buffer
    • Em cada pixel, ele emite o sceneUniqueTriangleId do triângulo mais próximo
    • Isso é combinado com depth de 32 bits para formar um valor de 64 bits, usando uma operação atômica de 64 bits
    • Em um pass separado, o triângulo é rasterizado novamente, as coordenadas baricêntricas são calculadas e o shading é feito
  • O WebGPU não tem atomics de 64 bits, portanto esse método não pode ser usado
  • O objetivo deste projeto é mostrar que o software rasterization funciona; por isso, o modelo rasterizado por software no fundo é branco e oferece apenas um shading razoável

Avaliação sobre implementar o próprio Nanite

  • A resposta mais simples é usar o UE5
  • Para inserir essa tecnologia em uma engine existente, o autor entende que primeiro é necessário implementar uma graphics pipeline baseada em compute e uma pipeline de renderização GPU-driven
  • Problemas como multi-step culling, gerenciamento de chunks de cena/mundo e meshes animadas surgem antes
  • A ordem sugerida é estabilizar essas etapas, depois tentar o software rasterizer e, em seguida, adicionar uma tecnologia no estilo Nanite
  • Em um toy renderer, uma hierarquia básica de meshlets pode ser um projeto de fim de semana, mas uma implementação real precisa lidar com problemas de simplification e de métrica de erro

Ferramentas usadas e materiais de referência

  • meshoptimizer é a base principal da implementação do projeto
    • Versões mais novas do meshoptimizer têm meshopt_SimplifySparse para um clone do Nanite
    • O projeto não foi atualizado para essa versão para manter o estado testado durante o desenvolvimento
  • METIS foi usado
  • Emscripten foi usado para executar meshoptimizer e METIS no navegador
  • O modelo da Jinx usou Arcane - Jinx do Sketchfab, com mesclagem de texturas, ajuste de UV e remoção de armas

1 comentários

 
GN⁺ 2024-09-06
Opiniões no Hacker News
  • Ah, que bom. É como se tivesse surgido uma implementação de terceiros da reprodução do Nanite.
    O Nanite representa malhas gráficas de uma forma muito inteligente. Não é uma árvore, mas um grafo acíclico direcionado, então repetições viram links, não cópias, e uma malha compartilha submalhas, que por sua vez também podem ser compartilhadas novamente. Ele também dá suporte a níveis de detalhe (LOD) internos à malha, de modo que submalhas são descartadas quando ficam pequenas o bastante.
    Com isso, dá para lidar com conteúdo repetido em escala muito grande usando uma quantidade finita de dados e tempos de renderização rápidos. A sacada é que, como há um número limitado de pixels na tela, também existe um limite superior para a quantidade de trabalho de renderização realmente necessária.
    Há um vídeo excelente da SIGGRAPH em que alguém da Epic explica isso. O design atual das GPUs não combina muito bem com o Nanite, então seriam necessárias novas operações de hardware para fazer mais processamento na GPU. Com a Nvidia distraída pelo mercado de IA, fica a dúvida se esse tipo de mudança vai acontecer.
    Para esse método funcionar bem, a cena precisa ter bastante instanciamento. Ele se encaixa bem em jogos AAA que criam conteúdo amplo reutilizando um número limitado de objetos, como aquele salão de estátuas idênticas da demo do Unreal Engine. Se você assistir a vídeos de Cyberpunk 2077 e procurar corrimãos e pilhas de lixo, verá as mesmas coisas se repetindo constantemente em contextos completamente diferentes.
    A criação de malhas Nanite é complexa por causa dos muitos offsets de links internos e, até agora, só o editor do Unreal Engine lidava com isso. Como o lado de reprodução foi aberto como open source, é bem provável que alguém também crie ferramentas de autoria.
    Por outro lado, os offsets internos do formato podem virar uma superfície de ataque, e parecem passíveis de abuso com conteúdo manipulado, como arquivos Microsoft Word .doc maliciosamente criados.

    • Embora se crie um grafo acíclico direcionado para cortar o grafo, os dados finais em disco são apenas uma lista plana de clusters com critérios de inclusão/exclusão. Parece haver um mal-entendido bem grande sobre onde o DAG é usado e como ele é criado.
      O DAG é gerado dinamicamente a partir dos dados de vértices e não tem relação com a forma como o artista organizou as submalhas. Também não é algo como “repetição vira link”.
      Além disso, como o resultado do corte do grafo varia para cada instância de objeto, não é possível usar instanciamento tradicional; por isso não entendo por que você acha que a cena precisa ter muito instanciamento para isso dar resultado.
    • Lá nos anos 2000, quando eu trabalhava no desenvolvimento para PS3, estava procurando uma boa forma de usar os muitos recursos de computação do Cell e de contornar a largura de banda de memória limitada do RSX. Também havia bastante espaço de armazenamento em Blu-ray disponível.
      Na época, avancei bastante em algo parecido com o Nanite, que eu chamava de malhas comprimidas. Foi o típico caso de arrogância de engenharia que sai pela culatra.
      O trabalho inicial parecia promissor, mas, quanto mais eu investigava o problema, mais complexo tudo ficava. Era preciso criar todo um pipeline de geração de assets, e o escopo era grande demais para terminar dentro do prazo, produzindo resultados bonitos sem estourar a memória.
      Cheguei a fazer algo que parecia renderizar malhas de grande escala com níveis de detalhe em cascata, mas era muito lento e ficava horrível se eu não espremesse a GPU para alcançar precisão subpixel. Foi um experimento interessante, mas pesado demais para o hardware e uma tarefa grande demais para eu tocar sozinho.
      Quando a Epic revelou o Nanite, fiquei realmente impressionado. Eles fizeram o que eu não consegui, de uma forma muito melhor do que o melhor que eu tinha imaginado. É uma daquelas tecnologias que, quando apareceu, não era hype, mas uma solução de verdade, uma joia técnica do mundo gráfico moderno. Se a Epic fosse uma empresa de capital aberto, eu teria considerado investir uma boa quantia só pela tecnologia Nanite.
    • A apresentação da SIGGRAPH mencionada provavelmente é "A Deep Dive into Nanite Virtualized Geometry": https://www.youtube.com/watch?v=eviSykqSUUw
      O vídeo curto de introdução em alto nível também era bom. É "What is virtualized micropolygon geometry? An explainer on Nanite": https://www.youtube.com/watch?v=-50MJf7hyOw
    • Não é um motor mainstream, mas o Bevy, um pequeno motor de jogos ECS em Rust, também dá suporte a algo parecido sob o nome de recurso "Virtual Geometry": https://bevyengine.org/news/bevy-0-14/#virtual-geometry-expe...
      Também há um artigo técnico aprofundado escrito por um dos autores desse recurso: https://jms55.github.io/posts/2024-06-09-virtual-geometry-be...
    • Lendo os artigos, fiquei com a impressão de que o maior ganho vem de coordenadas quantizadas e de níveis de detalhe dinâmicos em pequenos patches, em vez da malha inteira.
      Pelo que entendi da lógica do Nanite, ele mantém a precisão da malha em torno de aproximadamente 1 pixel. Por exemplo, se após a projeção em perspectiva o erro ficar em algo como meio pixel, é possível usar uma malha de menor detalhe com coordenadas arredondadas para algo em torno de 10 bits.
      Lembro vagamente que a quantização cumpria dois papéis. Além de reduzir o tamanho de armazenamento dos dados, ela também ajudava na geração de níveis de detalhe, fazendo os vértices encaixarem na mesma posição no espaço, para depois permitir a remoção de duplicatas.
  • Isso já foi mencionado algumas vezes nesta thread, mas o Bevy também tem uma implementação das ideias do Nanite. Às vezes isso é chamado de geometria virtual. Eu sou o autor, então posso responder perguntas :)
    O Scthe fez um trabalho realmente bom neste projeto. Conversamos sobre várias partes do processo de trabalho, e essa experiência também levou a melhorias no código do Bevy: https://github.com/bevyengine/bevy/pull/15023
    É sempre ótimo ver mais gente entrando nessa área. O Nanite tem muitas ideias excelentes.

  • A demo está usando a string de user agent para determinar compatibilidade? Isso não é bom. A compatibilidade de recursos deve ser avaliada caso a caso, detectando diretamente um recurso específico ou tentando usá-lo
    Eu uso Chromium, não Chrome, e também uso WebGPU o tempo todo, mas a demo manda usar Chrome. Eticamente, não posso fazer isso. Quero muito testar a demo, e parece ser um projeto que exigiu bastante esforço

    • A propósito, ela também não funciona no Chrome no Linux, nem no Android. Embora, para navegação de verdade, eu use quase sempre Firefox. Há algo bem estranho na lógica de detecção
    • Não parece ser isso. No Firefox com suporte experimental a WebGPU ativado, ela falha com um erro de compilação de shader em vez de uma mensagem separada
    • É bom mirar em detecção por recurso
      Quando eu mesmo criava um framework de componentes para navegador, muitas vezes a detecção era impossível, então precisava depender de browser sniffing. O código do Modernizr tem muitos hacks muito engenhosos para detecção de recursos, e às vezes hacks bem sujos. Houve um trabalho enorme para criar código de detecção confiável, e a detecção normalmente era feita por meio de efeitos colaterais
      Meu palpite é que a detecção de recursos Web3D não é simples. Uma busca rápida também não mostrou nenhuma biblioteca clara de detecção de recursos Web3D
      Parte do código do Modernizr para detectar suporte a :checked é assim:
      Modernizr.addTest('checked', function(){
      return Modernizr.testStyles('#modernizr input {width:100px} #modernizr :checked {width:200px;display:block}', function(elem, rule){
    • Não sei qual build você está usando, mas eu uso Ungoogled Chromium e a string de user agent é exatamente igual à do Google Chrome
      Você ativou a permissão de WebGL desse site nas configurações do site? No meu caso, acho que ela vinha desativada por padrão
    • Parece que a própria demo está simplesmente quebrada. Recebo este erro:
      WebGPU error [frame][validation]: Fill size (7160950) is not a multiple of 4 bytes.
      • While encoding [CommandEncoder "main-frame-cmd-buffer"].ClearBuffer([Buffer "rasterize-sw"], 0, 7160950).
  • Esta é a tese de doutorado de 2009, meio esquecida, de Federico Ponchio, que inventou o algoritmo de simplificação dinâmica de malhas no qual o Nanite se baseou. Tem muitas figuras
    https://vcg.isti.cnr.it/~ponchio/download/ponchio_phd.pdf São 107 páginas

  • É legal que funcione em algum grau, mas, como o WebGPU não tem operações atômicas de 64 bits, foi preciso fazer concessões bem grosseiras
    Espero que algum dia isso seja adicionado como uma extensão opcional. Pelo menos em hardware de classe desktop, o suporte em hardware é quase universal. AMD e Nvidia já têm isso há muito tempo, e a Apple passou a oferecer suporte a partir do M3

    • Para que são usadas as operações atômicas no rasterizador? Não sei o que operações atômicas fazem dentro do pipeline de renderização. Também olhei no GitHub, mas não encontrei onde eu esperaria ver operações atômicas
    • É a partir do M2
  • Ele diz que o iPhone 12 Pro Max não tem WebGPU, mas, ao ativar nos recursos experimentais, outros sites de demo de WebGPU[1] funcionam. Alguém conseguiu fazer isto rodar no iPhone? Seria bom se o web app informasse com mais detalhes o que falhou
    [1] https://webgpu.github.io/webgpu-samples/?sample=texturedCube

    • Ativei o WebGPU no Safari, mas aparecem vários erros de shader
      WebGPU error [init][validation]: 6 errors generated while compiling the shader: 50:22: unresolved call target 'pack4x8snorm' 50:9: cannot bitcast from '⊥' to 'f32' 54:10: unresolved call target 'unpack4x8snorm' 59:22: unresolved call target 'pack4x8unorm' 59:9: cannot bitcast from '⊥' to 'f32' 63:9: unresolved call target 'unpack4x8unorm'
    • O suporte a WebGPU no Safari ainda não está concluído, por isso continua como recurso experimental
  • O nome e a descrição são muito confusos e também parecem ter potencial de violação de marca registrada. Ao contrário do que é alegado, não tem nenhuma relação com o Nanite real do UE5; parece ser algo semelhante implementado por alguém sem relação com o UE5
    Também existe o Virtual Geometry do Bevy, que oferece funcionalidade parecida. Ele é escrito em Rust e integrado a uma engine de jogos, então tem potencial de ser muito mais útil: https://jms55.github.io/posts/2024-06-09-virtual-geometry-be...

    • Não acho que seja um grande problema. Pelo README, fica claro que é uma implementação
      Se eu dissesse que “implementei o GPT-3 da OpenAI em JS”, eu entenderia que a pessoa pegou a arquitetura do white paper e a reimplementou
  • Isto não é, de fato, o Nanite do UE5 rodando em WebGPU. É uma implementação independente das mesmas ideias do Nanite
    Essa técnica começou a aparecer em vários lugares. É verdade que o Nanite tornou a ideia famosa, mas Nanite não é o nome da técnica, e sim o nome de uma implementação específica

  • Fico curioso para saber como outros engines se saem em níveis de detalhe e sistemas semelhantes
    O Godot tem um recurso automático de nível de detalhe e, por si só, parece bem bom: https://docs.godotengine.org/en/stable/tutorials/3d/mesh_lod...
    O Unity também tem um sistema de nível de detalhe, mas, considerando a popularidade do engine, é preciso criar manualmente os modelos de nível de detalhe: https://docs.unity3d.com/Manual/LevelOfDetail.html, a menos que você procure um plugin na Asset Store
    Também vi uma abordagem interessante em um engine menos conhecido chamado NeoAxis: https://www.neoaxis.com/docs/html/NeoAxis_Levels.htm Só que o desempenho era muito ruim na minha antiga RX580, e ainda não testei na A580 atual
    Na minha visão, em termos de capacidade de colocar muita coisa na tela, o Unreal está bem à frente dos concorrentes. A desvantagem é que os artistas acabam querendo colocar assets de qualidade mais alta no jogo, o que pode inflar bastante o tamanho da instalação

    • Em teoria, o Nanite é superior a níveis de detalhe pré-calculados. Na prática, não dá para afirmar isso com tanta certeza. É difícil que ele seja tão bom quanto níveis de detalhe feitos manualmente por um artista, e também não é razoável esperar isso
      O custo de desempenho também é alto. Nanite ou geometria virtual não combinam bem com GPUs modernas. Se me lembro bem, a taxa máxima de preenchimento ficava em torno de 1/4. Isso porque a rasterização da GPU não opera por pixel, como shaders, mas em quads 2x2
    • GPUs Intel Arc são péssimas para renderização com Nanite. Isso porque não oferecem suporte em hardware nem a draw indireto, amplamente usado em renderizadores comandados pela GPU, nem às operações atômicas de 64 bits necessárias para o Nanite. A Intel emula draw indireto em software, então é lento
  • Sempre que vejo uma cena renderizada com tanta geometria estática repetitiva, lembro da voz daquele sujeito irritante de um antigo vídeo de vaporware falando em “detalhe ilimitado”
    O Nanite, ao contrário daquela coisa antiga, parece ter realmente resolvido o problema. Pelo que lembro, diziam que aquilo usava algo como octrees

    • Acho que a empresa que fazia essa afirmação se chamava Euclidean. Parece que era uma empresa australiana
      Havia boatos online de que usavam octrees, mas vídeos posteriores da Euclidean negaram isso categoricamente