Tutorial WebGL Sample: Unterschied zwischen den Versionen

Aus DGL Wiki
Wechseln zu: Navigation, Suche
K (Rechtschreibung korrigiert)
(Anpassung an die aktuelle Spezifikation)
 
(6 dazwischenliegende Versionen desselben Benutzers werden nicht angezeigt)
Zeile 1: Zeile 1:
Dies ist eine Beispielanwendung zum [[Benutzer:Coolcat/Tutorial_WebGL|WebGL-Tutorial]]. Zum Ausprobieren den Quelltext in eine Datei kopieren und mit einem [[Benutzer:Coolcat/Tutorial_WebGL|WebGL-fähigen Browser]] öffnen. Es wird eine Textur von der URL <tt><nowiki>"http://wiki.delphigl.com/wiki.png"</nowiki></tt> geladen. Sollte die Anwendung nicht funktionieren, stelle sicher, dass die Textur erreichbar ist.
+
Dies ist eine Beispielanwendung zum [[Tutorial_WebGL|WebGL-Tutorial]]. Zum Ausprobieren den Quelltext in eine Datei kopieren und mit einem [[Tutorial_WebGL|WebGL-fähigen Browser]] öffnen. Es wird eine Textur von der URL <tt><nowiki>"http://wiki.delphigl.com/wiki.png"</nowiki></tt> geladen. Sollte die Anwendung nicht funktionieren, stelle sicher, dass die Textur erreichbar ist.
  
 
Das Ganze sollte ungefähr so aussehen:
 
Das Ganze sollte ungefähr so aussehen:
Zeile 22: Zeile 22:
  
 
     <head>
 
     <head>
        <script type="text/javascript">
+
        <script type="text/javascript">
 
             var gl = null; // our WebGL rendering context
 
             var gl = null; // our WebGL rendering context
 
             var viewportWidth;
 
             var viewportWidth;
 
             var viewportHeight;
 
             var viewportHeight;
           
+
 
 
             var program; // shader program object
 
             var program; // shader program object
 
             var vbo;    // vertexbufferobject
 
             var vbo;    // vertexbufferobject
 +
            var ibo;    // indexbufferobject
 
             var texture; // texture object
 
             var texture; // texture object
  
Zeile 37: Zeile 38:
 
                 viewportWidth = canvas.width;
 
                 viewportWidth = canvas.width;
 
                 viewportHeight = canvas.height;
 
                 viewportHeight = canvas.height;
                 try {
+
 
                    // using Mozilla? (e.g. Firefox, ...)
+
                 var names = [ "webgl", "experimental-webgl", "moz-webgl", "webkit-3d" ];
                    if (!gl) { gl = canvas.getContext("moz-webgl"); }
+
                 for (var i=0; names.length>i; i++) {
                 } catch (e) { }
+
                    try {  
                try {
+
                        gl = canvas.getContext(names[i]);
                    // using Webkit? (e.g. Google Chrome, ...)
+
                        if (gl) { break; }
                    if (!gl) { gl = canvas.getContext("webkit-3d"); }  
+
                    } catch (e) { }
                } catch (e) { }
+
                }
               
 
 
                 if (!gl) {
 
                 if (!gl) {
 
                     alert("No known OpenGL context detected! Is it enabled?");
 
                     alert("No known OpenGL context detected! Is it enabled?");
 
                     return;
 
                     return;
 
                 }
 
                 }
 +
                // since WebGL is still experimental, we need some compatibility code
 +
                compatibilityCode();
  
 
                 // basic settings
 
                 // basic settings
Zeile 64: Zeile 66:
 
                 var fragmentShader = loadShader(gl.FRAGMENT_SHADER, fragmentShaderSource);
 
                 var fragmentShader = loadShader(gl.FRAGMENT_SHADER, fragmentShaderSource);
 
                 if (!vertexShader || !fragmentShader) {
 
                 if (!vertexShader || !fragmentShader) {
                     alert("Shader problem");
+
                     return;
 
                 }
 
                 }
               
+
 
 
                 // create program object
 
                 // create program object
 
                 program = gl.createProgram();
 
                 program = gl.createProgram();
               
+
 
 
                 // attach our two shaders to the program
 
                 // attach our two shaders to the program
 
                 gl.attachShader(program, vertexShader);
 
                 gl.attachShader(program, vertexShader);
 
                 gl.attachShader(program, fragmentShader);
 
                 gl.attachShader(program, fragmentShader);
               
+
 
                 // setup attributes and uniforms (optional)
