2 pontos por GN⁺ 2025-05-19 | 1 comentários | Compartilhar no WhatsApp
  • A demo de Nintendo 64 para a Revision 2025 obtém efeitos próximos de normal mapping, iluminação baked e especular em tempo real ao atualizar apenas a paleta, sem recalcular toda a textura
  • Quando a CPU lê a normal e a cor difusa em cada índice da paleta para criar uma nova paleta RGB, a textura paletizada reage como se tivesse iluminação por texel
  • A textura difusa e o normal map compartilham os mesmos índices de paleta, gerados com K-means clustering do scikit-learn como se fossem uma imagem de 6 canais
  • A iluminação dos prédios combina a cor ambiente no RGB dos vértices, a visibilidade do sol no alfa dos vértices, um irradiance map em cinza e dot(N, sun_dir) da luz solar direcional
  • Funciona bem para luz difusa direcional, mas tem grandes limitações com sombras, point lights, especular preciso e modelos grandes com texturas repetidas, exigindo pré-processamento para esconder os limites

Sombreamento atualizando apenas a paleta

  • A demo de Nintendo 64 foi criada para a Revision 2025 e usa efeitos próximos de iluminação baked, normal mapping e sombreamento especular em tempo real
  • No N64, o normal mapping já era conhecido como possível por experimentos anteriores de homebrew, e esta demo escolhe calcular em runtime não a textura, mas a paleta resultante da iluminação
  • Sem suporte de hardware dedicado, é possível executar código de sombreamento arbitrário na CPU, mas o cálculo é lento
  • Em texturas paletizadas, mudar apenas a paleta, e não todos os texels, faz a textura inteira parecer ter recebido o cálculo de iluminação
    • A paleta original é substituída por uma paleta sombreada
    • A textura paletizada é aplicada ao objeto como uma textura comum
    • Mesmo uma luz difusa simples dot(N,L) já produz um resultado bastante bom
  • O exemplo inicial desfazia a correção de gama da textura de cor para sombrear em espaço linear, mas isso não pôde ser aplicado na demo final porque os termos de ambiente e luz direta precisavam ser separados e combinados por hardware na unidade RDP do N64

Normal mapping em espaço do objeto

  • O normal mapping comum é feito em espaço tangente
    • Permite usar texturas repetidas
    • Consegue corrigir normais de vértice que variam suavemente com normais de detalhe
    • Um normal map em espaço tangente de cor única representa uma superfície lisa
  • Normais em espaço do objeto têm cálculo simples, mas grandes restrições
    • Os texels do normal map representam normais absolutas da superfície, não desvios em relação às normais dos vértices
    • O cálculo em runtime fica tão simples quanto ler cores de uma textura
    • Cada ponto da superfície precisa de um texel próprio, como em um lightmap

Paleta compartilhada pela textura difusa e pelo normal map

  • O objeto tem tanto uma textura difusa basecolor * ao quanto um normal map
  • As duas texturas compartilham os mesmos índices de paleta, gerados com K-means clustering do scikit-learn
    • As imagens são interpretadas como uma única imagem de 6 canais
    • Com um único índice, é possível obter tanto a normal quanto a cor difusa da superfície
  • No carregamento, ou a cada frame, as cores da paleta são percorridas
    • O código de shader na CPU cria uma nova cor RGB para cada índice
    • O resultado do loop vira a nova paleta com iluminação aplicada
  • Na prática, essa abordagem se adapta melhor a iluminação direcional
  • Só com a paleta é difícil representar efeitos como sombras, então ela precisa ser combinada com iluminação baked

Ambiente direcional baked e luz solar

  • Para uma iluminação mais realista, os prédios da demo armazenam separadamente a luz ambiente e a luz solar direta nas cores dos vértices
    • RGB do vértice: cor ambiente
    • Alfa do vértice: visibilidade do sol
  • O termo ambiente é dividido em intensidade direcional e cor
    • A intensidade direcional é um irradiance map em escala de cinza
    • A cor é o RGB dos vértices com saturação aumentada
  • O sol é uma luz direcional, e a visibilidade é transmitida pelo alfa dos vértices
  • A fórmula de sombreamento é a seguinte
