Willkommen zu unserem fünfzehnten Teil unserer Serie von WebGL Grundlagen. In diesem Teil werden wir Specular Maps thematisieren, die ihren Szenen mehr Realismus verleihen, indem Sie es ihnen leicht machen, zu bestimmen, wie reflektierend ein Objekt an jedem Punkt seiner Oberfläche ist, genauso wie normale Texturen es ihnen erlauben, deren detaillierte Farbe zu bestimmen. Was den neuen Code angeht, so ist dies eigentlich eine ziemlich einfache Erweiterung zu dem, was wir bereits behandelt haben, aber konzeptionell ist es ein kleiner Sprung.
Dieses Ergebnis werden Sie nach der Umsetzung erhalten:
Ein wichtiger Hinweis: Dieser Teil richtet sich an Personen mit fortgeschrittenen Programmierkenntnissen, aber ohne wirkliche Erfahrung mit 3D-Grafiken. Sie werden ein gutes Verständnis für den Code mitbringen und es zum Laufen bringen, so dass Sie so schnell wie möglich mit der Erstellung einer eigenen Website in 3D beginnen können.
Es existieren zwei verschiedene Möglichkeiten, den Code für dieses Beispiel zu erhalten. In den Browsereinstellungen mit „View Source“, während Sie sich die Live-Version ansehen oder wenn Sie GitHub verwenden, können Sie es aus dem Repository kopieren. Unabhängig davon für welchen Weg Sie sich entscheiden, sollten Sie ihren bevorzugten Texteditor herunterladen und sich den Code genau ansehen.
Bevor wir einen Blick auf den Code werfen, lohnt es sich wahrscheinlich den Hintergrund zu erklären. Bisher haben wir Texturen als eine nette und einfache Möglichkeit behandelt, unsere 3D-Objekte mit Bildern zu „skinnen“. Wir spezifizieren ein Bild und teilen unseren Objekten per per-Vertex-Koordinaten mit, welcher Teil des Bildes wohin gehen soll. Wenn wir also jedes Pixel im Objekt in unserem Fragment-Shader zeichnen, können wir den Teil des Bildes, der diesem Teil des Objekts entspricht ausarbeiten, seine Farbe von dem Sampler-Objekt zu nehmen, das die Textur im Shader darstellt und das als die Farbe des Objekts an diesem Punkt verwendet.
Specular Maps gehen noch einen Schritt weiter. Die Farbe eines Punktes in der Textur wird natürlich durch Rot-, Grün-, Blau- und Alpha-Komponenten bestimmt. Im Shader ist jede dieser Zahlen eine Fließkommazahl. Aber es gibt keinen besonderen Grund, warum wir Sie als Farbwerte verwenden müssen. Sie werden sich aus dem letzten Teil erinnern, dass der Glanz eines Materials durch eine einzige Gleitkommazahl bestimmt wird. Es gibt keinen Grund, warum wir Texturen nicht dazu benutzen sollten um eine „Shininess Map“ an den Fragment-Shader zu übergeben, so wie wir es normalerweise für eine Color Map verwenden.
Das ist also der Trick, den wir in diesem Beispiel anwenden. Zwei separate Texturen werden an den Fragment-Shader übergeben, der auf der Erde verwendet werden kann. Die Color Map sieht folgendermaßen aus:
… und eine Specular Map mit einer niedrigen Auflösung:
Das ist nur eine normale Gif-Datei, welche in Gimp erstellt wurde, wobei die Color Map als Ausgangspunkt genommen wurde. Es fiel der Entschluss die Rot-, Grün- und Blauanteile der Farbe an jedem Punkt auf den gleichen Wert zu setzen. Den Glanz des Punktes. Da die meiste Fläche des Bildes ziemlich dunkel war, fiel der Entschluss, dafür reines Weiß zu verwenden.
Wir gehen jetzt zum Code über. Die Unterschiede zwischen dem Code hier und im Teil 14 sind eigentlich sehr gering und ziemlich klar. Wie man erwarten kann, ist das wirklich wichtige Zeug im Fragment-Shader, also lasst uns einen Blick darauf werfen.
Die erste Änderung besteht darin, dass wir ein paar neue Uniforms haben, die angeben, ob wir die Color oder Specular Maps verwenden möchten oder nicht:
Als nächstes haben wir einheitliche Sampler für die beiden Texturen. Wir haben den alten uSampler, welcher für die Farbtextur verwendet und in uColorMapSampler umbenannt wurde. Wir haben einen neuen Sampler hinzugefügt, welcher die Specular Map repräsentiert:
Als nächstes kommt unser normaler Textbaustein, um den Fall zu behandeln, dass der Benutzer Lichteffekte ausschalten möchte und um die normale und die Lichtrichtung zu berechnen, wenn Sie es nicht tun:
Und schließlich bekommen wir den Code, der die Specular Map tatsächlich handhabt. Zuerst definieren wir eine Variable, die die Menge an spiegelnder Beleuchtung enthält, die wir anwenden werden. Diese wird natürlich Null sein, wenn das Fragment, das wir in Betracht ziehen, sich als nicht spiegelnd herausstellt, nachdem wir alle Berechnungen durchgeführt haben.
Als nächstes wollen wir den Glanz für diesen Teil des Materials herausfinden. Wenn der Benutzer angegeben hat, dass wir die Specular Map nicht verwenden sollen, dann beeinflusst dieser Code die Wahl zugunsten von 32.0. Ansonsten erhalten wir den Wert aus dem Wert der Specular Map für die Texturkoordinaten des Fragments, so wie wir zuvor den Wert der Color Maps gefunden haben. Jetzt hat unsere Specular Map tatsächlich den Glanzwert, welcher in allen drei Komponenten der Farbe bei jedem Bild gespeichert ist – Rot, Grün und Blau sind alle gleich, weshalb Sie als Graustufen erscheinen, wenn Sie als Bild betrachtet werden. Wir benutzen das Rote in diesem Code, obwohl wir auch die anderen hätten benutzen können, wenn wir es gewollt hätten:
Nun werden Sie sich erinnern, dass wir einen Weg benötigten, um zu sagen: „Dieses Stückchen des Materials ist nicht glänzend“ in der Specular Map. Der Entschluss fiel auf weiß, da es einen guten Kontrast zu den schwarzen Bereichen für die glänzenden Teile der Erde hatte. Daher führen wir keine Berechnungen für die Spiegelbeleuchtungen durch, wenn der Wert für die Helligkeit, wie er aus der Karte extrahiert wurde, größer oder gleich 255 ist.
Das nächste Stück Code ist genau die gleiche Glanzlichtberechnung, welche wir in der letzten Übung hatten, mit der Ausnahme, dass wir die Glanzkonstante verwenden, die wir aus der Karte extrahiert haben:
Und schließlich addieren wir alle Beiträge der verschiedenen Formen der Beleuchtung zusammen und gewichten damit die Farbe des Fragments, sei es aus der Color Map oder wenn uUseColorMap falsch ist, nur ein konstantes Weiß.
Wenn Sie so weit gekommen sind, sollten Sie soweit alles verstehen, was es über den Code für diese Übung zu wissen gibt. Es gibt auch noch andere Änderungen, aber keine davon ist es wert eine detaillierte Code-Beschreibung durchzuführen. InitShaders hat einen neuen Code, um mit den neuen Uniforms umzugehen. InitTextures muss die beiden neuen Texturen laden. Der Code, der die Teekanne geladen hat, wird durch eine initBuffers-Funktion ersetzt, genauso wie im Teil 11. DrawScene hat Code, um eine Kugel statt einer Teekanne zu zeichnen und um die Werte in den Benutzereingabefeldern unter dem Canvas zu nehmen und Sie in die entsprechenden Uniforms zu setzen.
Nun, sind wir mit dem vorletzten Teil fertig. Sie wissen jetzt, wie Sie eine Textur verwenden können, um Informationen über den Glanz eines Objekts zu erhalten. Wie Sie zweifelsohne bis zu diesem Punkt herausgefunden haben, gibt es nichts, was Sie davon abhalten könnte, Texturen zu verwenden, um andere fernkörnige Informationen an ihre Shader weiterzugeben – die Leute verwenden oft ähnliche Techniken, um detaillierte Maps der Variationen in den Oberflächen-Normals zu erstellen, die es ihnen ermöglichen, subtil holprige Oberflächen zu haben ohne dass Sie viele Ecken erstellen müssen. Wir werden uns das in einem später folgenden Beitrag etwas genauer ansehen.
Leave A Comment