www.jammni.de

Logo - Kleiner Drache

Logo - Drache3.2. Rendern der Vertex-Daten

Home >> Tutorials >> DirectX 9−Tutorial
 

Rendern der Dreiecke

Die Dreicke, welche wir zeichnen wollen, wurden im letzten Kapitel definiert. Jetzt müssen sie nur noch zur Anzeige gebracht werden. Schauen wir uns also dazu mal die geänderte Render-Methode etwas näher an:

Listing 5.3 - VertexBuffer.cs:
81:      private void Render()
82:      {
83:        if (device == null)
84:          return;
85:    
86:        // Backbuffer löschen und gleichzeitig die Zeichenfläche blau einfärben
87:        device.Clear(ClearFlags.Target, System.Drawing.Color.Black, 1.0f, 0);
88:        // Anfang der Szene
89:        device.BeginScene();
90:    
91:        device.SetStreamSource( 0, vertexBuffer, 0);
92:        device.VertexFormat = CustomVertex.TransformedColored.Format;
93:        device.DrawPrimitives(PrimitiveType.TriangleList, 0, 2);
94:    
95:        // Ende der Szene
96:        device.EndScene();
97:        device.Present();
98:      }

 
  Die erste neue Zeile ruft die Methode SetStreamSource() auf. Diese macht eigentlich nichts anderes, als dem Gerät mitzuteilen, dass es seine Vertex-Daten aus zweiten Parameter beziehen soll. Der erste Parameter gibt die Nummer des Streams an und der letzte Parameter gibt nur noch ein Offset an, ab dem erst die Vertex-Daten zu erwarten sind. Bei uns beginnen sie natürlich gleich am Anfang des VertexBuffers, deswegen also 0.

Die nächste Zeile teilt dem Gerät die Art der Vertices mit, damit die Daten richtig interpretiert werden. Und da es ja mehrere VertexBuffer im Programm geben kann, die noch dazu auch unterschiedliche Formate haben können, ist es recht ratsam, diesen Aufruf auch gleich direkt danach abzusetzen.

Und in Zeile 93 wird die Methode DrawPrimitive() aufgerufen. Diese Methode ist für das Zeichnen der Dreiecke zuständig. Sie bekommt drei Parameter, der erste gibt die grob gesagt die Art und Weise an, wie die Dreicke gezeichnet werden sollen. Doch dazu gibts gleich eine größere Erläuterung. Der zweite Parameter gibt den Eintrag des ersten Vertex an, ab dem die Dreiecke gerendert werden sollen. Naja und wie nicht anders zu erwarten war, gibt der letzte Parameter an, wieviele Dreiecke gerendert werden sollen.
Und als Ergebnis sind jetzt die beiden Dreiecke zu sehen, deren Eckfarben sanft ineinander übergeblendet werden.

Primitve-Types

Die Primitive-Types geben an, wie die Daten aus dem Vertex-Buffer zum Rendern interpretiert werden. In Direct3D gibt es mehrere vordefinierte Arten:

TriangleFan Zeichnet einen Fächer aus Dreiecken.
TriangleStrip Zeichnet eine Schlange bestehend aus Dreicken.
TriangleList Zeichnet voneinander unabhängige Dreiecke.
LineStrip Zeichnet eine zusammenhängende Linie (mit Knicken).
LineList Zeichnet voneinander unabhängige Linien.
PointList Zeichnet einzelne Punkte.
Tabelle2: Primitive-Types

Darstellung einer PointList

PointList

Eine PointList besteht, wie der Name schon sagt, aus einzelnen Punkten. In diesem Fall wird jeder Eintrag des VertexBuffers als separater Punkt gerendert. In den Bildern links steht V immer für einen Eintrag im VertexBuffer. V0 bezeichnet dabei den ersten Eintrag, V1 den zweiten Eintrag, usw.
Der dritte Parameter der DrawPrimitives()-Methode gibt die Anzahl der zu zeichnenden Punkte an.
 
Darstellung einer LineList

LineList

