1P by GN⁺ | ★ favorite | 댓글 1개
  • Nanite WebGPU는 WebGPU로 브라우저 안에서 UE5의 Nanite식 렌더링을 구현한 프로젝트이며, meshlet LOD 계층, 소프트웨어 래스터라이저, billboard impostor, 인스턴스/meshlet 단위 컬링을 포함함
  • 구현은 OBJ 입력을 브라우저에서 전처리하는 단순성과, 체크박스·슬라이더로 설정을 바꾸며 성능 변화를 실험하는 것을 주요 목표로 삼음
  • 데모는 Jinx 장면 640M triangles, Lucy/Dragons 등 최대 1.7B triangles 장면을 제공하며, Jinx의 흰 삼각형은 WebGPU 제약 때문에 32비트로 압축해 처리한 소프트웨어 래스터라이즈 결과임
  • WebGPU에는 atomic<u64>가 없어 visibility buffer 기반의 효율적인 소프트웨어 래스터라이저를 그대로 구현하기 어렵고, 현재 구현은 depth u16과 octahedron normal 2*u8을 32비트에 담아 정밀도 아티팩트를 감수함
  • 실제 Nanite식 구현에서 핵심 난제는 단순한 삼각형 수가 아니라 mesh simplification과 error metric이며, 저자는 자체 구현이 UE5와 달리 단순화·스트리밍·압축·visibility buffer·2-pass occlusion culling 등을 갖추지 않았다고 명시함

프로젝트 개요

  • Nanite WebGPU는 WebGPU를 사용해 웹 브라우저에서 Nanite식 렌더링을 구현한 프로젝트임
  • 포함된 주요 요소는 meshlet LOD hierarchy, 소프트웨어 래스터라이저, billboard impostor, 인스턴스 및 meshlet 단위 컬링임
  • 텍스처 모델과 per-vertex normal을 지원하며, 설정마다 슬라이더나 체크박스를 제공함
  • WebGPU는 Chrome에서만 사용할 수 있음
  • 전체 앱은 Deno를 사용해 오프라인에서도 실행 가능하며, 셰이더 단위 테스트도 이 방식으로 작성됨

데모 장면과 규모

  • Jinx 데모는 120×120 인스턴스, 640M triangles 규모임
    • 단일 Jinx 모델은 44k triangles에서 3k triangles, 59개 root meshlets로 단순화됨
    • 흰 삼각형은 하드웨어 래스터라이즈 영역과 먼 배경의 impostor 사이에 있는 소프트웨어 래스터라이즈 삼각형임
  • Lucy and dragons는 두 객체를 각각 70×70 인스턴스로 배치해 1.7B triangles를 구성함
    • 샘플 장면에서는 삼각형의 거의 98%가 소프트웨어 래스터라이즈되며, 이 경로가 하드웨어보다 훨씬 빠르다고 밝힘
  • Lucy는 110×110 인스턴스, 1.2B triangles 장면임
    • 단일 Lucy statue는 100k triangles에서 86 triangles의 단일 root meshlet으로 단순화됨
  • Dragons는 70×70 인스턴스, 1.2B triangles 장면임
    • 단일 dragon은 250k triangles에서 102 triangles의 단일 root meshlet으로 단순화됨
  • Bunnies는 500×500 인스턴스, 1.2B triangles 장면임
    • 단일 bunny는 5k triangles에서 96 triangles의 단일 root meshlet으로 단순화됨
    • bunny는 크기가 작아 대부분 frustum culling됨

