1 Punkte von GN⁺ 2024-09-06 | 1 Kommentare | Auf WhatsApp teilen
  • Nanite WebGPU ist ein Projekt, das Nanite-ähnliches Rendering aus UE5 per WebGPU im Browser umsetzt und eine Meshlet-LOD-Hierarchie, einen Software-Rasterizer, Billboard-Impostors sowie Culling auf Instanz- und Meshlet-Ebene umfasst
  • Die Implementierung zielt vor allem auf Einfachheit ab, indem OBJ-Eingaben im Browser vorverarbeitet werden, sowie darauf, über Checkboxen und Slider Einstellungen zu ändern und Performance-Veränderungen zu experimentieren
  • Die Demos bieten Szenen wie Jinx mit 640M triangles sowie Lucy/Dragons mit bis zu 1.7B triangles; die weißen Dreiecke bei Jinx sind Ergebnisse der Software-Rasterisierung, die wegen WebGPU-Einschränkungen auf 32 Bit komprimiert verarbeitet wurden
  • Da WebGPU kein atomic<u64> bietet, lässt sich ein effizienter, auf einem Visibility Buffer basierender Software-Rasterizer nicht unverändert umsetzen; die aktuelle Implementierung nimmt Präzisionsartefakte in Kauf, indem depth u16 und octahedron normal 2*u8 in 32 Bit gepackt werden
  • Die zentrale Schwierigkeit einer echten Nanite-ähnlichen Implementierung ist nicht die bloße Anzahl an Dreiecken, sondern mesh simplification und die error metric; der Autor weist ausdrücklich darauf hin, dass die eigene Implementierung anders als UE5 keine Vereinfachung, kein Streaming, keine Kompression, keinen Visibility Buffer und kein 2-pass occlusion culling enthält

Projektüberblick

  • Nanite WebGPU ist ein Projekt, das mit WebGPU Nanite-ähnliches Rendering im Webbrowser umsetzt
  • Zu den wichtigsten enthaltenen Elementen gehören meshlet LOD hierarchy, ein Software-Rasterizer, Billboard-Impostors sowie Culling auf Instanz- und Meshlet-Ebene
  • Es unterstützt Texturmodelle und per-vertex normals und stellt für jede Einstellung Slider oder Checkboxen bereit
  • WebGPU ist nur in Chrome verfügbar
  • Die gesamte App kann mit Deno auch offline ausgeführt werden; auch Shader-Unit-Tests sind auf diese Weise geschrieben

Demoszenen und Größenordnung

  • Die Jinx-Demo hat 120×120 Instanzen und umfasst 640M triangles
    • Ein einzelnes Jinx-Modell wird von 44k triangles auf 3k triangles und 59 root meshlets vereinfacht
    • Die weißen Dreiecke sind software-rasterisierte Dreiecke zwischen dem hardware-rasterisierten Bereich und den Impostors im fernen Hintergrund
  • Lucy and dragons platziert zwei Objekte jeweils als 70×70 Instanzen und bildet damit 1.7B triangles
    • In der Beispielszenen werden fast 98 % der Dreiecke software-rasterisiert; laut Autor ist dieser Pfad deutlich schneller als Hardware-Rasterisierung
  • Lucy ist eine Szene mit 110×110 Instanzen und 1.2B triangles
    • Eine einzelne Lucy-Statue wird von 100k triangles auf ein einzelnes root meshlet mit 86 triangles vereinfacht
  • Dragons ist eine Szene mit 70×70 Instanzen und 1.2B triangles
    • Ein einzelner Dragon wird von 250k triangles auf ein einzelnes root meshlet mit 102 triangles vereinfacht
  • Bunnies ist eine Szene mit 500×500 Instanzen und 1.2B triangles
    • Ein einzelner Bunny wird von 5k triangles auf ein einzelnes root meshlet mit 96 triangles vereinfacht
    • Da die Bunnies klein sind, werden die meisten per Frustum Culling entfernt