+
                 // setup attributes (optional)
 
                 gl.bindAttribLocation(program, 0, "aPosition");
 
                 gl.bindAttribLocation(program, 0, "aPosition");
 
                 gl.bindAttribLocation(program, 1, "aNormal");
 
                 gl.bindAttribLocation(program, 1, "aNormal");
 
                 gl.bindAttribLocation(program, 2, "aTexCoord");
 
                 gl.bindAttribLocation(program, 2, "aTexCoord");
                gl.uniform1i(gl.getUniformLocation(program, "uTexture"), 0);
+
 
               
 
 
                 // linking
 
                 // linking
 
                 gl.linkProgram(program);
 
                 gl.linkProgram(program);
                 if (!gl.getProgrami(program, gl.LINK_STATUS)) {
+
                 if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
 
                     alert(gl.getProgramInfoLog(program));
 
                     alert(gl.getProgramInfoLog(program));
 +
                    return;
 
                 }
 
                 }
 +
 +
                // setup uniforms (optional)
 +
                gl.useProgram(program);
 +
                gl.uniform1i(gl.getUniformLocation(program, "uTexture"), 0);
  
 
                 // setup VBO
 
                 // setup VBO
Zeile 96: Zeile 102:
 
                     -0.5, -0.5,  0.0,  0.0,  0.0,  1.0,  0.0,  1.0,
 
                     -0.5, -0.5,  0.0,  0.0,  0.0,  1.0,  0.0,  1.0,
 
                     0.5, -0.5,  0.0,  0.0,  0.6,  0.8,  1.0,  1.0,
 
                     0.5, -0.5,  0.0,  0.0,  0.6,  0.8,  1.0,  1.0,
               
+
                ];
                    // add an additional vertex, this is an workaround for this bug:
+
                // we need also some indices because of this annoying Firefox-Bug:
                    // https://bugzilla.mozilla.org/show_bug.cgi?id=521667
+
                // https://bugzilla.mozilla.org/show_bug.cgi?id=521667
                    0.0, 0.0, 0.0, 0.0, 0.0, 0.0,  0.0,  0.0
+
                var indices = [
                 ];                
+
                    0, 1, 2, 2, 1, 3
                 // create VBO
+
                 ];
 +
                 // create VBO and IBO
 
                 vbo = gl.createBuffer();
 
                 vbo = gl.createBuffer();
 
                 gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
 
                 gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
                 gl.bufferData(gl.ARRAY_BUFFER, new CanvasFloatArray(vertices), gl.STATIC_DRAW);
+
                 gl.bufferData(gl.ARRAY_BUFFER, new WebGLFloatArray(vertices), gl.STATIC_DRAW);
               
+
                ibo = gl.createBuffer();
 +
                gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, ibo);
 +
                gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new WebGLUnsignedShortArray(indices), gl.STATIC_DRAW);
 +
 
 
                 // create texture
 
                 // create texture
 
                 // =================================================
 
                 // =================================================
 
                 texture = loadTexture("http://wiki.delphigl.com/wiki.png");
 
                 texture = loadTexture("http://wiki.delphigl.com/wiki.png");
 +
 +
                // draw scene every 33 milliseconds
 +
                setInterval(draw, 33);
 +
            }
 +
 +
            function compatibilityCode() {
 +
                // Firefox compatibility code
 +
                // The WebGL*Array where named Canvas*Array in the past.
 +
                // However, this will only affect old nightly builds. The current nightly does already
 +
                // support the new names. (13 Dec 2009).
 +
                try {
 +
                    WebGLFloatArray;
 +
                }
 +
                catch (e) {
 +
                    try {
 +
                        WebGLArrayBuffer = CanvasArrayBuffer;
 +
                        WebGLByteArray = CanvasByteArray;
 +
                        WebGLUnsignedByteArray = CanvasUnsignedByteArray;
 +
                        WebGLShortArray = CanvasShortArray;
 +
                        WebGLUnsignedShortArray = CanvasUnsignedShortArray;
 +
                        WebGLIntArray = CanvasIntArray;
 +
                        WebGLUnsignedIntArray = CanvasUnsignedIntArray;
 +
                        WebGLFloatArray = CanvasFloatArray;
 +
                    }
 +
                    catch (e) {
 +
                        alert("Could not find Canvas array types for WebGL.");
 +
                    }
 +
                }
 +
 +
                // Google Chrome compatibility code
 +
                // Since a JavaScript function may have multiple return types, functions
 +
                // 'getProgrami' and 'getShaderi' where renamed. However, Chrome does still
 +
                // use the old names.  (30 Nov 2009)
 +
                if (!gl.getProgramParameter) {
 +
                    gl.getProgramParameter = gl.getProgrami;
 +
                }
 +
                if (!gl.getShaderParameter) {
 +
                    gl.getShaderParameter = gl.getShaderi;
 +
                }
 
             }
 
             }
  
