OpenGL in Visual Basic - Transparenz
von Hans Henning Klein
Einleitung
Nachdem wir nun ein wenig praktische Erfahrung im Erstellen von 3D-Objekten gesammelt haben, kommen wir zu dem wohl bekanntesten Spezialeffekt von OpenGL - der Transparenz. Nun ist Transparenz eigentlich kein eigener Effekt. Um Flächen mehr oder weniger durchsichtig zu gestalten, verwenden wir eine Technik, die sich Blending nennt. Genau genommen verwenden wir Alpha-Blending.
Was aber ist Alpha-Blending?
Abbildung 1: Auch wenn es kaum zu erkennen ist: Der Würfel ist hier teilweise durchsichtig!
Grundlagen
Alpha-Blending ist die Addition zweier Farben unter Einbeziehung ihrer Transparenz. Dazu müssen wir unser derzeitiges Farbmodell verändern. Alle Farben, die wir bisher benutzten, hatten das RGB-Format. Nun kommt ein weiterer Wert hinzu - der Alphawert. Die meisten Leute stellen sich den Alphawert einfach als eine Angabe über die Transparenz eines Materials vor. Dieser reicht von 0 (durchsichtig) bis 1 (undurchsichtig). Diese Vorstellung stimmt zwar nicht so ganz genau, wird uns aber zur Zeit genügen. Haben wir bisher unsere Farben mit glColor3f definiert, verwenden wir jetzt glColor4f und hängen als 4. Parameter den Alpha-Wert an. Blending wird in OpenGL recht einfach aktiviert: glEnable glcBlend
Davor müssen wir OpenGL aber noch mitteilen, wie es mit den Flächen umgehen soll, und hier wird es etwas kompliziert.
Alle, die mit Mathematik etwas auf Kriegsfuß stehen, lesen bitte über die Formeln hinweg und testen das Ganze später einfach mit verschiedenen Einstellungen.
Sehen wir uns zuerst an, was OpenGL eigentlich bei eingeschaltetem Blending überhaupt tut.
Die Berechnung läuft nach folgender Formel:
R, G, und B sind die Farbwerte, A ist der Alphawert. Die S-Bezeichner stellen das Pixel der Quelle (Source) und die D-Bezeichner das Pixel des Ziels (Destination) dar. Das Ziel ist dabei keine 3D-Welt, sondern die bis dahin gerenderte Grafik im Puffer.
(Rs Sr + Rd Dr,
Gs Sg + Gd Dg,
Bs Sb + Bd Db,
As Sa + Ad Da)
Vielleicht haben Sie das nicht alles auf Anhieb verstanden, doch das soll uns im Moment nicht weiter stören.
Eigentlich werden nur 4 Werte addiert. Nehmen wir für den Quellbereich einfach den Alpha-Wert der Quelle (neues Pixel) und nennen das As sowie für den Zielbereich 1 - As, dann ergibt sich folgende Formel:
(Rs As + Rd (1 - As),
Gs As + Gd (1 - As),
Bs As + Bs (1 - As),
As As + Ad (1 - As))
Im Ergebnis wird das einen transparenten Effekt haben. Je kleiner der Alpha-Wert der Quelle ist, um so transparenter wird diese dargestellt. Dazu möchte ich hier noch eine Tabelle vorstellen, welche die entsprechenden Konstanten aus OpenGL enthält und aufzeigt, wie diese wirken:
Konstante | Berücksichtigte Faktoren | Berechneter Blend-Faktor |
---|---|---|
GL_ZERO | Source oder Destination | (0, 0, 0, 0) |
GL_ONE | Source oder Destination | (1, 1, 1, 1) |
GL_DST_COLOR | Source | (Rd, Gd, Bd, Ad) |
GL_SRC_COLOR | Destination | (Rs, Gs, Bs, As) |
GL_ONE_MINUS_DST_COLOR | Source | (1, 1, 1, 1)-(Rd, Gd, Bd, Ad) |
GL_ONE_MINUS_SRC_COLOR | Destination | (1, 1, 1, 1)-(Rs, Gs, Bs, As) |
GL_SRC_ALPHA | Source oder Destination | (As, As, As, As) |
GL_ONE_MINUS_SRC_ALPHA | Source oder Destination | (1, 1, 1, 1)-(As, As, As, As) |
GL_DST_ALPHA | Source oder Destination | (Ad, Ad, Ad, Ad) |
GL_ONE_MINUS_DST_ALPHA | Source oder Destination | (1, 1, 1, 1)-(Ad, Ad, Ad, Ad) |
GL_SRC_ALPHA_SATURATE | Source | (f, f, f, 1) / f=min(As, 1-Ad) |
Abbildung 2: Konstanten für Blending
Das erschlägt Sie vermutlich etwas, aber mit ein wenig Experimentieren kommen Sie schnell hinter die Möglichkeiten. An OpenGL übergeben wird das Ganze mit der Funktion glBlendFunc. Diese erwartet als Parameter die Konstanten für Quelle und Ziel.
Bevor wir jetzt endlich so richtig loslegen, noch eine Kleinigkeit:
Transparente Flächen müssen immer zuletzt gerendert werden. Damit nicht genug müssen sie auch noch in der umgekehrten Reihenfolge ihrer Tiefe gezeichnet werden, sonst kommt es zu unschönen Artefakten. Das kann den Spaß an Transparenz ein wenig verderben, lässt sich aber leider nicht ändern.
Praxis
Wir verwenden für ein Beispielprojekt unseren Würfel aus Kapitel 5. Allerdings habe ich die Oberseite, die jetzt transparent werden soll, herausgenommen und mit einer eigenen Textur versehen. Die wenigen neuen Anweisungen stellen keine Herausforderung dar und so ist hier nur der relevante Teil der Sub Main aufgelistet.
glBegin bmQuads 'Ein Würfel ohne Deckel glColor4f 0.5, 0.5, 0.5, 1 'mittel Grau für Ausleuchtung / volles Alpha = undurchsichtig glNormal3f 0#, 1#, 0# 'Normale der Oberseite zeigt positiv entlang der Y Achse glTexCoord2f 1#, 1#: glVertex3f 1#, 1#, -1# 'Oben Rechts (Oberseite) glTexCoord2f 0#, 1#: glVertex3f -1#, 1#, -1# 'Oben Links (Oberseite) glTexCoord2f 0#, 0#: glVertex3f -1#, 1#, 1# 'Unten Links (Oberseite) glTexCoord2f 1#, 0#: glVertex3f 1#, 1#, 1# 'Unten Rechts (Oberseite) glNormal3f 0#, -1#, 0# 'Normale der Unterseite zeigt negativ entlang der Y Achse glTexCoord2f 1#, 1#: glVertex3f 1#, -1#, 1# 'Oben Rechts (Unterseite) glTexCoord2f 0#, 1#: glVertex3f -1#, -1#, 1# 'Oben Links (Unterseite) glTexCoord2f 0#, 0#: glVertex3f -1#, -1#, -1# 'Unten Links (Unterseite) glTexCoord2f 1#, 0#: glVertex3f 1#, -1#, -1# 'Unten Rechts (Unterseite) glNormal3f 0#, 0#, 1# 'Normale der Vorderseite zeigt positiv entlang der Z Achse glTexCoord2f 1#, 1#: glVertex3f 1#, 1#, 1# 'Oben Rechts (Vorderseite) glTexCoord2f 0#, 1#: glVertex3f -1#, 1#, 1# 'Oben Links (Vorderseite) glTexCoord2f 0#, 0#: glVertex3f -1#, -1#, 1# 'Unten Links (Vorderseite) glTexCoord2f 1#, 0#: glVertex3f 1#, -1#, 1# 'Unten Rechts (Vorderseite) glNormal3f 0#, 0#, -1# 'Normale der Rückseite zeigt negativ entlang der Z Achse glTexCoord2f 0#, 0#: glVertex3f 1#, -1#, -1# 'Unten Links (Rückseite) glTexCoord2f 1#, 0#: glVertex3f -1#, -1#, -1# 'Unten Rechts (Rückseite) glTexCoord2f 1#, 1#: glVertex3f -1#, 1#, -1# 'Oben Rechts (Rückseite) glTexCoord2f 0#, 1#: glVertex3f 1#, 1#, -1# 'Oben Links (Rückseite) glNormal3f -1#, 0#, 0# 'Normale der linke Seite zeigt negativ entlang der X Achse glTexCoord2f 1#, 1#: glVertex3f -1#, 1#, 1# 'Oben Rechts (Links) glTexCoord2f 0#, 1#: glVertex3f -1#, 1#, -1# 'Oben Links (Links) glTexCoord2f 0#, 0#: glVertex3f -1#, -1#, -1# 'Unten Links (Links) glTexCoord2f 1#, 0#: glVertex3f -1#, -1#, 1# 'Unten Rechts (Links) glEnd glBindTexture GL_TEXTURE_2D, Texture(2) 'Auswahl der gewünschten Textur glBlendFunc GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA 'Alpha-Blending für einfache Transparenz glEnable glcBlend 'Blending einschalten glBegin bmQuads 'Deckel glColor4f 1#, 1#, 1#, 0.2 'volle Ausleuchtung und 80% transparent glNormal3f 1#, 0#, 0# 'Normale der rechten Seite zeigt positiv entlang der X Achse glTexCoord2f 1#, 1#: glVertex3f 1#, 1#, -1# 'Oben Rechts (Rechts) glTexCoord2f 0#, 1#: glVertex3f 1#, 1#, 1# 'Oben Links (Rechts) glTexCoord2f 0#, 0#: glVertex3f 1#, -1#, 1# 'Unten Links (Rechts) glTexCoord2f 1#, 0#: glVertex3f 1#, -1#, -1# 'Unten Rechts (Rechts) glEnd 'Ende des Deckels glDisable glcBlend 'Blending ausschalten
Listing 1: Transparente Flächen erzeugen
Es geht weiter
Das waren die Grundlagen zum Alpha-Blending. Damit ist das Thema Blending allerdings noch lange nicht erschöpft. Blending kann auch auf Grundlage der RGB-Werte betrieben werden und macht viele exzellente Effekte mit übereinander liegenden Texturen möglich. Darauf werde ich aber erst in einem späteren Kapitel genauer eingehen. Im Kapitel 7 verlassen wir die fest im Quellcode verankerten Objekte und sehen, wie man dynamische Welten kreiert.
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.