2P by GN⁺ | ★ favorite | 댓글 1개
  • Revision 2025용 Nintendo 64 데모는 텍스처 전체를 다시 계산하지 않고 팔레트만 갱신해 노멀 매핑, 베이크된 조명, 실시간 스페큘러에 가까운 효과를 냄
  • CPU가 각 팔레트 인덱스에서 노멀과 확산색을 읽어 새 RGB 팔레트를 만들면, 팔레트 텍스처가 텍셀별 조명을 받은 것처럼 반응함
  • 확산 텍스처와 노멀 맵은 같은 팔레트 인덱스를 공유하며, scikit-learn의 K-means clustering으로 6채널 이미지처럼 묶어 생성됨
  • 건물 조명은 정점 RGB의 앰비언트 색, 정점 알파의 태양 가시성, 회색 irradiance map, 방향성 태양광의 dot(N, sun_dir)을 조합함
  • 방향성 확산광에는 효과적이지만 그림자, 포인트 라이트, 정확한 스페큘러, 반복 텍스처가 있는 큰 모델에서는 제약이 커서 전처리로 한계를 감춰야 함

팔레트만 갱신해 셰이딩하기

  • Nintendo 64 데모는 Revision 2025용으로 제작됐고, 베이크된 조명, 노멀 매핑, 실시간 스페큘러 셰이딩에 가까운 효과를 사용함
  • N64에서 노멀 매핑은 기존 홈브루 실험으로 가능성이 알려져 있었고, 이 데모는 런타임에 텍스처가 아니라 조명 결과 팔레트를 계산하는 쪽을 택함
  • 전용 하드웨어 지원 없이 CPU에서 임의의 셰이딩 코드를 실행할 수 있지만, 계산 속도는 느림
  • 팔레트 텍스처에서는 텍셀 전체가 아니라 팔레트만 바꿔도 텍스처 전체가 조명 계산을 받은 것처럼 보임
    • 원래 팔레트는 셰이딩된 팔레트로 대체됨
    • 팔레트 텍스처는 일반 텍스처처럼 오브젝트에 적용됨
    • 단순한 확산광 dot(N,L)만으로도 결과가 꽤 좋아 보임
  • 초기 예시는 색상 텍스처의 감마 보정을 되돌려 선형 공간에서 셰이딩했지만, 최종 데모에서는 앰비언트와 직접광 항을 분리해 N64의 RDP 유닛에서 하드웨어로 합성해야 해서 적용하지 못함

오브젝트 공간 노멀 매핑

  • 일반적인 노멀 매핑은 접선 공간에서 수행됨
    • 반복 텍스처를 사용할 수 있음
    • 세부 노멀이 부드럽게 변하는 정점 노멀을 보정할 수 있음
    • 단일 색상의 접선 공간 노멀 맵은 매끄러운 표면을 나타냄
  • 오브젝트 공간 노멀은 계산이 단순한 대신 제약이 큼
    • 노멀 맵의 텍셀은 정점 노멀로부터의 편차가 아니라 절대 표면 노멀을 나타냄
    • 런타임 계산은 텍스처에서 색을 읽는 수준으로 단순해짐
    • 모든 표면 지점에 라이트맵처럼 고유한 텍셀이 필요함

확산 텍스처와 노멀 맵이 공유하는 팔레트

  • 오브젝트는 확산 텍스처 basecolor * ao와 노멀 맵을 모두 가짐
  • 두 텍스처는 같은 팔레트 인덱스를 공유하며, 이 인덱스는 scikit-learn의 K-means clustering으로 생성됨
    • 이미지들은 하나의 6채널 이미지처럼 해석됨
    • 하나의 인덱스로 노멀과 표면 확산색을 모두 가져올 수 있음
  • 로딩 시점 또는 매 프레임마다 팔레트 색을 순회함
    • CPU 셰이더 코드가 각 인덱스에 대해 새 RGB 색을 만듦
    • 루프 결과가 조명이 적용된 새 팔레트가 됨
  • 이 접근은 실제로는 방향성 조명에 가장 잘 맞음
  • 팔레트만으로는 그림자 같은 효과를 표현하기 어려워, 베이크된 조명과 결합해야 함