ambient = vertex_rgb      * grey_irradiance_map(N)
direct  = vertex_alpha    * sun_color * dot(N, sun_dir)
color   = diffuse_texture * (ambient + direct)
  • As cores de vértice sujas da visibilidade do sol são mascaradas pelo cálculo N.L e acabam refletidas de forma mais limpa no resultado final da luz direta
  • Mesmo quando a iluminação baked é grosseira, o ambiente direcional pode parecer sofisticado graças aos detalhes da textura
  • Para o environment map desfocado, foi usada equirectangular projection pela simplicidade
    • HDRIs da Polyhaven já usam essa projeção
    • Como o sombreamento foi pré-calculado no carregamento, a matemática de amostragem mais complexa não foi um problema

Lidando com modelos grandes com texturas repetidas

  • O algoritmo de sombreamento original foi projetado para um único objeto e, no início, era testado apenas com potato_rock.obj
  • A malha do castelo na demo tinha texturas repetidas, o que causou problemas
  • A solução de contorno foi dividir a malha grande em várias submalhas e fazer cada submalha compartilhar conceitualmente o mesmo normal map em espaço do objeto
    • No Blender, a geometria foi agrupada manualmente com base no material e na orientação da superfície
    • Uma matriz world-to-model foi calculada com base nas normais dos polígonos de cada grupo
    • Essa matriz é aproximadamente próxima de um espaço tangente
  • Como cada grupo compartilha a paleta, a iluminação geral só fica correta em um sentido médio
  • O espaço tangente não é interpolado em runtime, então o resultado parece iluminação por face, o que é uma das maiores desvantagens da técnica

Aproximação de sombreamento especular

  • Como vários pontos da superfície compartilham a mesma cor sombreada, é difícil calcular point lights ou sombreamento especular com precisão
  • A abordagem em espaço de paleta se adapta bem à iluminação difusa direcional, que não precisa do vetor to camera V
  • O efeito especular foi tentado aproximando o objeto por uma esfera
    • O ponto a sombrear p é definido como p = radius * normal
    • Como muitos pontos da superfície compartilham o mesmo índice de paleta, o resultado inevitavelmente fica facetado
  • O highlight especular da demo parecia um pouco estranho, mas funcionava o suficiente para enganar a maioria das pessoas

Limitações e materiais relacionados

  • Na demo, as principais limitações foram escondidas com pré-processamento e composição da cena
    • Descontinuidades de iluminação e faixa de representação

      • Só há suporte a texturas em escala de cinza
      • Não há point lights
      • Esta técnica só é prática com pré-processamento sofisticado
      • A técnica de Spooky Iluha não tem problema de descontinuidade de iluminação, mas não se sabe se é possível resolver o mesmo problema mantendo tanto a luz ambiente quanto a direta
    • ROM e pesquisa anterior

