| Home WebGL Api Spickzettel
 WebGL Sicherheit
 
 Tutorial
 0 : WebGL Browser
 1 : Das erste Dreieck
 2 : 3D-Mathematik
 3 : Farbe
 4 : Animation
 5 : Interaktion I
 6 : Texturen
 7 : Beleuchtung I
 8 : Interaktion II
 
 Links
 WebGL Beispiele
 WebGL Frameworks
 ext. WebGL Tutorials
 
 
 Kontakt / Impressum
 webgl ([ät)] peter-strohm Punkt de
 
 
 | 3  Farbe>>>> Direkt zum Beispiel <<<<
     
  >>>Quellcode zum Beispiel <<<
 
 
 Nachdem Kapitel 2 sehr mathematiklastig wird es jetzt wieder mehr um die Javascript-Architektur und schöne bunte Farben gehen.
 
 Der Quellcode zum Beispiel aus Kapitel 1 hatte bewusst keine nennenswerte Strukturierung. Alle erforderlichen Schritte zur 
Darstellung des Dreiecks wurden nacheinander innerhalbe einer großen Funktion abgearbeitet.
 
 Das wird sich jetzt ändern. Obwohl funktional "nur" die Farbe hinzukommt, sieht ist der Quellcode nicht wiederzuerkennen. 
Ich habe den Ablauf in einzelne in sich zusammengehörige Funktionen unterteilt und einen Hauch von Objektorientierung verwendet, soweit 
Javascript dies zulässt und es mir sinnvoll erscheint.
 
 Was die Funktionalität des Beispiels betrifft, werden das Beispiel aus Kapitel 1 so erweitern, dass jedem Eckpunkt des 
Dreiecks ein eigener Farbwert zugeordnet werden kann.
 Die Fläche zwischen den Eckpunkten (also die Dreiecksfläche) wird mit 
interpolierten Farbwerten gefüllt.
 
 So sieht's aus:
 
  
 Bild 3.1 : Screenshot zum Beispiel 3
 
 hier geht's zur Live-Version 
 (WebGL-fähiger Browser erforderlich)
 
 Zunächst habe ich den Quellcode im Vergleich zum 
ersten Beispiel etwas umstrukturiert:
 Am Anfang werden zwei zusätzliche Javascript-Dateien eingebunden:
 
 | 6 | <script src="webgl-utils.js" ></script>
 |  | 7 | <script src="gl-matrix.js" ></script>
 | 
 webgl-utils.js wird freundlicherweise von Google 
zur Verfügung gestellt und  hilft bei der browserunabhängigen Initialisierung 
des WebGL-Contexts.
 
 gl-matrix.js ist eine speziell 
für WebGL angelegte Bibliothek von Matrix- und Vektorfunktionen. Darin findest 
Du auch eine Kapselung der in Tutorial zwei beschriebenen Perspektiv- und 
Projektionsmatrix, die ich verwenden werde.
 
 In kapitel3.html 
erstelle ich das globale Objekt
 WebGLApplicationmit zunächst sechs 
