Verwalten von Voxel-Daten

8

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?

Schatten
quelle

Antworten:

5

Müssen Sie jeden einzelnen Block (vorausgesetzt, Sie verwenden Blöcke) gleichzeitig im Speicher haben? Einige werden - besonders unter der Erde - oder hinter Bergen usw. verdeckt sein. Viele werden wahrscheinlich nur luftig / leer sein und könnten daher mit einer Flagge markiert werden.

Sie können auch ein LOD-Octree oder eine ähnliche Struktur verwenden, um zu versuchen, das aktuell sichtbare Detail in umgekehrter Beziehung zur Entfernung vom Beobachter zu halten. Wie von Jason angegeben, ist dies viel wahrscheinlicher, um Ihnen Leistung zu verschaffen, aber es ist eine große strukturelle Änderung gegenüber einer flachen Chunk-Map.

Lesen Sie diesen Artikel über Clipmaps aus meinem Lieblingsblog (er hat eine Voxel-Engine ähnlich der von Ihnen beschriebenen mit einer Voxelgröße von ~ einem Dezimeter).

ThorinII
quelle
2
Zunächst einmal, ja, ich benutze Brocken. Zweitens würde Ihr Vorschlag, völlig versteckte Brocken zu entladen, definitiv einiges helfen, danke. Eine mögliche Methode, die ich verwenden könnte, wäre, eine Okklusionsabfrage mit dem Begrenzungsrahmen des Blocks zu verwenden (da alle Blockgrößen bekannt sind), um festzustellen, ob ein Block sichtbar ist, und einen Block zu laden / entladen abhängig vom Ergebnis. Bearbeiten: Ich habe gerade Ihre Bearbeitung gesehen und diesen Blog habe ich bereits gesehen. Es ist der Grund, warum ich mit einer kleineren Voxelgröße experimentieren möchte =)
Shadow
Okklusion ist weit weniger wichtig als LOD. Okklusion bringt dir nichts, es sei denn, du bist unter der Erde oder schaust auf die Seite eines Berges. Mit LOD können Sie einen ganzen Planeten rendern. Okklusionsabfragen sind eine schlechte Idee, da sie einen GPU-> CPU-> GPU-Roundtrip einführen. Bedingtes Rendern ist zwar möglich, aber die CPU kann wahrscheinlich selbst gut genug.
Guter Punkt. Ich habe gerade LOD als zweites angegeben, weil es sich um einen großen Strukturwandel handelt.
ThorinII
3

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.

Ingenieur
quelle
0

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 .

Leggy7
quelle