Zeile 114: Zeile 163:
 
                 var script = document.getElementById(id);
 
                 var script = document.getElementById(id);
 
                 if (!script) { return null; }
 
                 if (!script) { return null; }
           
+
 
 
                 var source = "";
 
                 var source = "";
 
                 var child = script.firstChild;
 
                 var child = script.firstChild;
Zeile 126: Zeile 175:
 
                 return source;
 
                 return source;
 
             }
 
             }
+
 
 
             function loadShader(shaderType, shaderSource) {
 
             function loadShader(shaderType, shaderSource) {
 
                 var shader = gl.createShader(shaderType);
 
                 var shader = gl.createShader(shaderType);
Zeile 132: Zeile 181:
 
                 gl.shaderSource(shader, shaderSource);
 
                 gl.shaderSource(shader, shaderSource);
 
                 gl.compileShader(shader);
 
                 gl.compileShader(shader);
           
+
 
                 if (!gl.getShaderi(shader, gl.COMPILE_STATUS)) {
+
                 if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
 
                     alert(gl.getShaderInfoLog(shader));
 
                     alert(gl.getShaderInfoLog(shader));
 
                     return null;
 
                     return null;
 
                 }     
 
                 }     
           
+
 
 
                 return shader;
 
                 return shader;
 
             }
 
             }
Zeile 148: Zeile 197:
 
                 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
 
                 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
 
                 var image = new Image();
 
                 var image = new Image();
           
+
 
 
                 // register event handlers
 
                 // register event handlers
 
                 image.onload = function() {
 
                 image.onload = function() {
Zeile 159: Zeile 208:
 
                     alert("error while loading image '"+filename+"'.");
 
                     alert("error while loading image '"+filename+"'.");
 
                 }
 
                 }
           
+
 
 
                 // request image from server
 
                 // request image from server
 
                 image.src = filename;  
 
                 image.src = filename;  
           
+
 
 
                 // return texture object (asynchronous loading, texture NOT available yet!)
 
                 // return texture object (asynchronous loading, texture NOT available yet!)
 
                 return texture;
 
                 return texture;
Zeile 174: Zeile 223:
 
                 gl.useProgram(program);
 
                 gl.useProgram(program);
  
                 // setup interleaved VBO
+
                 // setup interleaved VBO and IBO
                 gl.bindBuffer(gl.ARRAY_BUFFER, vbo);                    
+
                 gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
 +
                gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, ibo);
 
                 gl.enableVertexAttribArray(0);
 
                 gl.enableVertexAttribArray(0);
 
                 gl.enableVertexAttribArray(1);
 
                 gl.enableVertexAttribArray(1);
 
                 gl.enableVertexAttribArray(2);
 
                 gl.enableVertexAttribArray(2);
                 gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 8, 0); // position
+
                 gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 8*4, 0*4); // position
                 gl.vertexAttribPointer(1, 3, gl.FLOAT, false, 8, 3); // normal
+
                 gl.vertexAttribPointer(1, 3, gl.FLOAT, false, 8*4, 3*4); // normal
                 gl.vertexAttribPointer(2, 2, gl.FLOAT, false, 8, 6); // texcoord
+
                 gl.vertexAttribPointer(2, 2, gl.FLOAT, false, 8*4, 6*4); // texcoord
  
 
                 // setup texture
 
                 // setup texture
 
                 gl.activeTexture(gl.TEXTURE0);
 
                 gl.activeTexture(gl.TEXTURE0);
 
                 gl.bindTexture(gl.TEXTURE_2D, texture);
 
                 gl.bindTexture(gl.TEXTURE_2D, texture);
               
+
 
 
                 // draw the buffer
 
                 // draw the buffer
                 gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
+
                 gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0);
 
             }
 
             }
 
         </script>
 
         </script>
 
+
 
         <script id="shader-vs" type="x-shader/x-vertex">
 
         <script id="shader-vs" type="x-shader/x-vertex">
 
             attribute vec3 aPosition;
 
             attribute vec3 aPosition;
 
             attribute vec3 aNormal;
 
             attribute vec3 aNormal;
             attribute vec3 aTexCoord;
+
             attribute vec2 aTexCoord;
 
             varying vec3 vNormal;
 
             varying vec3 vNormal;
 
             varying vec2 vTexCoord;  
 
             varying vec2 vTexCoord;  
Zeile 204: Zeile 254:
 
             }
 
             }
 
         </script>
 
         </script>
       
