www.jammni.de

Logo - Kleiner Drache

Logo - Drache3.1. VertexBuffer erstellen

Home >> Tutorials >> DirectX 9−Tutorial
 

Vertices

Wie die Überschrift schon vermuten lässt, werden wir uns zuerst mit den Vertices beschäftigen. Vertices ist zunächst einmal der Plural von Vertex - deswegen auch VertexBuffer. Aber was ist nun ein Vertex. Ein Vertex ist vom Prinzip her ein Punkt im Raum, an dem sich zwei Kanten treffen (z. B. die Spitze eines Dreiecks). Das heißt, ein Vertex hat zumindest drei Raumkoordinaten (x, y, z). Das ist aber noch nicht alles. In Direct3D kann ein Vertex noch viele weitere Eigenschaften haben, so zum Beispiel eine Farbe oder Texturinformationen.

Vertex-Formate

Genau für diese Zwecke sind in DirectX verschiedene Strukturen definiert, da nicht zwangsläufig alle Angaben enthalten sein müssen. In der folgenden Tabelle sind einige Strukturen aufgeführt und mit einer kleinen Erklärung der Unterschiede versehen. Doch zunächst noch eine kleine Beschreibung der dort gebrauchten Begriffe:
 
Abbildung eines Koordinatensystems mit einer eingezeichneten Ebene und dem Normalenvektor 3D-Koordinaten:
3D-Koordinaten heißt, dass der Vertex mindestens drei Felder für die x-, y- und z-Koordinate hat. Dabei handelt es sich um Raumkoordinaten, die noch nicht in für den Bildschirm passende Koordinaten umgewandelt wurden.
Normale:
Die Normale ist die Gerade, die man senkrecht auf eine Ebene stellen könnte, so dass sie immer einen Rechten Winkel zu der Ebene einnimmt (siehe Bild links). Die Normale kann ebenso für Geraden und Punkte konstruiert werden.
PositionOnly Enthält nur die 3D-Koordinaten des Vertex.
PositionNormal Enthält die 3D-Koordinaten sowie die Richtungsangabe der Normale.
PositionColor Enthält die 3D-Koordinaten sowie eine Farbe für den Vertex.
PositionTextured Enthält die 3D-Koordinaten sowie Texturinformationen.
Transformed Enthält die an die Bildschirmausgabe angepassten Koordinaten sowie den RHW-Parameter (wird für Nebel etc. benötigt).
Tabelle1: Einige Vertex-Formate

Es gibt natürlich noch einige weitere Formate, deren Funktion sich an Hand der Tabelle aber recht einfach erschließen sollte. Außerdem gibt es noch die Möglichkeit, eigene VertexBuffer-Formate zu definieren.

Aktualisierung der InitializeGraphics-Methode

In der InitializeGraphics-Methode hat sich natürlich einiges getan. Hier noch einmal der Code-Ausschnit:

Listing 5.1 - VertexBuffer.cs:
11:    VertexBuffer vertexBuffer = null;
    ...
21:    public bool InitializeGraphics()
22:    {
23:      try
24:      {
25:        // Die Hardware initialisieren und ein paar Parameter setzen
26:        PresentParameters presentParams = new PresentParameters();
27:        presentParams.Windowed=true;
28:        presentParams.SwapEffect = SwapEffect.Discard;
29:        device = new Device(0, DeviceType.Hardware, this, CreateFlags.SoftwareVertexProcessing, presentParams);
30:        vertexBuffer = new VertexBuffer(typeof(CustomVertex.TransformedColored), 6, device, 0, CustomVertex.TransformedColored.Format, Pool.Default);
31:        vertexBuffer.Created += new System.EventHandler(this.OnCreateVertexBuffer);
32:        this.OnCreateVertexBuffer(vertexBuffer, null);
33:        return true;
34:      }
35:      catch (DirectXException)
36:      {
37:        return false;
38:      }
39:    }

