1 điểm bởi GN⁺ 2024-09-06 | 1 bình luận | Chia sẻ qua WhatsApp
  • Nanite WebGPU là dự án triển khai kiểu render Nanite của UE5 ngay trong trình duyệt bằng WebGPU, bao gồm phân cấp meshlet LOD, software rasterizer, billboard impostor, và culling theo đơn vị instance/meshlet
  • Việc triển khai đặt mục tiêu chính là sự đơn giản khi tiền xử lý đầu vào OBJ trong trình duyệt, và thử nghiệm thay đổi hiệu năng bằng cách đổi thiết lập qua checkbox và slider
  • Demo cung cấp cảnh Jinx 640M triangles, Lucy/Dragons và các cảnh lên tới 1.7B triangles; các tam giác màu trắng của Jinx là kết quả software rasterize được nén và xử lý ở 32-bit do giới hạn của WebGPU
  • WebGPU không có atomic<u64>, nên khó triển khai nguyên dạng một software rasterizer hiệu quả dựa trên visibility buffer; triển khai hiện tại chấp nhận artifact về độ chính xác bằng cách nhét depth u16 và octahedron normal 2*u8 vào 32-bit
  • Trong một triển khai kiểu Nanite thực tế, vấn đề cốt lõi không phải số lượng tam giác đơn thuần mà là mesh simplification và error metric; tác giả nêu rõ triển khai của mình, khác với UE5, không có simplification, streaming, compression, visibility buffer, 2-pass occlusion culling, v.v.

Tổng quan dự án

  • Nanite WebGPU là dự án triển khai render kiểu Nanite trong trình duyệt web bằng WebGPU
  • Các thành phần chính được đưa vào gồm meshlet LOD hierarchy, software rasterizer, billboard impostor, culling theo đơn vị instance và meshlet
  • Hỗ trợ texture model và per-vertex normal, đồng thời cung cấp slider hoặc checkbox cho từng thiết lập
  • WebGPU chỉ có thể sử dụng trên Chrome
  • Toàn bộ ứng dụng có thể chạy offline bằng Deno, và các unit test cho shader cũng được viết theo cách này

Cảnh demo và quy mô

  • Demo Jinx có 120×120 instance, quy mô 640M triangles
    • Một model Jinx đơn lẻ được đơn giản hóa từ 44k triangles xuống 3k triangles, với 59 root meshlets
    • Các tam giác màu trắng là những tam giác software rasterize nằm giữa vùng hardware rasterize và impostor ở nền xa
  • Lucy and dragons bố trí hai object, mỗi object 70×70 instance, tạo thành 1.7B triangles
    • Trong cảnh mẫu, gần 98% tam giác được software rasterize, và tác giả cho biết đường xử lý này nhanh hơn phần cứng rất nhiều
  • Lucy là cảnh 110×110 instance, 1.2B triangles
    • Một tượng Lucy đơn lẻ được đơn giản hóa từ 100k triangles xuống một root meshlet duy nhất gồm 86 triangles
  • Dragons là cảnh 70×70 instance, 1.2B triangles
    • Một dragon đơn lẻ được đơn giản hóa từ 250k triangles xuống một root meshlet duy nhất gồm 102 triangles
  • Bunnies là cảnh 500×500 instance, 1.2B triangles
    • Một bunny đơn lẻ được đơn giản hóa từ 5k triangles xuống một root meshlet duy nhất gồm 96 triangles
    • Do bunny có kích thước nhỏ, phần lớn bị frustum culling

Tính năng đã triển khai

  • Meshlet LOD hierarchy

    • mesh preprocessing chạy trong trình duyệt
    • Sử dụng meshoptimizerMETIS qua WebAssembly
    • Cũng cung cấp file exporter để không phải chờ tiền xử lý giữa các lần refresh trang
  • Software rasterizer

    • WebGPU không có atomic<u64> cần thiết cho triển khai hiệu quả
    • Triển khai hiện tại pack depth u16 và octahedron-encoded normals 2*u8 vào 32-bit
    • Do giới hạn 32-bit, độ chính xác bị hy sinh đáng kể; mục tiêu là cho thấy rasterizer có hoạt động
    • Giới hạn này cũng ảnh hưởng tới depth pyramid dùng cho occlusion culling
  • Billboard impostors

    • Sử dụng 12 ảnh quanh trục UP và blend bằng dithering tùy theo vị trí camera
    • Không xử lý góc nhìn từ trên/dưới
    • Bao gồm cả diffuse và normal để thực hiện shading ở runtime
    • Impostors preview là demo tăng kích thước impostor texture

