WEBGL学习【十二】鼠标操作场景
阅读原文时间:2023年07月16日阅读:2




Listing 7-3 and 7-4, Texturing and Lighting With the Phong Reflection Model.


<meta charset="utf-8">  
<script id="shader-vs" type="x-shader/x-vertex">  
  // Vertex shader implemented to perform lighting according to the  
  // Phong reflection model. Forwards texture coordinates to fragment  
  // shader.  
  attribute vec3 aVertexPosition;  
  attribute vec3 aVertexNormal;  
  attribute vec2 aTextureCoordinates;

  uniform mat4 uMVMatrix;  
  uniform mat4 uPMatrix;  
  uniform mat3 uNMatrix;

  uniform vec3 uLightPosition;  
  uniform vec3 uAmbientLightColor;  
  uniform vec3 uDiffuseLightColor;  
  uniform vec3 uSpecularLightColor;

  varying vec2 vTextureCoordinates;  
  varying vec3 vLightWeighting;

  const float shininess = 32.0;

  void main() {  
    // Get the vertex position in eye coordinates  
    vec4 vertexPositionEye4 = uMVMatrix \* vec4(aVertexPosition, 1.0);  
    vec3 vertexPositionEye3 = vertexPositionEye4.xyz / vertexPositionEye4.w;

    // Calculate the vector (l) to the light source  
    vec3 vectorToLightSource = normalize(uLightPosition - vertexPositionEye3);

    // Transform the normal (n) to eye coordinates  
    vec3 normalEye = normalize(uNMatrix \* aVertexNormal);

    // Calculate n dot l for diffuse lighting  
    float diffuseLightWeightning = max(dot(normalEye,  
                                       vectorToLightSource), 0.0);

    // Calculate the reflection vector (r) that is needed for specular light  
    vec3 reflectionVector = normalize(reflect(-vectorToLightSource,  
                                               normalEye));

    // The camera in eye coordinates is located in the origin and is pointing  
    // along the negative z-axis. Calculate viewVector (v) in eye coordinates as:  
    // (0.0, 0.0, 0.0) - vertexPositionEye3  
    vec3 viewVectorEye = -normalize(vertexPositionEye3);

    float rdotv = max(dot(reflectionVector, viewVectorEye), 0.0);

    float specularLightWeightning = pow(rdotv, shininess);

    // Sum up all three reflection components and send to the fragment shader  
    vLightWeighting = uAmbientLightColor +  
                      uDiffuseLightColor \* diffuseLightWeightning +  
                      uSpecularLightColor \* specularLightWeightning;

     // Finally transform the geometry  
     gl\_Position = uPMatrix \* uMVMatrix \* vec4(aVertexPosition, 1.0);  
     vTextureCoordinates = aTextureCoordinates;  
  }  
</script>

<!--片元着色器-->  
<script id="shader-fs" type="x-shader/x-fragment">  
  precision mediump float;

  varying vec2 vTextureCoordinates;  
  varying vec3 vLightWeighting;  
  uniform sampler2D uSampler;

  void main() {  
    vec4 texelColor = texture2D(uSampler, vTextureCoordinates);

    //结合了纹理和光照的片段着色器(vLightWeighting包含已经计算得到的环境光和漫反射光)  
    gl\_FragColor = vec4(vLightWeighting.rgb \* texelColor.rgb, texelColor.a);  
  }  
</script>