Implementierte Funktionen

  • Meshlet LOD hierarchy

    • Das mesh preprocessing läuft im Browser
    • meshoptimizer und METIS werden über WebAssembly verwendet
    • Außerdem gibt es einen Datei-Exporter, damit man zwischen Seiten-Reloads nicht auf die Vorverarbeitung warten muss
  • Software rasterizer

    • WebGPU fehlt das für eine effiziente Implementierung nötige atomic<u64>
    • Die aktuelle Implementierung packt depth u16 und octahedron-encoded normals 2*u8 in 32 Bit
    • Wegen der 32-Bit-Begrenzung wird viel Präzision geopfert; Ziel ist zu zeigen, dass der Rasterizer funktioniert
    • Diese Einschränkung betrifft auch die für occlusion culling verwendete depth pyramid
  • Billboard impostors

    • Es werden 12 Bilder um die UP-Achse verwendet und je nach Kameraposition per Dithering geblendet
    • Ansichten von oben/unten werden nicht behandelt
    • Sowohl diffuse als auch normal sind enthalten, um Runtime-Shading durchzuführen
    • Impostors preview ist eine Demo mit größerer Impostor-Texturgröße

Culling und Rendering-Pfade

  • Culling besteht aus mehreren Stufen
    • Per-instance: frustum culling und occlusion culling
    • Per-meshlet: frustum culling und occlusion culling
    • Per-triangle: hardware backface culling und z-buffer
  • WebGPU hat kein early-z
  • Occlusion Culling verwendet nur eine depth pyramid, die aus dem Depth Buffer des vorherigen Frames erstellt wird
    • Reprojection und ein Two-Pass-Verfahren gibt es nicht
    • Schon die aktuelle Implementierung gilt als ausreichend, um viele Dreiecke zu cullen und Performance-Verbesserungen zu beurteilen
  • Es lässt sich zwischen GPU-driven rendering und einer einfachen CPU-Implementierung umschalten
    • Die CPU-Version ist nicht stark optimiert, kann aber im Debugger Schritt für Schritt ausgeführt werden
  • Die Funktion „Freeze culling“ ermöglicht es, beim Bewegen der Kamera nur das zu prüfen, was im letzten Frame gezeichnet wurde

Bedienung und Debugging

  • Bewegung erfolgt mit [W, S, A, D], Auf-/Abstieg mit [Z, SPACEBAR], schnelle Bewegung mit [Shift]
  • Wenn seltsame Ergebnisse auftreten, kann man sie prüfen, indem man die Culling-Optionen ein- und ausschaltet
    • Die Implementierung enthält einige kleinere Bugs
  • Weiße Dreiecke sind software-rasterisierte Dreiecke
    • Wegen des fehlenden atomic<u64> in WebGPU werden depth und normal auf 32 Bit komprimiert
    • 16-bit depth kann viele Artefakte wie z-fighting oder Leaks erzeugen
    • Wenn man den Software-Rasterizer deaktiviert, lassen sich raw Nanite meshlets leichter betrachten, es kann aber zu einem starken Performance-Einbruch kommen
  • Die FPS können durch das erzwungene VSync des Browsers schwanken; zur Timing-Prüfung dient der Button „Profile“

Designziele

  • Das erste Ziel des Projekts ist Einfachheit
    • Es startet mit einer OBJ-Datei und führt die gesamte Verarbeitung innerhalb der App aus
    • Es erfordert keinen separaten Vorverarbeitungsschritt wie einen Blender-Export
    • Angestrebt ist ein Ablauf, bei dem man in loadObjFile() einen Breakpoint setzen und bis zum Ende des ersten Frames mitverfolgen kann
  • Das zweite Ziel ist Experimentierfreude
    • Da es statt mit Rust und Vulkan als Webseite umgesetzt wurde, kann man einen Link anklicken, Checkboxen oder Slider ändern und die Performance-Auswirkungen sehen
    • Wenn beim Ändern einer einzelnen Einstellung die FPS stark einbrechen, lässt sich direkt erkennen, welche Optionen wichtig sind
  • Viel Code könnte optimiert werden, aber solange das Simplification-Problem nicht gelöst ist, wird diese Optimierung als nicht entscheidend angesehen

