41 WebGL绘制一个具有交互的立方体

来源:互联网 发布:c语言头文件是什么 编辑:程序博客网 时间:2024/05/21 07:06

增加交互事件,鼠标拖拽立方体上下左右旋转,鼠标滚轮放大缩小立方体。

<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <meta name="viewport"          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">    <meta http-equiv="X-UA-Compatible" content="ie=edge">    <title>Title</title>    <style>        body {            margin: 0;        }        #canvas {            margin: 0;            display: block;        }    </style></head><body onload="main()"><canvas id="canvas" height="800" width="1200"></canvas></body><script src="webgl/webgl-utils.js"></script><script src="webgl/webgl-debug.js"></script><script src="webgl/cuon-utils.js"></script><script src="webgl/cuon-matrix.js"></script><script>    //顶点着色器    var vertexShaderSource = "" +        "attribute vec4 a_Position;\n" +        "attribute vec2 a_TextCoord;\n" +        "uniform mat4 u_MvpMatrix;\n" +        "varying vec2 v_TexCoord;\n" +        "void main(){\n" +        "   gl_Position = u_MvpMatrix * a_Position;\n" +        "   v_TexCoord = a_TextCoord;\n" +        "}\n";    //片元着色器    var fragmentShaderSource = "" +        "#ifdef GL_ES\n" +        "precision mediump float;\n" +        "#endif\n" +        "uniform sampler2D u_Sampler;\n" +        "varying vec2 v_TexCoord;\n" +        "void main(){\n" +        "   gl_FragColor = texture2D(u_Sampler,v_TexCoord);\n" +        "}\n";    function main() {        var canvas = document.getElementById("canvas");        setCss();        window.onresize = function () {            setCss();        };        function setCss() {            canvas.height = window.innerHeight;            canvas.width = window.innerWidth;            canvas.style.width = canvas.width+"px";            canvas.style.height = canvas.height+"px";        }        var gl = getWebGLContext(canvas);        //初始化着色器        initShaders(gl, vertexShaderSource, fragmentShaderSource);        gl.clearColor(0.0, 0.0, 0.0, 1.0);        gl.enable(gl.DEPTH_TEST);        var u_MvpMatrix = gl.getUniformLocation(gl.program, "u_MvpMatrix");        if (!u_MvpMatrix) {            console.log("无法获取变量相关的存储位置");            return;        }        //获取需要绘制图形的次数        var n = initVertexBuffers(gl);        if (n < 0) {            console.log("创建缓冲区失败");            return;        }        //定义一个保存现在角度的数组[x,y,z]        var currentAngle = [0.0,0.0,10.0];        //添加交互的方法        initEventHandlers(canvas,currentAngle);        //将纹理存入着色器        if(!initTextures(gl)){            console.log("无法获取到纹理");            return;        }        //设置一个定时绘制的函数        var tick = function() {   // Start drawing            draw(gl, n, u_MvpMatrix,currentAngle);            requestAnimationFrame(tick);        };        tick();    }    function initEventHandlers(canvas, currentAngle) {        //添加拖拽事件        canvas.onmousedown = function (e) {            var downX = e.clientX;            var downY = e.clientY;            var factorX = 0.3;            var factorY = 0.2;            var beforeAngle = [];            beforeAngle[0] = currentAngle[0];            beforeAngle[1] = currentAngle[1];            beforeAngle[2] = currentAngle[2];            document.onmousemove = function (e) {                var moveX = e.clientX;                var moveY = e.clientY;                var x = factorX * (moveX - downX);                var y = factorY * (moveY - downY);                currentAngle[0] = Math.max(Math.min(beforeAngle[0] + y, 90.0), -90.0);                currentAngle[1] = beforeAngle[1] + x;            };            document.onmouseup = function () {                document.onmousemove = null;                document.onmouseup = null;            }        };        function wheel(e) {            console.log(e);            if (e.wheelDelta) {                //除了firfox浏览器,别的浏览器的处理                changeZ(-e.wheelDelta / 120, e);            } else if (e.detail) {                //firefox浏览器的测试                if (e.detail === -3) {                    changeZ(-1, e);                } else if (e.detail === 3) {                    changeZ(1, e);                } else {                    console.log("鼠标滚轮事件改了?", e);                }            }        }        function changeZ(index) {            console.log(currentAngle[2]);            currentAngle[2] = Math.max(Math.min(currentAngle[2] += index/5,20.0),1.0);        }        //添加鼠标滚轮事件        canvas.addEventListener("mousewheel",wheel);        canvas.addEventListener("DOMMouseScroll",wheel);//兼容火狐    }    function initVertexBuffers(gl) {        // Create a cube        //    v6----- v5        //   /|      /|        //  v1------v0|        //  | |     | |        //  | |v7---|-|v4        //  |/      |/        //  v2------v3        var vertices = new Float32Array([   // Vertex coordinates            1.0, 1.0, 1.0, -1.0, 1.0, 1.0, -1.0, -1.0, 1.0, 1.0, -1.0, 1.0,    // v0-v1-v2-v3 front            1.0, 1.0, 1.0, 1.0, -1.0, 1.0, 1.0, -1.0, -1.0, 1.0, 1.0, -1.0,    // v0-v3-v4-v5 right            1.0, 1.0, 1.0, 1.0, 1.0, -1.0, -1.0, 1.0, -1.0, -1.0, 1.0, 1.0,    // v0-v5-v6-v1 up            -1.0, 1.0, 1.0, -1.0, 1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, 1.0,    // v1-v6-v7-v2 left            -1.0, -1.0, -1.0, 1.0, -1.0, -1.0, 1.0, -1.0, 1.0, -1.0, -1.0, 1.0,    // v7-v4-v3-v2 down            1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0     // v4-v7-v6-v5 back        ]);        var texCoords = new Float32Array([   // Texture coordinates            1.0, 1.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0,    // v0-v1-v2-v3 front            0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 1.0, 1.0,    // v0-v3-v4-v5 right            1.0, 0.0, 1.0, 1.0, 0.0, 1.0, 0.0, 0.0,    // v0-v5-v6-v1 up            1.0, 1.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0,    // v1-v6-v7-v2 left            0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0,    // v7-v4-v3-v2 down            0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0     // v4-v7-v6-v5 back        ]);        // Indices of the vertices        var indices = new Uint8Array([            0, 1, 2, 0, 2, 3,    // front            4, 5, 6, 4, 6, 7,    // right            8, 9, 10, 8, 10, 11,    // up            12, 13, 14, 12, 14, 15,    // left            16, 17, 18, 16, 18, 19,    // down            20, 21, 22, 20, 22, 23     // back        ]);        //上面的立方的顶点坐标,纹理坐标和索引都是偷的教程上面的        //将顶点和纹理坐标都存储到缓冲区        if (!initArrayBuffer(gl, vertices, 3, gl.FLOAT, "a_Position")) {            return -1;        }        if (!initArrayBuffer(gl, texCoords, 2, gl.FLOAT, "a_TextCoord")) {            return -1;        }        //处理下标        var indexBuffer = gl.createBuffer();        if (!indexBuffer) {            console.log("无法创建缓冲区");            return -1;        }        gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);        gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, gl.STATIC_DRAW);        return indices.length;    }    function initArrayBuffer(gl, data, num, type, attribute) {        var buffer = gl.createBuffer();        if (!buffer) {            console.log("无法创建缓冲区对象");            return;        }        gl.bindBuffer(gl.ARRAY_BUFFER, buffer);        gl.bufferData(gl.ARRAY_BUFFER, data, gl.STATIC_DRAW);        var a_attribute = gl.getAttribLocation(gl.program, attribute);        if (a_attribute < 0) {            console.log("无法获取" + attribute + "变量的存储位置");            return false;        }        gl.vertexAttribPointer(a_attribute, num, type, false, 0, 0);        gl.enableVertexAttribArray(a_attribute);        return true;    }    function initTextures(gl) {        var texture = gl.createTexture();        if(!texture){            console.log("无法创建纹理对象");            return false;        }        var u_Sampler = gl.getUniformLocation(gl.program, "u_Sampler");        if(!u_Sampler){            console.log("无法获取到变量的存储位置");            return false;        }        var image = new Image();        image.onload = function () {            loadTexture(gl,texture,u_Sampler,image);        };        image.src = "./resources/sky_cloud.jpg";        return true;    }    /* 设置纹理相关信息供WebGL使用,并进行绘制*/    function loadTexture(gl,texture,u_Sampler,image) {        //对纹理图像进行y轴反转        gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL,1);        //开启0号纹理单元        gl.activeTexture(gl.TEXTURE0);        //向target绑定纹理对象        gl.bindTexture(gl.TEXTURE_2D,texture);        //配置纹理参数        gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MIN_FILTER,gl.LINEAR);        //配置纹理图像        gl.texImage2D(gl.TEXTURE_2D,0,gl.RGB,gl.RGB,gl.UNSIGNED_BYTE,image);        //将0号纹理传递给着色器        gl.uniform1i(u_Sampler,0);    }    function draw(gl, n, u_MvpMatrix,currentAngle) {        //设置视点位置        var viewProjectionMatrix = new Matrix4();        viewProjectionMatrix.setPerspective(30.0, canvas.width / canvas.height, 1.0, 100.0);        console.log(30.0, canvas.width / canvas.height, 1.0, 100.0);        viewProjectionMatrix.lookAt(0.0, 0.0, currentAngle[2], 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);        var mvpMatrix = new Matrix4();        mvpMatrix.set(viewProjectionMatrix);        mvpMatrix.rotate(currentAngle[0], 1.0, 0.0, 0.0);        mvpMatrix.rotate(currentAngle[1], 0.0, 1.0, 0.0);        gl.uniformMatrix4fv(u_MvpMatrix, false, mvpMatrix.elements);        gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);        gl.drawElements(gl.TRIANGLES, n, gl.UNSIGNED_BYTE, 0);    }</script></html>


将代码封装上传到了网上,作为保存,地址是http://download.csdn.net/detail/qq_30100043/9870043

原创粉丝点击