Categories: Sonstiges

Wie Sie einen Einstieg in die Arbeit mit Frame-Buffers finden.

Der Begriff „Frame Buffer“ bezieht sich traditionell auf den Speicherbereich, der die Farbdaten für das auf einem Computerbildschirm angezeigt Bild enthält. In WebGL ist ein Frame-Buffer eine Datenstruktur, welche die Speicherressourcen organisiert, die für die Darstellung eines Bildes benötigt werden. Ein WebGL-Grafikkontext hat einen Standard-Frame-Buffer, der für das Bild verwendet wird, das auf dem Bildschirm erscheint. Der Standard-Frame-Buffer wird durch den Aufruf von canvas.getContext() erzeugt, der den Grafikkontext erstellt. Seine Eigenschaften hängen von den Optionen ab, die an diese Funktion übergeben werden und können nach der Erstellung nicht mehr geändert werden. Es können jedoch zusätzliche Frame-Buffer erstellt werden, deren Eigenschaften vom WebGL-Programm gesteuert werden. Sie können für das Off-Screen-Rendering verwendet werden und sie werden für bestimmte erweiterte Rendering-Algorithmen benötigt.

Ein Framebuffer kann einen Color-Buffer verwenden, um die Farbdaten für ein Bild zu speichern, einen Depth-Buffer, um einen Tiefenwert für jedes Pixel zu speichern und einen sogenannten Stencil-Buffer. Die Buffer sollen mit dem Frame-Buffer „verbunden“ sein. Für einen nicht standardmäßigen Frame-Buffer können die Buffer vom WebGL-Programm jederzeit angehängt und entfernt werden. Ein Frame-Buffer benötigt nicht den vollen Satz von drei Buffern, aber Sie benötigen einen Color-Buffer, einen Depth Buffer oder beides, um den Frame-Buffer für das Rendern verwenden zu können. Wenn der Depth-Test beim Rendern in den Frame-Buffer nicht aktiviert ist, dann ist kein Depth-Buffer erforderlich. Zudem verwenden einige Rendering-Algorithmen wie z.B. das Shadow-Mapping einen Frame-Buffer mit einem Depth-Buffer, aber keinen Color-Buffer.

Die Rendering-Funktionen gl.drawArrays() zbd gl.drawElements() beeinflussen den aktuellen Frame-Buffer, der zunächst der Standard-Frame-Buffer ist. Der aktuelle Frame-Buffer kann durch Aufruf von

Copy to Clipboard

verändert werden. Der erste Parameter dieser Funktion ist immer gl.FRAMEBUFFER. Der zweite Parameter kann Null sein, um den Standard-Framebuffer für das Zeichnen auszuwählen oder es kann ein nicht standardmäßiger Frame-Buffer sein, der durch die Funktion gl.createFramebuffer () erstellt wurde, die im Folgenden erläutert wird.

Frame-Buffer-Operationen.

Bevor wir zu Beispielen für die Verwendung von nicht-standardmäßigen Framebuffern kommen, schauen wir uns einige WebGL-Einstellungen an, die das Rendern in den jeweils aktuellen Frame-Buffer beeinflussen. Beispiele, die wir bereits gesehen haben, sind die klare Farbe, die verwendet wird, um den Farbpuffer zu füllen, wenn gl.clear() aufgerufen wird und der aktivierte Zustand des Depth Tests.

Ein weiteres Beispiel, das die Verwendung des Depth Buffers beeinflusst, ist die Depth-Maske, ein boolescher Wert, der steuert, ob beim Rendern Werte in den Depth Buffer geschrieben werden. (Der aktivierte Zustand des Depth-Tests bestimmt, ob beim Rendern Werte aus dem Depth Buffer verwendet werden. Die Depth-Maske bestimmt, ob neue Werte in den Depth Buffer geschreiben werden.) Das Schreiben in den Depth Buffer kann mit dem Befehl

Copy to Clipboard

und durch den Aufruf von gl.depthMask (true) wieder eingeschaltet werden. Der Standardwert ist true.