In Zeile 11 wurde zunächst ein Objekt vom Typ VertexBuffer deklariert, welches später die Vertices für das Quadrat enthalten wird. In Zeile 30 wird das Objekt dann schließlich erstellt. Das Objekt bekommt dabei 6 Parameter übergeben.

VertexBuffer können immer nur Vertices eines Typs enthalten - und diesen Typ geben wir mit dem ersten Parameter an. Der zweite Parameter gibt an, wieviele Vertices der Buffer maximal aufnehmen kann. Normalerweise ist dies auch gleich der Anzahl der tatsächlich gespeicherten Vertices. Der dritte Parameter ist der Gerätekontext und der vierte Parameter besteht aus zahlreichen Flags zur Vertexverarbeitung. Von diesen zahlreichen Optionen brauchen wir aber erstmal keine. Wer mehr Interesse hat, sollte sich an dieser Stelle die SDK-Hilfe zu Gemüte ziehen.
An fünfter Stelle wird nocheinmal der Typ der Vertices übergeben. Das liegt daran, dass man auch eigene Vertex-Strukturen definieren kann. Also nicht wundern, dass es zweimal vorkommt. Und der letzte Parameter beschäftigt sich noch mit der Speicherung der Vertices. In unserem Fall reicht aber der Standardwert Pool.Default.

In Zeile 31 wird noch ein EventHandler erstellt, der OnCreateVertexBuffer nach der Erstellung aufruft. Selbiges passiert auch einmal von Hand in der darauf folgenden Zeile.

VertexBuffer befüllen

So, dass wars eigentlich auch schon zur Erstellung des VertexBuffers. Aber wir wollen den VertexBuffer auch gleich mal noch mit Daten füttern. Dazu noch einmal folgender Codeausschnitt zur Erinnerung:
 
Darstellung der Vertex am Beispiel eines Quadrates
Listing 5.2 - VertexBuffer.cs:
41:      public void OnCreateVertexBuffer(object sender, EventArgs e)
42:      {
43:        VertexBuffer vertexBuffer = (VertexBuffer)sender;
44:        GraphicsStream stm = vertexBuffer.Lock(0, 0, 0);
45:        CustomVertex.TransformedColored[] verts = new CustomVertex.TransformedColored[6];
46:    
47:        verts[0].X = 50;
48:        verts[0].Y = 50;
49:        verts[0].Z = 0.5f;
50:        verts[0].Rhw = 1;
51:        verts[0].Color = System.Drawing.Color.Blue.ToArgb();
        ...
72:        verts[5].X = 50;
73:        verts[5].Y = 250;
74:        verts[5].Z = 0.5f;
75:        verts[5].Rhw = 1;
76:        verts[5].Color = System.Drawing.Color.Lime.ToArgb();
77:        stm.Write(verts);
78:        vertexBuffer.Unlock();
79:      }
  In Zeile 44 erstellen wir eine Referenz auf einen GraphicStream, indem wir den VertexBuffer vor Veränderungen von anderer Stelle sperren. Die drei Parameter geben dabei Anfang und Größe des zu sperrenden Bereichs an sowie einige weitere Flags. 0 an zweiter Stelle sperrt den ganzen VertexBuffer.
Anschließend wird ein CustomVertex.TransformedColored-Array erstellt, welches die Informationen zu einzelnen Vertices enthalten wird. Dieses Array wird anschließend befüllt. Die X, Y und Z-Parameter geben natürlich die bereits in Bildschirmkoordinaten übersetzen Koordinaten des Objekts an. Rhw wird passend auf 1 gesetzt (wird mal wieder nicht benötigt) und Color gibt noch die Farbe des Vertex an. Zwischen je zwei verbundenen Vertices werden dann später die Farben ineinander übergeblendet.
In Zeile 77 wird das Array dann noch in den VertexBuffer geschrieben um anschließend noch die Sperre des VertexBuffers aufzuheben.

Im nächsten Unterkapitel werden wir dann den VertexBuffer auf den Bildschirm zaubern - also wieder schnell weiterlesen.