Culling và đường render

  • Culling gồm nhiều giai đoạn
    • Per-instance: frustum culling và occlusion culling
    • Per-meshlet: frustum culling và occlusion culling
    • Per-triangle: hardware backface culling và z-buffer
  • WebGPU không có early-z
  • Occlusion culling chỉ sử dụng depth pyramid được tạo từ depth buffer của frame trước
    • Không có reprojection hay cơ chế two-pass
    • Tác giả cho rằng chỉ riêng triển khai hiện tại cũng đủ để culling nhiều tam giác và đánh giá cải thiện hiệu năng
  • Có thể chuyển đổi giữa GPU-driven rendering và triển khai CPU đơn giản
    • Bản CPU không được tối ưu nhiều, nhưng có thể chạy từng bước bằng debugger
  • Tính năng “Freeze culling” cho phép di chuyển camera trong khi chỉ kiểm tra những thứ đã được vẽ ở frame cuối cùng

Khả năng sử dụng và debug

  • Di chuyển dùng [W, S, A, D], lên/xuống dùng [Z, SPACEBAR], di chuyển nhanh dùng [Shift]
  • Nếu thấy kết quả bất thường, có thể kiểm tra bằng cách bật/tắt các tùy chọn culling
    • Trong triển khai có một số bug nhỏ
  • Các tam giác màu trắng là tam giác được software rasterize
    • Do WebGPU thiếu atomic<u64>, depth và normal được nén vào 32-bit
    • 16-bit depth có thể tạo ra nhiều artifact như z-fighting hoặc leak
    • Tắt software rasterizer sẽ giúp dễ xem raw Nanite meshlets hơn, nhưng có thể làm hiệu năng giảm mạnh
  • FPS có thể dao động do trình duyệt cưỡng bức VSync; để kiểm tra timing, hãy dùng nút “Profile”

Mục tiêu thiết kế

  • Mục tiêu đầu tiên của dự án là tính đơn giản
    • Bắt đầu từ tệp OBJ và thực hiện toàn bộ xử lý bên trong ứng dụng
    • Không yêu cầu bước tiền xử lý riêng như export từ Blender
    • Hướng tới luồng cho phép đặt breakpoint tại loadObjFile() rồi theo dõi cho đến khi frame đầu tiên kết thúc
  • Mục tiêu thứ hai là tính thử nghiệm
    • Vì được làm dưới dạng trang web thay vì Rust và Vulkan, bạn có thể nhấp vào liên kết, thay đổi checkbox hoặc slider và xem biến động hiệu năng
    • Có thể trực tiếp kiểm chứng tùy chọn nào quan trọng, chẳng hạn FPS giảm mạnh khi đổi một thiết lập
  • Nhiều đoạn code có thể được tối ưu hóa, nhưng cho đến khi vấn đề simplification được giải quyết, các tối ưu đó được xem là chưa quan trọng

Khác biệt so với UE5 Nanite

  • Error metric sử dụng projected simplification error đơn giản
  • Meshlet simplification dùng cách đơn giản
  • Không có two-pass occlusion culling
    • Việc thêm vào không khó, nhưng debug phiền phức và phát sinh tương tác với các thiết lập GUI
    • Không phù hợp với mục tiêu vì làm giảm tính dễ đọc của code
  • Không có visibility buffer
    • Không thể triển khai do giới hạn atomic<u64>
  • Không có built-in shadows và multiview
  • Không có work queue bên trong shader
    • Với meshlet culling và LOD selection, dispatch một thread cho mỗi meshlet
  • Không có VRAM eviction và streaming cho các LOD không dùng
  • Không có compression
  • Khả năng mở rộng thấp với nhiều đối tượng khác nhau
    • Tập trung vào lượng bộ nhớ sử dụng có thể dự đoán trong các case demo
    • Cần biết trước giới hạn trên của drawn meshlets cho buffer chứa dữ liệu giữa các stage
  • Không có BVH hay triển khai phân cấp cho instance
    • Thực hiện frustum và occlusion culling trên toàn bộ instance