Ein Beispiel für die Verwendung der Depth-Masks ist das Rendern von transzulenter Geometrie. Wenn einige der Objekt in einer Szene lichtdurchlässig sind, sollten zuerst alle undurchsichtigen Objekte gerendert werden, gefolgt von den lichtdurchlässigen Objekten. (Angenommen, Sie haben ein transzulentes und anschließend ein opakes Objekt gerendert, das hinter dem transzulenten Objekt liegt. Der Depth-Test würde dazu führen, dass das opake durch das transzulente Objekt verdeckt wird. Aber transzulent bedeutet, dass das opake Objekt durch das transzulente Objekt sichtbar sein sollte. Daher ist es wichtig, zuerst alle undurchsichtigen Objekte zu rendern. Und es ist wichtig, das Schreiben in den Depth-Buffer auszuschalten, indem Sie gl.depthMask (false) aufrufen, während Sie die transparenten Objekte rendern. Der Grund dafür ist, dass ein durchsichtiges Objekt, das hinter ein andere durchsichtiges Objekt gezeichnet wird, durch das vordere Objekt gezeichnet wird, durch das vordere Objekt sichtbar sein sollte. Beachten Sie jedoch, dass der Depth-Test während des Renderns der transzulenten Objekte noch aktiviert werden muss, da ein transzulentes Objekt durch ein opakes Objekt ausgeblendet werden kann. Außerdem muss das Alpha-Blending eingeschaltet sein, während die transparenten Objekte gerendert werden.

Für eine vollständig korrekte Darstellung von transzulenten Objekten sollten die transzulenten Primitive vor dem Rendern in die Reihenfolge von hinten nach vorne sortiert werden. Das kann jedoch schwierig zu implementieren sein und akzeptable Ergebnisse lassen sich manchmal erzielen, wenn man die transzulenten Primitive in beliebiger Reihenfolge rendert.

Es ist auch möglich, das Schreiben in den Color-Buffer über die Color-Maks zu steuern. Der Color-Buffer hat vier „Kanäle“, die den roten, grünen, blauen und Alpha-Komponenten der Farbe entsprechen. Jeder Kanal kann separat gesteuert werden. Sie können z.B. das Schreiben auf dem roten und den Alpha-Farbkanal erlauben, während Sie das Schreiben auf den grünen und blauen Kanal blockieren. Dies geschieht mit dem Befehl

Copy to Clipboard

Die Funktion colorMask benötigt vier Parameter, einen für jeden Farbkanal. Ein wahrer Wert erlaubt das Schreiben in den Kanal, ein falscher Wert blockiert das Schreiben. Wenn beim Rendern das Schreiben für einen Kanal blockiert wird, wird der Wert der entsprechenden Farbkomponente einfach ignoriert.

Eine Verwendung der Color-Mask ist für die anaglyphen Stereowiedergabe. Ein Anaglyphen-Stereobild enthält zwei Bilder der Szene, eines für das linke und eines für das rechte Auge. Ein Bild wird nur in Rottöne gezeichnet, während das andere nur Kombinationen aus Grün und Blau verwendet. Die beiden Bilder werden aus leicht unterschiedlichen Blickwinkeln gezeichnet, entsprechend den Ansichten des linken und rechten Auges. Der Algorithmus für Anaglyphen-Stereo hat also die Form

Copy to Clipboard

Eine Möglichkeit, die Ansichten von den linken und rechten Augen einzurichten, besteht darin, die Ansicht einfach um einige Grade um die y-Achse zu drehen. Beachten Sie, dass der Depth Buffer, aber nicht der Color-Buffer, vor dem Zeichnen des zweiten Bildes gelöscht werden muss, da sonst der Depth-Test das Schreiben einiger Teile des zweiten Bildes verhindern würde.

Abschließend möchten wir auf das Blending ein wenig näher eingehen. Blending bezieht sich darauf, wie die Fragment-Farbe aus dem Fragment-Shader mit der aktuellen Farbe des Fragments im Color-Buffer kombiniert wird. Die Voreinstellung, vorausgesetzt, dass das Fragment den Depth-Test besteht, ist, due aktuelle Farbe durch die Fragmentfarbe zu ersetzen. Wenn das Überblenden aktiviert ist, kann die aktuelle Farbe durch eine Kombination aus der aktuellen Farbe und der Fragmentfarbe ersetzt werden, Früher haben wir nur darüber gesprochen, das Alpha-Blending für Transparenz mit den Befehlen einzuschalten.

Copy to Clipboard

Die Funktion gl.blendFunc() bestimmt, wie die neue Farbe aus der aktuellen Farbe und der Fragmentfarbe berechnet wird. Mit den hier gezeigten Parametern lautet die Formel für die neue Farbe in GLSL-Syntax wie folgt

Copy to Clipboard

wobei src die „Quell“-Farbe ist (d.h. die Farbe, die geschrieben wird, die Fragmentfarbe) und dest die „Zielfarbe“ ist (d.h. die Farbe, die sich derzeit im Color-Buffer befindet, was das Ziel des Rendervorgangs ist. Und src.a ist die Alpha-Komponente der Quellfarbe. Die Parameter von gl.blendFunc() bestimmen die Koeffizienten . Src.a und (1-src.a) – in der Formel. Die Standardkoeffizienten für die Blending-Funktion sind gegeben durch

Copy to Clipboard

die die Formel angibt.

Copy to Clipboard

Das heißt, die neue Farbe ist gleich der Quellfarbe, es gibt keine Überblendung. Andere Koeffizientenwerte sind möglich, aber wir werden sie hier nicht verwenden.

Beachten Sie, dass das Blending sowohl für die Alpha- als auch für die RGB-Komponenten der Farbe gilt, was wahrscheinlich nicht das ist, was Sie wollen. Wenn Sie mit einer durchsichtigen Farbe zeichnen, bedeutet dies, dass die Farbe, die in den Color-Buffer geschrieben wird, eine Alpha-Komponente von weniger als 1 aufweist, was beim Rendern auf einem Canvas auf einer Website den Canvas selbst durchsichtig macht und den Hintergrund des Canvas durchscheinen lässt. (Dies setzt voraus, dass der WebGL-Kontext mit einem Alpha-Kanal erstellt wurde, was der Standard ist). Um dies zu vermeiden, können Sie die Blending-Funktion mit dem alternativen Befehl einstellen.

Copy to Clipboard

Die beiden zusätzlichen Parameter spezifizieren separate Koeffizienten, die für die Alpha-Komponente in der Formel verwendet werden sollen, während die ersten beiden Parameter nur für die RGB-Komponenten verwendet werden. Das heißt, die neue Farbe für den Color-Buffer wird nach folgender Formel berechnet.

Copy to Clipboard

Bei dieser Formel bleibt die Alpha-Komponente im Ziel (der Color-Buffer) gleich wie ihr Ausgangswert.

Die durch gl.blendFunc (gl.ONE, gl.ONE) erstellte Blending-Funktion kann manchmal in Multipass-Algorithmen verwendet werden. In einem Multi-Pass-Algorithmus wird eine Szene mehrmals gerendert und die Ergebnisse werden irgendwie kombiniert, um das endgültige Bild zu erzeugen. (Anaglyphen-Stereo-Rendering ist ein Beispiel.) Wenn Sie einfach nur die Ergebnisse der verschiedenen Durchläufe addieren wollen, dann können Sie den Color-Buffer mit Nullen füllen, das Blending aktivieren und die Blend-Funktion während des Renderns auf (gl.ONE, gl.ONE) einstellen.

Als einfaches Beispiel verwendet das Beispielprogramm webgl/image-blur.html einen Multi-Pass-Algorithmus zur Implementierung der Unschärfe. Die Szene im Beispiel ist nur ein Texturbild, das auf ein Rechteck angewendet wird, so dass der Effekt darin besteht, das Texturbild zu verwischen. Die Technik besteht darin, die Szene neunmal zu zeichnen. Im Fragment-Shader wird dir Farbe durch neun geteilt. Das Blending wird verwendet, um die Fragmentfarben aus den neuen Durchgängen hinzuzufügen, so dass die endgültige Farbe im Color-Buffer der Durchschnitt der Farben aus den neun Durchgängen ist. Bei acht der neun Durchgänge ist die Szene leicht von ihrer usprünglichen Position versetzt, so dass die Farbe eines Pixels im Endbild der Mittelwert der Farben dieses Pixels und der umgebenden Pixel der urspünglichen Szene ist.

Rendern der Textur.

Der vorherige Unterabschnitt gilt für jeden Frame-Buffer. Aber wir haben noch keinen nicht-standardmäßigen Frame-Buffer verwendet. Wir wenden uns nun diesem Thema zu.

Eine Verwendung für einen nicht standardmäßigen Frame-Buffer ist das direkte Rendern in eine Textur. Das heißt, der von einem Texturbild belegte Speicher kann als Color-Buffer an den Frame-Buffer angehängt werden, so dass Renderingoperationen ihren Output an das Texturbild senden. Die Technik, die als Render-to-Texture bezeichnet wird, wird im Beispielprogramm web.gl/render-to-texture.html verwendet.

Der Texturspeicher wird normalerweise zugewiesen, wen ein Bild mit der Funktion gl.texImage2D oder gl.copyTexImage2D in die Textur geladen wird. Es gibt jedoch eine Version von gl.texImage2D, mit der man Speicher allokieren kann, ohne ein Bild in diesen Speicher zu laden. Hier ist ein Beispiel aus dem Beispielprogramm:

Copy to Clipboard

Es ist der Null-Parameter am Ende der letzten Zeile, der gl.texImage2D anweist, neuen Speicher zuzuweisen, ohne vorhandene Bilddaten zu laden, um diesen Speicher zu füllen. Stattdessen wird der neue Speicher mit Nullen gefüllt. Der erste Parameter von gl.texImage3D ist das Texturziel. Das Ziel ist gl.TEXTURE_2D für normale Texturen, aber andere Werte werden für die Arbeit mit Cubemap-Texturen verwendet. Der vierte und fünfte Parameter bestimmen die Höhe und Breite des Bildes. Sie sollten die Potenz von zwei sein. Die anderen Parameter haben in der Regel die hier gezeigten Werte. Beachten Sie, dass das Texturobjekt zuerst erstellt und gebunden werden muss. Gl.texImage2D gilt für die Textur, die aktuell an die aktive Textureinheit gebunden ist.
Um die Textur an einen Frame-Buffer anzuhängen, müssen Sie ein Frame-Buffer-Objekt erstellen und dieses Objekt durch Bindung zum aktuellen Frame-Buffer machen. Zum Beispiel,

Copy to Clipboard

Dann kann mit der Funktion gl.framebufferTexture2D die Textur an den Frame-Buffer angehängt werden:

Copy to Clipboard

Der erste Parameter ist immer gl.FRAMEBUFFER. Der zweite Parameter besagt, dass ein Color-Buffer angehängt wird. (Das letzte Zeichen in gl.Color_ATTACHMENT0 ist eine Null, was die Möglichkeit bietet, mehr als einen Color-Buffer an einen Frame-Buffer anzuhängen. Im Standard WebGL 1.0 ist nur ein Color-Buffer erlaubt.) Der dritte Parameter ist das gleiche Texturziel, das in gl.texIMage2D verwendet wurde und der vierte ist das Texturobjekt. Der letzte Parameter ist die Mipmap-Ebene. Sie ist in der Regel Null, was bedeutet, dass das Rendern auf das Texturbild selbst und nicht auf eines seiner Mipmap-Bilder erfolgt.
Mit diesem Setup bist du bereit, den Frame-Buffer zu binden und an die Textur zu zeichnen. Nachdem Sie die Textur gezeichnet haben, rufen Sie den Befehl

Copy to Clipboard

um wieder mit dem Zeichnen im Standard-Frame-Buffer zu beginnen. Die Textur ist bereit für den Einsatz bei nachfolgenden Renderingoperationen. Das Texturobjekt kann an eine Textureinheit gebunden werden und eine Sampler2D-Variable kann im Shader-Programm verwendet werden, um aus der Textur zu lesen. Sie werden sehr wahrscheinlich verschiedene Shaderprogramme verwenden, um an die Textur und auf dem Bildschirm zu zeichnen. Erinnern Sie sich daran, dass die Funktion gl.useProgram() verwendet wird, um das Shader-Programm anzugeben.
Im Beispielprogramm wird die Textur animiert und für jeden Frame der Animation ein neues Bild in die Textur zeichnet. Das Texturbild ist 2D, so dass der Depth-Test während des Rendern deaktiviert wird. Das bedeutet, dass der Frame-Buffer keinen Depth-Buffer benötigt. In Kurzform hat die Rendering-Funktionim Beispielprogramm die Form

Copy to Clipboard

Beachten Sie, dass das Ansichtsfenster von Hand eingestellt werden muss, wenn Sie in einen nicht standardmäßigen Frame-Buffer zeichnen. Es muss dann beim Zeichnen des On-Screen-Bildes zurückgesetzt werden, um die Größe des Canvas, auf der das On-Screen-Bild gerendert wird, zu erreichen. Wir sollten auch beachten, dass in diesem Programm nur ein Texturobjekt verwendet wird, so dass es während der Initialisierung ein für allemal gebunden werden kann. In diesem Fall ist es nicht notwendig, gl.bindTexture() in der draw() Funktion aufzurufen.

Dieses Beispiel könnte ohne Frame-Buffer implementiert werden. Die Version, die wir hier umsetzen werden, wird effizient sein, da sie das Bild nach dem Rendern nicht kopieren müssen.

Render-Buffer.

Es ist oft sinnvoll, Speicher aus einem Texturobjekt als Color-Buffer für einen Frame-Buffer zu verwenden. Manchmal ist es jedoch sinnvoller, einen separaten Speicher für den Puffer zu erstellen, der keiner Textur zugeordnet ist. Für den Depth Buffer ist das der typische Fall. Für solche Fälle kann der Speicher als Render-Buffer angelegt werden. Ein Render-Buffer repräsentiert einen Speicher, der an einen Frame-Buffer angehängt werden kann, um als Color , Depth oder Stencil Buffer verwendet zu werden. Um einen solchen zu verwenden, müssen Sie den Render-Buffer erstellen und Speicher für ihn allokieren. Die Speicherzuweisung erfolgt über die Funktion gl.renderbufferStorage(). Der Renderbuffer muss durch den Aufruf von gl.bindRenderbuffer() gebunden werden, bevor der Speicher allokiert wird. Hier ist ein Beispiel, das einen Renderbuffer für die Verwendung als Depth Buffer erstellt:

Copy to Clipboard

Der erste Parameter für gl.bindRenderbuffer und gl.renderbufferStorage muss gl.RENDERBUFFER sein. Der zweite Parameter zu gl.renderbufferStorage gibt an, wie der Render-Buffer verwendet wird. Der Wert gl.Depth_COMPONENT16 ist für einen Depth Buffer mit 16 Bit für jedes Pixel. Für einen Color-Buffer, der RGBA-Farben mit vier Acht-Bit-Werten pro Pixel enthält, wäre der zweite Parameter gl.RGB4. Andere Werte sind möglich, wie gl.RGB565, das 16 Bit pro Pixel mit 5Bit für den roten Farbkanal, 6 Bit für Grün und 5 Bit für Blau verwendet. Für einen Stencil-Buffer wäre der Wert gl.STENCIL_INDEX8. Die letzten beiden Parameter von gl.renderbufferStorage sind die Breite und Höhe des Buffers.

Die Funktion gl.framebufferRenderbuffer() wird verwendet, um einen Renderbuffer anzuhängen, der als einer der Buffer in einem Framebuffer verwendet werden soll. Es hat die Form

Copy to Clipboard

Der Framebuffer muss durch den Aufruf von gl.bindFramebuffer gebunden werden, bevor diese Funktion aufgerufen wird. Der erste und dritte Parameter von gl.framebufferRenderbuffer müssen abgebildet werden. Der letzte Parameter ist der Renderbuffer. Der zweite Parameter gibt an, wie der Renderbuffer verwendet wird. Es kann gl.COLOR_ATTACHMENT0, gl.DEPTH_ATTACHMENT oder gl.STENCIL_ATTACHMENT sein.

Dynamische Cubemap-Texturen.

Um eine 3D-Szene in einen Framebuffer zu rendern, benötigen wir sowohl einen Color-Buffer als auch einen Depth-Buffer. Ein Beispiel finden Sie im Beispielprogramm webgl/cube-camera.html. In diesem Beispiel wird Render-to-Texture für eine Cubemap-Textur verwendet. Die Cubemap-Textur wird dann als Environment Map auf einer reflektierenden Oberfläche verwendet. Zusätzlich zur Environmental Map verwendet das Programm eine weitere Cubemap-Textur für eine Skybox.

Die Umgebung beinhaltet in diesem Fall die Hintergrund-Skybox, aber auch mehrere farbige Würfel, die nicht Teil der Skybox-Textur sind. Die reflektierende Kugel in der Mitte des Bildes reflektiert sowohl die Würfel als auch die Skybox, was bedeutet, dass die Textur der Environment Map nicht die gleiche sein kann wie die Textur der Skybox – sie muss die Würfel beinhalten. Darüber hinaus kann die Szene animiert werden und die Würfel können sich bewegen. Die Reflexion in der Kugel muss sich mit der Bewegung der Würfel verändern. Das bedeutet, dass die Textur der Environment Map in jedem Frame neu erstellt werden muss. Dazu können wir einen Frame-Buffer verwenden, um in die Cubemap-Textur zu rendern.

Eine Cubemap-Textur besteht aus sechs Bildern, jeweils eines für die positive und negative Richtung der x-, y- und z-Achse. Jedes Bild ist einem anderen Texturziel zugeordnet (ähnlich gl.TEXTURE_2D). Um eine Cubemap zu erstellen, müssen wir Speicher für alle sechs Seiten bereitstellen. Hier ist der Code aus dem Beispielprogramm:

Copy to Clipboard

Wir müssen auch einen Frame-Buffer sowie einen Render-Buffer für die Verwendung als Depth-Buffer erstellen und wir müssen den Depth Buffer an den Frame Buffer anhängen. Der gleiche Frame Buffer kann verwendet werden, um alle sechs Bilder für die Textur darzustellen, wobei die Color-Buffer-Befestigung des Frame-Buffers nach Bedarf geändert wird. Um eines der sechs Cubemap-Bilder als Color-Buffer anzuhängen, geben wir einfach das entsprechende cubemap-Texturziel im Aufruf von gl.framebufferTexture2D() an. Beispielsweise wird der Befehl

Copy to Clipboard

das negative z-Bild aus dem Texturobjekt dynamicsCubemap anhängen, das als Color-Buffer im aktuell gebundenen Frame-Buffer verwendet werden soll.

Nachdem die sechs Texturbilder gerendert wurden, ist die Cubemap-Textur einsatzbereit. Abgesehen davon, dass sechs 3D-Bilder anstelle eines 2D-Bildes gerendert werden, ist dies alles sehr ähnlich dem Render-to-Texture-Beispiel.

Die Frage bleibt, wie man die sechs Bilder der Szene rendert, die für die Cubemap-Textur benötigt werden. Um eine Environment Map für ein reflektierendes Objekt zu erstellen, benötigen wir Bilder der Umgebung, die dieses Objekt umgibt. Die Bilder können mit einer Kamera aufgenommen werden, die sich in der Mitte des Objekts befindet. Die Grundidee ist, die Kamera in die sechs Richtungen der positiven und negativen Koordinatenachsen zu richten und ein Bild in jede Richtung aufzunehmen, aber es ist schwierig, die Details korrekt darzustellen. (Und beachten Sie, dass, wenn wir das Ergebnis auf einen Punkt auf der Oberfläche anwenden, wir nur eine Annäherung an die richtige Reflexion haben. Für eine geometrisch korrekte Reflexion an diesem Punkt bräuchten wir die Ansicht von genau diesem Punkt aus, nicht die Ansicht aus der Mitte des Objekts, aber wir können nicht realistisch eine andere Environment Map für jeden Punkt auf der Oberfläche erstellen. Die Annäherung sieht gut aus, solange andere Objekte in der Szene nicht zu nahe an der reflektierenden Oberfläche sind.)

Eine „Kamera“ bedeutet in Wirklichkeit eine Projektionstransformation und eine Viewing-Transformation. Die Projektion benötigt ein Sichtfeld von neunzig Grad, um eine Seite des Würfels abzudecken und sein Seitenverhältnis ist 1, da die Seiten des Würfels quadratisch sind. Wir können die Projektionsmatrix mit einem glMatrix-Befehl erstellen, wie z.B.

Copy to Clipboard

wobei die letzten beiden Parameter, der Nah- und Fernbereich, so gewählt werden sollten, dass alle Objekte in der Szene einbezogen werden. Wenn wir keine Viewing Transformation anwenden, befindet sich die Kamera im Ursprung und zeigt in Richtung der negativen z-Achse. Wenn das reflektierende Objekt den Ursprung hat, wie es sich im Beispielprogramm befindet, können wir die Kamera ohne Viewing Transformation verwenden, um das Negativ-Z-Bild für die Cubemap-Textur aufzunehmen.

Aber wegen der Details, wie die Bilder für Cubemap-Texturen gespeichert werden müssen, stellt sich heraus, dass wir eine einzige Transformation anwenden müssen.

Die sechs Seiten des Würfels sind schwarz dargestellt, als ob die Seiten des Würfels geöffnet und flach ausgelegt wären. Jede Seite ist mit der entsprechenden Koordinatenachsenrichtung gekennzeichnet. Duplikate der Plus- und Minus-Y-Seiten werden grau dargestellt, um zu zeigen, wie diese Seiten an der negativen z-Seite befestigt sind. Die Bilder, die wir für die Cubemap machen, müssen genauso zusammenpassen wie die Seiten in diesem Layout. Die Seiten im Layout werden jedoch von der Außenseite des Würfels aus betrachtet, während die Kamera ein Bild von der Innenseite des Würfels macht. Um die richtige Ansicht zu erhalten, müssen wir das Bild von der Kamera horizontal filtern. Nach einigen Experimenten stellten wir fest, dass wir es auch vertikal umdrehen müssen, vielleicht weil Webbilder im Hinblick auf die OpenGL-Konvention verkehrt herum gespeichert werden. Wir können beide Flips mit einer Skalierungstransformation um (-1, -1, 1, 1) durchführen. Zusammenfassend lässt sich sagen, dass der Code für die Erstellung des negativen z-Bildes der Cubemap wie folgt lautet

Copy to Clipboard

Die Funktion in der letzten Zeile rendert die Szene, mit Ausnahme des zentralen reflektierenden Objekts selbst und ist dafür verantwortlich, die Projektions- und Modleview-Matrizen an die Shaderprogramme zu senden.

Für die anderen fünf Bilder müssen wir die Kamera in eine andere Richtung richten, bevor wir das Bild aufnehmen können. Dies kann durch Hinzufügen einer entsprechenden Rotation zur View-Transformation erreicht werden. Zum Beispiel müssen wir für das positive x-Bild die Kamera um -90 Grad um die y-Achse drehen. Als View-Transformation benötigen wir den Befehl

Copy to Clipboard

Es könnte einfacher sein, sich dies als eine Modelltransformation vorstellen, die die positive x-Seite des Würfels vor der Kamera in Sichtweite dreht.

Im Beispielprogramm werden die sechs Cubemap-Bilder in der Funktion createDynamicCubemap() erstellt.

Dieses dynamische Cubemap-Programm ist ein schönes Beispiel, da es so viele der Konzepte und Techniken nutzt, die wir abgedeckt haben. Nehmen Sie sich eine Minute Zeit, um über alles nachzudenken, was in dieser Demoversion des Beispielprogramms vor sich geht und wie es implementiert wurde.

Vielen Dank für ihren Besuch.

3DMaster