Wie kann ein großes Geländegitter effizient gerendert werden?

10

Vor kurzem hatte ich ein Problem mit dem Gedanken, wie ich am besten ein Terrain in mein Spiel einbauen kann. In anderen Projekten habe ich normalerweise Höhenkarten verwendet, daher basierte die gesamte Kernarbeit auf dem verwendeten Motor, aber dies kann jetzt nicht durchgeführt werden, da das Gelände Millionen spezifischer Polygone enthält, die genau gezeichnet werden müssen. Außerdem können viele von ihnen nicht aus dem Y-Vektor analysiert werden (aufgrund von darunter verborgenen Polygonen), dh eine Höhenkarte ist hier nicht nützlich. In diesem Fall musste ich ein COLLADA-Objekt verwenden.

Jemand sagte mir, ich solle das Modell manuell in eine Software wie Blender aufteilen, aber leider ist dies auch nicht möglich, da diese Terrains in Blöcken in einer anderen Software erstellt und anschließend in das Spiel geladen werden (das ist die Idee). Daher wäre es eine große Arbeit, sie jedes Mal manuell in Scheiben schneiden zu müssen.

Daher habe ich seit einer Woche untersucht, wie ich dieses Problem lösen und dieses Netz, das Gelände, entsprechend dem Kamera-Frustrum prozedural laden kann, um so viel Leistung wie möglich zu sparen. Ich bin auf viele Dokumente zur prozeduralen Netzgenerierung gestoßen und denke, dass mein Problem gelöst werden könnte, indem das Netz in Oktrees abgebildet wird. Zumindest für mich ist das GROSSE Arbeit, und deshalb bin ich hier, weil ich nicht riskieren möchte, den falschen Weg zu gehen, ohne vorher von erfahrenen Leuten zu hören.

Kurz gesagt, ich habe Millionen von Eckpunkten und Indizes, die zusammen das Gelände bilden, aber aus offensichtlichen Gründen kann ich sie nicht gleichzeitig zeichnen. Es ist eine Art Verfahren erforderlich. Was ist der beste Weg, um ein großes Netz als Gelände zu behandeln? Gibt es ein bestimmtes Buch darüber? Gibt es einen besten Weg, um es zu implementieren?

Entschuldigung für jeden Fehler, ich bin ein Neuling in diesem Bereich.

Karl Marny
quelle

Antworten:

12

Grundlegendes Chunking ist ein guter Anfang. Bei Bedarf können Sie später zu komplexeren Datenstrukturen wie Octrees wechseln. Teilen Sie Ihr Gelände vorerst einfach in Blöcke mit bestimmten Abmessungen auf, wenn Sie das Modell von der Festplatte laden.

Abhängig von Ihren Daten möchten Sie Ihr Gelände entweder in Säulen auf einer Ebene über die gesamte Höhe oder in Würfel im Raum aufteilen. Der Code ist nicht vollständig (fmod, Vektorinitialisierung, Indizes, ...), sollte Ihnen aber einen Anfang geben.

// Load vertices from disk
struct point { double x, y, z; };    
vector<point> vertices;

// Create container for chunks
typedef pair<int, int> key;
unordered_map<key, vector<point>> chunks;
const int chunksize = 10;

// For each vertex
for (int i = 0; i < vertices.size(); ++i) {
    // Fetch global coordinates
    int x = vertices[i].x,
        y = vertices[i].y,
        z = vertices[i].z;

    // Find containing chunk
    key k;
    k.first  = x / chunksize;
    k.second = z / chunksize;

    // Calculate local coordinates
    point p;
    p.x = x % chunksize;
    p.y = y;
    p.z = z % chunksize;

    // Add to chunk
    chunks[k].push_back(p);
}

// Create separate buffers for each chunk
// ...

Da Sie das Netz jetzt aufgeteilt haben, können Sie LOD- und Culling-Techniken ausführen, um das Rendern versteckter Blöcke zu überspringen.

  • Ansichtsentfernung ist, wo Sie beginnen. Sie würden nur Blöcke innerhalb einer bestimmten Entfernung rendern, z. B. die Sichtweite Ihrer Kamera. Je kleiner der Sichtabstand ist, desto mehr Leistung erhalten Sie, da weniger Teile des Geländes gezeichnet werden müssen.

  • Das Keulen von Kegelstumpf ist eine übliche Technik, um nur Netze zu rendern, die sich mit dem Kegelstumpf der Kamera schneiden. Dies wird Ihnen höchstwahrscheinlich den größten Leistungsgewinn bringen.

Experimentieren Sie mit der Blockgröße und dem Betrachtungsabstand, um die besten Ergebnisse zu erzielen. Die Blockgröße ist ein Kompromiss zwischen genauem Keulen und einfacher Berechnung. Zur weiteren Optimierung können Sie sich diese erweiterten Optimierungen ansehen.

  • Das Okklusions-Culling kann durchgeführt werden, indem die Netze auf der CPU mit sehr geringer Auflösung gerendert werden. Auf diese Weise können Sie Netze, die hinter anderen verborgen sind, frühzeitig erkennen. Sie müssen nicht an die GPU gesendet werden, sodass Sie viele Vertex-Shader-Ausführungen speichern, die sonst ausgeführt worden wären, bevor Sie die Dreiecke zurückweisen.

  • Detaillierungsgrad bedeutet, dass Sie Netze mit niedrigerer Auflösung Ihrer Chunks berechnen. Basierend auf der Entfernung zur Kamera wählen Sie eines der zu zeichnenden Netze aus. Auf diese Weise können Sie die Anzahl der Scheitelpunkte reduzieren, da weit entfernte Blöcke nicht so viele Details benötigen. Dieser Ansatz eignet sich gut für Oktrees, da Sie mehrere Würfel für Bereiche weit von der Kamera entfernt zu einem Netz mit niedriger Auflösung zusammenführen können. Es ist jedoch nicht trivial, die Kanten zwischen zwei Blöcken unterschiedlicher Auflösung nahtlos zusammenzuführen.

Danijar
quelle