베이크된 방향성 앰비언트와 태양광

  • 데모의 건물에는 더 현실적인 조명을 넣기 위해 앰비언트와 직접 태양광을 정점 색상에 분리해 저장함
    • 정점 RGB: 앰비언트 색
    • 정점 알파: 태양 가시성
  • 앰비언트 항은 방향성 강도와 색상으로 나뉨
    • 방향성 강도는 회색조 irradiance map
    • 색상은 채도를 높인 정점 RGB
  • 태양은 방향성 조명이며, 가시성은 정점 알파로 전달됨
  • 셰이딩 공식은 다음과 같음
ambient = vertex_rgb      * grey_irradiance_map(N)
direct  = vertex_alpha    * sun_color * dot(N, sun_dir)
color   = diffuse_texture * (ambient + direct)
  • 지저분한 태양 가시성 정점 색상은 N.L 계산으로 마스킹되어 최종 직접광 결과에 정리되어 반영됨
  • 방향성 앰비언트는 베이크된 조명이 거칠어도 텍스처 디테일 덕분에 결과가 고급스럽게 보일 수 있음
  • 흐린 환경 맵에는 단순함 때문에 equirectangular projection을 사용함
    • Polyhaven HDRI가 이미 이 투영을 사용함
    • 셰이딩을 로드 시점에 미리 계산했기 때문에 복잡한 샘플링 수학이 문제가 되지 않음

반복 텍스처가 있는 큰 모델 처리

  • 원래 셰이딩 알고리듬은 단일 오브젝트용으로 설계됐고, 초기에는 potato_rock.obj로만 테스트됨
  • 데모의 성곽 메시에는 반복 텍스처가 있어 문제가 생김
  • 우회책은 큰 메시를 여러 서브메시로 나누고, 각 서브메시가 개념적으로 같은 오브젝트 공간 노멀 맵을 공유하게 만드는 방식임
    • Blender에서 재질과 표면 방향 기준으로 지오메트리를 수동 그룹화함
    • 각 그룹의 폴리곤 노멀을 기반으로 world-to-model 행렬을 계산함
    • 이 행렬은 대략적인 접선 공간에 가까움
  • 각 그룹은 팔레트를 공유하므로 전체 조명은 평균적인 의미에서만 맞음
  • 접선 공간은 런타임에 보간되지 않아 면 단위 조명처럼 보이며, 이 점이 기법의 가장 큰 단점 중 하나임

스페큘러 셰이딩의 근사

  • 여러 표면 지점이 같은 셰이딩 색을 공유하기 때문에 포인트 라이트나 스페큘러 셰이딩을 정확히 계산하기 어려움
  • 팔레트 공간 접근은 to camera 벡터 V가 필요 없는 확산 방향성 조명에 잘 맞음
  • 스페큘러 효과는 오브젝트를 구로 근사하는 방식으로 시도함
    • 셰이딩할 점 pp = radius * normal로 둠
    • 많은 표면 지점이 같은 팔레트 인덱스를 공유하므로 결과는 각져 보일 수밖에 없음
  • 데모의 스페큘러 하이라이트는 다소 이상해 보였지만, 대부분의 사람을 속일 정도로는 동작함

한계와 관련 자료

  • 데모에서는 주요 한계를 전처리와 장면 구성으로 숨기려 함
    • 조명 불연속과 표현 범위

      • 회색조 텍스처만 지원함
      • 포인트 라이트는 없음
      • 이 기법은 정교한 전처리가 있을 때만 실용적임
      • Spooky Iluha의 기법에는 조명 불연속 문제가 없지만, 앰비언트와 직접광을 모두 유지하면서 같은 문제를 해결할 수 있는지는 알 수 없음
    • ROM과 이전 연구

댓글과 토론

