Die Community zu .NET und Classic VB.
Menü

OpenGL in Visual Basic - Formen und Farben

 von 

Grundlagen 

Nachdem wir mit viel Aufwand ein wenig beeindruckendes schwarzes Fenster erzeugt haben, kommen wir nun zu den ersten Formen und damit zu den Grundflächen, aus denen jede 3D-Welt besteht. Eigentlich besteht jede 3D-Welt nur aus dreieckigen Flächen; in der Grafikprogrammierung oft einfach als Polygone bezeichnet. Selbst die komplexen Welten von z.B. Unreal Tournament bestehen "nur" aus Tausenden von Dreiecken. Anhand diverser Daten der Vertices (Eckpunkte) eines Dreiecks, sowie der Beleuchtung, Textur und Oberflächeneigenschaften berechnet die Grafikengine für jedes Pixel dessen Farbe.
Bevor Sie jetzt das nackte Grauen packt, wir werden später lernen, dass OpenGL auch komfortable Möglichkeiten hat, komplexe Figuren darzustellen. Aber für den Anfang ist es wichtig, dass Sie den Umgang mit den einfachsten Grundformen einer 3D-Welt verstehen.

Um zu wissen, wie Grafiken in 3D dargestellt werden, sehen wir uns zuerst das Koordinatensystem an. Jeder Punkt (oder Eckpunkt einer Fläche) wir durch 3 Koordinaten definiert: X für waagerecht, Y für senkrecht und Z für die Tiefe. Der Mittelpunkt unserer 3D-Welt mit den Koordinaten 0,0,0 ist dabei in der Mitte des Bildschirms. Die Z-Koordinate wird von OpenGL umgerechnet, damit alle Objekte in der richtigen Reihenfolge auf dem flachen Bildschirm dargestellt werden.


Abbildung 1: Das (rechtshändige) Koordinatensystem von OpenGL

Formen  

Wie bereits in der Einführung besprochen, werden alle Zeichenoperationen in der Endlos-Schleife erzeugt, in der das Programm läuft. Daher ändern wir in diesem Kapitel nur die Sub Main und zeichnen ein einfaches Dreieck und ein einfaches Viereck in unser Fenster:

Public Sub Main()
   Dim frm As Form
 
   PrgRun = True 'Flag = das Programm läuft
   Set frm = New Form1 'Fenster für OpenGL-Ausgabe
   frm.ScaleMode = vbPixels 'das Fenster muss zwingend in Pixel bemessen werden
 
   If CreateGLWindow(frm, 640, 480, 16) Then 'Fenster initialisieren
      Do 'Endlosschleife, in der das Fenster laufend gelöscht und neu aufgebaut wird.
         'Die Laufzeit dieser Schleife ist ausschlaggebend, wieviele Objekt gezeichnet werden können
         glClear clrColorBufferBit Or clrDepthBufferBit ' löscht das Fenster und den Tiefenpuffer
         glLoadIdentity 'setzt die aktuelle Modell-Matrix zurück
 
'--- neuer Code seit der Einführung ---
 
'ab hier zeichnen wir ein Dreieck in unser Fenster
         glTranslatef -1.5, 0#, -6#  'Setzt den neuen Zeichenpunkt. Ab dieser Koordinate werden nun alle Zeichenoperationen berechnet
         'Das heißt wir verschieben den Punkt um 1,5 Einheiten nach Links und 6 Einheiten "in den Bildschirm"
 
         glBegin bmTriangles 'Anfang eines Dreiecks
            glVertex3f 0#, 1#, 0# 'obere Ecke
            glVertex3f -1#, -1#, 0# 'untere linke Ecke
            glVertex3f 1#, -1#, 0# 'untere rechte Ecke
         glEnd 'Ende des Dreiecks
 
         glTranslatef 3#, 0#, 0# 'Zeichenpunkt um 3 Einheiten nach rechts verschieben
 
         glBegin bmQuads 'Anfang eines Vierecks
            glVertex3f -1#, 1#, 0# 'linke obere Ecke
            glVertex3f 1#, 1#, 0# 'rechte obere Ecke
            glVertex3f 1#, -1#, 0# 'untere rechte Ecke
            glVertex3f -1#, -1#, 0# 'untere linke Ecke
         glEnd 'Ende des Vierecks
 
'--- Ende neuer Code seit der Einführung
 
         SwapBuffers (frm.hDC) 'Puffer tauschen (Double Buffering)
         DoEvents
      Loop While PrgRun 'Programm nur beenden, wenn PrgRun = False
      'PrgRun ist Global definiert und wird im KeyDown-Ereignis von Form1 bei drücken von Escape gesetzt.
      'alles freigeben und Programm beenden
      If hrc <> 0 Then 'hatten wir einen Gerätekontext für OpenGL?
         wglMakeCurrent 0, 0 'Freigeben des Gerätekontexts
         wglDeleteContext (hrc) 'Freigeben des Renderingkontexts
      End If
      Unload frm
      Set frm = Nothing
      End
   End If
End Sub

Listing 1: Sub Main für einfache Polygone