<script type="text/javascript">  
    // globals  
    var gl;  
    var pwgl = {};  
    // Keep track of ongoing image loads to be able to handle lost context  
    pwgl.**ongoingImageLoads** \= \[\];  
    var canvas;

    function createGLContext(canvas) {  
        var names = \["webgl", "experimental-webgl"\];  
        var context = null;  
        for (var i=0; i < names.**length**; i++) {  
            try {  
                context = canvas.**getContext**(names\[i\]);  
            } catch(e) {}  
            if (context) {  
                break;  
            }  
        }  
        if (context) {  
            context.**viewportWidth** \= canvas.**width**;  
            context.**viewportHeight** \= canvas.**height**;  
        } else {  
            alert("Failed to create WebGL context!");  
        }  
        return context;  
    }

    function loadShaderFromDOM(id) {  
        var shaderScript = **document**.getElementById(id);

        // If we don't find an element with the specified id  
        // we do an early exit  
        if (!shaderScript) {  
            return null;  
        }

        // Loop through the children for the found DOM element and  
        // build up the shader source code as a string  
        var shaderSource = "";  
        var currentChild = shaderScript.**firstChild**;  
        while (currentChild) {  
            if (currentChild.**nodeType** \== 3) { // 3 corresponds to TEXT\_NODE  
                shaderSource += currentChild.**textContent**;  
            }  
            currentChild = currentChild.**nextSibling**;  
        }

        var shader;  
        if (shaderScript.**type** \== "x-shader/x-fragment") {  
            shader = gl.**createShader**(gl.**FRAGMENT\_SHADER**);  
        } else if (shaderScript.**type** \== "x-shader/x-vertex") {  
            shader = gl.**createShader**(gl.**VERTEX\_SHADER**);  
        } else {  
            return null;  
        }

        gl.shaderSource(shader, shaderSource);  
        gl.compileShader(shader);

        if (!gl.**getShaderParameter**(shader, gl.**COMPILE\_STATUS**) &&  
            !gl.isContextLost()) {  
            alert(gl.getShaderInfoLog(shader));  
            return null;  
        }  
        return shader;  
    }

    function setupShaders() {  
        var vertexShader = loadShaderFromDOM("shader-vs");  
        var fragmentShader = loadShaderFromDOM("shader-fs");

        var shaderProgram = gl.createProgram();  
        gl.attachShader(shaderProgram, vertexShader);  
        gl.attachShader(shaderProgram, fragmentShader);  
        gl.linkProgram(shaderProgram);

        if (!gl.**getProgramParameter**(shaderProgram, gl.**LINK\_STATUS**) &&  
            !gl.isContextLost()) {  
            alert("Failed to link shaders: " + gl.getProgramInfoLog(shaderProgram));  
        }

        gl.useProgram(shaderProgram);  
        pwgl.**vertexPositionAttributeLoc** \=  
            gl.**getAttribLocation**(shaderProgram, "aVertexPosition");

        pwgl.**vertexNormalAttributeLoc** \=  
            gl.**getAttribLocation**(shaderProgram, "aVertexNormal");

        pwgl.**vertexTextureAttributeLoc** \=  
            gl.**getAttribLocation**(shaderProgram, "aTextureCoordinates");

        pwgl.**uniformMVMatrixLoc** \=  
            gl.getUniformLocation(shaderProgram, "uMVMatrix");

        pwgl.**uniformProjMatrixLoc** \=  
            gl.getUniformLocation(shaderProgram, "uPMatrix");

        pwgl.**uniformNormalMatrixLoc** \=  
            gl.getUniformLocation(shaderProgram, "uNMatrix");

        pwgl.**uniformSamplerLoc** \=  
            gl.getUniformLocation(shaderProgram, "uSampler");

        pwgl.**uniformLightPositionLoc** \=  
            gl.getUniformLocation(shaderProgram, "uLightPosition");

        pwgl.**uniformAmbientLightColorLoc** \=  
            gl.getUniformLocation(shaderProgram, "uAmbientLightColor");

        pwgl.**uniformDiffuseLightColorLoc** \=  
            gl.getUniformLocation(shaderProgram, "uDiffuseLightColor");

        pwgl.**uniformSpecularLightColorLoc** \=  
            gl.getUniformLocation(shaderProgram, "uSpecularLightColor");

        gl.enableVertexAttribArray(pwgl.**vertexPositionAttributeLoc**);  
        gl.enableVertexAttribArray(pwgl.**vertexNormalAttributeLoc**);  
        gl.enableVertexAttribArray(pwgl.**vertexTextureAttributeLoc**);

        pwgl.**modelViewMatrix** \= mat4.create();  
        pwgl.**projectionMatrix** \= mat4.create();  
        pwgl.**modelViewMatrixStack** \= \[\];  
    }

    function pushModelViewMatrix() {  
        var copyToPush = mat4.create(pwgl.**modelViewMatrix**);  
        pwgl.**modelViewMatrixStack**.push(copyToPush);  
    }

    function popModelViewMatrix() {  
        if (pwgl.**modelViewMatrixStack**.**length** \== 0) {  
            throw "Error popModelViewMatrix() - Stack was empty ";  
        }  
        pwgl.**modelViewMatrix** \= pwgl.**modelViewMatrixStack**.pop();  
    }

    function setupFloorBuffers() {  
        pwgl.**floorVertexPositionBuffer** \= gl.createBuffer();  
        gl.**bindBuffer**(gl.**ARRAY\_BUFFER**, pwgl.**floorVertexPositionBuffer**);

        var floorVertexPosition = \[  
            // Plane in y=0  
            5.0,   0.0,  5.0,  //v0  
            5.0,   0.0, -5.0,  //v1  
            -5.0,   0.0, -5.0,  //v2  
            -5.0,   0.0,  5.0\]; //v3

        gl.**bufferData**(gl.**ARRAY\_BUFFER**, new Float32Array(floorVertexPosition),  
            gl.**STATIC\_DRAW**);

        pwgl.**FLOOR\_VERTEX\_POS\_BUF\_ITEM\_SIZE** \= 3;  
        pwgl.**FLOOR\_VERTEX\_POS\_BUF\_NUM\_ITEMS** \= 4;

        //指定地板的法向量的方向  
        // Specify normals to be able to do lighting calculations  
        pwgl.**floorVertexNormalBuffer** \= gl.createBuffer();  
        gl.**bindBuffer**(gl.**ARRAY\_BUFFER**, pwgl.**floorVertexNormalBuffer**);

        var floorVertexNormals = \[  
            0.0,   1.0,  0.0,  //v0  
            0.0,   1.0,  0.0,  //v1  
            0.0,   1.0,  0.0,  //v2  
            0.0,   1.0,  0.0\]; //v3

        gl.**bufferData**(gl.**ARRAY\_BUFFER**, new Float32Array(floorVertexNormals),  
            gl.**STATIC\_DRAW**);

        pwgl.**FLOOR\_VERTEX\_NORMAL\_BUF\_ITEM\_SIZE** \= 3;  
        pwgl.**FLOOR\_VERTEX\_NORMAL\_BUF\_NUM\_ITEMS** \= 4;

        // Setup texture coordinates buffer  
        pwgl.**floorVertexTextureCoordinateBuffer** \= gl.createBuffer();  
        gl.**bindBuffer**(gl.**ARRAY\_BUFFER**, pwgl.**floorVertexTextureCoordinateBuffer**);  
        var floorVertexTextureCoordinates = \[  
            2.0, 0.0,  
            2.0, 2.0,  
            0.0, 2.0,  
            0.0, 0.0  
        \];

        gl.**bufferData**(gl.**ARRAY\_BUFFER**, new Float32Array(floorVertexTextureCoordinates),  
            gl.**STATIC\_DRAW**);

        pwgl.**FLOOR\_VERTEX\_TEX\_COORD\_BUF\_ITEM\_SIZE** \= 2;  
        pwgl.**FLOOR\_VERTEX\_TEX\_COORD\_BUF\_NUM\_ITEMS** \= 4;

        // Setup index buffer  
        pwgl.**floorVertexIndexBuffer** \= gl.createBuffer();  
        gl.**bindBuffer**(gl.**ELEMENT\_ARRAY\_BUFFER**, pwgl.**floorVertexIndexBuffer**);  
        var floorVertexIndices = \[0, 1, 2, 3\];

        gl.**bufferData**(gl.**ELEMENT\_ARRAY\_BUFFER**, new Uint16Array(floorVertexIndices),  
            gl.**STATIC\_DRAW**);

        pwgl.**FLOOR\_VERTEX\_INDEX\_BUF\_ITEM\_SIZE** \= 1;  
        pwgl.**FLOOR\_VERTEX\_INDEX\_BUF\_NUM\_ITEMS** \= 4;  
    }

    function setupCubeBuffers() {  
        pwgl.**cubeVertexPositionBuffer** \= gl.createBuffer();  
        gl.**bindBuffer**(gl.**ARRAY\_BUFFER**, pwgl.**cubeVertexPositionBuffer**);

        var cubeVertexPosition = \[  
            // Front face  
            1.0,  1.0,  1.0, //v0  
            -1.0,  1.0,  1.0, //v1  
            -1.0, -1.0,  1.0, //v2  
            1.0, -1.0,  1.0, //v3

            // Back face  
            1.0,  1.0, -1.0, //v4  
            -1.0,  1.0, -1.0, //v5  
            -1.0, -1.0, -1.0, //v6  
            1.0, -1.0, -1.0, //v7

            // Left face  
            -1.0,  1.0,  1.0, //v8  
            -1.0,  1.0, -1.0, //v9  
            -1.0, -1.0, -1.0, //v10  
            -1.0, -1.0,  1.0, //v11

            // Right face  
            1.0,  1.0,  1.0, //12  
            1.0, -1.0,  1.0, //13  
            1.0, -1.0, -1.0, //14  
            1.0,  1.0, -1.0, //15

            // Top face  
            1.0,  1.0,  1.0, //v16  
            1.0,  1.0, -1.0, //v17  
            -1.0,  1.0, -1.0, //v18  
            -1.0,  1.0,  1.0, //v19

            // Bottom face  
            1.0, -1.0,  1.0, //v20  
            1.0, -1.0, -1.0, //v21  
            -1.0, -1.0, -1.0, //v22  
            -1.0, -1.0,  1.0, //v23  
        \];

        gl.**bufferData**(gl.**ARRAY\_BUFFER**, new Float32Array(cubeVertexPosition),  
            gl.**STATIC\_DRAW**);

        pwgl.**CUBE\_VERTEX\_POS\_BUF\_ITEM\_SIZE** \= 3;  
        pwgl.**CUBE\_VERTEX\_POS\_BUF\_NUM\_ITEMS** \= 24;

        // Specify normals to be able to do lighting calculations  
        pwgl.**cubeVertexNormalBuffer** \= gl.createBuffer();  
        gl.**bindBuffer**(gl.**ARRAY\_BUFFER**, pwgl.**cubeVertexNormalBuffer**);

        //指定立方体的每一个面的法向量  
        var cubeVertexNormals = \[  
            // Front face  
            0.0,  0.0,  1.0, //v0  
            0.0,  0.0,  1.0, //v1  
            0.0,  0.0,  1.0, //v2  
            0.0,  0.0,  1.0, //v3

            // Back face  
            0.0,  0.0, -1.0, //v4  
            0.0,  0.0, -1.0, //v5  
            0.0,  0.0, -1.0, //v6  
            0.0,  0.0, -1.0, //v7

            // Left face  
            -1.0,  0.0,  0.0, //v8  
            -1.0,  0.0,  0.0, //v9  
            -1.0,  0.0,  0.0, //v10  
            -1.0,  0.0,  0.0, //v11

            // Right face  
            1.0,  0.0,  0.0, //12  
            1.0,  0.0,  0.0, //13  
            1.0,  0.0,  0.0, //14  
            1.0,  0.0,  0.0, //15

            // Top face  
            0.0,  1.0,  0.0, //v16  
            0.0,  1.0,  0.0, //v17  
            0.0,  1.0,  0.0, //v18  
            0.0,  1.0,  0.0, //v19

            // Bottom face  
            0.0, -1.0,  0.0, //v20  
            0.0, -1.0,  0.0, //v21  
            0.0, -1.0,  0.0, //v22  
            0.0, -1.0,  0.0, //v23  
        \];

        gl.**bufferData**(gl.**ARRAY\_BUFFER**, new Float32Array(cubeVertexNormals),  
            gl.**STATIC\_DRAW**);

        pwgl.**CUBE\_VERTEX\_NORMAL\_BUF\_ITEM\_SIZE** \= 3;  
        pwgl.**CUBE\_VERTEX\_NORMAL\_BUF\_NUM\_ITEMS** \= 24;

        // Setup buffer with texture coordinates  
        pwgl.**cubeVertexTextureCoordinateBuffer** \= gl.createBuffer();  
        gl.**bindBuffer**(gl.**ARRAY\_BUFFER**, pwgl.**cubeVertexTextureCoordinateBuffer**);  
        var textureCoordinates = \[  
            //Front face  
            0.0, 0.0, //v0  
            1.0, 0.0, //v1  
            1.0, 1.0, //v2  
            0.0, 1.0, //v3

            // Back face  
            0.0, 1.0, //v4  
            1.0, 1.0, //v5  
            1.0, 0.0, //v6  
            0.0, 0.0, //v7

            // Left face  
            0.0, 1.0, //v8  
            1.0, 1.0, //v9  
            1.0, 0.0, //v10  
            0.0, 0.0, //v11

            // Right face  
            0.0, 1.0, //v12  
            1.0, 1.0, //v13  
            1.0, 0.0, //v14  
            0.0, 0.0, //v15

            // Top face  
            0.0, 1.0, //v16  
            1.0, 1.0, //v17  
            1.0, 0.0, //v18  
            0.0, 0.0, //v19

            // Bottom face  
            0.0, 1.0, //v20  
            1.0, 1.0, //v21  
            1.0, 0.0, //v22  
            0.0, 0.0, //v23  
        \];

        gl.**bufferData**(gl.**ARRAY\_BUFFER**, new Float32Array(textureCoordinates),gl.**STATIC\_DRAW**);  
        pwgl.**CUBE\_VERTEX\_TEX\_COORD\_BUF\_ITEM\_SIZE** \= 2;  
        pwgl.**CUBE\_VERTEX\_TEX\_COORD\_BUF\_NUM\_ITEMS** \= 24;

        pwgl.**cubeVertexIndexBuffer** \= gl.createBuffer();  
        gl.**bindBuffer**(gl.**ELEMENT\_ARRAY\_BUFFER**, pwgl.**cubeVertexIndexBuffer**);  
        var cubeVertexIndices = \[  
            0, 1, 2,      0, 2, 3,    // Front face  
            4, 6, 5,      4, 7, 6,    // Back face  
            8, 9, 10,     8, 10, 11,  // Left face  
            12, 13, 14,   12, 14, 15, // Right face  
            16, 17, 18,   16, 18, 19, // Top face  
            20, 22, 21,   20, 23, 22  // Bottom face  
        \];  
        gl.**bufferData**(gl.**ELEMENT\_ARRAY\_BUFFER**, new Uint16Array(cubeVertexIndices),  
            gl.**STATIC\_DRAW**);  
        pwgl.**CUBE\_VERTEX\_INDEX\_BUF\_ITEM\_SIZE** \= 1;  
        pwgl.**CUBE\_VERTEX\_INDEX\_BUF\_NUM\_ITEMS** \= 36;  
    }

    function textureFinishedLoading(image, texture) {  
        gl.**bindTexture**(gl.**TEXTURE\_2D**, texture);  
        gl.**pixelStorei**(gl.**UNPACK\_FLIP\_Y\_WEBGL**, true);

        gl.**texImage2D**(gl.**TEXTURE\_2D**, 0, gl.**RGBA**, gl.**RGBA**, gl.**UNSIGNED\_BYTE**,  
            image);

        gl.**generateMipmap**(gl.**TEXTURE\_2D**);

        gl.**texParameteri**(gl.**TEXTURE\_2D**, gl.**TEXTURE\_MAG\_FILTER**, gl.**LINEAR**);  
        gl.**texParameteri**(gl.**TEXTURE\_2D**, gl.**TEXTURE\_MIN\_FILTER**, gl.**LINEAR**);

        gl.**texParameteri**(gl.**TEXTURE\_2D**, gl.**TEXTURE\_WRAP\_S**, gl.**MIRRORED\_REPEAT**);  
        gl.**texParameteri**(gl.**TEXTURE\_2D**, gl.**TEXTURE\_WRAP\_T**, gl.**MIRRORED\_REPEAT**);  
        gl.**bindTexture**(gl.**TEXTURE\_2D**, null);  
    }

    function loadImageForTexture(url, texture) {  
        var image = new **Image**();  
        image.**onload** \= function() {  
            pwgl.**ongoingImageLoads**.splice(pwgl.**ongoingImageLoads**.indexOf(image), 1);  
            textureFinishedLoading(image, texture);  
        }  
        pwgl.**ongoingImageLoads**.push(image);  
        image.**src** \= url;  
    }

    function setupTextures() {  
        // Texture for the table  
        pwgl.**woodTexture** \= gl.createTexture();  
        loadImageForTexture("./resources/wood\_128x128.jpg", pwgl.**woodTexture**);

        // Texture for the floor  
        pwgl.**groundTexture** \= gl.createTexture();  
        loadImageForTexture("./resources/wood\_floor\_256.jpg", pwgl.**groundTexture**);

        // Texture for the box on the table  
        pwgl.**boxTexture** \= gl.createTexture();  
        loadImageForTexture("./resources/wicker\_256.jpg", pwgl.**boxTexture**);

        //创建一个立方体  
        pwgl.**colorCube** \= gl.createTexture();  
        loadImageForTexture("./resources/xiuxiuba.bmp", pwgl.**colorCube**);  
    }

    function setupBuffers() {  
        setupFloorBuffers();  
        setupCubeBuffers();  
    }

    //设置光源位置,环境光颜色,漫反射光颜色,镜面反射光  
    function setupLights() {  
        gl.uniform3fv(pwgl.**uniformLightPositionLoc**, \[0.0, 20.0, 0.0\]);  
        gl.uniform3fv(pwgl.**uniformAmbientLightColorLoc**, \[0.2, 0.2, 0.2\]);  
        gl.uniform3fv(pwgl.**uniformDiffuseLightColorLoc**, \[0.7, 0.7, 0.7\]);  
        gl.uniform3fv(pwgl.**uniformSpecularLightColorLoc**, \[0.8, 0.8, 0.8\]);  
    }

    function uploadModelViewMatrixToShader() {  
        gl.uniformMatrix4fv(pwgl.**uniformMVMatrixLoc**, false, pwgl.**modelViewMatrix**);  
    }

    function uploadProjectionMatrixToShader() {  
        gl.uniformMatrix4fv(pwgl.**uniformProjMatrixLoc**,  
            false, pwgl.**projectionMatrix**);  
    }

    //上传法向量的矩阵到着色器  
    function uploadNormalMatrixToShader() {  
        var normalMatrix = mat3.create();  
        //计算矩阵的逆  
        mat4.toInverseMat3(pwgl.**modelViewMatrix**, normalMatrix);  
        //计算转置矩阵  
        mat3.transpose(normalMatrix);  
        //把法向量矩阵传给着色器  
        gl.uniformMatrix3fv(pwgl.**uniformNormalMatrixLoc**, false, normalMatrix);  
    }

    function drawFloor() {  
        // Bind position buffer  
        gl.**bindBuffer**(gl.**ARRAY\_BUFFER**, pwgl.**floorVertexPositionBuffer**);  
        gl.**vertexAttribPointer**(pwgl.**vertexPositionAttributeLoc**,  
            pwgl.**FLOOR\_VERTEX\_POS\_BUF\_ITEM\_SIZE**,  
            gl.**FLOAT**, false, 0, 0);

        // Bind normal buffer  
        gl.**bindBuffer**(gl.**ARRAY\_BUFFER**, pwgl.**floorVertexNormalBuffer**);  
        gl.**vertexAttribPointer**(pwgl.**vertexNormalAttributeLoc**,  
            pwgl.**FLOOR\_VERTEX\_NORMAL\_BUF\_ITEM\_SIZE**,  
            gl.**FLOAT**, false, 0, 0);

        // Bind texture coordinate buffer  
        gl.**bindBuffer**(gl.**ARRAY\_BUFFER**, pwgl.**floorVertexTextureCoordinateBuffer**);  
        gl.**vertexAttribPointer**(pwgl.**vertexTextureAttributeLoc**,  
            pwgl.**FLOOR\_VERTEX\_TEX\_COORD\_BUF\_ITEM\_SIZE**,  
            gl.**FLOAT**, false, 0, 0);

        gl.**activeTexture**(gl.**TEXTURE0**);  
        gl.**bindTexture**(gl.**TEXTURE\_2D**, pwgl.**groundTexture**);

        // Bind index buffer and draw the floor  
        gl.**bindBuffer**(gl.**ELEMENT\_ARRAY\_BUFFER**, pwgl.**floorVertexIndexBuffer**);  
        gl.**drawElements**(gl.**TRIANGLE\_FAN**, pwgl.**FLOOR\_VERTEX\_INDEX\_BUF\_NUM\_ITEMS**,  
            gl.**UNSIGNED\_SHORT**, 0);  
    }

    function drawCube(texture) {  
        // Bind position buffer  
        gl.**bindBuffer**(gl.**ARRAY\_BUFFER**, pwgl.**cubeVertexPositionBuffer**);  
        gl.**vertexAttribPointer**(pwgl.**vertexPositionAttributeLoc**,  
            pwgl.**CUBE\_VERTEX\_POS\_BUF\_ITEM\_SIZE**,  
            gl.**FLOAT**, false, 0, 0);

        // Bind normal buffer  
        gl.**bindBuffer**(gl.**ARRAY\_BUFFER**, pwgl.**cubeVertexNormalBuffer**);  
        gl.**vertexAttribPointer**(pwgl.**vertexNormalAttributeLoc**,  
            pwgl.**CUBE\_VERTEX\_NORMAL\_BUF\_ITEM\_SIZE**,  
            gl.**FLOAT**, false, 0, 0);

        // Bind texture coordinate buffer  
        gl.**bindBuffer**(gl.**ARRAY\_BUFFER**, pwgl.**cubeVertexTextureCoordinateBuffer**);  
        gl.**vertexAttribPointer**(pwgl.**vertexTextureAttributeLoc**,  
            pwgl.**CUBE\_VERTEX\_TEX\_COORD\_BUF\_ITEM\_SIZE**,  
            gl.**FLOAT**, false, 0, 0);

        gl.**activeTexture**(gl.**TEXTURE0**);  
        gl.**bindTexture**(gl.**TEXTURE\_2D**, texture);

        // Bind index buffer and draw cube  
        gl.**bindBuffer**(gl.**ELEMENT\_ARRAY\_BUFFER**, pwgl.**cubeVertexIndexBuffer**);

        gl.**drawElements**(gl.**TRIANGLES**, pwgl.**CUBE\_VERTEX\_INDEX\_BUF\_NUM\_ITEMS**,  
            gl.**UNSIGNED\_SHORT**, 0);  
    }

    function drawTable(){  
        // Draw a simple table by modifying the modelview matrix  
        // (translate and scale) and then use the function drawCube()  
        // to draw a table top and four table legs.

        pushModelViewMatrix();  
        mat4.translate(pwgl.**modelViewMatrix**, \[0.0, 1.0, 0.0\], pwgl.**modelViewMatrix**);  
        mat4.scale(pwgl.**modelViewMatrix**, \[2.0, 0.1, 2.0\], pwgl.**modelViewMatrix**);  
        uploadModelViewMatrixToShader();  
        uploadNormalMatrixToShader();  
        // Draw the actual cube (now scaled to a cuboid) with woodTexture  
        drawCube(pwgl.**woodTexture**);  
        popModelViewMatrix();

        // Draw the table legs  
        for (var i=-1; i<=1; i+=2) {  
            for (var j= -1; j<=1; j+=2) {  
                pushModelViewMatrix();  
                mat4.translate(pwgl.**modelViewMatrix**, \[i\*1.9, -0.1, j\*1.9\], pwgl.**modelViewMatrix**);  
                mat4.scale(pwgl.**modelViewMatrix**, \[0.1, 1.0, 0.1\], pwgl.**modelViewMatrix**);  
                uploadModelViewMatrixToShader();  
                uploadNormalMatrixToShader();  
                drawCube(pwgl.**woodTexture**);  
                popModelViewMatrix();  
            }  
        }  
    }

    //var currentAngle;  
    function draw(currentTime) {  
        pwgl.**requestId** \= **requestAnimFrame**(draw);  
        if (currentTime === **undefined**) {  
            currentTime = Date.now();  
        }  
        currentTime = Date.now();

        // Update FPS if a second or more has passed since last FPS update  
        if(currentTime - pwgl.**previousFrameTimeStamp** \>= 1000) {  
            pwgl.**fpsCounter**.**innerHTML** \= pwgl.**nbrOfFramesForFPS**;  
            pwgl.**nbrOfFramesForFPS** \= 0;  
            pwgl.**previousFrameTimeStamp** \= currentTime;  
        }

        gl.viewport(0, 0, gl.**viewportWidth**, gl.**viewportHeight**);  
        gl.clear(gl.**COLOR\_BUFFER\_BIT** | gl.**DEPTH\_BUFFER\_BIT**);  
        mat4.perspective(60, gl.**viewportWidth** / gl.**viewportHeight**,  
            1, 100.0, pwgl.**projectionMatrix**);  
        mat4.identity(pwgl.**modelViewMatrix**);  
        mat4.lookAt(\[8, 12, 8\],\[0, 0, 0\], \[0, 1,0\], pwgl.**modelViewMatrix**);  
        mat4.rotateY(pwgl.**modelViewMatrix**, pwgl.**yRot**, pwgl.**modelViewMatrix**);

        //旋转  
        pwgl.**yRot** += 0.01;  
        //鼠标移动  
        mat4.rotateX(pwgl.**modelViewMatrix**, pwgl.**currentAngle**\[0\], pwgl.**modelViewMatrix**);  
        mat4.rotateY(pwgl.**modelViewMatrix**, pwgl.**currentAngle**\[1\], pwgl.**modelViewMatrix**);  
        //鼠标滚轮  
        mat4.translate(pwgl.**modelViewMatrix**, \[0, 0, pwgl.**zTri**\], pwgl.**modelViewMatrix**);

        uploadModelViewMatrixToShader();  
        uploadProjectionMatrixToShader();  
        uploadNormalMatrixToShader();  
        gl.uniform1i(pwgl.**uniformSamplerLoc**, 0);

        drawFloor();

        // Draw table  
        pushModelViewMatrix();  
        mat4.translate(pwgl.**modelViewMatrix**, \[0.0, 1.1, 0.0\], pwgl.**modelViewMatrix**);  
        uploadModelViewMatrixToShader();  
        uploadNormalMatrixToShader();  
        drawTable();  
        popModelViewMatrix();

        // Calculate the position for the box that is initially  
        // on top of the table but will then be moved during animation  
        pushModelViewMatrix();  
        if (currentTime === **undefined**) {  
            currentTime = Date.now();  
        }  
        if (pwgl.**animationStartTime** \=== **undefined**) {  
            pwgl.**animationStartTime** \= currentTime;  
        }  
        // Update the position of the box  
        if (pwgl.**y** < 5) {  
            // First move the box vertically from its original position on top of  
            // the table (where y = 2.7) to 5 units above the floor (y = 5).  
            // Let this movement take 3 seconds  
            pwgl.**y** \= 2.7 + (currentTime - pwgl.**animationStartTime**)/3000 \* (5.0-2.7);  
        }  
        else {  
            // Then move the box in a circle where one revolution takes 2 seconds  
            pwgl.**angle** \= (currentTime - pwgl.**animationStartTime**)/2000\*2\*Math.**PI** % (2\*Math.**PI**);

            pwgl.**x** \= Math.cos(pwgl.**angle**) \* pwgl.**circleRadius**;  
            pwgl.**z** \= Math.sin(pwgl.**angle**) \* pwgl.**circleRadius**;  
        }

        mat4.translate(pwgl.**modelViewMatrix**, \[pwgl.**x**, pwgl.**y**, pwgl.**z**\], pwgl.**modelViewMatrix**);  
        mat4.scale(pwgl.**modelViewMatrix**, \[0.5, 0.5, 0.5\], pwgl.**modelViewMatrix**);  
        uploadModelViewMatrixToShader();  
        uploadNormalMatrixToShader();  
        drawCube(pwgl.**boxTexture**);  
        popModelViewMatrix();

        // Update number of drawn frames to be able to count fps  
        pwgl.**nbrOfFramesForFPS**++;  
    }

    function handleContextLost(event) {  
        event.preventDefault();  
        **cancelRequestAnimFrame**(pwgl.**requestId**);

        // Ignore all ongoing image loads by removing  
        // their onload handler  
        for (var i = 0; i < pwgl.**ongoingImageLoads**.**length**; i++) {  
            pwgl.**ongoingImageLoads**\[i\].**onload** \= **undefined**;  
        }  
        pwgl.**ongoingImageLoads** \= \[\];  
    }

    function init() {  
        // Initialization that is performed during first startup, but when the  
        // event webglcontextrestored is received is included in this function.  
        setupShaders();  
        setupBuffers();  
        setupLights();  
        setupTextures();  
        gl.clearColor(0.0, 0.0, 0.0, 1.0);  
        gl.**enable**(gl.**DEPTH\_TEST**);

        // Initialize some varibles for the moving box  
        pwgl.**x** \= 0.0;  
        pwgl.**y** \= 2.7;  
        pwgl.**z** \= 0.0;  
        pwgl.**circleRadius** \= 4.0;  
        pwgl.**angle** \= 0;

        //Y轴旋转角度  
        pwgl.**yRot** \= 0;  
        //Z轴移动角度  
        pwgl.**zTri** \= 0;

        // Initialize some variables related to the animation  
        pwgl.**animationStartTime** \= **undefined**;  
        pwgl.**nbrOfFramesForFPS** \= 0;  
        pwgl.**previousFrameTimeStamp** \= Date.now();  
    }

    function handleContextRestored(event) {  
        init();  
        pwgl.**requestId** \= **requestAnimFrame**(draw,canvas);  
    }

    //处理鼠标的事件  
    var dragging = false;         // Dragging or not  
    var lastX = -1, lastY = -1;   // Last position of the mouse  
    function handleMouseDown(ev) {  
        var x = ev.**clientX**, y = ev.**clientY**;  
        // Start dragging if a moue is in <canvas>  
        var rect = ev.**target**.getBoundingClientRect();  
        if (rect.**left** <= x && x < rect.**right** && rect.**top** <= y && y < rect.**bottom**) {  
            lastX = x; lastY = y;  
            dragging = true;  
        }  
    }  
    function handleMouseMove(ev) {  
        var x = ev.**clientX**, y = ev.**clientY**;  
        if (dragging) {  
            var factor = 100/canvas.**height**; // The rotation ratio  
            var dx = factor \* (x - lastX);  
            var dy = factor \* (y - lastY);  
            // Limit x-axis rotation angle to -90 to 90 degrees  
            pwgl.**currentAngle**\[0\] = Math.max(Math.min(pwgl.**currentAngle**\[0\] + dy, 90.0), -90.0);  
            pwgl.**currentAngle**\[1\] = pwgl.**currentAngle**\[1\] + dx;  
        }  
        lastX = x, lastY = y;  
    }  
    function handleMouseUp() {  
        dragging = false;  
    }

    /\*  
    \* 在非firefox浏览器中,滚轮向上滚动返回的数值是120,向下滚动返回-120  
        而在firefox浏览器中,滚轮向上滚动返回的数值是-3,向下滚动返回3  
    \* \*/  
    //鼠标滚轮  
    var scrollFunc = function (e) {  
        e = e || **window**.**event**;

        var t1 = **document**.getElementById("wheelDelta");  
        var t2 = **document**.getElementById("detail");  
        if (e.**wheelDelta**) {//IE/Opera/Chrome  
            t1.**value** \= "IE、Opera、Safari、Chrome";  
            t2.**value** \= e.**wheelDelta**;  
            if (e.**wheelDelta** \== 120){  
                pwgl.**zTri** += 1.0;  
            } else {  
                pwgl.**zTri** \-= 1.0;  
            }  
        } else if (e.**detail**) {//Firefox  
            t1.**value** \= "Firefox";  
            t2.**value** \= e.**detail**;  
            if (e.**wheelDelta** \== -3){  
                pwgl.**zTri** += 1.0;  
            } else {  
                pwgl.**zTri** \-= 1.0;  
            }  
        }  
        //ScrollText(direct);

    }  
    /\*注册事件\*/  
    if (**document**.addEventListener) {  
        **document**.addEventListener('DOMMouseScroll', scrollFunc, false);  
    }//W3C  
    **window**.**onmousewheel** \= **document**.onmousewheel = scrollFunc;//IE/Opera/Chrome/Safari

    function startup() {  
        canvas = **document**.getElementById("myGLCanvas");  
        canvas = **WebGLDebugUtils**.makeLostContextSimulatingContext(canvas);

        canvas.addEventListener('webglcontextlost', handleContextLost, false);  
        canvas.addEventListener('webglcontextrestored', handleContextRestored, false);  
        //canvas.addEventListener("", )  
        canvas.addEventListener('mousedown', handleMouseDown, false);  
        canvas.addEventListener('mousemove', handleMouseMove, false);  
        canvas.addEventListener('mouseup', handleMouseUp, false);  
        //canvas.addEventListener('onmousewheel', handlemosew)

        gl = createGLContext(canvas);  
        init();

        //注册一个事件响应的函数【鼠标移动控制】  
        pwgl.**currentAngle** \= \[0.0, 0.0\];  
        //initEventHandlers(canvas, currentAngle);

        pwgl.**fpsCounter** \= **document**.getElementById("fps");

        // Uncomment the three lines of code below to be able to test lost context  
        // window.addEventListener('mousedown', function() {  
        //   canvas.loseContext();  
        // });

        // Draw the complete scene  
        draw();  
    }  
</script>

FPS: --

(IE/Opera)


手机扫一扫

移动阅读更方便

阿里云服务器
腾讯云服务器
七牛云服务器

你可能感兴趣的文章