1<!DOCTYPE html>
2<html xmlns="http://www.w3.org/1999/xhtml">
3    <head>
4        <meta content="text/html; charset=utf-8" http-equiv="Content-Type" />
5        <title>WebGL-Beispiel 3 : Farbe</title>
6    <script src="webgl-utils.js" ></script>
7    <script src="gl-matrix.js" ></script>
8    <script type="text/javascript">
9    "use strict";
10    /*global window */ // tells jslint that 'window' is defined!
11    /*global WebGLUtils */ // tells jslint that 'WebGLUtils' is defined!
12    /*global mat4 */ // tells jslint that 'mat4' is defined!
13    /*global Float32Array */ // tells jslint that 'Float32Array' is defined!
14
15    var WebGLApplication = {};
16
17    /**
18    * globales Core-Objekt, dass gekapselten Zugriff aus zentrale
19    * Properties gewährt.
20    */
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        };
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        };
43    }());
44
45    /**
46    * Beschreibt ein einfachstes 3D-Modell aus Raumpunkten und
47    * zugehörigen Farbwerten.
48    */
49    WebGLApplication.Model = function () {
50        this.vertices = null;
51        this.verticesBuffer = null;
52        this.colors = null;
53        this.colorBuffer = null;
54        this.mvMatrix = null;
55    };
56
57    /**
58    * Speichert alle Adressen der Variablen, die zwischen JavaScript und
59    * den Shadern ausgetauscht werden.
60    */
61    WebGLApplication.ShaderVarLocations = function () {
62        this.vertexAttribute = null;
63        this.colorAttribute = null;
64        this.mvMatrixUniform = null;
65        this.pMatrixUniform = null;
66        this.update = function (gl, programObject) {
67            this.vertexAttribute = gl.getAttribLocation(programObject, "av4Position");
68            this.colorAttribute = gl.getAttribLocation(programObject, "av4VertexFarbe");
69            this.mvMatrixUniform = gl.getUniformLocation(programObject, "um4ModelviewMatrix");
70            this.pMatrixUniform = gl.getUniformLocation(programObject, "um4PerspektivMatrix");
71        };
72    };
73
74    /**
75    * Initialisiert die WebGL-Umgebung und erstellt das Shader-Program objekt
76    * @param {canvas} canvas die Zeichenfläche innerhalb der HTML-Seite.
77    * @param {String} vertexShaderString der Quellcode des VertexShaders
78    * @param {String} fragmentShaderString der Quellcode des FragmentShaders
79    * @param {String} eine ID aus dem DOM, in die ggf. Fehlermeldungen geschrieben werden
80    * @return {WebGLContex} der erzeugte WebGL-Context    
81    */
82    WebGLApplication.init = function (canvas, vertexShaderString, fragmentShaderString, statusAusgabeDOM_ID) {
83        var gl, programObject, compilerErfolg, fShader, vShader, webGLBrowserStatus, linkerErfolg;
84        this.Core.setMember("canvas", canvas);
85        try {
86            this.Core.setMember("gl", WebGLUtils.setupWebGL(canvas));
87        } catch (e) { }
88
89        if (!this.Core.getMember("gl")) {
90            webGLBrowserStatus = window.document.getElementById(statusAusgabeDOM_ID);
91            webGLBrowserStatus.innerHTML = "Dein Browser unterstützt WebGL (noch) nicht. Die <a href=\"http://webgl.peter-strohm.de/webgltutorial0.php\">Liste der Bro wser mit WebGL-Support<\/a> kann Dir weiterhelfen.";
92        }
93
94        gl = this.Core.getMember("gl");
95        programObject = gl.createProgram();
96        this.Core.setMember("programObject", programObject);
97
98        vShader = gl.createShader(gl.VERTEX_SHADER); // Das Vertex-Shader-Objekt wird angelegt
99        gl.shaderSource(vShader, vertexShaderString); // - mit seinem Quelltext verknüpft
100        gl.compileShader(vShader); // - kompiliert
101        // Check the compile status
102        compilerErfolg = gl.getShaderParameter(vShader, gl.COMPILE_STATUS);
103        if (!compilerErfolg) {
104            window.alert("Fehler beim erstellen des VertexShaders : \n\n" + gl.getShaderInfoLog(vShader));
105            gl.deleteShader(vShader);
106            return false;
107        } else {
108            gl.attachShader(programObject, vShader);
109        }
110
111        fShader = gl.createShader(gl.FRAGMENT_SHADER);
112        gl.shaderSource(fShader, fragmentShaderString);
113        gl.compileShader(fShader);
114        compilerErfolg = gl.getShaderParameter(fShader, gl.COMPILE_STATUS);
115        if (!compilerErfolg) {
116            window.alert("Fehler beim erstellen des FragmentShaders : \n\n" + gl.getShaderInfoLog(fShader));
117            gl.deleteShader(fShader);
118            return false;
119        } else {
120            gl.attachShader(programObject, fShader);
121        }
122
123        gl.linkProgram(programObject); // Das Shader-Program-Objekt ist vollständig und muss gelinkt werden.
124        // Fehlerüberprüfung: Hat das Linken geklappt ?:
125        linkerErfolg = gl.getProgramParameter(programObject, gl.LINK_STATUS);
126        if (!linkerErfolg) {
127            window.alert("Fehler beim Linken des ShaderPrograms : \n\n" + gl.getProgramInfoLog(programObject));
128            gl.deleteProgram(programObject);
129            return false;
130        }
131        gl.useProgram(programObject); // Da theoretisch mehrere Shader-Program-Objekte möglich sind, muss
132                                                        // angegeben werden, welches benutzt werden soll.
133        return gl;
134    };
135
136    /**
137    * Erstellt eine Perspektivische Projektionsmatrix und übergibt sie an die Shader
138    * @param zNah {double} Z-Koordinate der nahen Begrenzungsebene des Sichtfelds
139    * @param zFern {double} Z-Koordinate der fernen Begrenzungsebene des Sichtfelds
140    * @param zFern {double} Öffnungswinkel des Sichtfelds in Grad
141    */
142    WebGLApplication.setupViewpoint = function (zNah, zFern, sichtfeldOeffnungswinkel) {
143        var
144            aspektVerhaeltnis,
145            pMatrix,
146            canvas;
147        // Jetzt wird die Perspektivmatrix angelegt:
148        // Die Perspektivmatrix sorgt dafür, dass die Raumkoordinaten der Vertizes auf der zweidimensionalen Webseite
149        // so dargestellt werden, dass die Tiefenwirkung entsteht.
150        canvas = this.Core.getMember("canvas");
151        aspektVerhaeltnis = canvas.width / canvas.height;
152        pMatrix = mat4.perspective(sichtfeldOeffnungswinkel, aspektVerhaeltnis, zNah, zFern);
153        this.Core.getMember("gl").uniformMatrix4fv(this.Core.getMember("shaderVarLocations").pMatrixUniform, false, pMatrix);
154
155    };
156
157    /**
158    * Erzeugt Daten eines 3D-Modells (hier nur ein Dreieck) und übergibt diese an die Shader
159    */
160    WebGLApplication.bufferModel = function () {
161        var
162            gl,
163            Model,
164            shaderVarLocations;
165
166        gl = this.Core.getMember("gl");
167        Model = new this.Model();
168        this.Core.setMember("Model", Model);
169
170        if (this.Core.getMember("shaderVarLocations") === null) {
171            shaderVarLocations = new WebGLApplication.ShaderVarLocations(gl);
172            shaderVarLocations.update(gl, this.Core.getMember("programObject"));
173            this.Core.setMember("shaderVarLocations", shaderVarLocations);
174        }
175
176        // Ein Array mit den Koordinaten, der Eckpunkte des Dreiecks das dargestellt wird.
177        Model.vertices = new Float32Array([
178            0.0, 1.0, 0.0, //x y z des ersten Dreieckpunktes
179            -1.0, -1.0, 0.0, //x y z des zweiten Dreieckpunktes
180            1.0, -1.0, 0.0]); //x y z des dritten Dreieckpunktes
181        Model.vertexBuffer = gl.createBuffer(); // ein WebGL-Buffer-Objekt wird erzeugt
182        gl.bindBuffer(gl.ARRAY_BUFFER, Model.vertexBuffer); // ...und als aktives Objekt gesetzt
183        gl.bufferData(gl.ARRAY_BUFFER, Model.vertices, gl.STATIC_DRAW); // die Arraydaten werden an den aktiven Puffer übergeben
184
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);
193
194        Model.mvMatrix = mat4.identity();
195        mat4.translate(Model.mvMatrix, [0.0, 0.0, -3.0]);
196        gl.uniformMatrix4fv(shaderVarLocations.mvMatrixUniform, false, Model.mvMatrix);
197    };
198
199    /**
200    * Löscht den Bildschirm und zeichnet das aktive Modell neu.
201    * @param gl {WebGLContext} aktiver WebGLContext
202    */
203    WebGLApplication.drawScene = function (gl) {
204        var shaderVarLocations,
205            Model;
206        shaderVarLocations = this.Core.getMember("shaderVarLocations");
207        Model = this.Core.getMember("Model");
208        gl.clearColor(0.0, 0.0, 0.0, 1.0); // RGB-Alpha Farbe zum Löschen des Hintergrundes
209        gl.clear(gl.COLOR_BUFFER_BIT); // Hintergrund löschen
210
211        gl.bindBuffer(gl.ARRAY_BUFFER, Model.colorBuffer);
212        gl.vertexAttribPointer(shaderVarLocations.colorAttribute, 4, gl.FLOAT, false, 0, 0);
213        gl.enableVertexAttribArray(shaderVarLocations.colorAttribute);
214
215        gl.bindBuffer(gl.ARRAY_BUFFER, Model.vertexBuffer); // ...und als aktives Objekt gesetzt
216        gl.vertexAttribPointer(shaderVarLocations.vertexAttribute, 3, gl.FLOAT, false, 0, 0);
217        gl.enableVertexAttribArray(shaderVarLocations.vertexAttribute);
218
219        gl.drawArrays(gl.TRIANGLES, 0, 3);
220    };
221
222    /**
223    * Zentrale Einstiegsstelle des WebGL-Programms. Wird nach dem Laden der HTML-Seite
224    * ausgeführt und ruft synchron alle weiteren Methoden auf.
225    */
226    function meinWebGLStart() {
227        var
228            meineCanvas,
229            gl,
230            fragmentShaderQuellcode,
231            vertexShaderQuellcode;
232
233        meineCanvas = window.document.getElementById("meineWebGLCanvas"); // canvas ist die "Leinwand" innerhalb der HTML Seite, auf die gezeichnet werden kann
234
235        vertexShaderQuellcode =
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';
246
247        fragmentShaderQuellcode =
248            'precision mediump float;\n\
249             varying vec4 vFarbe; \n\
250             void main() \n\
251             { \n\
252                 gl_FragColor = vFarbe;\n\
253             } \n';
254
255        gl = WebGLApplication.init(meineCanvas, vertexShaderQuellcode, fragmentShaderQuellcode, "webGLBrowserStatus");
256
257        WebGLApplication.bufferModel();
258        WebGLApplication.setupViewpoint(0.1, 100.0, 90);
259
260        WebGLApplication.drawScene(gl);
261    }
262
263    /**
264    * Event-Zuordnung: Sobald die Seite geladen ist, wird meinWebGLStart() ausgeführt.
265    */
266    window.onload = function () {
267        meinWebGLStart();
268    };
269
270    </script>
271    
272    </head>
273    <body>
274        <noscript><h2>JavaScript ist in Deinem Browser deaktiviert oder wird nicht unterstützt. Ohne JavaScript kann diese Seite nicht korrekt dargestellt wer den.</h2> </noscript>
275        <p id="webGLBrowserStatus"></p>
276        <a href="webgltutorial3.php">zurück zum Tutorial</a><br />
277        <canvas id="meineWebGLCanvas" width="500" height="500"></canvas>
278        <br />
279        <a href="webgltutorial3.php">zurück zum Tutorial</a>
280    </body>
281</html>
282
283