Unterschiede zu UE5 Nanite

  • Als Error Metric wird ein einfacher projected simplification error verwendet
  • Die Meshlet-Simplification ist einfach gehalten
  • Es gibt kein Two-Pass Occlusion Culling
    • Es hinzuzufügen wäre nicht schwierig, aber das Debugging wäre mühsam und es gäbe Wechselwirkungen mit den GUI-Einstellungen
    • Da es die Lesbarkeit des Codes beeinträchtigen würde, passt es nicht zu den Zielen
  • Es gibt keinen Visibility Buffer
    • Wegen der Einschränkung bei atomic<u64> lässt sich das nicht implementieren
  • Es gibt keine built-in Shadows und kein Multiview
  • Es gibt keine Work Queue im Shader
    • Für Meshlet Culling und LOD Selection wird pro Meshlet ein Thread dispatched
  • Es gibt kein VRAM Eviction und Streaming ungenutzter LODs
  • Es gibt keine Compression
  • Für viele unterschiedliche Objekte skaliert es schlecht
    • Der Fokus liegt im Demo-Fall auf vorhersehbarem Speicherverbrauch
    • Für den Buffer, der Daten zwischen Stages hält, muss die Obergrenze der drawn Meshlets im Voraus bekannt sein
  • Es gibt keine BVH- oder Hierarchie-Implementierung für Instances
    • Frustum und Occlusion Culling werden für alle Instances durchgeführt

Was die Anzahl der Dreiecke voraussetzt

  • Allein anhand einer Zahl wie „Milliarden von triangles“ lässt sich Performance schwer beurteilen; sie hängt von vielen Faktoren ab
  • Dense Meshes

    • Viele Dense Meshes in der Nähe können sich negativ auf die Performance auswirken
    • Wenn sie jedoch so nah sind, dass sie einen großen Teil des Bildschirms bedecken, greift Occlusion Culling
    • Dense Geometry hat kleine Meshlets, nimmt auf dem Bildschirm wenig Raum ein und lässt sich leicht per Occlusion/Cone Culling ausblenden
  • Instance Count

    • Jede Instance besitzt eine mat4x3-Transformationsmatrix und verbraucht VRAM
    • Während eines Frames muss außerdem die Liste der zu rendernden Elemente gespeichert werden
    • Im Worst Case rendert jede Instance die dichtesten Meshlets
    • In der Implementierung werden instanceCount * bottomLevelMeshletsCount * sizeof(vec2u) Bytes alloziert
    • Das Standardlimit für WebGPU Storage Buffer in Chrome liegt bei 128 MB; die Demoszene wurde entsprechend angepasst
  • Scene Arrangement

    • Die Szene der App ordnet Objekte in einem Quadrat an
    • Entfernte Objekte sind nur teilweise sichtbar, aber coarse Meshlet-LODs umfassen größere Bereiche und erzeugen Overdraw
    • Dense Grid Placement rendert mehr nahe Dreiecke, ist wegen geringer Tiefenunterschiede aber vorteilhaft für Occlusion Culling
    • Bei weit entfernten Objekten kann ein beliebiger entfernter Pixel die Depth Pyramid verunreinigen

Warum die Jinx-Szene schwierig ist

  • Der Jinx-Charakter ist schlank und hat Hohlräume zwischen Armen und Oberkörper, was Occlusion Culling erschwert
  • Das Modell lässt sich schlecht vereinfachen, sodass selbst das gröbste LOD 3k triangles hat
  • Es entstehen Situationen, in denen sich viele Dreiecke von 1 Pixel Größe aufsummieren
  • Der Software-Rasterizer hilft deutlich, aber wegen der Szenenanordnung werden die meisten Instances als Impostor gerendert
  • In nahen Bereichen übernimmt der Hardware-Rasterizer; Hardware-Rasterizer, Software-Rasterizer und Impostor haben jeweils unterschiedliche Stärken

Überraschende Punkte bei der Nanite-Implementierung

  • Das Ziel des DAG ist nicht einfach, für entfernte Objekte weniger Dreiecke zu verwenden, sondern über den gesamten Bildschirm hinweg eine Konsistenz nahe 1 pixel == 1 triangle zu halten
  • Discrete LOD Meshes haben pro LOD separate Geometry und sind schwer zu handhaben, wenn Zwischenstufen nötig sind; dafür braucht man Continuous LOD
  • Die Meshlet Hierarchy ermöglicht es, Geometry auf der gewählten Detailstufe zu samplen
  • Mehr Zeit fließt in Culling und Meshlet-Arbeit als in Nanite selbst
  • Eine Meshlet-LOD-Hierarchy zum Laufen zu bringen ist einfach, sie effizient zu machen dagegen schwierig
  • Wenn sich ein Mesh nicht sauber vereinfachen lässt, entstehen wie bei Jinx Situationen mit rund 3.000 triangles, die einen einzelnen Pixel abdecken
  • Wenn man pixelgroße Triangles möchte, braucht man einen Software-Rasterizer; auch ein Billboard Impostor ist als auf Stabilität ausgelegter Fallback nützlich

