{
Haha, diese beiden Lektionen wurden schon vor langer Zeit übersetzt, aber sie wurden noch nicht veröffentlicht. Alle haben schon lange gewartet (Wartet jemand noch länger?)
einfache Transparenz
Die überwiegende Mehrheit der Spezialeffekte in OpenGL hängt mit irgendeiner Art von (Farb-)Mischung zusammen.
Unter Farbmischung versteht man das Kombinieren der Farbe eines bestimmten Pixels mit der Farbe des entsprechenden auf dem Bildschirm gezeichneten Pixels.
Wie die beiden Farben kombiniert werden, hängt von den Werten der Alphakanalkomponenten der Farbe und/oder der verwendeten Farbmischfunktion ab.
Alpha ist normalerweise die 4. Farbkomponente am Ende des Farbwerts.
In den vorherigen Lektionen haben wir GL_RGB verwendet, um die drei Farbkomponenten anzugeben.
Der entsprechende GL_RGBA kann den Wert der Alpha-Komponente angeben.
Um noch einen Schritt weiter zu gehen, können wir glColor4f() anstelle von glColor3f() verwenden.
Die meisten Menschen sind sich einig, dass die Alpha-Komponente die Transparenz eines Materials darstellt.
Dies bedeutet, dass ein Alpha-Wert von 0,0 ein Material darstellt, das vollständig transparent ist.
Ein Alpha-Wert von 1,0 stellt ein Material dar, das völlig undurchsichtig ist.
Farbmischformel
Wenn Sie sich nicht für Mathematik interessieren und einfach nur sehen möchten, wie Sie Transparenz erreichen, überspringen Sie diesen Abschnitt.
Wenn Sie tiefer verstehen möchten, wie (Farb-)Mischung funktioniert, ist dieser Abschnitt genau das Richtige für Sie.
『CKERs Zusatz: Es ist eigentlich nicht schwierig^-^. Die Formel im Originalartikel lautet wie folgt. Lassen Sie CKER noch einmal darüber sprechen.
Tatsächlich besteht das Grundprinzip des Mischens darin, die Farbe jedes Pixels und die Hintergrundfarbe des zu trennenden Bildes gemäß den RGB-Regeln zu trennen.
Gemäß - RGB-Farbkomponente des Bildes * Alphawert + RGB-Farbkomponente des Hintergrunds * (1-Alpha-Wert)
- Nach dem Mischen mit einer so einfachen Formel werden die durch Mischen erhaltenen RGB-Komponenten schließlich wieder zusammengeführt. 』
Die Formel lautet wie folgt:
(Rs Sr + Rd Dr, Gs Sg + Gd Dg, Bs Sb + Bd Db, As Sa + Ad Da)
OpenGL berechnet das Farbmischungsergebnis dieser beiden Pixel gemäß der obigen Formel.
Die Kleinbuchstaben s und r repräsentieren Quellpixel bzw. Zielpixel. Die Großbuchstaben S und D sind die entsprechenden Farbmischungsfaktoren.
Diese bestimmen, wie Sie die Farben für diese Pixel mischen.
In den meisten Fällen sind die Alpha-Mischwerte jedes Farbkanals gleich.
Auf diese Weise haben wir (As, As, As, As) für das Quellpixel,
Die Zielpixel sind 1, 1, 1, 1) – (As, As, As, As).
Die obige Formel wird wie folgt:
(Rs As + Rd (1 - As), Gs As + Gd (1 - As), Bs As + Bs (1 - As), As As + Ad (1 - As))
Diese Formel erzeugt einen transparenten/transluzenten Effekt.
Farbmischung in OpenGL
Die Schritte zum Implementieren der Farbmischung in OpenGL ähneln dem zuvor erwähnten OpenGL-Prozess.
Legen Sie dann die Formel fest und deaktivieren Sie den Schreibtiefen-Cache beim Zeichnen transparenter Objekte.
Weil wir das Objekt hinter einer halbtransparenten Form zeichnen möchten.
Dies ist nicht die richtige Art, Farben zu mischen, aber bei einfachen Projekten funktioniert es meistens gut.
Rui Martins‘ Ergänzung: Der richtige Farbmischungsprozess sollte darin bestehen, zuerst die gesamte Szene zu zeichnen und dann die transparenten Grafiken zu zeichnen.
Und sie werden in umgekehrter Reihenfolge des Tiefenpuffers gezeichnet (die am weitesten entfernten Objekte werden zuerst gezeichnet).
Erwägen Sie die Alpha-Überblendung zweier Polygone (1 und 2). Unterschiedliche Zeichenreihenfolgen führen zu unterschiedlichen Ergebnissen.
(Hier wird davon ausgegangen, dass Polygon 1 dem Beobachter am nächsten liegt. Der korrekte Prozess sollte dann zuerst Polygon 2 und dann Polygon 1 zeichnen.
Wie Sie in der Realität sehen können,
Das Licht, das hinter diesen beiden <transparenten> Polygonen kommt, passiert immer zuerst Polygon 2.
Anschließend durchläuft es Polygon 1 und erreicht schließlich das Auge des Betrachters. )
Wenn Tiefen-Caching aktiviert ist, sollten Sie transparente Grafiken nach Tiefe sortieren.
Und zeichnen Sie diese transparenten Objekte, nachdem alle Szenen gezeichnet wurden. Andernfalls erhalten Sie falsche Ergebnisse.
Ich weiß, dass es manchmal schmerzhaft ist, dies zu tun, aber es ist der richtige Weg, es zu tun.
Wir verwenden den Code aus Lektion 7.
Fügen Sie zunächst zwei neue Variablen am Anfang des Codes hinzu. Aus Gründen der Übersichtlichkeit habe ich den gesamten Code umgeschrieben.
}
Var
h_RC: HGLRC; // Rendering-Kontext (Schattierungsbeschreibungstabelle).
h_DC: HDC; // Gerätekontext (Gerätebeschreibungstabelle)
h_Wnd: HWND; // Fensterhandle
h_Instance: HINST; // Programminstanz (Instanz).
Tasten: Array[0..255] Of Boolean; // Array für Tastaturroutinen
Licht: Boolean; // Lichtquelle ein/aus
blend : Boolean; // Blending AUS/EIN (neu)
lp : Boolean; // Ist die L-Taste gedrückt?
fp : Boolean; // Ist die F-Taste gedrückt?
bp : Boolean; // Ist die B-Taste gedrückt (Neu)
xrot : GLfloat; // X-Rotation
yrot: GLfloat; // Y-Rotation
xspeed : GLfloat; // X-Rotationsgeschwindigkeit
yspeed: GLfloat; // Y-Rotationsgeschwindigkeit
z: GLfloat = -5,0 f; // Abstand tief in den Bildschirm hinein
LightAmbient: Array[0..3] Of GLfloat = (0.5, 0.5, 0.5, 1.0); //Umgebungslichtparameter (neu)
LightDiffuse: Array[0..3] Of GLfloat = (1.0, 1.0, 1.0, 1.0); // Diffuse Lichtparameter (neu)
LightPosition: Array[0..3] Of GLfloat = (0.0, 0.0, 2.0, 1.0); // Lichtquellenposition (neu)
filter: GLuint; // Filtertyp
Textur: Array[0..2] Of GLuint; // Speicherplatz für 3 Texturen
PROcedure glGenTextures(n: GLsizei; Var Textures: GLuint);
opengl32;
Prozedur glBindTexture(target: GLenum; texture: GLuint);
opengl32;
Funktion gluBuild2DMipmaps(target: GLenum; Components, width, height: GLint;
Format, atype: GLenum; Daten: Pointer): Integer; externer Glu32-Name
'gluBuild2DMipmaps';
{
Fahren Sie dann mit LoadGLTextures() fort.
Finden Sie heraus, ob (TextureImage[0]=LoadBMP('Data/Crate.bmp'))
Diese Zeile. Wir verwenden jetzt eine getönte Glastextur anstelle der Holzkistentextur aus der vorherigen Lektion.
if (TextureImage[0]=LoadBMP("Data/glass.bmp")); // Glas-Bitmap laden (geändert)
}
Funktion LoadTexture: boolean; //Bitmap laden und in eine Textur umwandeln
Var
Status: boolean; // Statusanzeige
TextureImage: Array[0..1] Of PTAUX_RGBImageRec; // Texturspeicherplatz erstellen
Beginnen
Status := false;
ZeroMemory(@TextureImage, sizeof(TextureImage)); // Zeiger auf NULL setzen
TextureImage[0] := LoadBMP('Walls.bmp');
Wenn TextureImage[0] <> Null, dann
Beginnen
Status := TRUE; // Status auf TRUE setzen
glGenTextures(1, Texture[0]); // Textur erstellen
// Nächste Filterkarte erstellen
glBindTexture(GL_TEXTURE_2D, Textur[0]);
// Textur erzeugen
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, 3, TextureImage[0].sizeX,
TextureImage[0].sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE,
TextureImage[0].data);
glBindTexture(GL_TEXTURE_2D, textur[1]); //Verwende eine typische Textur, die aus Bitmap-Daten generiert wird
// Textur erzeugen
glTexImage2D(GL_TEXTURE_2D, 0, 3, TextureImage[0].sizeX,
TextureImage[0].sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE,
TextureImage[0].data);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); // Lineare Filterung
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // Lineare Filterung
//MipMapped-Textur erstellen
glBindTexture(GL_TEXTURE_2D, Textur[2]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
GL_LINEAR_MIPMAP_NEAREST); // (neu)
gluBuild2DMipmaps(GL_TEXTURE_2D, 3, TextureImage[0].sizeX,
TextureImage[0].sizey, GL_RGB, GL_UNSIGNED_BYTE,
TextureImage[0].data); //(neu) }
Ende;
Wenn zugewiesen(TextureImage[0]) Dann // Ob die Textur existiert
Wenn zugewiesen(TextureImage[0].data) Dann // Ob das Texturbild vorhanden ist
TextureImage[0].data := Nil; // Den vom Texturbild belegten Speicher freigeben
TextureImage[0] := Nil; // Bildstruktur freigeben
Ergebnis := Status; // Rückgabestatus
Ende;
{
Fügen Sie die folgenden zwei Zeilen zum glInit()-Codeabschnitt hinzu.
Die erste Linie zeichnet dieses Objekt mit voller Helligkeit und verleiht ihm eine Alpha-Überblendung von 50 % (halbtransparent).
Wenn die Mischoption aktiviert ist, ist dieses Objekt zu 50 % transparent.
Die zweite Zeile legt die Art der verwendeten Mischung fest.
Hinzugefügt von Rui Martins:
Ein Alphakanalwert von 0,0 bedeutet, dass das Material des Objekts vollständig transparent ist.
1,0 bedeutet völlig undurchsichtig.
}
Prozedur glInit(); // Hier alle Einstellungen für OpenGL starten
Beginnen
If (Not LoadTexture) Then // Rufen Sie die Unterroutine zum Laden der Textur auf
exit; // Wenn das Laden fehlschlägt, beenden
glEnable(GL_TEXTURE_2D); // Texturzuordnung aktivieren
glShadeModel(GL_SMOOTH); // Schattenglättung aktivieren
glClearColor(0.0, 0.0, 0.0, 0.0); // schwarzer Hintergrund
glClearDepth(1.0); //Setze den Tiefenpuffer
glEnable(GL_DEPTH_TEST); // Tiefentest aktivieren
glDepthFunc(GL_LESS); // Art des durchgeführten Tiefentests
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); //Hochoptimierte perspektivische Projektionsberechnung
glLightfv(GL_LIGHT1, GL_AMBIENT, @LightAmbient[0]); // Umgebungslicht einstellen
glLightfv(GL_LIGHT1, GL_DIFFUSE, @LightDiffuse[0]); // Diffuses Licht einstellen
glLightfv(GL_LIGHT1, GL_POSITION, @LightPosition); // Lichtquellenposition
glEnable(GL_LIGHT1); // Lichtquelle Nr. 1 aktivieren
glColor4f(1.0, 1.0, 1.0, 0.5); // Volle Helligkeit, 50 % Alpha-Blending (neu)
glBlendFunc(GL_SRC_ALPHA, GL_ONE); // Durchscheinende Mischfunktion basierend auf dem Alphakanalwert des Quellpixels (neu)
Ende;
{Suchen Sie gegen Ende von Lektion 7 den folgenden Codeausschnitt.
Wenn Tasten[VK_LEFT] Dann //Wird die linke Richtungstaste gedrückt?
yspeed := yspeed - 0,01; //Wenn ja, yspeed reduzieren
Nach dem obigen Code fügen wir den folgenden Code hinzu.
Diese Leitungen überwachen, ob die B-Taste gedrückt wird.
Wenn ja, prüft der Computer, ob die Mischoption aktiviert ist.
Stellen Sie es dann auf den entgegengesetzten Zustand ein.
}
If (keys[ord('B')] And Not bp) Then //Die B-Taste wird gedrückt und bp ist FALSE?
Beginnen
bp := TRUE; // Wenn ja, wird bp auf TRUE gesetzt
blend := Nicht mischen; // Mischoptionen auf TRUE / FALSE umstellen
If (blend) Then // Ist die Mischung aktiviert?
Beginnen
glEnable(GL_BLEND); // Blending einschalten
glDisable(GL_DEPTH_TEST); // Tiefentests ausschalten
Ende
Sonst // sonst
Beginnen
glDisable(GL_BLEND); // Blending ausschalten
glEnable(GL_DEPTH_TEST); // Tiefentest einschalten
Ende;
Ende;
If (Not keys[ord('B')]) Then // Wird die B-Taste losgelassen?
Beginnen
bp := FALSE; // Wenn ja, setze bp auf FALSE
Ende;
{
Aber wie können Sie die Farbe der Mischung festlegen, wenn Sie Texture Mapping verwenden? Das ist ganz einfach.
Beim Anpassen des Texturmodus wird die Farbe jedes Pixels der Texturtextur durch den Alphakanalparameter bestimmt.
Wird durch Multiplikation der aktuellen Pixelfarbe erhalten.
Die gezeichnete Farbe ist beispielsweise (0,5, 0,6, 0,4).
Wir multiplizieren die Farben miteinander, um (0,5, 0,6, 0,4, 0,2) zu erhalten.
(Wenn der Alpha-Parameter nicht angegeben ist, ist er standardmäßig Null).
Das ist es! Die Implementierung von Alpha Blending in OpenGL ist in der Tat sehr einfach!
}
{
Originalnotiz (13.11.99)
Mein (NeHe) Farbmischcode wurde geändert, um die angezeigten Objekte realistischer aussehen zu lassen.
Wenn Sie den Alpha-Parameter zum gleichzeitigen Mischen der Quellpixel und Zielpixel verwenden, werden die künstlichen Spuren des Objekts offensichtlich.
Dadurch erscheint die Rückseite des Objekts an den Seiten dunkler.
Im Grunde wird das Objekt seltsam aussehen.
Die Farbmischmethode, die ich verwendet habe, ist vielleicht nicht die beste, aber sie funktioniert.
Wenn die Beleuchtung aktiviert ist, sehen Objekte realistisch aus.
Vielen Dank an Tom für die Bereitstellung des Originalcodes. Die von ihm verwendete Farbmischmethode ist korrekt.
Aber das Objekt sieht nicht so attraktiv aus wie erwartet :)
Der Code wurde aufgrund der Behebung von Problemen mit der glDepthMask()-Funktion auf einigen Grafikkarten erneut geändert.
Dieser Befehl scheint beim Aktivieren oder Deaktivieren des Tiefenpuffertests auf einigen Karten nicht sehr effektiv zu sein.
Deshalb habe ich den Code zum Aktivieren oder Deaktivieren des Tiefenpuffertests in die altmodischen Versionen glEnable und glDisable umgewandelt.
Alpha-Blending von Textur-Maps
Der für die Textur-Map verwendete Alpha-Parameter kann ebenso wie die Farbe aus der Problem-Map abgelesen werden.
Die Methode ist wie folgt: Sie müssen das erforderliche Material laden und gleichzeitig seinen Alpha-Parameter erhalten.
Verwenden Sie dann das Farbformat von GL_RGBA, wenn Sie glTexImage2D() aufrufen.
}