Điều kiện ẩn sau số lượng tam giác

  • Khó đánh giá hiệu năng chỉ bằng con số “hàng chục tỷ triangles”; hiệu năng phụ thuộc vào nhiều yếu tố
  • Dense meshes

    • Nếu có nhiều dense mesh ở gần, hiệu năng có thể bị ảnh hưởng tiêu cực
    • Tuy nhiên, nếu ở gần đến mức che phủ nhiều màn hình, occlusion culling sẽ hoạt động
    • Dense geometry có meshlet nhỏ, chiếm ít không gian trên màn hình và dễ bị occlusion/cone culling
  • Số lượng instance

    • Mỗi instance có ma trận transform mat4x3, tiêu thụ VRAM
    • Trong frame cũng cần lưu danh sách các mục sẽ render
    • Trường hợp xấu nhất là mỗi instance render các meshlet dense nhất
    • Theo triển khai, cấp phát instanceCount * bottomLevelMeshletsCount * sizeof(vec2u) byte
    • Giới hạn mặc định của WebGPU storage buffer trên Chrome là 128MB, và cảnh demo được điều chỉnh theo điều này
  • Bố trí scene

    • Scene của ứng dụng bố trí đối tượng thành hình vuông
    • Các đối tượng ở xa chỉ hiện một phần, nhưng coarse meshlet LOD bao phủ vùng rộng hơn nên gây overdraw
    • Dense grid placement render nhiều tam giác ở gần hơn, nhưng chênh lệch độ sâu nhỏ nên thuận lợi cho occlusion culling
    • Các đối tượng ở xa có thể khiến một pixel xa bất kỳ làm nhiễm depth pyramid

Vì sao cảnh Jinx khó xử lý

  • Nhân vật Jinx mảnh, có khoảng trống giữa tay và thân, khiến occlusion culling khó hơn
  • Mô hình không được đơn giản hóa tốt, nên ngay cả coarse LOD nhất cũng có 3k triangles
  • Dẫn đến tình huống tích lũy nhiều tam giác kích thước 1 pixel
  • Software rasterizer giúp ích đáng kể, nhưng do cách bố trí scene, phần lớn instance được render bằng impostor
  • Ở vùng gần, hardware rasterizer đảm nhiệm; hardware rasterizer, software rasterizer và impostor mỗi loại có thế mạnh riêng

Những điểm đáng ngạc nhiên trong triển khai Nanite

  • Mục tiêu của DAG không chỉ là dùng ít tam giác cho đối tượng ở xa, mà là duy trì tính nhất quán trên toàn màn hình gần với 1 pixel == 1 triangle
  • Với discrete LOD mesh, mỗi LOD là geometry riêng, nên khó đáp ứng khi cần mức trung gian; vì vậy cần continuous LOD
  • Meshlet hierarchy cho phép sampling geometry ở mức chi tiết đã chọn
  • Thời gian dành cho culling và xử lý meshlet nhiều hơn bản thân Nanite
  • Làm cho meshlet LOD hierarchy chạy được thì dễ, nhưng làm cho nó hiệu quả thì khó
  • Nếu mesh không được đơn giản hóa gọn gàng, sẽ xuất hiện tình huống như Jinx: khoảng 3.000 triangles cùng phủ một pixel đơn lẻ
  • Nếu muốn pixel-sized triangles, cần software rasterizer; billboard impostor cũng hữu ích như một fallback thiên về ổn định