Properties (Eigenschaften, Elementen):
 
 | 21 | WebGLApplication.Core = (function () {
 |  | 22 |     var members = {
 |  | 23 |         // Zeiger zum WebGLProgram-Objekt
 |  | 24 |         programObject: 0,
 |  | 25 |         canvas: null,
 |  | 26 |         gl: null,
 |  | 27 |         pMatrix: null,
 |  | 28 |         model: null,
 |  | 29 |         shaderVarLocations: null
 |  | 30 |     };
 | 
 
 Die Kapselung der Properties wird über die folgenden
 setMemberundgetMemberMethoden realisiert. Die Technik ist 
einem Heise-Artikel von Jan Petzold entnommen.
 
 | 31 | return {
 |  | 32 |     getMember: function (key) {
 |  | 33 |         if (typeof members[key] !== 'undefined') {
 |  | 34 |             return members[key];
 |  | 35 |         } else {
 |  | 36 |             return false;
 |  | 37 |         }
 |  | 38 |     },
 |  | 39 |     setMember: function (key, value) {
 |  | 40 |         members[key] = value;
 |  | 41 |     }
 |  | 42 | };
 | 
 
 Der Rest des Code Refactorings ist weniger aufregend als es vielleicht beim 
ersten Blick auf den Quellcode erscheinen mag.
 Die Methoden
 
 init
 bufferModel
 setupViewpointund
 
 drawScenewerden nacheinander abgearbeitet und machen genau das, was ihr Name andeutet. :-D
 
 Kommen wir nun endlich zur Farbe:
 
  3.1  Der Weg der Farbe - rückwärtsEs sind mehrere Schritte zu programmieren bzw. Stufen zu durchlaufen, bevor 
die Farbe auf dem Dreieck ankommt. Ich werde hier diese Schritte "rückwärts" 
erläutern. D.h. wir beginnen beim letzten Schritt, dem Fragmentshader.
 Wie kommen nun die Farben auf das Dreieck? :
 Eine wichtige Rolle hierbei spielen wieder der Vertex- und der 
Fragment-Shader. (Du erinnerst dich: Shader sind die Mini-Programme, die in 
der Grafikkarte ausgeführt werden)
 Sehen wir uns zunächst die Veränderung im Fragment-Shader an:
 
 
 
| Neu : Fragmentshader mit Farbe kapitel3.html | Alt : alles weiß kapitel1.html |  
| | 248 | 'precision mediump float;\n\
 |  | 249 |  varying vec4 vFarbe; \n\
 |  | 250 |  void main()  \n\
 |  | 251 |  {     \n\
 |  | 252 |      gl_FragColor = vFarbe;\n\
 |  | 253 |  } \n';
 | 
 | | 62 | 'precision mediump float;\n\
 |  | 63 | void main()  \n\
 |  | 64 | {     \n\
 |  | 65 |     gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);\n\
 |  | 66 | } \n';
 | 
 |  Wie du im direkten Vergleich siehst, wurde die Variable
 vColorneu eingeführt. Sie ist als vec4 deklariert, hat also 4 Element: rot, 
grün, blau und Opazität. Die fest definierte WebGL-Variablegl_FragColorwird mit dem Wert vonvColorbelegt. 
Mit anderen Worten: vColor wird "durchgereicht".Wie kommt nun der Farbwert in
 vColor? Zur Beantwortung dieser 
Frage müssen wir uns zunächst mit dem Schlüsselwortvaryingauseinandersetzen.Variablen die mit dem Schlüsselwort varying gekennzeichnet sind bilden 
eine Schnittstelle zwischen Vertex- und Fragment-Shader. Sie sind im Vertexshader 
AUSGANGSvariablen und im Fragmentshader EINGANGSvariablen. Demzufolge müssen 
sie in beiden Shadern vom gleichen Typ sein und den gleichen Namen tragen wie 
du hier im neuen Vertex-Shader sehen kannst:
 
 
 | 236 | 'attribute vec4 av4Position; \n\
 |  | 237 |  attribute vec4 av4VertexFarbe; \n\
 |  | 238 |  uniform mat4 um4PerspektivMatrix; \n\
 |  | 239 |  uniform mat4 um4ModelviewMatrix; \n\
 |  | 240 |  varying vec4 vFarbe; \n\
 |  | 241 |  void main() \n\
 |  | 242 |  { \n\
 |  | 243 |      gl_Position = um4PerspektivMatrix * um4ModelviewMatrix * av4Position;  \n\
 |  | 244 |      vFarbe = av4VertexFarbe; \n\
 |  | 245 |  } \n';
 | 
 
 Wie du siehst passiert auch im Vertex-shader mit der Farbe nichts 
aufregendes: Sie wird als
  attribute vec4 av4VertexFarbein den Vertexshader hineingegeben und 
alsvFarbewie gerade 
beschrieben an den Fragmentshader weitergegeben. Kurz gesagt: die 
Farbe wird unverändert durchgereicht.
 Dir fällt sicherlich auf, dass Zeile 1 und 2 des Vertexshaders sehr ähnlich 
aussehen. Position und Farbe der einzelnen Vertices werden hier praktisch 
gleich behandelt: Beides sind Vektoren die "von 
außen" mit Inhalt gefüllt werden.
 
 Hier als kleiner Einschub die drei Schlüsselwörter vor Variablen in den 
Shader-scripten in der Übersicht:
 
 
 
	Tabelle  3.1 : die drei Shader-Spezialvariablentypen
	| attribute | Attribute ( attribute) sind Variablen, die sich speziell 
	   auf Vertices beziehen und nur im Vertex-Shader verwendet werden. 
	   Typisches Beispiel sind die Koordinaten (x,y,z). Ihr Wert unterscheidet 
	   sich i.d.R. von einem Vertex zum nächsten. |  
	| uniform | Als uniform werden Shadervariablen gekennzeichnet, die außerhalb der 
	  Shader "einheitlich" (uniform) festgelegt werden. Sie können sowohl in 
	  Vertex- als auch in Fragmentshader verwendet werden. Ein Beispiele sind 
	  die Modelview oder Perspektivmatrix. Beide werden außerhalb der Shader 
	  berechnet und in den Shadern nicht mehr verändert. |  
	| varying | "varying" Variablen bilden die Schnittstelle zwischen Vertex- und 
	  Fragmentshader. Ihr Inhalt wird vom Vertex-Shader an den  Fragmentshader 
	  weitergegeben. Varyings müssen in beiden Shadern mit jeweils gleichem 
	  Namen und Typ deklariert werden. Varying werden bei der Rasterung automatisch zwischen den Vertices 
	  interpoliert. Im Beispiel zu diesem Kapitel sieht man diese 
	  Interpolation sehr gut am Farbverlauf des Dreiecks: die drei Vertices 
	  haben festgelegte Farben, die Fläche dazwischen wird vom Fragmentshader 
	  mit interpolierten "Zwischenfarben" gefüllt.
 
 |  
 Die Schlüsselwörter in Tabelle 3.1 werden auch bei anderen Themen wieder 
auftauchen.
 
 Verfolgen wir den Weg der Farbe weiter. Zuletzt hast du gesehen, dass der 
Farbwert durch den Vertex-Shader durchgereicht wird. Wie kommt der Wert nun in 
den Vertex-Shader hinein?
 Die Antwort liegt in Zeile 68 von kapitel3.html.
Dort wird mit der
 update()-Methode vonShaderVarLocationsermittelt, welche "Adressen" die Attribute und 
Uniforms im Vertex-Shader haben.Mit diesen Adressen wird WebGL in der
 drawScene()Methode in den
Zeilen 211 - 213 (für die Farbe) mitgeteilt, zu welcher Buffer zu welchem 
Attribut gehört und in welchem Datenformat der Buffer zu lesen ist (4
Element bilden eine Farbe, alle Elemente sind vom Typ gl.FLOAT).
 
 | 211 | gl.bindBuffer(gl.ARRAY_BUFFER, Model.colorBuffer);
 |  | 212 | gl.vertexAttribPointer(shaderVarLocations.colorAttribute, 4, gl.FLOAT,  false, 0, 0);
 |  | 213 | gl.enableVertexAttribArray(shaderVarLocations.colorAttribute);
 | 
 
 Das zugehörige
 Float32Arraymit den drei 
vierdimensionalen Farbwerten wurde bereits in den Zeilen 185 bis 192 erzeugt und als 
Buffer an die Shader übergeben.
 
 | 185 | Model.colors = new Float32Array([
 |  | 186 |     1.0, 0.0, 0.0, 1.0, //rot
 |  | 187 |     0.0, 1.0, 0.0, 1.0, //grün
 |  | 188 |     0.0, 0.0, 1.0, 1.0]); //blau
 |  | 189 |  |  | 190 | Model.colorBuffer = gl.createBuffer();
 |  | 191 | gl.bindBuffer(gl.ARRAY_BUFFER, Model.colorBuffer);
 |  | 192 | gl.bufferData(gl.ARRAY_BUFFER, Model.colors, gl.STATIC_DRAW);
 | 
 
 Wenn dir die RGBAlpha Farbdarstellung 
geläufig ist, kannst du hier die Farben der einzelnen Dreieckspunkte verändern.
Die Farbwerte zwischen den Vertices wird der Fragmentshader automatisch 
für jeden Pixel interpolieren.
 
 createBuffer()erzeugt einen neuen Puffer im Grafikspeicher. Die 
Daten werden mitbindBufferundbufferDataan WebGL 
bzw. die GPU übergeben.
 Ich habe den Signalfluss der Farbe in dieseem Kapitel "von innen nach außen" 
beschrieben. Wenn Du das soweit nachvollzogen hast, kannst du dir die 
parallele Kette der VertexPOSITIONEN im Quellcode anschauen. Das Prinzip ist 
sehr ähnlich.
 
 Im nächsten Kapitel werde ich mich dem Thema Animation zuwenden. Es bleibt 
spannend!
 Thanks to Giles Thomas and his project 
LearningWebGL.com
 
 |