PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Direct3D: Effizientes Texture Mapping


Robbson
2006-03-29, 08:41:13
Hallo!

Als Anfänger hinsichtlich der Programmierung von Direct3D Applikationen beschäftigt mich zur Zeit die große Frage, wie man wohl ein effizientes Texture Mapping durchführen kann, ohne "Extrawürste". Was ich damit meine, soll an dem folgenden einfachen Beispiel gezeigt werden.

Man nehme einen (einzigen) Würfel. Dessen Vertices und Kanten sind über indizierte Primitives recht effizient definierbar. So genügen 8 Vertices und ein Array für 36 Indices, wenn der Würfel mit eine Triangle List erzeugt bzw. gerendert werden soll. Noch effektiver (weniger Indices) ginge es über Triangle Strips, doch leider sind die für den Würfel unbrauchbar, da bei der Hinzunahme eines weiteren Vertex offensichtlich nicht bestimmbar ist, über welche Dreieckseite das neue Dreieck aufgespannt werden soll.

Aber egal ob Triangle Strip oder List, kommen wir nun endlich zur Texturierung. Der Würfel soll so texturiert werden, daß alle vertikalen Flächen (vorne, rechts, hinten, links) mit Textur A (3x wiederholend) überspannt sind. Die obere und untere Seite sind hingegen mit einer anderen Textur B zu versehen.

Hier stellt sich nun die Frage, wie dieses Ziel erreicht werden kann. Hat jeder Vertex zwei Texturkoordinaten (U,V), dann reichen diese in diesem Fall nicht aus, da jeder Vertex von min. 2 verschiedenen Texturen benutzt wird.

Lösungsmöglichkeiten:
1. Jede Seite des Würfels bekommt eigene Vertices (jeweils 4 Stück), sodaß genügend U,V Koord. zur Verfügung stehen. Allerdings erhöht sich nicht nur die Anzahl der nötigen Vertices von 8 auf 24. Vielmehr gibt es zahlreiche redundante Vertices mit denselben Koordinaten, nur damit ein zusätzliches Paar an Texturkoord. zur Verfügung steht.

2. Jeder Vertex bekommt ein oder zwei zusätzliche(s) Paar(e) an Texturkoordinaten. Das erscheint zunächst am sinnvollsten. Allerdings müssen die Texturen dann womöglich in verschiedenen Stages gerendert werden, denn FVF erlaubt nur bis zu acht zusätzliche Texturkoordinaten für die weiteren Texture Stages. Sollen später noch andere Texturen darübergelegt werden, reichen womöglich die Stages nicht mehr aus.

3. Die komplette Texturierung des Würfels geschieht über eine einzige Textur, die wie folgend (aufgeklappt)gespeichert wird:

# B
#### bzw. AAAA
# B

Allerdings müssten so mehrere Texturen doppelt gespeichert werden, da die vertikalen Seiten ja jeweils nur mit ein und derselben Textur bekleidet werden sollen. Außerdem reichen auch hier die vorhandenen Texturkoordinaten der Vertices nicht (8 Paare).

Der Knackpunkt bei allen 3 Varianten liegt wohl in der Speicherung der zusätzlich nötigen Texturkoodinaten. Hier kann ich mich nicht so recht zu einem Kompromiss entscheiden. Natürlich spielen auch andere Parameter eine Rolle (etwa das Zusammenführen von Einzeltexturen zu Atlases), die hier aber nicht im Fokus liegen.
Für die erste Variante spricht (trotz des Overheads an Vertices), daß jede Fläche bspw. separat gekennzeichnet werden kann, wenn die texturierten Dreiecke später vor dem Rendern sortiert werden müssen.

Oder gibt es noch andere, effizientere und praktischere Methoden für den Würfelfall? Genauso ist die Problematik auch für andere Körper zutreffend, etwa bei benachbarten Flächen mit jeweils unterschiedlichen Texturen.