Das Problem der Mesh Simplification

  • Simplification ist nicht das Problem „ein Mesh nehmen und auf X % triangles reduzieren“, sondern ein Problem, das im Kontext von Meshlets und METIS gelöst wird
  • UE5 nutzt eigenen Mesh-Simplification-Code als ersten Schritt der Asset Pipeline
    • Die hier eingesparten Kosten bringen kaskadierende Vorteile für das gesamte nachgelagerte System
    • In Brian Karis’ SIGGRAPH-Material heißt es, dass der LOD Graph in einem einzelnen Root Cluster endet und jedes Modell auf 128 triangles vereinfacht werden kann
  • Beim Jinx-Modell gab es das Problem, dass die Simplification an einem bestimmten Punkt stehen blieb
    • Es kam vor, dass bei Eingabe von X triangles wieder dieselben X triangles zurückkamen
    • Der Algorithmus stürzte mit einer Assertion ab
    • Danach wurde es so geändert, dass Mesh-Teile, die nicht ausreichend reduziert werden, mehrere Roots im DAG erlauben
  • Das Bunny-Modell wurde zunächst zu einem einzelnen Meshlet mit 128 tris vereinfacht, aber nach geänderten Bedingungen zeigte sich das Problem, dass es nicht zu einem einzelnen Root konvergiert
    • Viele Meshlets konnten die Triangle-Zahl nicht ausreichend reduzieren, und es gab auch viele „nicht volle“ Meshlets mit weniger als 128 triangles
  • Verwandte Diskussionen:

Error Metric

  • Beim Rendern eines Meshes mit 20.000.000 Dreiecken über eine Meshlet-Hierarchie muss ausgewählt werden, welches Meshlet das „richtige“ ist.
  • Dieses Auswahlproblem ist der Kern von Nanite; Simplification, Meshlet-DAG und Software-Rasterizer sind eher Voraussetzungen, um damit umzugehen.
  • Die Implementierung nutzt den von meshoptimizer bereitgestellten projected simplification error.
  • Der Autor hält diese Metrik nicht für eine gute Metrik für Nanite und meint, dass auch andere Vertex-Attribute in die Funktion einfließen sollten.
    • Pro Attribut sollte man ein Weight vergeben können.
    • Die Normals im Gesicht von Jinx waren ein großes Problem.
  • Referenzmaterial:

Warum der Software-Rasterizer keine Texturen ausgibt

  • Beim Hardware-Rasterizer lassen sich abhängig vom Ergebnis des Depth Tests Depth Texture, Color und Normal gemeinsam schreiben.
  • Wenn beim Software-Rasterizer mehrere Threads in dasselbe Pixel schreiben, entsteht eine Race Condition.
  • Die übliche Lösung ist ein Visibility Buffer.
    • Für jedes Pixel wird die sceneUniqueTriangleId des nächstgelegenen Dreiecks ausgegeben.
    • Diese wird mit 32-bit Depth zu einem 64-bit-Wert kombiniert, auf den 64-bit Atomic Operations angewendet werden.
    • In einem separaten Pass wird das Dreieck erneut gerastert; dabei werden baryzentrische Koordinaten berechnet und das Shading durchgeführt.
  • WebGPU bietet keine 64-bit Atomics, daher ist dieser Ansatz nicht nutzbar.
  • Ziel dieses Projekts ist zu zeigen, dass Software-Rasterisierung funktioniert. Deshalb ist das per Software gerasterte Modell im Hintergrund weiß und bietet nur ein angemessenes Shading.

Einschätzung zur eigenen Nanite-Implementierung

  • Die einfachste Antwort ist, UE5 zu verwenden.
  • Um diese Technik in eine bestehende Engine einzubauen, müsse man nach Ansicht des Autors zunächst eine compute-basierte Graphics Pipeline und eine GPU-driven Rendering Pipeline implementieren.
  • Probleme wie Multi-Step Culling, Scene/World Chunk Management und animierte Meshes treten zuerst auf.
  • Vorgeschlagen wird die Reihenfolge, diese Schritte zuerst zu stabilisieren, danach den Software-Rasterizer zu versuchen und anschließend Nanite-like Tech hinzuzufügen.
  • In einem Toy Renderer kann eine grundlegende Meshlet-Hierarchie ein Wochenendprojekt sein, in einer echten Implementierung müssen jedoch die Probleme rund um Simplification und Error Metric behandelt werden.