Wenn Sie das Fenster vergrößern, werden Sie feststellen, dass die gezeichneten Formen die Größenänderung mitmachen.
Das sind nun keine einfachen Grafiken mehr sondern Objekte in einer 3D-Welt, deren Darstellung von ihrer relativen Größe in dieser Welt und dem Abstand der Kamera (des Beobachters) abhängt.

Farben  

Kommen wir nun zu den Farben. Die Farben werden im RGB-Format angegeben. Im Gegensatz zu VB sind die Werte nicht von 0 bis 255 sondern von 0 bis 1 definiert. OpenGL verwendet immer die zuletzt definierte Farbe als Zeichenfarbe. Daher müssen wir für ein einfarbiges Objekt die Farbe auch nur einmal setzen.

Public Sub Main()
   Dim frm As Form
 
   PrgRun = True 'Flag = das Programm läuft
   Set frm = New Form1 'Fenster für OpenGL-Ausgabe
   frm.ScaleMode = vbPixels 'das Fenster muss zwingend in Pixel bemessen werden
 
   If CreateGLWindow(frm, 640, 480, 16) Then 'Fenster initialisieren
      Do 'Endlosschleife in der das Fenster laufend gelöscht und neu aufgebaut wird.
         'Die Laufzeit dieser Schleife ist ausschlaggebend, wieviele Objekt gezeichnet werden können
         glClear clrColorBufferBit Or clrDepthBufferBit ' löscht das Fenster und den Tiefenpuffer
         glLoadIdentity 'setzt die aktuelle Modell-Matrix zurück
 
'--- neuer Code seit der Einführung ---
 
'ab hier zeichnen wir ein Dreieck in unser Fenster
         glTranslatef -1.5, 0#, -6#  'Setzt den neuen Zeichenpunkt. Ab dieser Koordinate werden nun alle Zeichenoperationen berechnet
         'Das heißt, wir verschieben den Punkt um 1,5 Einheiten nach Links und 6 Einheiten "in den Bildschirm"
 
         glBegin bmTriangles 'Anfang eines Dreiecks
            glColor3f 1#, 0#, 0# 'setzt die Zeichenfarbe auf Rot
            glVertex3f 0#, 1#, 0# 'obere Ecke
            glColor3f 0#, 1#, 0# 'setzt die Zeichenfarbe auf Grün
            glVertex3f -1#, -1#, 0# 'untere linke Ecke
            glColor3f 0#, 0#, 1# 'setzt die Zeichenfarbe auf Blau
            glVertex3f 1#, -1#, 0# 'untere rechte Ecke
         glEnd 'Ende des Dreiecks
 
         glTranslatef 3#, 0#, 0# 'Zeichenpunkt um 3 Einheiten nach rechts verschieben
 
         glColor3f 0.7, 0.7, 1#   'setzt die Zeichenfarbe einmal auf Hellblau für alle Ecken
         glBegin bmQuads 'Anfang eines Vierecks
            glVertex3f -1#, 1#, 0# 'linke obere Ecke
            glVertex3f 1#, 1#, 0# 'rechte obere Ecke
            glVertex3f 1#, -1#, 0# 'untere rechte Ecke
            glVertex3f -1#, -1#, 0# 'untere linke Ecke
         glEnd 'Ende des Vierecks
 
'--- Ende neuer Code seit der Einführung
 
         SwapBuffers (frm.hDC) 'Puffer tauschen (Double Buffering)
         DoEvents
      Loop While PrgRun 'Programm nur beenden, wenn PrgRun = False
      'PrgRun ist Global definiert und wird im KeyDown-Ereignis von Form1 bei drücken von Escape gesetzt.
      'alles freigeben und Programm beenden
      If hrc <> 0 Then 'hatten wir einen Gerätekontext für OpenGL?
         wglMakeCurrent 0, 0 'Freigeben des Gerätekontexts
         wglDeleteContext (hrc) 'Freigeben des Renderingkontexts
      End If
      Unload frm
      Set frm = Nothing
      End
   End If
End Sub

Listing 2: Sub Main für farbige Polygone


Abbildung 2: Die Arbeit trägt erste Früchte...

Es geht weiter  

Manche werden sich jetzt zu Recht fragen, ob später jedes von mehreren hundert Objekten so in der Sub Main hinterlegt werden muss. Dem ist natürlich nicht so, aber zum besseren Verständnis lassen wir das jetzt mal noch so.
Im 2. Kapitel beginnen wir dann endlich mit echtem 3D, drehen Flächen im Raum und erstellen erste 3D-Objekte.

Beispielprojekt  

Beispielprojekt zum Tutorial [193998 Bytes]

Ihre Meinung  

Falls Sie Fragen zu diesem Tutorial haben oder Ihre Erfahrung mit anderen Nutzern austauschen möchten, dann teilen Sie uns diese bitte in einem der unten vorhandenen Themen oder über einen neuen Beitrag mit. Hierzu können sie einfach einen Beitrag in einem zum Thema passenden Forum anlegen, welcher automatisch mit dieser Seite verknüpft wird.