Vấn đề mesh simplification

  • Simplification không phải là bài toán “nhận mesh rồi giảm xuống X% triangles”, mà là bài toán được thực hiện trong ngữ cảnh meshlet và METIS
  • UE5 dùng code mesh simplification riêng làm bước đầu tiên trong asset pipeline
    • Chi phí giảm được ở đây mang lại lợi ích dây chuyền cho toàn bộ hệ thống phía sau
    • Trong tài liệu SIGGRAPH của Brian Karis, LOD graph kết thúc bằng một root cluster duy nhất, và cho biết bất kỳ model nào cũng có thể được đơn giản hóa xuống 128 triangles
  • Mô hình Jinx gặp vấn đề simplification bị dừng ở một điểm nhất định
    • Có tình huống đưa vào X triangles nhưng nhận lại đúng X triangles
    • Thuật toán crash vì assertion
    • Sau đó, các phần mesh không giảm đủ được chuyển sang cho phép nhiều root trong DAG
  • Mô hình bunny ban đầu được đơn giản hóa thành một meshlet 128 tris duy nhất, nhưng khi đổi điều kiện thì lộ ra vấn đề không đi về một root duy nhất
    • Nhiều meshlet không giảm đủ số triangle, và cũng có nhiều meshlet “chưa đầy” với ít hơn 128 triangles
  • Thảo luận liên quan:

Chỉ số lỗi

  • Khi render một mesh 20.000.000 tam giác bằng hệ phân cấp meshlet, cần chọn meshlet nào là meshlet “đúng”
  • Bài toán lựa chọn này là cốt lõi của Nanite, còn simplification, meshlet DAG và software rasterizer gần như là các điều kiện tiên quyết để xử lý nó
  • Phần triển khai sử dụng projected simplification error do meshoptimizer cung cấp
  • Tác giả cho rằng metric này không phải là metric tốt cho Nanite, và các vertex attribute khác cũng nên được đưa vào hàm
    • Cần có thể gán weight cho từng attribute
    • Normal trên khuôn mặt Jinx là vấn đề lớn
  • Tài liệu tham khảo:

Vì sao software rasterizer không xuất texture

  • Trong hardware rasterizer, có thể ghi đồng thời depth texture, color và normal tùy theo kết quả depth test
  • Trong software rasterizer, nếu nhiều thread ghi vào cùng một pixel sẽ phát sinh race condition
  • Cách giải quyết phổ biến là visibility buffer
    • Xuất sceneUniqueTriangleId của tam giác gần nhất cho mỗi pixel
    • Kết hợp nó với depth 32-bit để tạo thành giá trị 64-bit và dùng atomic operation 64-bit
    • Ở một pass riêng, rasterize lại tam giác, tính barycentric coordinates rồi thực hiện shading
  • WebGPU không có 64-bit atomics nên không thể dùng cách này
  • Mục tiêu của dự án này là cho thấy software rasterization hoạt động được; vì vậy mô hình được software rasterize ở nền có màu trắng và chỉ cung cấp shading ở mức hợp lý

Nhận định về việc tự triển khai Nanite

  • Câu trả lời đơn giản nhất là dùng UE5
  • Nếu muốn đưa công nghệ này vào một engine hiện có, trước hết cần triển khai graphics pipeline dựa trên compute và GPU-driven rendering pipeline
  • Các vấn đề như multi-step culling, quản lý scene/world chunk và animated meshes sẽ xuất hiện trước
  • Trình tự được đề xuất là ổn định các bước này, sau đó thử software rasterizer, rồi mới thêm công nghệ kiểu Nanite
  • Trong toy renderer, meshlet hierarchy cơ bản có thể là dự án cuối tuần, nhưng triển khai thực tế phải xử lý các vấn đề về simplification và error metric

Công cụ và tài liệu tham khảo đã dùng

  • meshoptimizer là nền tảng cốt lõi của phần triển khai dự án
    • Các phiên bản meshoptimizer mới hơn có meshopt_SimplifySparse dành cho clone Nanite
    • Dự án không cập nhật lên phiên bản đó để giữ nguyên trạng thái đã thử nghiệm trong quá trình phát triển
  • Đã sử dụng METIS
  • Emscripten được dùng để chạy meshoptimizer và METIS trong trình duyệt
  • Mô hình Jinx dùng Arcane - Jinx trên Sketchfab, đồng thời đã thực hiện gộp texture, điều chỉnh UV và loại bỏ vũ khí

