In three.js können wir einfach die Geometrie zusammenführen, um die Anzahl der Draw-Aufrufe zu begrenzen und damit die Leistung zu steigern. In einem einfachen Test mit einem Material konnte ich 50.000 Cubes + Shadows @ 60fps auf meiner GTX660-GPU zeichnen. Ohne das Zusammenführen der Geometrie verursachten bereits 5.000 Würfel ein Problem.
Ich frage mich, wie ich die Vorteile des Renderns jedes Würfelnetzes für sich behalten kann. Wie wählt man beispielsweise ein Würfelnetz aus, wenn alles zu einer Geometrie zusammengeführt wird? Standardmäßig ist das natürlich nicht möglich.
Gibt es eine übliche Technik für dieses Problem? Immerhin habe ich auch nach dem Zusammenführen alle nicht zusammengeführten Netzobjekte. Es muss also eine Möglichkeit geben, sie für die Kommissionierung zu verwenden?
Was ich auf den Punkt bringen möchte
- SimCity-ähnliches Spiel für Lernzwecke
- Jedes Haus ist ein Würfelnetz
- Sie möchten 50.000 Häuser rendern und Häuser hinzufügen und entfernen können
- Die Hausauswahl per Mauszeiger (Picking) muss möglich sein
Antworten:
OK ich habe es. Nachdem ich die gesamte Geometrie zusammengeführt habe, habe ich immer noch die einzelnen Netze in einem Array. Ich kann diese Netze also einfach für das Raycasting verwenden, obwohl sie nicht einmal gerendert werden. Ich habe eine Weile gebraucht, um das zu realisieren.
Für die Auswahl verwende ich diese Octree-Implementierung: http://threejs.org/examples/#webgl_octree_raycasting
Dadurch werden die Schnittpunkttests pro Aktualisierung von 50.000 auf ~ 500 gesenkt. Ohne den Octree werden die fps stark abnehmen.
Der orangefarbene Picking-Rumpf, den Sie sehen, ist das jetzt gerenderte Netz (+1 Draw Call) mit geändertem Material und geänderter Größe.
Ich denke, der nächste Schritt besteht darin, eine Art Kartenpartitionierung zu implementieren. Teilen Sie die zusammengeführte Geometrie in mehrere Teile auf. Der Grund dafür ist, dass die zusammengeführte Geometrie eine große Anzahl von Eckpunkten aufweist. Das heißt, wenn ich die Karte zu 99% vom Bildschirm verschiebe, muss die Grafikkarte immer noch alle Scheitelpunkte verarbeiten, da die Geometrie immer noch sichtbar ist, mindestens 1% davon. Wenn es also aufgebrochen ist, müssen nur die sichtbaren Teile gerendert werden.
quelle
Zum Auswählen können Sie auch IDs für jeden Cube auf ein anderes Renderziel rendern und einfach überprüfen, wie sich der ID-Wert am Cursor befindet. Der Vorteil ist, dass die Auswahl pixelgenau ist und auch bei komplexeren Geometrien effizient funktioniert.
Wenn alle Objekte dieselbe Geometrie haben, können Sie instanziiertes Rendern verwenden. Ein Stream definiert die Geometrie, während ein anderer Eigenschaften pro Instanz definiert (z. B. Transformation). Für das Kegelstumpf-Culling müssten Sie den Instanz-Stream für jeden Frame basierend auf dem Sichtbarkeitstest erstellen. Wenn Sie jedoch eine große Anzahl von Objekten haben, möchten Sie diese Objekte möglicherweise in einem losen Octree oder etwas anderem platzieren, um das Keulen zu beschleunigen.
quelle
Ich bin mir über die Einzelheiten von three.js nicht sicher, aber im Allgemeinen fallen mir zwei mögliche Leistungsprobleme ein: OpenGL:
quelle
Ein anderer Ansatz, den Sie wählen können, besteht darin, ein Scheitelpunktattribut in Ihre Geometrie zu integrieren und die Hervorhebungslogik in Ihren Fragment-Shader einzufügen. Dies ist äußerst nützlich, wenn Sie nicht zwei Kopien von Daten im Speicher haben möchten und mehr Kontrolle darüber haben, wie die Hervorhebung implementiert wird.
quelle