구현된 기능

  • Meshlet LOD hierarchy

    • mesh preprocessing은 브라우저에서 실행됨
    • meshoptimizerMETIS를 WebAssembly로 사용함
    • 페이지 새로고침 사이에 전처리를 기다리지 않도록 파일 exporter도 제공함
  • Software rasterizer

    • WebGPU에는 효율 구현에 필요한 atomic<u64>가 없음
    • 현재 구현은 depth u16과 octahedron-encoded normals 2*u8을 32비트에 패킹함
    • 32비트 제한 때문에 정밀도를 크게 희생하며, 목표는 래스터라이저가 동작함을 보여주는 데 있음
    • 이 제한은 occlusion culling에 쓰이는 depth pyramid에도 영향을 줌
  • Billboard impostors

    • UP축 주위의 12개 이미지를 사용하고, 카메라 위치에 따라 dithering으로 blend함
    • 위/아래 시점은 처리하지 않음
    • diffuse와 normal을 모두 포함해 런타임 shading을 수행함
    • Impostors preview는 impostor texture size를 키운 데모임

컬링과 렌더링 경로

  • 컬링은 여러 단계로 구성됨
    • Per-instance: frustum culling과 occlusion culling
    • Per-meshlet: frustum culling과 occlusion culling
    • Per-triangle: hardware backface culling과 z-buffer
  • WebGPU에는 early-z가 없음
  • occlusion culling은 이전 프레임 depth buffer로 만든 depth pyramid만 사용함
    • reprojection과 two-pass 방식은 없음
    • 현재 구현만으로도 많은 삼각형을 컬링하고 성능 개선을 판단하기에 충분하다고 봄
  • GPU-driven rendering과 단순한 CPU 구현 사이를 전환할 수 있음
    • CPU 버전은 많은 최적화를 하지 않았지만, 디버거로 단계 실행이 가능함
  • “Freeze culling” 기능은 카메라를 움직이면서 마지막 프레임에 그려진 것만 검사할 수 있게 함

사용성과 디버깅

  • 이동은 [W, S, A, D], 상승/하강은 [Z, SPACEBAR], 빠른 이동은 [Shift]를 사용함
  • 이상한 결과가 보이면 culling 옵션을 켜고 끄는 방식으로 확인할 수 있음
    • 구현에는 일부 작은 버그가 있음
  • 흰 삼각형은 소프트웨어 래스터라이즈된 삼각형임
    • WebGPU의 atomic<u64> 부재 때문에 depth와 normal을 32비트에 압축함
    • 16-bit depth는 z-fighting이나 leak 같은 아티팩트를 많이 만들 수 있음
    • 소프트웨어 래스터라이저를 끄면 raw Nanite meshlets를 보기 쉬워지지만 큰 성능 저하가 생길 수 있음
  • FPS는 브라우저의 강제 VSync 때문에 흔들릴 수 있으며, 타이밍 확인에는 “Profile” 버튼을 사용함

설계 목표

  • 프로젝트의 첫 번째 목표는 단순성
    • OBJ 파일에서 시작해 모든 처리를 앱 안에서 수행함
    • Blender export 같은 별도 전처리 단계를 요구하지 않음
    • loadObjFile()에 breakpoint를 걸고 첫 프레임이 끝날 때까지 따라갈 수 있게 하는 흐름을 지향함
  • 두 번째 목표는 실험성
    • Rust와 Vulkan 대신 웹페이지로 만들었기 때문에 링크를 클릭하고 체크박스나 슬라이더를 바꾸며 성능 변화를 볼 수 있음
    • 설정 하나를 바꿨을 때 FPS가 크게 떨어지는 식으로 어떤 옵션이 중요한지 직접 확인할 수 있음
  • 많은 코드가 최적화될 수 있지만, simplification 문제가 해결되기 전까지는 그 최적화가 중요하지 않다고 봄