Hacker News 의견들
  • N64에서 현실적인 그래픽을 보는 건 정말 인상적이고, 이 데모는 PS2의 "ICO"가 떠오름
    예전부터 N64 그래픽 하드웨어를 추상화해서 현대적인 기본 도형, 조명, 셰이딩, 이 데모처럼 조명을 미리 구워 넣는 도구 등을 제공하는 SDK를 만들 수 있을지 궁금했음
    N64는 같은 세대 기준으로 꽤 독특한 하드웨어를 갖고 있고, 자세한 내용은 Copetti.org에 있음: https://www.copetti.org/writings/consoles/nintendo-64/

    • N64는 SGI가 설계했고, SGI가 3D 그래픽에 끼친 영향력을 생각하면 오히려 N64가 그 세대에서 가장 표준적인 하드웨어에 가까웠을 거라고 봄
      OpenGL 라이브러리가 없었다면 오히려 조금 놀랄 듯함
      다만 큰 단서가 있는데, 1) 이 시스템은 CPU가 붙은 그래픽 카드처럼 봐야 하고 2) 그래픽 시스템이 직접 노출되어 있음
      그래픽 칩 구조는 결국 지저분하고 서로 호환 안 되는 난장판이 되기 쉬워서, 가속기 제조사들은 보통 참조 문서를 공개하기보다 OpenGL, DirectX, CUDA, Vulkan 같은 중간 API를 공개하는 쪽을 선호함
      그렇게 하면 내부 구현을 계속 호환 안 되는 구조로 유지할 수 있음. 참조 문서를 공개하지 않으면 하드웨어 하위 호환성을 지킬 필요도 없고, 장점은 새로운 설계를 만들 수 있다는 것이지만 단점은 아무도 직접 쓰기 어렵다는 것임
      그래서 그 세대 콘솔처럼 직접 접근권이 생기면 본능적으로 질겁하게 됨
      덧붙이면 OpenGL은 SGI에서 나왔고, Nvidia도 전직 SGI 엔지니어들이 창업했음
    • Shadow of the Colossus도 떠오름: https://www.youtube.com/watch?v=xMKtYM8AzC8
  • N64 그래픽 트릭을 다룬 글이 마지막에 "Is this the future?"라는 질문으로 끝나는 게 마음에 듦

  • 이 게임 엔지니어들이 얼마나 천재적이었는지 볼 때마다 놀라움
    엄청난 제약 속에서 상상력 넘치고 훌륭한 해법을 만들어냈음

    • 제약은 비범한 창의성을 요구하고 만들어냄
      pico8, Animal Well, 그리고 수많은 놀라운 게임의 비밀이 바로 그것임
      이번 주말에 내 2D 픽셀 아트 게임 제작기 제작기를 위한 훨씬 나은 구조를 떠올리지 않았으면 좋았을 텐데. 이제 출시까지 또 한 달은 더 걸리게 생김 :(
    • 이건 N64 전성기에 쓰인 기법이 아니라 새로 나온 작업
    • 당시 엔지니어들도 대단했겠지만, 이건 명시된 것처럼 2025년 작업이고 게임 개발보다는 데모신 쪽에 가까움
  • 지금은 더 빠른 시스템이 있어서 정말 좋지만, 예전 게임에서 제약을 우회해야 했던 재미가 있었고 제대로 해냈을 때 만족감이 정말 컸음
    HN 독자라면 래스터 인터럽트(https://en.wikipedia.org/wiki/Raster_interrupt)와 빔 레이싱에 익숙할 것임. 개인적으로는 Atari 800과 연결해서 생각해 왔음
    원래는 https://youtu.be/GuHqw_3A-vo?t=33 같은 걸 할 수 없어야 했지만, Display List Interrupts 덕분에 가능했음
    최근까지 몰랐던 건 Atari 2600 게임들이 이런 광기에 얼마나 많이 기대고 있었는지였음: https://www.youtube.com/watch?v=sJFnWZH5FXc
    이런 걸 보면 하드웨어 발전이 멈추더라도 수십 년 동안 계속 더 흥미로운 걸 찾아낼 수 있겠다는 생각이 듦

  • 데모신과 이런 작업은 인상적이지만, 대체로 더 단순하고 비어 있는 장면으로 흐르는 경향이 보임
    게임 배경이나 게임 메커니즘의 일부로 들어갈 만한 것에 가까움. 대부분의 기법으로는 완전한 경험을 만들 만큼 자원이 충분하지 않은 것처럼 느껴짐
    더 인상적인 건 FastDoom이나 여러 Mario 64 최적화 프로젝트처럼 오래된 하드웨어에서 훨씬 나은 성능을 짜내는 작업임
    때로는 콘텐츠와 기능을 추가하면서도 그렇게 함. 데모신 개발자들과 이런 더 포괄적인 작업 사이에 연결점이 있을지도 궁금함

  • 90년대 셰어웨어 게임에서 비슷한 팔레트 기반 조명 기법을 썼음
    기본적으로 VGA 256색 팔레트를 구성할 때, 지원하는 각 색마다 그 색의 N단계 밝기 그라데이션을 넣어 두는 방식임
    그러면 색상 인덱스를 더하거나 빼는 것만으로 각 색의 밝기를 쉽게 바꿀 수 있었음

  • PS1과 PS2 시절의 최적화가 그리움
    대부분은 에뮬레이션으로 1080p나 4K 이상으로 올려 보면 정말 멋짐. 개인적으로는 Halo 2 시대 그래픽을 4K로 보는 정도면 충분하다고 봄
    물론 Halo 2는 Xbox 게임이지만, Halo MCC에서 Halo 2를 클래식 그래픽으로 해보면 아직도 놀랍게 보임
    GT3의 열기 아지랑이 효과가 잘 요약해 줌
    "GT3 데모에서 시애틀 코스를 해질녘에 보여줬는데, 지면에서 열기가 올라오며 일렁이는 장면이 있었다. PS3에서는 그 열기 아지랑이 효과를 재현할 수 없다. read-modify-write가 PS2를 쓰던 때만큼 빠르지 않기 때문이다. 그런 것들이 있다."
    https://old.reddit.com/r/ps2/comments/1cktw88/gran_turismos_...
    https://youtu.be/ybi9SdroCTA?t=4103
    UE5 같은 새 엔진처럼 실제 열파를 에뮬레이션하려는 게 아니라, 프레임률을 박살내지 않도록 트릭으로 처리한 것임. 솔직히 RTX가 프레임률을 크게 깎아 먹는 걸 보면 이런 저렴한 트릭 쪽이 더 좋음
    299MHz MIPS가 이런 걸 돌림
    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 (부트 화면 보고 울컥함)
    Black, Renderware는 미친 엔진이었음: 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
    Jak and Daxter, Ratchet도 있음
    GC 쪽은 RE4, Metroid, Zelda들 등 당연히 엄청나게 좋아 보임
    무릎 꿇게 됨

    • PS2에 대해서는 맞지만, PSX는 애매함
      Pentium 90, 거의 100 정도와는 비빌 수 있었겠지만, 3DFX가 붙은 MMX Pentium이면 PSX를 압도하고 N64와 같거나 더 나았을 것임
      MIPS CPU는 훌륭해서 낮은 클럭에서도 놀라운 일을 해냄. PSP나 SGI Irix만 봐도 그렇음
      또 PS2의 "GPU"는 R4k CPU와 같은 것이 아님
      덧붙이면 PS2의 Deus Ex 이식판은 PC판에 비해 형편없었고 Unreal 엔진을 완전히 감당하지 못했음
      PS2가 미친 효과를 냈던 건 맞지만, 그 이식판에서는 레벨이 정말 작았음. Deus Ex는 게임의 큰 부분이 거의 오픈 월드에 가까웠다는 점도 감안해야 함
    • 아직도 Halo 3가 일부 현대 게임보다 훨씬 좋아 보인다고 생각함
      블러, 블룸, 풀과 식생의 팝인 같은 건 실제로 좋아 보이지 않고, 그냥 다 꺼두는 것보다 더 나빠 보임
      빠른 속도의 1인칭 슈터에서는 고다각형 모델을 감상할 틈도 없는데 그게 무슨 의미가 있는지도 모르겠음
      내 눈에는 Halo 3 텍스처 해상도면 충분함. 텍스처 크기가 2배나 4배가 되어도 알아챌 것 같지 않고, 눈에 띄는 건 하드웨어 요구사항뿐임
    • "299MHz MIPS가 이걸 돌린다"는 말은 어느 정도만 맞음
      GoW2 영상은 PCSX2에서 캡처된 것이고, 그 클립에서는 업스케일링과 다른 편의 기능의 이점을 봤을 가능성이 큼
      나머지 영상은 다 보지 않았지만, 어쨌든 GoW2가 PS2에서 이룬 성취는 대단했음