Es wäre schön, wenn mir jemand einen heißen Tipp geben könnte. Leider habe ich in den vielen Dokumenten (etwa von nVidia oder Microsoft) noch nix brauchbares für solche Fälle gefunden. ;(

Grüße,
Robbson.

Coda
2006-03-29, 13:32:53
Man nehme einen (einzigen) Würfel. Dessen Vertices und Kanten sind über indizierte Primitives recht effizient definierbar. So genügen 8 Vertices und ein Array für 36 Indices, wenn der Würfel mit eine Triangle List erzeugt bzw. gerendert werden soll. Noch effektiver (weniger Indices) ginge es über Triangle Strips, doch leider sind die für den Würfel unbrauchbar, da bei der Hinzunahme eines weiteren Vertex offensichtlich nicht bestimmbar ist, über welche Dreieckseite das neue Dreieck aufgespannt werden soll.
Man kann "degenerated triangles" (also nullfläche) einfügen um beliebige Meshes zu strippen. Aber indizierte Geometry ist meistens eh genauso effizient.

Oder gibt es noch andere, effizientere und praktischere Methoden für den Würfelfall?
Nicht wirklich. Aber das ist auch ein Extremfall. Normal hast du viel detailierte Meshes wo Dreiecke mit dem gleichen Vertex viel öfter die gleichen Texturkoordinaten haben.

micki
2006-03-29, 15:31:38
Man kann "degenerated triangles" (also nullfläche) einfügen um beliebige Meshes zu strippen. Aber indizierte Geometry ist meistens eh genauso effizient.
von hardware werden degenerierte triangles nur erkannt, wenn man sie indiziert, ansonsten kommen sie in den rasterizer.

indiziert und mit degenerierten tris (bei trianglestrips) ist das affizienteste.

Coda
2006-03-29, 15:33:10
von hardware werden degenerierte triangles nur erkannt, wenn man sie indiziert
Quelle? Das Trisetup müsste sie eigentlich auf jedenfall rausschmeißen, nur durch den Vertexshader gehen sie dann halt.

Xmas
2006-03-29, 18:24:33
- Texturatlas verwenden, so dass das gesamte Objekt in einem Drawcall ohne Texturwechsel gerendert werden kann.
- An Kanten wo unterschiedliche Teile des Texturatlas zusammentreffen Vertices duplizieren. Das gilt auch dort wo eine Textur komplett um ein Objekt herumgeht. Bei diesem Würfel brauchst du für die mit A texturierten Flächen 10 Eckpunkte, da die Texturkoordinaten von 0 bis 4 gehen sollten, nicht von 0 bis 3 und dann wieder auf 0 (es sei denn die Textur soll zwischendrin gespiegelt werden).
- indizierte Strips mit degenerierten Dreiecken sind in der Regel eine gute Wahl.

Coda
2006-03-29, 19:03:11
- indizierte Strips mit degenerierten Dreiecken sind in der Regel eine gute Wahl.
Trilists auch.

Robbson
2006-03-29, 20:22:50
Erstmal recht herzlichen Dank für die Infos! ;)

Also soweit ich das verstanden habe, wird bei den degenerated Triangles zunächst eines der bestehenden Dreiecke (bzw. eine oder mehrere von dessen Kanten) noch einmal definiert (überlagert), sodaß man sich den weiteren Verlauf des Triangle Strips "aussuchen" kann.

Nun gut, das wäre im Endeffekt (trotz der Mehrfachdefinition von einigen Dreiecken) dann noch einen Tick effizienter als eine Triangle List. Also statt 36 Indices müßten es dann... ähm... halt weniger sein. :rolleyes: Aber nicht so wenig, als würden alle Dreiecke in einer Ebene liegen und es würden keine degenerated Triangles benötigt.

Aber was nützt diese ganze Effizienz im Fall des Würfels, bei dem man statt 8 Vertices ganze 24 erzeugen muß, um jede Seite indiviudell texturieren zu können. Jedenfalls soll das wohl die gängiste Methode sein.