Verwendete Tools und Referenzen

  • meshoptimizer ist die zentrale Grundlage der Projektimplementierung.
    • Neuere meshoptimizer-Versionen enthalten meshopt_SimplifySparse für einen Nanite-Clone.
    • Das Projekt wurde nicht auf diese Version aktualisiert, um den während der Entwicklung getesteten Stand beizubehalten.
  • METIS wurde verwendet.
  • Emscripten wurde genutzt, um meshoptimizer und METIS im Browser auszuführen.
  • Für das Jinx-Modell wurde Arcane - Jinx von Sketchfab verwendet; dabei wurden Texturen zusammengeführt, UVs angepasst und die Waffen entfernt.

1 Kommentare

 
GN⁺ 2024-09-06
Hacker-News-Kommentare
  • Oh, sehr schön. Das ist im Grunde eine Third-Party-Implementierung für die Wiedergabe von Nanite.
    Nanite stellt Grafik-Meshes auf sehr clevere Weise dar. Es ist kein Baum, sondern ein gerichteter azyklischer Graph, sodass Wiederholungen nicht kopiert, sondern verlinkt werden, und ein Mesh Teil-Meshes gemeinsam nutzen kann, die ihrerseits ebenfalls wieder gemeinsam genutzt werden können. Es unterstützt auch Detailstufen (LOD) innerhalb eines Meshes, sodass Teil-Meshes wegfallen, wenn sie klein genug werden.
    Dadurch lassen sich mit endlichen Datenmengen und kurzen Renderzeiten sehr große Mengen an wiederholtem Content verarbeiten. Die Einsicht dabei ist, dass die tatsächlich nötige Renderarbeit nach oben begrenzt ist, weil die Anzahl der Pixel auf dem Bildschirm begrenzt ist.
    Das SIGGRAPH-Video mit der Erklärung von jemandem von Epic ist ausgezeichnet. Das aktuelle GPU-Design passt nicht besonders gut zu Nanite, daher wären neue Hardware-Operationen nötig, wenn man mehr Verarbeitung auf die GPU verlagern wollte. Da Nvidia derzeit vom AI-Markt völlig vereinnahmt ist, ist fraglich, ob es zu solchen Änderungen kommt.
    Damit dieser Ansatz gut funktioniert, braucht eine Szene viele Instanzen. Für AAA-Spiele, die mit einer begrenzten Zahl von Objekten große Welten aufbauen, passt das gut, wie etwa die Halle mit den identischen Statuen in einer Unreal-Engine-Demo. Wenn man sich Gameplay-Videos von Cyberpunk 2077 anschaut und auf Geländer und Müllhaufen achtet, sieht man, dass dieselben Dinge in völlig anderen Kontexten ständig wiederholt werden.
    Die Erstellung von Nanite-Meshes ist komplex, weil es viele interne Link-Offsets gibt, und bisher konnte das nur der Unreal-Engine-Editor verarbeiten. Jetzt, da die Wiedergabeseite Open Source geworden ist, ist gut möglich, dass jemand auch Tools zur Erstellung baut.
    Allerdings könnten die internen Offsets des Formats eine Angriffsfläche darstellen, und es wirkt so, als ließe sich das mit manipulierten Inhalten missbrauchen, ähnlich wie bei bösartig präparierten Microsoft-Word-.doc-Dateien.

    • Man erzeugt zwar einen gerichteten azyklischen Graphen für den Graph-Schnitt, aber die endgültigen Daten auf der Festplatte sind nur eine flache Liste von Clustern mit Include/Exclude-Kriterien. Hier scheint es ein ziemlich großes Missverständnis darüber zu geben, wofür der DAG verwendet wird und wie er erzeugt wird.
      Der DAG wird dynamisch anhand der Vertex-Daten aufgebaut und hat nichts damit zu tun, wie ein Artist die Teil-Meshes strukturiert hat. Es ist also nicht so, dass „Wiederholungen zu Links werden“.
      Außerdem fällt das Ergebnis des Graph-Schnitts für jede Objektinstanz anders aus, sodass man kein traditionelles Instancing verwenden kann; deshalb verstehe ich nicht, warum man meint, dass viele Instanzen in einer Szene Voraussetzung für die Wirksamkeit seien.
    • Früher, in den 2000ern, habe ich für die PS3 entwickelt und nach einer guten Möglichkeit gesucht, die reichlich vorhandenen Rechenressourcen des Cell zu nutzen und die begrenzte Speicherbandbreite des RSX zu umgehen. Speicherplatz auf Blu-ray stand reichlich zur Verfügung.
      Damals habe ich etwas ziemlich Ähnliches wie Nanite recht weit vorangetrieben; wir nannten es komprimierte Meshes. Typische fehlgeleitete technische Hybris.
      Die frühe Arbeit sah vielversprechend aus, aber je tiefer wir eingestiegen sind, desto komplexer wurde das Ganze. Wir hätten eine komplette Pipeline zur Asset-Erstellung bauen müssen, und das war zu groß, um es in vertretbarer Zeit fertigzubekommen, mit gutem visuellen Ergebnis und ohne den Speicher zu sprengen.
      Wir kamen ungefähr so weit, dass es so aussah, als könne man großskalige Meshes mit gestaffelten Detailstufen rendern, aber es war extrem langsam und sah miserabel aus, wenn man die GPU nicht bis ans Limit trieb, um Subpixel-Genauigkeit zu erreichen. Es war ein interessantes Experiment, aber für die Hardware zu viel und als Solo-Aufgabe ebenfalls zu groß.
      Als Epic Nanite vorgestellt hat, war ich wirklich verblüfft. Sie haben geschafft, woran ich gescheitert bin, und zwar auf eine Weise, die weit über das hinausging, was ich mir als Bestfall ausgemalt hatte. Es ist eine dieser Technologien, die bei ihrem Erscheinen keine Übertreibung, sondern eine echte Lösung waren, und ein technisches Juwel der modernen Grafik. Wäre Epic börsennotiert gewesen, hätte ich allein wegen der Nanite-Technologie ernsthaft erwogen, viel Geld zu investieren.
    • Mit dem erwähnten SIGGRAPH-Vortrag ist wahrscheinlich "A Deep Dive into Nanite Virtualized Geometry" gemeint: https://www.youtube.com/watch?v=eviSykqSUUw
      Auch das kurze Video als Einführung auf hoher Ebene war gut: "What is virtualized micropolygon geometry? An explainer on Nanite": https://www.youtube.com/watch?v=-50MJf7hyOw
    • Kein Mainstream-Engine, aber die kleine Rust-ECS-Game-Engine Bevy unterstützt etwas Ähnliches ebenfalls unter dem Funktionsnamen "Virtual Geometry": https://bevyengine.org/news/bevy-0-14/#virtual-geometry-expe...
      Es gibt auch einen technischen Deep Dive von einem der Autoren dieser Funktion: https://jms55.github.io/posts/2024-06-09-virtual-geometry-be...
    • Nachdem ich die Paper gelesen habe, hatte ich den Eindruck, dass der größte Gewinn aus quantisierten Koordinaten und dynamischen Detailstufen auf Ebene kleiner Patches statt des gesamten Meshes kommt.
      So wie ich die Logik von Nanite verstehe, geht es darum, die Genauigkeit des Meshes ungefähr auf eine Präzision von 1 Pixel zu halten. Wenn der Fehler etwa nach der Perspektivprojektion nur bei einem halben Pixel liegt, kann man zum Beispiel ein Mesh mit niedrigerem Detailgrad verwenden, bei dem die Koordinaten auf etwa 10 Bit gerundet wurden.
      Soweit ich mich erinnere, erfüllte die Quantisierung zwei Funktionen: Sie verringerte nicht nur die Datengröße bei der Speicherung, sondern half auch bei der Erzeugung von Detailstufen, indem Vertices auf dieselbe Position im Raum geschnappt wurden, sodass man danach Duplikate entfernen konnte.
  • Das wurde in diesem Thread schon ein paar Mal erwähnt, aber Bevy hat ebenfalls eine Umsetzung der Nanite-Ideen. Man nennt es manchmal virtuelle Geometrie. Ich bin der Autor davon und kann Fragen beantworten :)
    Scthe hat bei diesem Projekt wirklich großartige Arbeit geleistet. Wir haben im Lauf der Arbeit über verschiedene Teile davon gesprochen, und auf Grundlage dieser Erfahrung wurde auch der Bevy-Code verbessert: https://github.com/bevyengine/bevy/pull/15023
    Es ist immer schön, wenn mehr Leute in dieses Feld einsteigen. In Nanite stecken wirklich viele großartige Ideen.

  • Verwendet die Demo zur Beurteilung der Kompatibilität den User-Agent-String? Das ist nicht gut. Feature-Kompatibilität sollte fallweise beurteilt werden, indem man die jeweiligen Funktionen direkt erkennt oder ausprobiert
    Ich nutze Chromium statt Chrome und habe WebGPU ebenfalls immer aktiviert, aber die Demo fordert mich auf, Chrome zu verwenden. Das kann ich aus ethischen Gründen nicht tun. Ich würde die Demo wirklich gern ausprobieren; es wirkt wie ein Projekt, in das viel Arbeit geflossen ist

    • Zur Information: Auch unter Chrome auf Linux und auf Android funktioniert es nicht. Tatsächlich nutze ich zum normalen Surfen fast immer Firefox. An der Erkennungslogik ist irgendetwas ziemlich seltsam
    • So scheint es nicht zu sein. In Firefox mit aktivierter experimenteller WebGPU-Unterstützung scheitert es mit einem Shader-Kompilierungsfehler statt mit einer separaten Meldung
    • Es ist gut, Feature-Erkennung anzustreben
      Als ich selbst ein Komponenten-Framework für Browser gebaut habe, war Erkennung oft nicht möglich, sodass man auf Browser-Sniffing angewiesen war. Im Code von Modernizr gibt es viele sehr clevere Hacks zur Feature-Erkennung, manchmal auch ziemlich schmutzige Hacks. In verlässlichen Erkennungscode ist enorm viel Arbeit geflossen, und die Erkennung erfolgte meist über Nebeneffekte
      Meiner Vermutung nach ist die Erkennung von Web3D-Features nicht einfach. Selbst bei einer schnellen Suche habe ich keine eindeutige Bibliothek zur Web3D-Feature-Erkennung gefunden
      Ein Teil des Erkennungscodes von Modernizr für die Unterstützung von :checked sieht so aus:
      Modernizr.addTest('checked', function(){
      return Modernizr.testStyles('#modernizr input {width:100px} #modernizr :checked {width:200px;display:block}', function(elem, rule){
    • Ich weiß nicht, welchen Build Sie verwenden, aber ich nutze Ungoogled Chromium, und mein User-Agent-String ist exakt derselbe wie bei Google Chrome
      Haben Sie in den Seiteneinstellungen die WebGL-Berechtigung für diese Site aktiviert? Bei mir war sie anscheinend standardmäßig deaktiviert
    • Die Demo selbst scheint einfach kaputt zu sein. Ich bekomme diesen Fehler:
      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).
  • Hier ist die etwas untergegangene Dissertation von Federico Ponchio aus dem Jahr 2009, der den dynamischen Mesh-Vereinfachungsalgorithmus erfunden hat, auf dem Nanite basiert. Sie enthält auch viele Abbildungen
    https://vcg.isti.cnr.it/~ponchio/download/ponchio_phd.pdf 107 Seiten

  • Dass es zumindest teilweise funktioniert, ist beeindruckend, aber weil WebGPU keine 64-Bit-Atomics hat, mussten wohl einige ziemlich grobe Kompromisse eingegangen werden
    Hoffentlich wird das irgendwann als optionale Erweiterung hinzugefügt. Zumindest auf Hardware der Desktop-Klasse ist Hardware-Unterstützung fast überall vorhanden. AMD und Nvidia haben sie schon lange, und Apple unterstützt sie seit dem M3

    • Wofür werden Atomics im Rasterizer verwendet? Ich verstehe nicht, was Atomics innerhalb der Rendering-Pipeline tun. Ich habe auch auf GitHub nachgesehen, konnte aber nicht finden, an welcher Stelle Atomics erwartet wurden
    • Seit dem M2
  • Bei meinem iPhone 12 Pro Max steht, dass es kein WebGPU gibt, aber wenn ich es in den experimentellen Features aktiviere, funktionieren andere WebGPU-Demo-Sites[1]. Hat das hier jemand auf einem iPhone zum Laufen gebracht? Es wäre gut, wenn die Web-App genauer mitteilen würde, woran es gescheitert ist
    [1] https://webgpu.github.io/webgpu-samples/?sample=texturedCube

    • Ich habe WebGPU in Safari aktiviert, aber es erscheinen jede Menge Shader-Fehler
      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'
    • Die WebGPU-Unterstützung in Safari ist noch nicht abgeschlossen, deshalb bleibt sie eine experimentelle Funktion
  • Name und Beschreibung sind sehr irreführend und wirken potenziell wie eine Markenrechtsverletzung. Entgegen der Behauptung hat das überhaupt nichts mit dem tatsächlichen Nanite aus UE5 zu tun; offenbar hat jemand ohne Beziehung zu UE5 etwas Ähnliches implementiert
    Es gibt auch Bevy Virtual Geometry mit ähnlicher Funktionalität. Es ist in Rust geschrieben und in eine Game-Engine integriert, daher ist es potenziell viel nützlicher: https://jms55.github.io/posts/2024-06-09-virtual-geometry-be...

    • Das scheint kein großes Problem zu sein. Im README ist klar ersichtlich, dass es sich um eine Implementierung handelt
      Wenn ich sage, ich hätte „OpenAIs GPT-3 in JS implementiert“, würde ich darunter verstehen, dass ich die Architektur aus dem Whitepaper übernommen und neu implementiert habe
  • Das ist nicht tatsächlich UE5 Nanite, das auf WebGPU läuft. Es ist eine unabhängige Implementierung derselben Ideen wie Nanite
    Diese Technik taucht inzwischen an mehreren Stellen auf. Nanite hat die Idee zwar berühmt gemacht, aber Nanite ist nicht der Name der Technik, sondern der Name einer bestimmten Implementierung.

  • Mich würde interessieren, wie weit andere Engines bei LOD und ähnlichen Systemen sind.
    Godot hat eine automatische LOD-Funktion, und die sieht für sich genommen ziemlich gut aus: https://docs.godotengine.org/en/stable/tutorials/3d/mesh_lod...
    Unity hat ebenfalls ein LOD-System, aber trotz der Popularität der Engine muss man die LOD-Modelle manuell erstellen – außer man sucht im Asset Store nach Plugins: https://docs.unity3d.com/Manual/LevelOfDetail.html
    Bei der weniger bekannten Engine NeoAxis habe ich auch einen interessanten Ansatz gesehen: https://www.neoaxis.com/docs/html/NeoAxis_Levels.htm Allerdings war die Performance auf meiner alten RX580 sehr schlecht; auf meiner aktuellen A580 habe ich es noch nicht ausprobiert.
    Meiner Ansicht nach liegt Unreal bei der Fähigkeit, viele Dinge gleichzeitig auf den Bildschirm zu bringen, ziemlich deutlich vor den Konkurrenten. Der Nachteil ist, dass Artists dann gern noch höherwertige Assets ins Spiel packen wollen, wodurch die Installationsgröße stark anwachsen kann.

    • Theoretisch ist Nanite vorab berechneten LODs überlegen. In der Praxis lässt sich das aber schwer so eindeutig sagen. Es ist schwer, so gut zu sein wie von Artists direkt erstellte LODs, und das zu erwarten wäre auch nicht vernünftig.
      Auch die Performance-Kosten sind hoch. Nanite beziehungsweise virtuelle Geometrie passt nicht gut zu modernen GPUs. Wenn ich mich richtig erinnere, lag die maximale Fillrate bei ungefähr 1/4. Der GPU-Rasterizer arbeitet nämlich nicht wie Shader auf Pixelebene, sondern in 2x2-Quads.
    • Intel Arc GPUs sind für Nanite-Rendering miserabel. Der Grund ist, dass sie weder Indirect Draw, das in GPU-gesteuerten Renderern weit verbreitet ist, noch die für Nanite nötigen 64-Bit-Atomics in Hardware unterstützen. Intel emuliert Indirect Draw in Software, was langsam ist.
  • Immer wenn ich so eine gerenderte Szene mit viel repetitiver statischer Geometrie sehe, muss ich an diese nervige Stimme aus einem alten Vaporware-Video denken, die von „unbegrenztem Detail“ geschwärmt hat.
    Nanite scheint dieses Problem im Gegensatz zu diesem alten Ding tatsächlich gelöst zu haben. Soweit ich mich erinnere, hieß es damals, dass dort so etwas wie ein Octree verwendet wurde.

    • Die Firma, die diese Behauptung aufgestellt hat, hieß wohl Euclidean. Ich glaube, das war ein australisches Unternehmen.
      Online kursierten Gerüchte, dass sie Octrees verwenden, aber in späteren Euclidean-Videos wurde das ausdrücklich verneint.