UE5 Nanite와의 차이

  • error metric은 단순한 projected simplification error를 사용함
  • meshlet simplification은 단순한 방식임
  • two-pass occlusion culling이 없음
    • 추가는 어렵지 않지만 디버깅이 번거롭고 GUI 설정과 상호작용이 생김
    • 코드 가독성을 해치기 때문에 목표와 맞지 않음
  • visibility buffer가 없음
    • atomic<u64> 제한 때문에 구현할 수 없음
  • built-in shadows와 multiview가 없음
  • 셰이더 안의 work queue가 없음
    • meshlet culling과 LOD selection에는 meshlet당 thread를 dispatch함
  • 사용하지 않는 LOD의 VRAM eviction과 streaming이 없음
  • compression이 없음
  • 많은 서로 다른 객체에는 확장성이 낮음
    • 데모 케이스에서 예측 가능한 메모리 사용량에 초점을 맞춤
    • stage 사이 데이터를 담을 buffer를 위해 drawn meshlets의 상한을 미리 알아야 함
  • instance용 BVH나 계층 구현이 없음
    • 모든 instance를 대상으로 frustum 및 occlusion culling을 수행함

삼각형 수가 의미하는 조건

  • “수십억 triangles”라는 숫자만으로 성능을 판단하기 어렵고, 성능은 여러 요인에 좌우됨
  • Dense meshes

    • 가까운 곳에 dense mesh가 많으면 성능에 부정적일 수 있음
    • 단, 화면을 많이 덮을 정도로 가까우면 occlusion culling이 작동함
    • dense geometry는 meshlet이 작아 화면에서 차지하는 공간이 작고 occlusion/cone culling되기 쉬움
  • Instance count

    • 각 instance는 mat4x3 transform matrix를 가져 VRAM을 소비함
    • 프레임 중에는 렌더링할 항목 목록도 저장해야 함
    • 최악의 경우 각 instance가 가장 dense한 meshlets를 렌더링함
    • 구현상 instanceCount * bottomLevelMeshletsCount * sizeof(vec2u) bytes를 할당함
    • Chrome의 WebGPU storage buffer 기본 한도는 128MB이며, 데모 장면은 이를 반영해 조정됨
  • Scene arrangement

    • 앱의 장면은 객체를 정사각형으로 배치함
    • 먼 객체는 일부만 보이지만 coarse meshlet LOD가 더 넓은 부분을 포함해 overdraw가 생김
    • dense grid placement는 가까운 삼각형을 더 많이 렌더링하지만, 깊이 차이가 작아 occlusion culling에는 유리함
    • 멀리 떨어진 객체는 임의의 먼 픽셀이 depth pyramid를 오염시킬 수 있음

Jinx 장면이 어려운 이유

  • Jinx 캐릭터는 마르고 팔과 몸통 사이에 빈 공간이 있어 occlusion culling을 어렵게 함
  • 모델이 잘 단순화되지 않아 가장 coarse LOD도 3k triangles를 가짐
  • 1픽셀 크기의 많은 삼각형이 누적되는 상황이 생김
  • 소프트웨어 래스터라이저가 크게 도움이 되지만, 장면 배치 때문에 대부분 instance는 impostor로 렌더링됨
  • 가까운 영역에서는 hardware rasterizer가 담당하며, hardware rasterizer·software rasterizer·impostor는 각각 다른 강점을 가짐

Nanite 구현에서 놀라운 점

  • DAG의 목표는 단순히 먼 객체에 적은 삼각형을 쓰는 것이 아니라, 화면 전체에서 1 pixel == 1 triangle에 가까운 일관성을 유지하는 것임
  • discrete LOD mesh는 각 LOD가 별도 geometry라 중간 단계가 필요할 때 대응하기 어렵고, continuous LOD가 필요함
  • meshlet hierarchy는 선택한 세부 수준에서 geometry를 sampling할 수 있게 함
  • Nanite 자체보다 culling과 meshlet 작업에 더 많은 시간이 들어감
  • meshlet LOD hierarchy는 동작하게 만드는 것은 쉽지만 효율적으로 만들기는 어려움
  • mesh가 깔끔하게 단순화되지 않으면 Jinx처럼 단일 픽셀을 덮는 약 3,000 triangles 같은 상황이 생김
  • pixel-sized triangles를 원한다면 소프트웨어 래스터라이저가 필요하고, billboard impostor도 안정성 중심의 fallback으로 유용함