- Texturatlas verwenden, so dass das gesamte Objekt in einem Drawcall ohne Texturwechsel gerendert werden kann.
- An Kanten wo unterschiedliche Teile des Texturatlas zusammentreffen Vertices duplizieren. Das gilt auch dort wo eine Textur komplett um ein Objekt herumgeht. Bei diesem Würfel brauchst du für die mit A texturierten Flächen 10 Eckpunkte, da die Texturkoordinaten von 0 bis 4 gehen sollten, nicht von 0 bis 3 und dann wieder auf 0 (es sei denn die Textur soll zwischendrin gespiegelt werden).
- indizierte Strips mit degenerierten Dreiecken sind in der Regel eine gute Wahl.


Das mit dem Textureatlas ist klar (zumindest in Bezug auf die Texturwechsel). Ja und das mit dem Wrapping der Textur wiederholend um den Würfel drumherum (zusammen mit 10 Eckpunkten) ist jetzt wo Du's sagst auch einleuchtend... und ich dachte schon es gibt eine andere Variante, um die 2 züsätzlichen Vertices (für diesen Fall) zu umgehen. Würde ich aber eine einzige Textur (nicht wiederholend) um den Würfel legen, dann wären ja auch die 2 zusätzlichen Vertices nötig.... (oder reichen in diesem Fall 8 Vertices?)

Für den "Spezialfall" des Würfels bleibt letzendlich nur eine Triangle List auf Basis von 24 Vertices. Ein Triangle Strip würde zwar weniger Indices bedeuten, doch von den 24 mehrfach überlagerten Vertices würden nicht alle korrekt verbunden werden, sondern lediglich 8 von ihnen, sodaß einige als reine UV-Koordinaten verkommen, die selbst nicht einmal verbunden sind... hmmm... aber man kann doch keine Textur über Punkte legen, die zusammen überhaupt keine (Dreiecks-)Fläche definieren... :confused: also dürfte ein Triangle Strip hier keinesfalls zur Anwendung kommen.

Robbson.

Xmas
2006-03-31, 22:47:21
Du kannst auch einen Triangle Strip verwenden, nur lustigerweise sind dafür in diesem Fall genauso 24 Indizes notwendig. Dann ist es besser, Triangle Lists zu verwenden.

Wenn du die A-Textur abwechselnd spiegeln willst, kommst du mit 8 Eckpunkten aus (0, 1, 0, 1). Oder auch (0, 1, 2, 1).

Allerdings würde ich mir erst dann Gedanken um die effizientere Organisation der Vertices machen, wenn diese sich wirklich als bremsend herausstellt.

Robbson
2006-04-01, 17:13:37
Du kannst auch einen Triangle Strip verwenden, nur lustigerweise sind dafür in diesem Fall genauso 24 Indizes notwendig. Dann ist es besser, Triangle Lists zu verwenden.


Ok, dann kann ich das ja mal lassen. ;-)


Allerdings würde ich mir erst dann Gedanken um die effizientere Organisation der Vertices machen, wenn diese sich wirklich als bremsend herausstellt.

Nun ja, bis zur letzten Performance-Optimierung will ich in den Anfängen natürlich noch nicht gehen, allerdings ist ein unperformanter Ausgangspunkt kein guter für spätere Ergänzungen.
Prinzipbedingt wird es in meinen "Leveln" sehr viele koplanare Flächen geben, die bei der Initialisierung am besten noch 'rausgerechnet werden müßten.
Aber als nächstes müssen erstmal Objekte und Texturen her... ohje... alles was mit kreativer und theoretischer Grafik zu tun hat, liegt bei mir ein paar Jährchen in der Vergangenheit und nun ist nicht mehr viel davon übrig. :frown:
Wobei ich mich mit best. Techniken natürlich auch noch garnicht beschäftigt habe. Allerdings motivert die Anwendung zu neuem Streben. :-)

Robbson.