LineList verhält sich analog zu PointList, nur mit dem Unterschied, dass hier einzelne, voneinander unabhängige Linien gezeichnet werden. Damit Direct3D hier keinen Fehler meldet, muss die Anzahl der zu zeichnenden Vertices immer eine gerade Zahl sein.
Hier gibt der dritte Parameter der DrawPrimitives()-Methode natürlich die Anzahl der zu zeichnenden Linien an - und nicht die Anzahl der enthaltenen Vertices.
 
Darstellung eines LineStrip

LineStrip

LineStrip zeichnet eine zusammenhängende Linie. Die Linie wird dabei zunächst zwischen V0 und V1 gezeichnet. Als nächstes wird die Linie von V1 zu V2 gezeichnet, dann von V2 zu V3, usw. Diese Struktur ist also effizienter im Speicherumgang, wenn eine zusammenhängende Linie gezeichnet werden soll.
Der dritte Parameter der DrawPrimitives()-Methode gibt hier die Anzahl der zu zeichnenden Linienabschnitte ein. Die Anzahl der Vertices im VertexBuffer ist damit natürlich auch schon festgeschrieben. Sie muss eins größer sein, als die Anzahl der zu zeichnenden Linien.
 
Darstellung einer TriangleList

TriangleList

Eine TriangleList enthält für jedes Dreieck je drei Vertices. Die Dreiecke werden unabhängig von einander gezeichnet.
Der dritte Parameter der DrawPrimitives()-Methode gibt in diesem Fall die Anzahl der Dreiecke an - also ein Drittel der Anzahl der benutzten Vertices.
Bei der Definition der Dreiecke ist zu beachten, dass diese nur sichtbar sind, wenn sie im Uhrzeigersinn definiert wurden. Dreiecke, deren Vertices entgegen dem Uhrzeigersinn definiert wurden, werden also nicht angezeigt (und damit nicht gerendert). Dieser Vorgang des Aussortierens wird als Culling bezeichnet und in jedem Frame ausgeführt. Je nach Betrachtungsposition werden dabei unterschiedliche Dreiecke aussortiert. Über die RenderState.CullMode-Eigenschaft des Device-Objekts kann dieses Verhalten jedoch geändert werden. Zur Wahl stehen drei Werte:
  • CounterClockwise (Default-Wert)
    Sortiert Dreiecke aus, dessen Rückseite zum Benutzer zeigt.
  • Clockwise
    Sortiert die Dreiecke aus, deren Vorderseite zum Benutzer zeigt.
  • None
    Sortiert keine Dreiecke aus.

Darstellung eines TriangleStrip

TriangleStrip

Ein TriangleStrip ist ein Streifen, der aus mehreren Dreiecken besteht. Dabei teilt jedes Dreieck (ausgenommen das Erste) zwei seiner Vertices mit dem vorhergehenden Dreick.
Der dritte Parameter der DrawPrimitives()-Methode gibt auch in diesem Fall die Anzahl der Dreiecke an - also Anzahl der Vertices - 2.
Die interne Drehrichtung jedes zweiten Dreiecks wird beim Rendern aber umgedreht. Nur dadurch ist es möglich, dass alle Dreiecke angezeigt werden können und nicht jedes zweite Dreieck dem Culling-Prozess zum Opfer fällt. Im Bild links sind deshalb die Richtungen für die Definition der Dreiecke wieder mit eingezeichnet.
 
Darstellung eines TriangleFan

TriangleFan

Der TriangleFan spannt einen Fächer von Dreiecken auf. Dabei besteht jedes Dreieck (ausgenommen wieder das erste Dreieck) aus dem ersten Vertex, einem neuen Vertex und einem Vertex vom vorhergehenden Dreieck. Das Bild links veranschaulicht das ganze mal ein bisschen.
Der dritte Parameter der DrawPrimitives()-Methode gibt auch in diesem Fall die Anzahl der Dreiecke an - also Anzahl der Vertices - 2.
Auch hier ist wieder auf die Richtung der Vertex-Definitionen zu achten.