Mesh simplification 문제

  • 단순화는 “mesh를 받아 X% triangles로 줄이는” 문제가 아니라 meshlet과 METIS 문맥 안에서 수행되는 문제임
  • UE5는 자체 mesh simplification code를 asset pipeline의 첫 단계로 사용함
    • 여기서 줄인 비용은 이후 시스템 전체에 연쇄적 이득을 줌
    • Brian Karis의 SIGGRAPH 자료에서는 LOD graph가 단일 root cluster로 끝나며, 어떤 모델도 128 triangles로 단순화할 수 있다고 밝힘
  • Jinx 모델은 단순화가 특정 지점에서 멈추는 문제가 있었음
    • 입력 X triangles를 넣어도 같은 X triangles가 돌아오는 상황이 생김
    • 알고리듬이 assertion으로 crash함
    • 이후 충분히 줄지 않는 mesh 부분은 DAG에 여러 root를 허용하도록 바꿈
  • bunny 모델은 처음에는 단일 128 tris meshlet으로 단순화됐지만, 조건을 바꾸자 단일 root로 가지 않는 문제가 드러남
    • 많은 meshlet이 충분히 triangle을 줄이지 못했고, 128 triangles보다 적은 “full이 아닌” meshlet도 많았음
  • 관련 논의:

Error metric

  • 20,000,000 triangles mesh를 meshlet hierarchy로 렌더링할 때, 어떤 meshlet이 “올바른” meshlet인지 선택해야 함
  • 이 선택 문제가 Nanite의 핵심이며, simplification, meshlet DAG, software rasterizer는 이를 다루기 위한 전제 조건에 가까움
  • 구현은 meshoptimizer가 제공하는 projected simplification error를 사용함
  • 저자는 이 metric이 Nanite에 좋은 metric은 아니며, 다른 vertex attribute도 함수에 포함돼야 한다고 봄
    • attribute별 weight를 줄 수 있어야 함
    • Jinx 얼굴의 normal이 큰 문제였음
  • 참고한 자료:

소프트웨어 래스터라이저가 텍스처를 출력하지 않는 이유

  • hardware rasterizer에서는 depth test 결과에 따라 depth texture, color, normal을 함께 쓸 수 있음
  • 소프트웨어 래스터라이저에서 여러 thread가 같은 픽셀에 쓰면 race condition이 생김
  • 일반적인 해결책은 visibility buffer
    • 각 pixel에 가장 가까운 triangle의 sceneUniqueTriangleId를 출력함
    • 이를 32-bit depth와 결합해 64-bit 값으로 만들고 64-bit atomic operation을 사용함
    • 별도 pass에서 triangle을 다시 rasterize하고 barycentric coordinates를 계산해 shading함
  • WebGPU에는 64-bit atomics가 없어 이 방식을 사용할 수 없음
  • 이 프로젝트의 목표는 소프트웨어 래스터라이즈가 동작함을 보여주는 것이며, 그래서 배경의 소프트웨어 래스터라이즈 모델은 흰색이고 reasonable shading만 제공함

자체 Nanite 구현에 대한 판단

  • 가장 단순한 답은 UE5를 사용하는 것임
  • 기존 엔진에 이 기술을 넣으려면 먼저 compute 기반 graphics pipeline과 GPU-driven rendering pipeline을 구현하는 단계가 필요하다고 봄
  • multi-step culling, scene/world chunk management, animated meshes 같은 문제가 먼저 등장함
  • 이 단계들이 안정화된 뒤 software rasterizer를 시도하고, 그 다음에 Nanite-like tech를 추가하는 순서가 제시됨
  • toy renderer에서 기본 meshlet hierarchy는 주말 프로젝트가 될 수 있지만, 실제 구현은 simplification과 error metric 문제를 다뤄야 함

