Ich programmiere seit ungefähr 4 Monaten in C ++ als Hobby und ich habe es wirklich geliebt, Dinge mit Voxeln zu erstellen. Ich habe ein "Spiel" geschrieben (eher eine persönliche Herausforderung, da ich wirklich nur das Terrain, kein Gameplay) habe, das eine Minecraft-ähnliche Welt geschaffen hat, aber kürzlich habe ich darüber nachgedacht, ein Spiel / eine Herausforderung / etc. Zu schreiben Dabei wird ein Algorithmus wie Marching Cubes oder Dual Contouring verwendet und die Voxelgröße reduziert. Als ich mein Minecraft-ähnliches Projekt schrieb, speicherte ich die Daten jedes Blocks in einem mehrdimensionalen Array von nicht signierten Kurzschlüssen (wodurch ich bis zu 65536 verschiedene Blocktypen erhielt). Außerdem habe ich zum Rendern nur einen Punkt (als GLubyte) und einen anderen GLubyte gespeichert, um anzugeben, welche der 6 Flächen dem dargestellten Punkt zugewandt ist. Ich habe das Gesicht dann mit einem Geometrie-Shader gerendert.
Bei dem neuen Projekt, über das ich nachgedacht habe, kann ich mich nicht darum kümmern, wie ich möglicherweise genug Voxeldaten speichern kann, um Voxel von etwa 5 cm oder 10 cm im Vergleich zu den alten 1 m großen Voxeln zu haben, die ich hatte. Als ich einen Blockbereich von 704 x 704 x 704 gerendert habe, hat mein altes Projekt etwa 670 MB RAM verwendet. Wenn ich die Voxelgröße auf 10 cm verkleinern und den gleichen Renderabstand beibehalten würde, wären das etwa 649 GB Voxel-Daten (unter der Annahme von 2 Bytes pro Voxel und einer Fläche von 7040 ^ 3 Voxeln). Gibt es eine Möglichkeit, die Voxeldaten effizienter zu speichern, sodass ich immer noch eine Vielzahl verschiedener Voxeltypen habe?
Der Standardansatz für Engines wie Ken Silvermans VoxLap und dessen Nachfolger Ace of Spades besteht darin, die RLE-Komprimierung und verschiedene andere Tricks auf Bitebene zu verwenden, um die Daten zu speichern und darauf zuzugreifen. Diese Art der 1D-Komprimierung ist in der Regel sehr effizient und wesentlich einfacher zu verwenden als Octrees. Ich glaube, Silvermans Motor hat eine Voxelauflösung von etwa 10 cm Würfel erreicht. Etwas, das Sie heute normalerweise nicht sehen und das auf viel schwächerer Hardware erreicht wurde.
Ich glaube, es ist auch wahr, dass sein Ansatz keine Farben für unbelichtete Voxel gespeichert hat, sondern stattdessen die Farbe für Oberflächenvoxel als Funktion der Höhe berechnet hat oder indem er sich daran erinnert hat, welche Bereiche des Geländes aufgestrahlt wurden, und diese als "frischen Boden" gefärbt hat ". Sie könnten eine Art kontinuierliche Funktion wie Perlin-Rauschen verwenden, um dies zu tun, aber es könnte für große Oberflächen schnell teuer werden (es sei denn, dies wird möglicherweise auf der GPU ausgeführt).
Octrees sind nicht schlecht, aber in der Praxis schwierig zu verwenden, und die cacheeffiziente Zuweisung ist erheblich schwieriger als RLE, das sich leicht per Block linearisieren lässt. Das wegweisende Papier von Tero Karras und Samuli Laine zu SVOs zeigt, wie viel Aufwand in die wirklich performante Octree-Implementierung investiert wird - und dies berücksichtigt nur das Rendern, nicht das Gameplay oder die Netzwerkkommunikation.
quelle
Ich weiß nicht, wie weit Sie in Ihrem Projekt gegangen sind, aber ich und ein Freund von mir verwenden den Dual Marching Cubes- Algorithmus, der auf der Octree-Chunck-Struktur basiert und ein Dual-Grid zum Rendern der Daten verwendet. Es hat viele Vorteile, wie einen sehr geringen Speicherbedarf und ein sehr schnelles Rendern. Es mag etwas schwierig sein, Level Of Detail (LOD) in Chunk-Rändern mit anderen Chunks zu implementieren , aber wenn Sie etwas Freizeit haben, können Sie herausfinden, wie sich Ogre3D-Entwickler verhalten haben .
quelle