zoukankan      html  css  js  c++  java
  • WEBGL学习【十二】鼠标操作场景

    <!DOCTYPE HTML>
    <html lang="en">
    <head>
        <title>Listing 7-3 and 7-4, Texturing and Lighting With the Phong Reflection Model.</title>
        <script src="./lib/webgl-debug.js"></script>
        <script src="./lib/glMatrix.js"></script>
        <script src="./lib/webgl-utils.js"></script>
    
        <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 = "IEOperaSafariChrome";
                    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>
    
    </head>
    
    <body onload="startup();">
    <canvas id="myGLCanvas" width="500" height="500"></canvas>
    <div id="fps-counter">
        FPS: <span id="fps">--</span>
    </div>
    <p><label for="wheelDelta"> 浏览器类型:</label>(IE/Opera)<input type="text" id="wheelDelta"/></p>
    <p><label for="detail"> 滚动值:</label><input type="text" id="detail"/></p>
    </body>
    
    </html>
    
  • 相关阅读:
    Apache-Shiro
    Linux下的Nginx安装
    Linux安装Redis
    Linux安装ftp组件vsftpd
    Spring笔记(二)
    Spring笔记(一)
    MySQL事务
    rocketMQ基本理解
    2018面试题小结
    v-if和v-show
  • 原文地址:https://www.cnblogs.com/52tech/p/9325112.html
Copyright © 2011-2022 走看看