사용된 도구와 참고 자료

  • meshoptimizer가 프로젝트 구현의 핵심 기반임
    • newer meshoptimizer versions에는 Nanite clone을 위한 meshopt_SimplifySparse가 있음
    • 프로젝트는 개발 중 테스트한 상태를 유지하기 위해 해당 버전으로 업데이트하지 않음
  • METIS를 사용함
  • Emscripten은 meshoptimizer와 METIS를 브라우저에서 실행하는 데 사용됨
  • Jinx 모델은 Sketchfab의 Arcane - Jinx를 사용했으며, 텍스처 병합, UV 조정, 무기 제거를 수행함

댓글과 토론

Hacker News 의견들
  • 오, 좋네요. Nanite 재생의 서드파티 구현이 나온 셈입니다
    Nanite는 그래픽 메시를 아주 영리하게 표현합니다. 트리가 아니라 방향 비순환 그래프라서 반복은 복사가 아니라 링크가 되고, 메시가 하위 메시를 공유하며 그 하위 메시도 다시 공유할 수 있습니다. 메시 내부 세부 수준(LOD)도 지원해서 하위 메시가 충분히 작아지면 빠집니다
    그래서 유한한 데이터와 빠른 렌더링 시간으로 매우 큰 반복 콘텐츠를 다룰 수 있습니다. 화면에는 픽셀 수가 한정돼 있으니 실제로 필요한 렌더링 작업량에도 상한이 있다는 통찰입니다
    Epic 쪽 사람이 설명한 SIGGRAPH 영상이 아주 좋습니다. 현재 GPU 설계는 Nanite와 잘 맞지 않아서, 더 많은 처리를 GPU에서 하려면 새 하드웨어 연산이 필요합니다. Nvidia가 AI 시장에 정신이 팔린 상황에서 그런 변화가 생길지는 의문입니다
    이 방식이 효과를 내려면 장면에 인스턴싱이 많아야 합니다. Unreal Engine 데모의 동일한 조각상 홀처럼, 제한된 수의 객체를 재사용해 넓은 콘텐츠를 만드는 AAA 게임에는 잘 맞습니다. Cyberpunk 2077 영상을 보며 난간과 쓰레기 더미를 찾으면, 같은 것들이 완전히 다른 맥락에서 계속 반복되는 걸 볼 수 있습니다
    Nanite 메시 제작은 내부 링크 오프셋이 많아 복잡하고, 지금까지는 Unreal Engine 편집기만 처리했습니다. 재생 쪽이 오픈소스가 됐으니 누군가 제작 도구도 만들 가능성이 큽니다
    다만 포맷의 내부 오프셋은 공격 표면이 될 수 있고, 악의적으로 만든 Microsoft Word .doc 파일처럼 조작된 콘텐츠로 악용 가능해 보입니다

    • 그래프 절단을 위해 방향 비순환 그래프를 만들긴 하지만, 최종 디스크 데이터는 포함/제외 기준을 가진 클러스터의 평면 목록일 뿐입니다. DAG가 어디에 쓰이고 어떻게 만들어지는지에 대해 꽤 큰 오해가 있어 보입니다
      DAG는 정점 데이터를 바탕으로 동적으로 만들어지며, 아티스트가 하위 메시를 어떻게 구성했는지와는 관련이 없습니다. “반복이 링크가 된다”는 식도 아닙니다
      또 객체 인스턴스마다 그래프 절단 결과가 달라서 전통적인 인스턴싱을 쓸 수 없는데, 왜 장면에 인스턴싱이 많아야 효과가 난다고 보는지 모르겠습니다
    • 예전 2000년대에 PS3 개발을 하면서 Cell의 많은 연산 자원을 괜찮게 쓸 방법과 RSX의 제한적인 메모리 대역폭을 우회할 방법을 찾고 있었습니다. Blu-ray 저장 공간은 넉넉히 쓸 수 있었고요
      그때 Nanite와 비슷한 것을 꽤 진행했는데, 압축 메시라고 불렀습니다. 전형적인 빗나간 엔지니어링 자만심이었습니다
      초반 작업은 유망해 보였지만 문제를 파고들수록 전체가 점점 복잡해졌습니다. 에셋 생성 파이프라인 전체를 만들어야 했고, 보기 좋은 결과를 내면서 메모리를 터뜨리지 않는 수준으로 시간 안에 끝내기엔 너무 컸습니다
      큰 규모의 메시를 계단식 세부 수준으로 렌더링하는 것처럼 보이는 정도까지는 만들었지만, 매우 느렸고 GPU를 혹사해 서브픽셀 정확도를 맞추지 않으면 형편없어 보였습니다. 재미있는 실험이었지만 하드웨어에도 너무 벅찼고 혼자 맡기엔 과제가 너무 컸습니다
      Epic이 Nanite를 공개했을 때는 정말 놀랐습니다. 제가 못 한 일을, 제가 상상한 최선보다도 훨씬 뛰어난 방식으로 해낸 겁니다. 등장했을 때 과장이 아니라 진짜 해결책이었던 기술 중 하나이고, 현대 그래픽 세계의 기술적 보석입니다. Epic이 상장사였다면 Nanite 기술만 보고도 꽤 큰돈을 넣을 생각을 했을 정도입니다
    • 언급한 SIGGRAPH 발표는 아마 "A Deep Dive into Nanite Virtualized Geometry"일 겁니다: https://www.youtube.com/watch?v=eviSykqSUUw
      짧은 고수준 소개 영상도 괜찮았습니다. "What is virtualized micropolygon geometry? An explainer on Nanite"입니다: https://www.youtube.com/watch?v=-50MJf7hyOw
    • 주류 엔진은 아니지만, 작은 Rust ECS 게임 엔진인 Bevy도 "Virtual Geometry"라는 기능 이름으로 비슷한 것을 지원합니다: https://bevyengine.org/news/bevy-0-14/#virtual-geometry-expe...
      이 기능 작성자 중 한 명이 쓴 기술 심층 글도 있습니다: https://jms55.github.io/posts/2024-06-09-virtual-geometry-be...
    • 논문들을 읽어보니 가장 큰 이득은 양자화된 좌표와 전체 메시가 아닌 작은 패치 단위의 동적 세부 수준에서 나온다는 인상을 받았습니다
      제가 이해한 Nanite의 논리는 메시 정확도를 대략 1픽셀 정밀도에 맞춰 유지하는 것입니다. 예를 들어 원근 투영 후 오차가 반 픽셀 정도에 그친다면, 좌표를 10비트 정도로 반올림한 낮은 디테일 메시를 쓸 수 있습니다
      양자화가 두 가지 역할을 했던 것으로 어렴풋이 기억합니다. 데이터 저장 크기를 줄일 뿐 아니라 정점들을 공간상의 같은 위치로 스냅해 세부 수준 생성에도 도움을 주고, 이후 중복을 제거할 수 있습니다
  • 이 스레드에서 몇 번 언급됐지만, Bevy에도 Nanite 아이디어의 구현이 있습니다. 때로는 가상 지오메트리라고 부릅니다. 제가 그 작성자라 질문에 답할 수 있습니다 :)
    이 프로젝트에 대해서는 Scthe가 정말 잘했습니다. 작업 과정의 여러 부분을 함께 얘기했고, 그 경험을 바탕으로 Bevy 코드도 개선됐습니다: https://github.com/bevyengine/bevy/pull/15023
    이 분야에 더 많은 사람이 뛰어드는 건 언제나 반갑습니다. Nanite에는 멋진 아이디어가 정말 많습니다

  • 데모가 호환성 판단에 사용자 에이전트 문자열을 쓰는 건가요? 그건 좋지 않습니다. 기능 호환성은 특정 기능을 직접 감지하거나 사용해 보면서 사례별로 판단해야 합니다
    저는 Chrome이 아니라 Chromium을 쓰고 있고 WebGPU도 항상 쓰는데, 데모는 Chrome을 쓰라고 합니다. 윤리적으로 그렇게 할 수는 없습니다. 데모를 꼭 써보고 싶은데, 많은 노력이 들어간 프로젝트로 보입니다

    • 참고로 Linux의 Chrome에서도, Android에서도 동작하지 않습니다. 실제 브라우징은 거의 Firefox를 쓰지만요. 감지 로직에 뭔가 꽤 이상한 점이 있습니다
    • 그런 것 같지는 않습니다. 실험적 WebGPU 지원을 켠 Firefox에서는 별도 메시지 대신 셰이더 컴파일 오류로 실패합니다
    • 기능별 감지를 목표로 하는 건 좋습니다
      브라우저용 컴포넌트 프레임워크를 직접 만들 때는 감지가 자주 불가능해서 브라우저 스니핑에 의존해야 했습니다. Modernizr 코드에는 기능 감지를 위한 매우 영리한 해킹, 때로는 아주 지저분한 해킹이 많습니다. 신뢰할 수 있는 감지 코드를 만들기 위해 엄청난 작업이 들어갔고, 감지도 보통 부작용을 통해 이뤄졌습니다
      제 추측으로는 Web3D 기능 감지가 단순하지 않습니다. 빠르게 검색해 봐도 명확한 Web3D 기능 감지 라이브러리는 보이지 않았습니다
      Modernizr의 :checked 지원 감지 코드 일부는 이렇습니다:
      Modernizr.addTest('checked', function(){
      return Modernizr.testStyles('#modernizr input {width:100px} #modernizr :checked {width:200px;display:block}', function(elem, rule){
    • 사용 중인 빌드는 모르겠지만, 저는 Ungoogled Chromium을 쓰고 있고 사용자 에이전트 문자열은 Google Chrome과 정확히 같습니다
      사이트 설정에서 해당 사이트의 WebGL 권한을 켰나요? 제 경우 기본값으로 꺼져 있었던 것 같습니다
    • 데모 자체가 그냥 깨진 것 같습니다. 이런 오류가 납니다:
      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).
  • Nanite의 기반이 된 동적 메시 단순화 알고리즘을 발명한 Federico Ponchio의 다소 묻힌 2009년 박사논문입니다. 그림도 많습니다
    https://vcg.isti.cnr.it/~ponchio/download/ponchio_phd.pdf 107쪽입니다

  • 어느 정도 동작한다는 건 멋지지만, WebGPU에 64비트 원자 연산이 없어서 꽤 거친 타협을 해야 했습니다
    언젠가 선택적 확장으로 추가되면 좋겠습니다. 적어도 데스크톱급 하드웨어에서는 하드웨어 지원이 거의 보편적입니다. AMD와 Nvidia는 오래전부터 있었고, Apple은 M3부터 지원했습니다

    • 래스터라이저에서 원자 연산의 사용처가 뭔가요? 렌더링 파이프라인 안에서 원자 연산이 무엇을 하는지 모르겠습니다. GitHub도 봤지만 원자 연산을 기대한 위치를 찾지 못했습니다
    • M2부터입니다
  • iPhone 12 Pro Max에는 WebGPU가 없다고 나오지만, 실험적 기능에서 켜니 다른 WebGPU 데모 사이트[1]는 동작합니다. iPhone에서 이걸 성공한 사람이 있나요? 웹 앱이 무엇이 실패했는지 더 자세히 알려주면 좋겠습니다
    [1] https://webgpu.github.io/webgpu-samples/?sample=texturedCube

    • Safari에서 WebGPU를 켰지만 셰이더 오류가 잔뜩 보입니다
      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'
    • Safari의 WebGPU 지원은 아직 끝나지 않았기 때문에 실험적 기능으로 남아 있습니다
  • 이름과 설명이 매우 혼란스럽고 상표권 침해 소지도 있어 보입니다. 주장과 달리 UE5의 실제 Nanite와는 완전히 무관하고, UE5와 관계없는 사람이 비슷한 것을 구현한 것으로 보입니다
    비슷한 기능을 제공하는 Bevy의 Virtual Geometry도 있습니다. Rust로 작성됐고 게임 엔진에 통합돼 있어서 훨씬 유용할 가능성이 큽니다: https://jms55.github.io/posts/2024-06-09-virtual-geometry-be...

    • 큰 문제는 아닌 것 같습니다. README를 보면 구현체라는 점이 분명합니다
      제가 “OpenAI의 GPT-3를 JS로 구현”했다고 하면, 백서의 아키텍처를 가져와 다시 구현했다는 뜻으로 이해할 겁니다
  • 이건 실제로 WebGPU에서 돌아가는 UE5 Nanite가 아닙니다. Nanite와 같은 아이디어를 독립적으로 구현한 것입니다
    이 기법은 여러 곳에서 나타나기 시작했습니다. Nanite가 그 아이디어를 유명하게 만든 건 맞지만, Nanite는 기법의 이름이 아니라 특정 구현의 이름입니다

  • 다른 엔진들은 세부 수준과 유사 시스템에서 어느 정도인지 궁금합니다
    Godot에는 자동 세부 수준 기능이 있고, 그 자체로는 꽤 좋아 보입니다: https://docs.godotengine.org/en/stable/tutorials/3d/mesh_lod...
    Unity에도 세부 수준 시스템이 있지만, 엔진 인기에 비해 세부 수준 모델을 수동으로 만들어야 합니다: https://docs.unity3d.com/Manual/LevelOfDetail.html 에셋 스토어에서 플러그인을 찾지 않는다면요
    덜 알려진 NeoAxis라는 엔진에서도 흥미로운 접근을 봤습니다: https://www.neoaxis.com/docs/html/NeoAxis_Levels.htm 다만 제 예전 RX580에서는 성능이 매우 나빴고, 현재 A580에서는 아직 안 해봤습니다
    제가 보기엔 화면에 많은 것을 올리는 능력에서는 Unreal이 경쟁자들보다 꽤 앞서 있습니다. 단점은 아티스트들이 더 높은 품질의 에셋을 게임에 넣고 싶어져서 설치 용량이 크게 부풀 수 있다는 점입니다

    • 이론적으로 Nanite는 미리 계산한 세부 수준보다 우월합니다. 실제로는 그렇게 단정하기 어렵습니다. 아티스트가 직접 만든 세부 수준만큼 좋기는 힘들고, 그렇게 기대하는 것도 합리적이지 않습니다
      성능 비용도 큽니다. Nanite나 가상 지오메트리는 현대 GPU와 잘 맞지 않습니다. 기억상 최대 채우기율이 1/4 정도였던 것 같습니다. GPU 래스터화는 셰이더처럼 픽셀 단위가 아니라 2x2 쿼드 단위로 동작하기 때문입니다
    • Intel Arc GPU는 Nanite 렌더링에 형편없습니다. GPU 주도 렌더러에서 널리 쓰이는 간접 드로우와 Nanite에 필요한 64비트 원자 연산을 둘 다 하드웨어로 지원하지 않기 때문입니다. Intel은 간접 드로우를 소프트웨어로 에뮬레이션해서 느립니다
  • 이렇게 반복적인 정적 지오메트리가 많은 렌더링 장면을 볼 때마다, 예전 베이퍼웨어 영상에서 “무제한 디테일”을 떠들던 짜증나는 사람 목소리가 떠오릅니다
    Nanite는 그 오래된 무언가와 달리, 정말로 그 문제를 해결한 것 같습니다. 그쪽은 옥트리 같은 걸 쓴다는 얘기가 있었던 것으로 기억합니다

    • 그 주장을 했던 회사는 Euclidean이라는 곳이었던 것 같습니다. 호주 회사였던 듯합니다
      온라인 소문으로는 옥트리를 쓴다는 얘기가 있었지만, 이후 Euclidean 영상들은 그걸 딱 잘라 부인했습니다