Terrain & Multi-Texturierung

7

Ich verwende OpenGL (Version 4.4) (und C ++, wenn das wichtig ist).

Ich habe einen Terrain-Renderer erstellt. Das Terrain wird als 3D-Skalarfeld (Isofläche / Voxel) gespeichert. Es wird eine leicht modifizierte Version von Marching Cubes verwendet , um eine Polygonisierung durchzuführen (Konvertieren des Skalarfelds in Dreiecke).

Derzeit texturiere ich das Gelände mit einer horizontalen (Gras) Textur und einer vertikalen (Schmutz) Textur. Wenn ich dann die Textur anwende, berechne ich einfach den Betrag der horizontalen und vertikalen Textur, der für das aktuelle Dreieck erforderlich ist, abhängig von den Normalen des aktuellen Dreiecks. Je mehr eine Normale nach oben (oder unten) zeigt, desto dominanter ist die horizontale (Gras-) Textur.

Terrain Renderer in Aktion

Terrain Vollbild

Die Frage ist nun, was der beste (oder ein guter) Weg wäre, um Multi-Texturing im Gelände durchzuführen. Ich werde allen Werten im Skalarfeld auch einen Voxeltypwert geben . Die Hauptfrage ist also, wie mit dem Rendern umgegangen werden soll. Ich habe ein paar Ideen, wie dies getan werden könnte, aber ich bin mir nicht sicher, welche meiner Ideen die beste wäre oder ob es noch einen besseren Weg gibt.

Erste Idee

  • Binden Sie alle benötigten Texturen und fordern Sie dabei glActiveTexture(...)jede Textur auf, die es gibt.
  • Jetzt kann das Netz mit einem einzigen glDraw*(...)Aufruf gerendert werden .
  • Dies funktioniert natürlich nur, wenn der Shader weiß, wann und wo jede Textur verwendet werden soll oder dass die Informationen zur Verwendung jeder Textur im Puffer gespeichert sind, als eine Art Wert, den der Shader verwendet, um zu "erkennen", welche Textur sein soll benutzt. Wie bereits erwähnt, kann dies der Wert vom Voxeltyp sein.

Problem: Die maximale Anzahl von Texturen, die gleichzeitig gebunden werden können, ist sehr begrenzt, so dass (und wahrscheinlich) einige Probleme auftreten können.

Zweite Idee

  • Binden Sie eine einzelne Textur und Anruf glDraw*(...)mit einem bestimmten firstund countWert, so dass nur ein Teil des Netzes gemacht wird. Welches ist natürlich der Teil, der die gebundene Textur verwendet.
  • Schleifen Sie dabei das Obige, bis das gesamte Netz mit allen einzelnen Texturen gerendert ist.

Ich sehe kein wirkliches Problem mit dieser Idee. Das einzige zusätzliche, was wir berücksichtigen müssen, ist, dass alle Dreiecke nach ihrem voxel typeWert sortiert werden müssen .

Obwohl wir die Texturen nicht verblassen könnten, wie im obigen Bild.

Dritte Idee

  • Teilen Sie das Netz in einzelne Puffer (VBOs und VAOs) auf, sodass jeder Puffer nur eine einzige (oder mehrere) Textur (en) verwendet. Grundsätzlich das gleiche wie bei der zweiten Idee, obwohl hier der Puffer physisch gemäß den Texturen aufgeteilt würde.

Vierte Idee?

oder gibt es einen noch besseren weg?

Randnotiz

  • Jede Textur hat einen eigenen Griff, daher kann keiner von ihnen als Texturatlas verwendet werden .
Vallentin
quelle

Antworten:

2

Anstelle von glActiveTexture können Sie ein Texturarray binden und so viele Texturen abtasten, wie Sie möchten ... ABER !! Dass es teuer ist, wenn Sie 16 Schichten haben, werden Sie 16 Proben lesen und dann werden wahrscheinlich nur eine oder zwei vorherrschen.

Sie können ein Texturarray binden und dann den Index der zwei (oder drei) vorherrschenden Texturen und das Stichprobengewicht angeben.

Stichprobengewicht und -index können andere Texturen oder Parameter sein, die vom Scheitelpunkt übergeben werden.

ilmale
quelle
Wie binde ich ein Texturarray und erstelle es?
Vallentin
Ein Textur-Array ist im Grunde eine Textur3d ohne Interpolation auf dem Z. Link. Aber ich habe jetzt gelesen, dass jede Textur ihren eigenen Griff hat ..: - /
ilmale
Ich verwende Textur-Arrays für die Multitexturierung eines Geländes und habe zwei markante Indizes für jeden Scheitelpunkt gespeichert. dh (1,0,7,3,0,3) für einen Scheitelpunkt bedeutet Textur eins mit 0,7 Gewicht und Textur 3 mit 0,3. Aber ich kann keinen Weg finden, diese ohne Artefakte zu verwenden. Wenn wir einfach die interpolierten Werte für Indizes verwenden, treten Artefakte auf, wenn sich die Indizes zwischen den Scheitelpunkten ändern. Zum Beispiel ist Scheitelpunkt A vollständig Textur 1 und Scheitelpunkt B ist vollständig Textur 2. Wenn wir sie im Pixel-Shader interpolieren, gibt es Pixel, bei denen der Texturindex 2 wird. Haben Sie Vorschläge für dieses Problem?
Morteza Khosravi
1

Wenn Sie kreativ mit den Daten sind, die Sie in Ihre Verts packen, können Sie einen Texturatlas erstellen.

Grundsätzlich benötigen Sie 3 Sätze UV-Daten anstelle des üblichen Einzelsatzes. Jedes repräsentiert die Zuordnung für eine der 3 Texturen, die von diesem Dreieck verwendet werden. Ihr Farbkanal bestimmt, wie viel diese durchscheinen.

Mit einem Voxelfeld können Sie diese Mischung durch die Entfernung vom Scheitelpunkt berechnen.

Lachsmoose
quelle
0

Aus den von Ihnen vorgeschlagenen Optionen würde ich mich daran halten, das Netz in Teilnetze aufzuteilen, die nach Material / Textur sortiert sind. Dies kann tatsächlich schneller gerendert werden, wenn Ihr Datensatz wirklich riesig ist. OpenGL-Draw-Aufrufe schlagen möglicherweise aufgrund von Speichermangel fehl, obwohl Sie es wirklich hart pushen müssten, um dies zu erreichen.

Wenn Sie es jedoch wirklich ernst meinen, Ihren Terrain-Renderer zu optimieren, sollten Sie sich wahrscheinlich mit Virtual Texture Mapping (manchmal auch als "Megatextures" bezeichnet) befassen. Dies ist wahrscheinlich die effizienteste Methode zur Verwaltung großer Texturdatensätze.

glampert
quelle