1 comentários

 
GN⁺ 2025-05-19
Comentários do Hacker News
  • Ver gráficos realistas no N64 é realmente impressionante, e esta demo me lembra "ICO", do PS2
    Há tempos eu me perguntava se seria possível criar um SDK que abstraísse o hardware gráfico do N64 e oferecesse primitivas modernas, iluminação, sombreamento, ferramentas para pré-calcular iluminação como nesta demo, etc.
    O N64 tinha um hardware bem peculiar para a sua geração, e há detalhes no Copetti.org: https://www.copetti.org/writings/consoles/nintendo-64/

    • O N64 foi projetado pela SGI e, considerando a influência da SGI em gráficos 3D, eu diria que o N64 provavelmente era o hardware mais próximo do padrão naquela geração
      Eu até ficaria um pouco surpreso se não houvesse uma biblioteca OpenGL
      Mas há uma ressalva importante: 1) esse sistema deve ser visto como uma placa de vídeo com CPU acoplada e 2) o sistema gráfico é exposto diretamente
      A arquitetura de chips gráficos acaba facilmente virando uma bagunça suja e incompatível entre si, então fabricantes de aceleradores normalmente preferem expor APIs intermediárias como OpenGL, DirectX, CUDA e Vulkan, em vez de publicar documentação de referência
      Assim, eles podem continuar mantendo a implementação interna incompatível. Se não publicam a documentação de referência, também não precisam manter retrocompatibilidade de hardware; a vantagem é poder criar novos projetos, mas a desvantagem é que quase ninguém consegue usá-los diretamente
      Por isso, quando se tem acesso direto como nos consoles daquela geração, a reação instintiva é entrar em pânico
      Além disso, o OpenGL veio da SGI, e a Nvidia também foi fundada por ex-engenheiros da SGI
    • Também me lembra Shadow of the Colossus: https://www.youtube.com/watch?v=xMKtYM8AzC8
  • Gosto que um texto sobre truques gráficos do N64 termine com a pergunta "Is this the future?"

    • Hoje em dia, a escala do desenvolvimento indie para N64 cresceu de forma absurda, e a plataforma está cheia de vida
      Cerca de uma dúzia de títulos populares foram decompilados em arquivos-fonte legíveis [1], facilitando ports para PC sem emulador e permitindo inúmeros mods que rodam no hardware original
      Há vários remakes de fãs de Zelda [2], além de jogos completos com novas dungeons e história
      O lado de Mario 64 está especialmente aquecido; Kaze otimizou profundamente o jogo [3] e também está criando seu próprio engine e uma sequência. Se você gosta de análises técnicas aprofundadas sobre retro, o canal dele é uma verdadeira mina de ouro
      Também surgem demos absurdas como Portal [4], que infelizmente chamou a atenção do departamento jurídico da Valve
      Jogos perdidos como Dinosaur Planet, da Rare, depois de vazados, também foram polidos até quase um estado lançável, decompilados e vêm passando por um renascimento indie próprio [5]
      [1] https://wiki.deco.mp/index.php/N64
      [2] https://m.youtube.com/watch?v=bZl8xKDUryI
      [3] https://m.youtube.com/channel/UCuvSqzfO_LV_QzHdmEj84SQ
      O canal inteiro é excelente, e há dezenas de análises profundas como esta: https://m.youtube.com/watch?v=DdXLpoNLywg
      O jogo e o engine dele também são lindos: https://youtu.be/Drame-4ufso
      [4] https://m.youtube.com/watch?v=yXzoZ2AfWwg
      [5] https://m.youtube.com/watch?v=s0QSiPRmWaI
  • Fico impressionado toda vez que vejo como esses engenheiros de jogos eram geniais
    Sob restrições enormes, eles criavam soluções imaginativas e excelentes

    • Restrições exigem e geram uma criatividade extraordinária
      Esse é justamente o segredo de pico8, Animal Well e de inúmeros jogos incríveis
      Eu só queria não ter pensado neste fim de semana em uma estrutura muito melhor para o criador do meu jogo de pixel art 2D. Agora parece que vai levar mais um mês até o lançamento :(
    • Esta não é uma técnica usada no auge do N64, mas um trabalho novo
    • Os engenheiros da época também certamente eram incríveis, mas isto, como indicado, é um trabalho de 2025 e está mais próximo da demoscene do que do desenvolvimento de jogos
  • Hoje é ótimo termos sistemas mais rápidos, mas havia uma diversão em contornar as limitações nos jogos antigos, e a satisfação era enorme quando se conseguia fazer direito
    Leitores do HN provavelmente conhecem raster interrupts (https://en.wikipedia.org/wiki/Raster_interrupt) e beam racing. Pessoalmente, eu sempre associei isso ao Atari 800
    Em teoria, não deveria ser possível fazer algo como https://youtu.be/GuHqw_3A-vo?t=33, mas os Display List Interrupts tornaram isso possível
    Algo que eu não sabia até recentemente era o quanto os jogos de Atari 2600 dependiam desse tipo de insanidade: https://www.youtube.com/watch?v=sJFnWZH5FXc
    Ver coisas assim me faz pensar que, mesmo se o avanço do hardware parasse, ainda poderíamos continuar descobrindo coisas mais interessantes por décadas

  • A demoscene e trabalhos desse tipo são impressionantes, mas, em geral, parecem tender a cenas mais simples e vazias
    Algo mais próximo do que poderia entrar como cenário de jogo ou como parte de uma mecânica de jogo. Com a maioria das técnicas, dá a impressão de que não há recursos suficientes para criar uma experiência completa
    O que é mais impressionante é o trabalho de extrair desempenho muito melhor de hardware antigo, como o FastDoom ou vários projetos de otimização do Mario 64
    Às vezes fazem isso até adicionando conteúdo e funcionalidades. Fico me perguntando se talvez exista alguma conexão entre desenvolvedores da demoscene e esses trabalhos mais abrangentes

  • Jogos shareware dos anos 90 usavam uma técnica parecida de iluminação baseada em paleta
    Basicamente, ao montar a paleta VGA de 256 cores, a ideia era colocar, para cada cor suportada, uma gradação de brilho em N níveis daquela cor
    Assim era possível alterar facilmente o brilho de cada cor apenas somando ou subtraindo o índice da cor

  • Sinto falta da otimização da época do PS1 e do PS2
    A maioria fica realmente bonita quando você roda em emulação e sobe para 1080p ou 4K ou mais. Pessoalmente, acho que gráficos da era de Halo 2 em 4K já são suficientes
    Claro que Halo 2 é um jogo de Xbox, mas, se você joga Halo 2 no Halo MCC com gráficos clássicos, ele ainda parece impressionante
    O efeito de miragem de calor do GT3 resume bem isso
    "Na demo de GT3, mostraram o circuito de Seattle ao entardecer, e havia uma cena em que o calor subia do chão, ondulando. No PS3 não dá para reproduzir esse efeito de miragem de calor. É porque read-modify-write não é tão rápido quanto era quando se usava o PS2. Existem coisas assim."
    https://old.reddit.com/r/ps2/comments/1cktw88/gran_turismos_...
    https://youtu.be/ybi9SdroCTA?t=4103
    Não era uma tentativa de emular ondas de calor reais como em engines novas tipo UE5, mas sim de resolver com um truque para não destruir a taxa de quadros. Sinceramente, vendo o quanto RTX derruba o framerate, prefiro esses truques baratos
    Um MIPS de 299 MHz rodava isso
    Shadow of the Colossus: https://www.youtube.com/watch?v=xMKtYM8AzC8
    GoW2: https://youtu.be/IpKLwIIdvuk?si=TjifKmlYsUuvhk0F&t=970
    FFXII: https://youtu.be/NytHoYOs_4M?si=jE1Fxy40khEvV6Bn&t=51
    GT4: https://www.youtube.com/watch?v=F6lZIxk_h9g (fiquei emocionado vendo a tela de boot)
    Black, a Renderware era uma engine insana: https://youtu.be/bZBjcwyq7fQ?si=Pev5ifpksJm4X6Oi&t=356
    Valkyrie Profile 2: https://youtu.be/9ScjO4NuUtA?si=Z29cR-hLsT2pnP2I&t=38
    Rouge Galaxy: https://youtu.be/iR1evzyl-7Q?si=fldm3-NnuFxOITMn&t=624
    Burnout 3: https://www.youtube.com/watch?v=_r5r0nE1sA4
    Também tem Jak and Daxter e Ratchet
    No lado do GC, RE4, Metroid, os Zeldas etc. obviamente parecem incríveis
    Dá vontade de se ajoelhar

    • Sobre o PS2, concordo, mas o PSX é discutível
      Ele talvez competisse com um Pentium 90, quase 100, mas um Pentium MMX com 3DFX esmagaria o PSX e ficaria no nível do N64 ou melhor
      A CPU MIPS era excelente e fazia coisas surpreendentes mesmo com clock baixo. Basta ver o PSP ou o SGI Irix
      Além disso, a "GPU" do PS2 não é a mesma coisa que uma CPU R4k
      Acrescentando: o port de Deus Ex para PS2 era péssimo em comparação com a versão de PC e não dava conta plenamente da engine Unreal
      É verdade que o PS2 produzia efeitos insanos, mas nesse port os níveis eram realmente pequenos. Também é preciso levar em conta que grande parte de Deus Ex era quase um mundo aberto
    • Ainda acho que Halo 3 parece muito melhor do que alguns jogos modernos
      Blur, bloom, pop-in de grama e vegetação e coisas assim não ficam realmente bons; parecem piores do que simplesmente desligar tudo
      Num FPS acelerado, você nem tem tempo de apreciar modelos com muitos polígonos, então nem sei qual é o sentido disso
      Para meus olhos, a resolução das texturas de Halo 3 já é suficiente. Acho que eu nem perceberia se o tamanho das texturas dobrasse ou quadruplicasse; o que ficaria evidente seriam apenas os requisitos de hardware
    • A frase "um MIPS de 299 MHz roda isso" só é correta até certo ponto
      O vídeo de GoW2 foi capturado no PCSX2, e é provável que, nesse clipe, ele tenha se beneficiado de upscaling e outros recursos de conveniência
      Não vi todos os outros vídeos, mas, de todo modo, o que GoW2 conseguiu no PS2 foi impressionante