1 bình luận

 
GN⁺ 2024-09-06
Ý kiến Hacker News
  • Ồ, hay đấy. Xem như đã có một triển khai bên thứ ba cho việc phát lại Nanite.
    Nanite biểu diễn mesh đồ họa rất thông minh. Nó không phải cây mà là đồ thị có hướng không chu trình nên phần lặp lại không bị sao chép mà trở thành liên kết, mesh có thể chia sẻ submesh và các submesh đó cũng có thể tiếp tục được chia sẻ. Nó cũng hỗ trợ mức độ chi tiết (LOD) bên trong mesh, nên khi submesh đủ nhỏ thì sẽ bị lược bỏ.
    Nhờ vậy có thể xử lý lượng nội dung lặp lại rất lớn với dữ liệu hữu hạn và thời gian render nhanh. Ý tưởng cốt lõi là số pixel trên màn hình là hữu hạn, nên khối lượng công việc render thực sự cần thiết cũng có một giới hạn trên.
    Video SIGGRAPH do một người bên Epic giải thích rất hay. Thiết kế GPU hiện tại không thực sự phù hợp với Nanite, nên nếu muốn chuyển thêm nhiều xử lý sang GPU thì sẽ cần các phép toán phần cứng mới. Trong bối cảnh Nvidia đang mải mê với thị trường AI, khó nói liệu thay đổi đó có xảy ra hay không.
    Cách này chỉ phát huy hiệu quả khi cảnh có nhiều instancing. Nó rất hợp với các game AAA tạo nội dung rộng lớn bằng cách tái sử dụng một số lượng đối tượng hạn chế, như sảnh tượng giống hệt nhau trong demo Unreal Engine. Nếu xem video Cyberpunk 2077 và để ý lan can cùng các đống rác, bạn sẽ thấy cùng một số thứ cứ lặp đi lặp lại trong những ngữ cảnh hoàn toàn khác nhau.
    Việc tạo mesh Nanite khá phức tạp vì có nhiều offset liên kết nội bộ, và từ trước đến nay chỉ Unreal Engine editor mới xử lý được. Giờ phần phát lại đã thành mã nguồn mở, có khả năng sẽ có ai đó làm luôn công cụ tạo nội dung.
    Tuy vậy, các offset nội bộ của định dạng này có thể trở thành bề mặt tấn công, và có vẻ cũng có thể bị lợi dụng bằng nội dung bị chỉnh sửa như các file Microsoft Word .doc được tạo ác ý.

    • Dù đúng là người ta tạo đồ thị có hướng không chu trình để cắt đồ thị, dữ liệu cuối cùng trên đĩa chỉ là một danh sách phẳng các cluster có tiêu chí bao gồm/loại trừ. Có vẻ đang có một hiểu lầm khá lớn về DAG được dùng ở đâu và được tạo ra như thế nào.
      DAG được tạo động dựa trên dữ liệu đỉnh, không liên quan tới cách nghệ sĩ cấu trúc submesh. Nó cũng không phải kiểu “phần lặp lại trở thành liên kết”.
      Ngoài ra, kết quả cắt đồ thị khác nhau theo từng instance của đối tượng nên không thể dùng instancing truyền thống, vì vậy tôi không hiểu tại sao lại cho rằng phải có nhiều instancing trong cảnh thì mới hiệu quả.
    • Hồi những năm 2000, khi làm phát triển PS3, tôi từng tìm cách tận dụng tương đối tốt lượng tài nguyên tính toán lớn của Cell và né tránh băng thông bộ nhớ hạn chế của RSX. Lúc đó dung lượng lưu trữ Blu-ray thì khá dư dả.
      Khi ấy tôi đã tiến khá xa với một thứ tương tự Nanite, gọi là compressed meshes. Đó đúng kiểu sự tự phụ kỹ thuật đi sai hướng.
      Công việc ban đầu trông rất hứa hẹn, nhưng càng đào sâu thì toàn bộ hệ thống càng trở nên phức tạp. Phải xây cả pipeline tạo asset, và quy mô đó quá lớn để có thể hoàn thành đúng thời gian mà vẫn cho ra kết quả đẹp mắt mà không làm nổ bộ nhớ.
      Tôi đã làm được tới mức nhìn như đang render các mesh rất lớn với mức độ chi tiết phân tầng, nhưng nó cực chậm và còn ép GPU làm việc quá sức; nếu không đạt được độ chính xác subpixel thì hình ảnh trông rất tệ. Đây là một thử nghiệm thú vị, nhưng phần cứng lúc đó quá đuối và với một người làm thì bài toán cũng quá lớn.
      Khi Epic công bố Nanite, tôi thực sự kinh ngạc. Họ đã làm được điều mà tôi không làm nổi, theo cách còn vượt xa mức tốt nhất tôi từng hình dung. Đây là một trong số ít công nghệ mà khi ra mắt không phải cường điệu mà là lời giải thực sự, một viên ngọc kỹ thuật của thế giới đồ họa hiện đại. Nếu Epic là công ty niêm yết, tôi thậm chí đã nghĩ tới việc rót một khoản tiền khá lớn chỉ vì công nghệ Nanite.
    • Bài trình bày SIGGRAPH được nhắc tới có lẽ là "A Deep Dive into Nanite Virtualized Geometry": https://www.youtube.com/watch?v=eviSykqSUUw
      Một video giới thiệu ngắn ở mức khái quát cũng khá ổn: "What is virtualized micropolygon geometry? An explainer on Nanite": https://www.youtube.com/watch?v=-50MJf7hyOw
    • Không phải engine chủ lưu, nhưng engine game Rust ECS nhỏ tên Bevy cũng hỗ trợ một thứ tương tự dưới tên tính năng "Virtual Geometry": https://bevyengine.org/news/bevy-0-14/#virtual-geometry-expe...
      Cũng có một bài viết đào sâu kỹ thuật do một trong những tác giả của tính năng này viết: https://jms55.github.io/posts/2024-06-09-virtual-geometry-be...
    • Sau khi đọc các bài báo, tôi có cảm giác lợi ích lớn nhất đến từ tọa độ lượng tử hóa và mức độ chi tiết động trên từng patch nhỏ thay vì toàn bộ mesh.
      Theo cách tôi hiểu, logic của Nanite là giữ độ chính xác của mesh vào khoảng mức chính xác 1 pixel. Ví dụ, nếu sai số sau phép chiếu phối cảnh chỉ khoảng nửa pixel, thì có thể dùng một mesh ít chi tiết hơn với tọa độ đã được làm tròn xuống cỡ 10 bit.
      Tôi nhớ mang máng lượng tử hóa đóng hai vai trò. Nó không chỉ giảm kích thước lưu trữ dữ liệu mà còn giúp tạo mức độ chi tiết bằng cách snap các đỉnh về cùng một vị trí trong không gian, rồi sau đó có thể loại bỏ phần trùng lặp.
  • Đã được nhắc vài lần trong thread này, nhưng Bevy cũng có một triển khai ý tưởng Nanite. Đôi khi nó được gọi là virtual geometry. Tôi là tác giả của nó nên có thể trả lời câu hỏi :)
    Scthe đã làm rất tốt với dự án này. Chúng tôi đã cùng trao đổi về nhiều phần trong quá trình thực hiện, và dựa trên kinh nghiệm đó, mã Bevy cũng đã được cải thiện: https://github.com/bevyengine/bevy/pull/15023
    Luôn vui khi thấy có thêm nhiều người bước vào lĩnh vực này. Nanite thực sự có rất nhiều ý tưởng hay.

  • Bản demo có dùng chuỗi user agent để xác định khả năng tương thích không? Điều đó không ổn. Tính tương thích tính năng nên được đánh giá theo từng trường hợp bằng cách trực tiếp phát hiện hoặc thử sử dụng chính tính năng đó
    Tôi dùng Chromium chứ không phải Chrome, và cũng luôn dùng WebGPU, nhưng bản demo lại bảo tôi dùng Chrome. Về mặt đạo đức tôi không thể làm thế được. Tôi rất muốn thử bản demo này, trông như một dự án đã được đầu tư rất nhiều công sức

    • Nhân tiện, nó cũng không chạy trên Chrome của Linux hay trên Android. Dù vậy, khi duyệt web thực tế thì tôi hầu như chỉ dùng Firefox. Có gì đó khá kỳ lạ trong logic phát hiện
    • Có vẻ không phải vậy. Trên Firefox có bật hỗ trợ WebGPU thử nghiệm, nó thất bại bằng lỗi biên dịch shader thay vì hiện thông báo riêng
    • Nhắm tới việc phát hiện theo từng tính năng là điều tốt
      Khi tự xây dựng framework component cho trình duyệt, tôi thường phải dựa vào browser sniffing vì nhiều khi không thể phát hiện được. Trong mã của Modernizr có rất nhiều mẹo rất thông minh để phát hiện tính năng, đôi khi cũng là những mẹo cực kỳ lộn xộn. Đã có một khối lượng công việc khổng lồ để tạo ra mã phát hiện đáng tin cậy, và việc phát hiện thường cũng được thực hiện thông qua các tác dụng phụ
      Tôi đoán rằng việc phát hiện tính năng Web3D không hề đơn giản. Tìm nhanh cũng không thấy thư viện phát hiện tính năng Web3D nào thật sự rõ ràng
      Một phần mã phát hiện hỗ trợ :checked của Modernizr trông như thế này:
      Modernizr.addTest('checked', function(){
      return Modernizr.testStyles('#modernizr input {width:100px} #modernizr :checked {width:200px;display:block}', function(elem, rule){
    • Tôi không biết bạn đang dùng bản build nào, nhưng tôi dùng Ungoogled Chromium và chuỗi user agent của nó giống hệt Google Chrome
      Bạn đã bật quyền WebGL cho trang đó trong phần cài đặt trang web chưa? Hình như ở chỗ tôi nó mặc định bị tắt
    • Có vẻ chính bản demo bị lỗi. Tôi gặp lỗi này:
      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).
  • Đây là luận án tiến sĩ năm 2009 khá ít được biết đến của Federico Ponchio, người đã phát minh ra thuật toán đơn giản hóa mesh động làm nền tảng cho Nanite. Cũng có rất nhiều hình minh họa
    https://vcg.isti.cnr.it/~ponchio/download/ponchio_phd.pdf dài 107 trang

  • Việc nó hoạt động được ở một mức độ nào đó là rất ấn tượng, nhưng vì WebGPU không có atomic 64-bit nên đã phải chấp nhận những đánh đổi khá thô
    Hy vọng một ngày nào đó nó sẽ được bổ sung dưới dạng extension tùy chọn. Ít nhất trên phần cứng cấp desktop thì hỗ trợ phần cứng gần như đã phổ biến. AMD và Nvidia đã có từ lâu, còn Apple hỗ trợ từ M3

    • Atomic được dùng vào việc gì trong rasterizer vậy? Tôi không hiểu atomic làm gì bên trong pipeline dựng hình. Tôi cũng đã xem GitHub nhưng không tìm ra chỗ nào lẽ ra cần atomic
    • Là từ M2
  • Nó báo iPhone 12 Pro Max không có WebGPU, nhưng khi tôi bật trong tính năng thử nghiệm thì trang demo WebGPU khác[1] lại chạy được. Có ai chạy cái này thành công trên iPhone chưa? Sẽ tốt hơn nếu ứng dụng web cho biết chi tiết hơn là phần nào đã thất bại
    [1] https://webgpu.github.io/webgpu-samples/?sample=texturedCube

    • Tôi đã bật WebGPU trong Safari nhưng thấy đầy lỗi 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'
    • Hỗ trợ WebGPU của Safari vẫn chưa hoàn tất nên nó vẫn được giữ ở dạng tính năng thử nghiệm
  • Tên gọi và mô tả rất dễ gây nhầm lẫn, và còn có vẻ có nguy cơ xâm phạm nhãn hiệu. Trái với tuyên bố, nó hoàn toàn không liên quan đến Nanite thật của UE5, mà có vẻ chỉ là một người không liên quan tới UE5 đã tự triển khai thứ gì đó tương tự
    Bevy Virtual Geometry cũng cung cấp tính năng tương tự. Nó được viết bằng Rust và tích hợp vào game engine nên có khả năng hữu ích hơn nhiều: https://jms55.github.io/posts/2024-06-09-virtual-geometry-be...

    • Có vẻ không phải vấn đề lớn. Nếu xem README thì rõ ràng đây là một bản triển khai
      Nếu tôi nói mình đã “triển khai GPT-3 của OpenAI bằng JS”, bạn sẽ hiểu là tôi lấy kiến trúc trong whitepaper và triển khai lại nó
  • Đây thực ra không phải là UE5 Nanite chạy trên WebGPU. Đây là một bản triển khai độc lập các ý tưởng tương tự Nanite
    Kỹ thuật này đang bắt đầu xuất hiện ở nhiều nơi. Đúng là Nanite đã khiến ý tưởng đó trở nên nổi tiếng, nhưng Nanite không phải tên của kỹ thuật, mà là tên của một bản triển khai cụ thể

  • Tôi tò mò không biết các engine khác đang ở mức nào về hệ thống mức độ chi tiết và các hệ thống tương tự
    Godot có tính năng mức độ chi tiết tự động, và bản thân nó trông khá ổn: https://docs.godotengine.org/en/stable/tutorials/3d/mesh_lod...
    Unity cũng có hệ thống mức độ chi tiết, nhưng so với độ phổ biến của engine thì bạn vẫn phải tự tạo các model mức độ chi tiết, trừ khi tìm plugin trên asset store: https://docs.unity3d.com/Manual/LevelOfDetail.html
    Tôi cũng đã thấy một cách tiếp cận thú vị ở một engine ít được biết đến hơn là NeoAxis: https://www.neoaxis.com/docs/html/NeoAxis_Levels.htm tuy nhiên trên chiếc RX580 cũ của tôi thì hiệu năng rất tệ, còn trên A580 hiện tại thì tôi vẫn chưa thử
    Theo tôi thấy, về khả năng đưa nhiều thứ lên màn hình thì Unreal đang vượt khá xa các đối thủ. Nhược điểm là các artist sẽ muốn đưa asset chất lượng cao hơn vào game, nên dung lượng cài đặt có thể phình ra rất nhiều

    • Về mặt lý thuyết, Nanite vượt trội hơn mức độ chi tiết được tính toán sẵn. Nhưng trên thực tế thì khó khẳng định dứt khoát như vậy. Nó khó có thể tốt bằng mức độ chi tiết do artist tự làm, và kỳ vọng như vậy cũng không hợp lý
      Chi phí hiệu năng cũng lớn. Nanite hay virtual geometry không thực sự hợp với GPU hiện đại. Nếu tôi nhớ không nhầm thì tốc độ fillrate tối đa chỉ khoảng 1/4. Lý do là rasterization trên GPU không hoạt động theo từng pixel như shader, mà theo từng quad 2x2
    • Intel Arc GPU rất tệ khi render Nanite. Vì nó không hỗ trợ bằng phần cứng cả indirect draw, vốn được dùng rộng rãi trong renderer do GPU điều phối, lẫn các phép toán atomic 64-bit mà Nanite cần. Intel mô phỏng indirect draw bằng phần mềm nên chậm
  • Mỗi khi nhìn thấy một cảnh render có quá nhiều hình học tĩnh lặp đi lặp lại như thế này, tôi lại nhớ đến giọng nói khó chịu trong mấy video vaporware ngày xưa từng thao thao về “chi tiết không giới hạn”
    Nanite, không giống thứ cũ kỹ đó, có vẻ như thực sự đã giải quyết được vấn đề ấy. Tôi nhớ mang máng là bên đó từng nói họ dùng thứ gì đó như octree

    • Công ty từng đưa ra tuyên bố đó hình như là Euclidean. Có lẽ là một công ty của Úc
      Có tin đồn trên mạng nói họ dùng octree, nhưng các video sau này của Euclidean đã thẳng thừng phủ nhận điều đó