Direct 3D für 2D

 

Direct3D für 2D Spiele? Warm eigetntlich?Für 2D-Spiele gibt es doch DirectDraw? Diese Frage stellen sich, glaube ich, einige von euch und die Antwort ist simpel. Direct3D bietet im Gegensatz zu DirectDraw die volle Funktionspalette des 3D-Beschleunigers, war DirectDraw bisher nur auf das Anzeigen von Grafiken beschränkt, kann man mit Direct3D z.B. Sprites rotieren (drehen) oder gar transparent darstellen. Hier eine Liste von Funktionen die man mit Direct3D realisieren kann:

Schon allein durch den Alphablendingeffekt, werden einem Tausende neuer Möglichkeiten eröffnet.

 

texturierte Polygone

Nun da ich euch nun so "heiß" auf Direct3D gemacht habe, wäre es wohl erwähnenswert, dass die Handhabung ein wenig schwieriger ist, als bei DirectDraw. Hier erst mal die Schritte, die man benötigt, um ein Sprite in Direct3D darzustellen.

  1. DirectDraw initialisieren
  2. Direct3D initialisieren
  3. Textur laden
  4. zwei Dreicke zeichnen und die Textur zuweisen
  5. Flip durchführen

 

Der 4. Punkt ist wohl der wichtigste von Allen. 1. und 2. sind je in den Tutorials Direct Draw Tutorial und Direct3D - Initialisierung beschrieben. Also fangen wir bei 3. an.

 

Textur laden

Das Laden einer Textur unterscheidet sich ein wenig im Laden eines normal Surfaces. Zu beachten ist, dass die Ausmaße des Bitmap eine Potenz von 2 Darstellen, also z.B. 2, 4, 16, 32, 64, 128, 256... usw. . Mögliche Auflösungen sind also z.B. 256x256, 32x64 oder 32x256. Aber Vorsicht, einige Grafikkarten unterstützen Texturen bis zu einer Auflösung von 512x512, deswegen empfehle ich diese Auflösung nicht zu überschreiten. Ok, hier also der etwas abgeänderte Code zum Laden eines Textur-Surface:

Dim ddsTextur As DirectDrawSurface7
Dim SurfaceDesc As DDSURFACEDESC2
'surfaceDESC festlegen (Surface wird als Textur verwendet)
    SurfaceDESC.lFlags = DDSD_CAPS Or DDSD_HEIGHT Or DDSD_WIDTH
    SurfaceDESC.ddsCaps.lCaps = DDSCAPS_OFFSCREENPLAIN Or DDSCAPS_VIDEOMEMORY
    SurfaceDESC.lWidth = 512
    SurfaceDESC.lHeight = 256
    'ein paar Texurflags setzten
    If Device3D.GetDeviceGuid() = "IID_IDirect3DHALDevice" Then 'für Hardware
            SurfaceDESC.ddsCaps.lCaps = DDSCAPS_TEXTURE
            SurfaceDESC.ddsCaps.lCaps2 = DDSCAPS2_TEXTUREMANAGE
            SurfaceDESC.lTextureStage = 0
    Else 'für Software
            SurfaceDESC.ddsCaps.lCaps = DDSCAPS_TEXTURE
            SurfaceDESC.ddsCaps.lCaps2 = 0
            SurfaceDESC.lTextureStage = 0
    End If
    'Surface erstellen
    Set ddsTextur = DDraw.CreateSurfaceFromFile("C:\Test.bmp", SurfaceDESC)

 

Dreicke zeichenen und die Textur zuweisen

 

Nun das Wichtigste! Wie bekomme ich ein rechteckiges Sprite in 3D hin? Alles muss also aus Dreiecken bestehen, also muss ein Rechteck mit 2 Dreiecken erzeugt werden. Das Bild veranschaulicht die Theorie:

 

Demnach müssten wir ja eigentlich 6 Vertexe angeben, für jedes Dreieck drei. Das geht auch, aber Direct3D, bietet Möglichkeiten dies zu vereinfachen. Eigentlich wäre es sowieso viel einfacher, wenn wir nur vier Vertexe angeben würden (für die vier Ecken des Rechtecks). Also um es etwas zu beschleunigen ;) , wir müssen ein sogennantes TRIANGLESTRIP zeichnen. In solch einem TRIANGLESTRIP, werden dann die restlichen Vertexe automatisch ergänzt, wir müssen lediglich nur die Randvertexe angeben. Die Punkte müssen in folgender reihenfolge "gezechnet" werden:

 

In Worten: Oben links, oben rechts, unten links, unten rechts. Hier erst mal der Quellcode:

Dim Vertex(3) As D3DTLVERTEX 'Das Vertex Array
Dim vColor As Long 'Farbwert für den Vertex
Dim AlphaValue As Double 'Alphawert (für Transparenz)

AlphaValue= 0.5 '1=undurchsichtig... bis ...0=durchsichtig
vColor = dx.CreateColorRGBA(1, 1, 1, AlphaValue)

dx.CreateD3DTLVertex 10, 20, 0, 1, vColor, 1, 0, 0, Vertex(0)
dx.CreateD3DTLVertex 20, 20, 0, 1, vColor, 1, 1, 0, Vertex(1)
dx.CreateD3DTLVertex 10, 10, 0, 1, vColor, 1, 0, 1, Vertex(2)
dx.CreateD3DTLVertex 20, 10, 0, 1, vColor, 1, 1, 1, Vertex(3)

Device3D.SetTexture 0, ddsTextur
Device3D.DrawPrimitive D3DPT_TRIANGLESTRIP, D3DFVF_TLVERTEX, Vertex(0), 4, D3DDP_DEFAULT

In der ersten Zeile, wird ein Array aus 4 Vertexen (0 bis 3) deklariert. Ganz wichtig! Hierbei muss es sich um ein D3DTLVERTEX handeln, warum das erkläre ich in einem späteren Tutorial, soviel vorraus ein TLVERTEX ist optimal zum Anzeigen von Sprites. Die vColor-Variable enthält schließlich eine Farbe, die für jeden Vertex festgelegt werden kann (so kann man manuell Licht- und Spezialeffekte erstellen). Hier jedoch wird vColor durch dx.CreateColorRGBA auf Weiß festgelegt. Der Wert in AlphaValue legt hier die Transparenz des Surfaces fest (der Wert kann von 0 bis 1 gehen). Wir erstellen hier also, z.B. ein halbtransparentes Sprite (0.5 ist ja die hälfte von 1 :) ). Jetzt das Wichtigste! Mit dx.CreateD3DTLVertex, wird ein Vertex erzeugt der dann in dem Vertexarray an einer bestimmten Stelle abgelegt wird. Also z.B. Vertex(0) ist gleich dem Punkt links oben usw. . Mit Device3D-SetTexture wird unser geladenes Textursurface als Textur für die nachfolgende Zeichenoperation verwendet. Mit DrawPrimitive, wird dann unser besagtes TRIANGLESTRIP gezeichnet, es wird hierbei das Vertexarray,Vertex(0) und die Anzahl der enthaltenen Vertexe, vier, angegeben. So das wars, nur noch ein Flip und das ganze ist auf dem Bildschirm.

 

Wer nix verstanden hat oder Hilfe braucht, der lade sich bitte das Sourcecodebeispiel herunter: D3d_basic.zip


Autor: Alexander Ney / Mehr Tutorials auf www.vb-overkill.de.vu