+
 
 
         <script id="shader-fs" type="x-shader/x-fragment">
 
         <script id="shader-fs" type="x-shader/x-fragment">
 
             varying vec3 vNormal;
 
             varying vec3 vNormal;

Aktuelle Version vom 13. Dezember 2009, 13:00 Uhr

Dies ist eine Beispielanwendung zum WebGL-Tutorial. Zum Ausprobieren den Quelltext in eine Datei kopieren und mit einem WebGL-fähigen Browser öffnen. Es wird eine Textur von der URL "http://wiki.delphigl.com/wiki.png" geladen. Sollte die Anwendung nicht funktionieren, stelle sicher, dass die Textur erreichbar ist.

Das Ganze sollte ungefähr so aussehen:

webgl-sample.jpg

<html>
    <!--
     * WebGL-Test
     * 
     * This sample is part of the WebGL Tutorial at http://delphigl.com
     *
     * Author:
     * Coolcat (Martin Weusten)
     *   see: http://wiki.delphigl.com/index.php/Benutzer:Coolcat
     *
     * Licence for this file:
     * Creative Commons Attribution 3.0 (CC-BY 3.0)
     *   see: http://creativecommons.org/licenses/by/3.0/
    -->

    <head>
        <script type="text/javascript">
            var gl = null; // our WebGL rendering context
            var viewportWidth;
            var viewportHeight;

            var program; // shader program object
            var vbo;     // vertexbufferobject
            var ibo;     // indexbufferobject
            var texture; // texture object

            function init() { 
                // request rendering context from the canvas
                // =================================================
                var canvas = document.getElementById("canvas");
                viewportWidth = canvas.width;
                viewportHeight = canvas.height;

                var names = [ "webgl", "experimental-webgl", "moz-webgl", "webkit-3d" ];
                for (var i=0; names.length>i; i++) {
                    try { 
                        gl = canvas.getContext(names[i]);
                        if (gl) { break; }
                    } catch (e) { }
                }
                if (!gl) {
                    alert("No known OpenGL context detected! Is it enabled?");
                    return;
                }
                // since WebGL is still experimental, we need some compatibility code
                compatibilityCode();

                // basic settings
                // =================================================
                gl.clearColor(0, 0, 0, 1);
                gl.enable(gl.DEPTH_TEST);

                // setup shaders
                // =================================================
                var vertexShaderSource = getShaderSource("shader-vs");
                var fragmentShaderSource = getShaderSource("shader-fs");

                var vertexShader = loadShader(gl.VERTEX_SHADER, vertexShaderSource);
                var fragmentShader = loadShader(gl.FRAGMENT_SHADER, fragmentShaderSource);
                if (!vertexShader || !fragmentShader) {
                    return;
                }

                // create program object
                program = gl.createProgram();

                // attach our two shaders to the program
                gl.attachShader(program, vertexShader);
                gl.attachShader(program, fragmentShader);

                // setup attributes (optional)
                gl.bindAttribLocation(program, 0, "aPosition");
                gl.bindAttribLocation(program, 1, "aNormal");
                gl.bindAttribLocation(program, 2, "aTexCoord");

                // linking
                gl.linkProgram(program);
                if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
                    alert(gl.getProgramInfoLog(program));
                    return;
                }

                // setup uniforms (optional)
                gl.useProgram(program);
                gl.uniform1i(gl.getUniformLocation(program, "uTexture"), 0);

                // setup VBO
                // =================================================

                // define some vertexdata
                var vertices = [
                    // position XYZ, normal XYZ, texcoord UV => 8 floats per vertex
                    -0.5,  0.5,  0.0,  0.6,  0.0,  0.8,  0.0,  0.0,
                     0.5,  0.5,  0.0,  0.6,  0.0,  0.8,  1.0,  0.0,
                    -0.5, -0.5,  0.0,  0.0,  0.0,  1.0,  0.0,  1.0,
                     0.5, -0.5,  0.0,  0.0,  0.6,  0.8,  1.0,  1.0,
                ];
                // we need also some indices because of this annoying Firefox-Bug:
                // https://bugzilla.mozilla.org/show_bug.cgi?id=521667
                var indices = [
                    0, 1, 2, 2, 1, 3
                ];
                // create VBO and IBO
                vbo = gl.createBuffer();
                gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
                gl.bufferData(gl.ARRAY_BUFFER, new WebGLFloatArray(vertices), gl.STATIC_DRAW);
                ibo = gl.createBuffer();
                gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, ibo);
                gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new WebGLUnsignedShortArray(indices), gl.STATIC_DRAW);

                // create texture
                // =================================================
                texture = loadTexture("http://wiki.delphigl.com/wiki.png");

                // draw scene every 33 milliseconds
                setInterval(draw, 33);
            }

            function compatibilityCode() {
                // Firefox compatibility code
                // The WebGL*Array where named Canvas*Array in the past.
                // However, this will only affect old nightly builds. The current nightly does already
                // support the new names. (13 Dec 2009).
                try {
                    WebGLFloatArray;
                }
                catch (e) {
                    try {
                        WebGLArrayBuffer = CanvasArrayBuffer;
                        WebGLByteArray = CanvasByteArray;
                        WebGLUnsignedByteArray = CanvasUnsignedByteArray;
                        WebGLShortArray = CanvasShortArray;
                        WebGLUnsignedShortArray = CanvasUnsignedShortArray;
                        WebGLIntArray = CanvasIntArray;
                        WebGLUnsignedIntArray = CanvasUnsignedIntArray;
                        WebGLFloatArray = CanvasFloatArray;
                    }
                    catch (e) {
                        alert("Could not find Canvas array types for WebGL.");
                    }
                }

                // Google Chrome compatibility code
                // Since a JavaScript function may have multiple return types, functions 
                // 'getProgrami' and 'getShaderi' where renamed. However, Chrome does still
                // use the old names.  (30 Nov 2009)
                if (!gl.getProgramParameter) {
                    gl.getProgramParameter = gl.getProgrami;
                }
                if (!gl.getShaderParameter) {
                    gl.getShaderParameter = gl.getShaderi;
                }
            }

            function getShaderSource(id) {
                var script = document.getElementById(id);
                if (!script) { return null; }

                var source = "";
                var child = script.firstChild;
                while (child) {
                    // node is a "textnode" ?
                    if (child.nodeType == 3) {
                        source += child.textContent;
                    }
                    child = child.nextSibling;
                }
                return source;
            }

            function loadShader(shaderType, shaderSource) {
                var shader = gl.createShader(shaderType);
                if (!shader) { return null; }    
                gl.shaderSource(shader, shaderSource);
                gl.compileShader(shader);

                if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
                    alert(gl.getShaderInfoLog(shader));
                    return null;
                }    

                return shader;
            }

            function loadTexture(filename) {
                // preparations
                var texture = gl.createTexture();
                gl.bindTexture(gl.TEXTURE_2D, texture);
                gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
                gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
                var image = new Image();

                // register event handlers
                image.onload = function() {
                    gl.bindTexture(gl.TEXTURE_2D, texture);
                    gl.texImage2D(gl.TEXTURE_2D, 0, image);
                    gl.generateMipmap(gl.TEXTURE_2D);
                    draw(); // texture now available, we can redraw the scene
                }
                image.onerror = function() {
                    alert("error while loading image '"+filename+"'.");
                }

                // request image from server
                image.src = filename; 

                // return texture object (asynchronous loading, texture NOT available yet!)
                return texture;
            }

            function draw() {
                gl.viewport(0, 0, viewportWidth, viewportHeight);
                gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT );

                // setup shader
                gl.useProgram(program);

                // setup interleaved VBO and IBO
                gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
                gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, ibo);
                gl.enableVertexAttribArray(0);
                gl.enableVertexAttribArray(1);
                gl.enableVertexAttribArray(2);
                gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 8*4, 0*4); // position
                gl.vertexAttribPointer(1, 3, gl.FLOAT, false, 8*4, 3*4); // normal
                gl.vertexAttribPointer(2, 2, gl.FLOAT, false, 8*4, 6*4); // texcoord

                // setup texture
                gl.activeTexture(gl.TEXTURE0);
                gl.bindTexture(gl.TEXTURE_2D, texture);

                // draw the buffer
                gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0);
            }
        </script>
 
        <script id="shader-vs" type="x-shader/x-vertex">
            attribute vec3 aPosition;
            attribute vec3 aNormal;
            attribute vec2 aTexCoord;
            varying vec3 vNormal;
            varying vec2 vTexCoord; 
            void main() {
                gl_Position = vec4(aPosition, 1.0);
                vTexCoord = aTexCoord;
                vNormal = aNormal;
            }
        </script>

        <script id="shader-fs" type="x-shader/x-fragment">
            varying vec3 vNormal;
            varying vec2 vTexCoord;
            uniform sampler2D uTexture;
            void main() {
                gl_FragColor = texture2D(uTexture, vTexCoord);
            }
        </script>
    </head>
    <body onload="init()">
        <div style="text-align: center">
            <canvas id="canvas" width="512" height="512"></canvas>
        </div>
    </body>
</html>