SOURCE

console 命令行工具 X clear

                    
>
console
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <!-- import CSS -->
    <script type="text/javascript" src="https://cdn.bootcdn.net/ajax/libs/gl-matrix/3.4.2/gl-matrix.js"></script>
    <!-- 最新版本的 Bootstrap 核心 CSS 文件 -->
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css"
          integrity="sha384-HSMxcRTRxnN+Bdg0JdbxYKrThecOKuH5zCYotlSAcp1+c8xmyTe9GYg1l9a69psu" crossorigin="anonymous">

    <!-- 可选的 Bootstrap 主题文件(一般不用引入) -->
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap-theme.min.css"
          integrity="sha384-6pzBo3FDv/PJ8r2KRkGHifhEocL+1X2rVCTTkUfGk7/0pbek5mMa1upzvWbrUbOZ" crossorigin="anonymous">

    <!-- jQuery (Bootstrap 的所有 JavaScript 插件都依赖 jQuery,所以必须放在前边) -->
    <script src="https://fastly.jsdelivr.net/npm/jquery@1.12.4/dist/jquery.min.js"
            integrity="sha384-nvAa0+6Qg9clwYCGGPpDQLVpLNn0fRaROjHqs13t4Ggj3Ez50XnGQqc/r8MhnRDZ"
            crossorigin="anonymous"></script>
    <!-- 最新的 Bootstrap 核心 JavaScript 文件 -->
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js"
            integrity="sha384-aJ21OjlMXNL5UyIl/XNwTMqvzeRMZH2w8c5cRVpzpU8Y5bApTppSuUkhZXN0VxHd"
            crossorigin="anonymous"></script>
    <style type="text/css">
        .myBtn {
            position: absolute;
            width: 150px;
            display: flex;
            flex-direction: column;
            margin: 4px;
            color: #845EC2;

        }
    </style>
    <script id="vShader" type="x-shader/x-vertex">
        attribute vec3 aVertexPosition;
        attribute vec4 aVertexColor;
        varying vec4 vColor;
        uniform mat4 uMVMatrix;
        uniform mat4 uProjectMatrix;
        void main(){
            gl_Position = uProjectMatrix * uMVMatrix * vec4(aVertexPosition, 1.0);
            vColor = aVertexColor;
        }
    </script>
    <script id="fShader" type="x-shader/x-fragment">
        precision mediump float;
        varying vec4 vColor;
        void main(){
            gl_FragColor = vColor;
        }
    </script>
</head>
<body>
<div class="myBtn">
    <button type="button" id="myButton2" data-loading-text="Loading..." class="btn btn-primary">
        开始/暂停旋转摄像机
    </button>
    <button type="button" id="myButton" data-loading-text="Loading..." class="btn btn-primary">
        开始/暂停旋转立方体
    </button>
</div>
<canvas id="myCanvas" width="800" height="800"></canvas>
<script type="text/javascript">

    let canvas;
    let gl;
    let shaderProgram;
    let cubeBuffer;
    let cubeAxisBuffer;
    let axisBuffer;
    let mVMatrix;
    let projectionMatrix;
    let mvMatrixStack;
    let thetaCube = 0;
    let thetaCamera = 45;
    let rotateCube = false;
    let rotateCamera = false;
    let timer = -1;


    function loadGlMatrix() {
        window["mat2"] = glMatrix.mat2;
        window["mat2d"] = glMatrix.mat2d;
        window["mat3"] = glMatrix.mat3;
        window["mat4"] = glMatrix.mat4;
        window["quat"] = glMatrix.quat;
        window["quat2"] = glMatrix.quat2;
        window["vec2"] = glMatrix.vec2;
        window["vec3"] = glMatrix.vec3;
        window["vec4"] = glMatrix.vec4;
        window["glMatrix"] = glMatrix.glMatrix;

        mVMatrix = mat4.create();
        projectionMatrix = mat4.create();
        mvMatrixStack = [];
    }

    function loadGl() {
        canvas = document.getElementById('myCanvas');
        let context = canvas.getContext('webgl') || canvas.getContext('experimental-webgl');
        if (context) {
            gl = context;
        } else {
            alert('不支持webgl');
        }
    }

    function loadShader() {
        var vShaderSource = document.getElementById('vShader').innerText;
        var fShaderSource = document.getElementById('fShader').innerText;

        let vShader = gl.createShader(gl.VERTEX_SHADER);
        gl.shaderSource(vShader, vShaderSource);
        gl.compileShader(vShader);

        let fShader = gl.createShader(gl.FRAGMENT_SHADER);
        gl.shaderSource(fShader, fShaderSource);
        gl.compileShader(fShader);

        if (!gl.getShaderParameter(vShader, gl.COMPILE_STATUS) | !gl.getShaderParameter(fShader, gl.COMPILE_STATUS)) {
            alert('程序编译失败');
            return;
        }

        shaderProgram = gl.createProgram();
        gl.attachShader(shaderProgram, vShader);
        gl.attachShader(shaderProgram, fShader);

        gl.linkProgram(shaderProgram);
        if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {
            alert('程序连接失败');
            return;
        }
        gl.useProgram(shaderProgram);
    }

    function setupAxisBuffers() {
        let axisVertex = [
            //x轴xyz, rgba
            0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0,
            4.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0,

            //y轴xyz, rgba
            0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 1.0,
            0.0, 4.0, 0.0, 0.0, 1.0, 0.0, 1.0,

            //z轴xyz, rgba
            0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0,
            0.0, 0.0, 4.0, 0.0, 0.0, 1.0, 1.0,
        ];

        axisBuffer = gl.createBuffer();
        gl.bindBuffer(gl.ARRAY_BUFFER, axisBuffer);
        gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(axisVertex), gl.STATIC_DRAW);
    }

    function setupCubeBuffers() {
        let cubeVertex = [
            -1.0, -1.0, -1.0, 132, 94, 194, 255,
            -1.0, 1.0, -1.0, 132, 94, 194, 255,
            1.0, -1.0, -1.0, 132, 94, 194, 255,
            -1.0, 1.0, -1.0, 132, 94, 194, 255,
            1.0, 1.0, -1.0, 132, 94, 194, 255,
            1.0, -1.0, -1.0, 132, 94, 194, 255,

            -1.0, -1.0, 1.0, 214, 93, 177, 255,
            1.0, -1.0, 1.0, 214, 93, 177, 255,
            -1.0, 1.0, 1.0, 214, 93, 177, 255,
            -1.0, 1.0, 1.0, 214, 93, 177, 255,
            1.0, -1.0, 1.0, 214, 93, 177, 255,
            1.0, 1.0, 1.0, 214, 93, 177, 255,

            -1.0, 1.0, -1.0, 255, 111, 145, 255,
            -1.0, 1.0, 1.0, 255, 111, 145, 255,
            1.0, 1.0, -1.0, 255, 111, 145, 255,
            -1.0, 1.0, 1.0, 255, 111, 145, 255,
            1.0, 1.0, 1.0, 255, 111, 145, 255,
            1.0, 1.0, -1.0, 255, 111, 145, 255,

            -1.0, -1.0, -1.0, 255, 150, 113, 255,
            1.0, -1.0, -1.0, 255, 150, 113, 255,
            -1.0, -1.0, 1.0, 255, 150, 113, 255,
            -1.0, -1.0, 1.0, 255, 150, 113, 255,
            1.0, -1.0, -1.0, 255, 150, 113, 255,
            1.0, -1.0, 1.0, 255, 150, 113, 255,

            -1.0, -1.0, -1.0, 255, 199, 95, 255,
            -1.0, -1.0, 1.0, 255, 199, 95, 255,
            -1.0, 1.0, -1.0, 255, 199, 95, 255,
            -1.0, -1.0, 1.0, 255, 199, 95, 255,
            -1.0, 1.0, 1.0, 255, 199, 95, 255,
            -1.0, 1.0, -1.0, 255, 199, 95, 255,

            1.0, -1.0, -1.0, 249, 248, 113, 255,
            1.0, 1.0, -1.0, 249, 248, 113, 255,
            1.0, -1.0, 1.0, 249, 248, 113, 255,
            1.0, -1.0, 1.0, 249, 248, 113, 255,
            1.0, 1.0, -1.0, 249, 248, 113, 255,
            1.0, 1.0, 1.0, 249, 248, 113, 255,
        ];

        cubeBuffer = gl.createBuffer();
        gl.bindBuffer(gl.ARRAY_BUFFER, cubeBuffer);

        let numberOfPoint = 36; //总节点数
        let FLOATSIZE = Float32Array.BYTES_PER_ELEMENT; //每个元素4个字节
        let UINTSIZE = Uint8Array.BYTES_PER_ELEMENT; //每个元素1个字节
        let vertexSizeInBytes = 3 * FLOATSIZE + 4 * UINTSIZE;//每个顶点所占字节数

        let realBuffer = new ArrayBuffer(numberOfPoint * vertexSizeInBytes);
        var vertexSizeInFloats = vertexSizeInBytes / Float32Array.BYTES_PER_ELEMENT;
        var positionView = new Float32Array(realBuffer);
        var colorView = new Uint8Array(realBuffer);
        var positionOffsetInFloats = 0;
        var colorOffsetInBytes = 3 * FLOATSIZE;

        var k = 0;
        for (let i = 0; i < numberOfPoint; i++) {
            positionView[positionOffsetInFloats] = cubeVertex[k];
            positionView[1 + positionOffsetInFloats] = cubeVertex[k + 1];
            positionView[2 + positionOffsetInFloats] = cubeVertex[k + 2];
            colorView[colorOffsetInBytes] = cubeVertex[k + 3];
            colorView[1 + colorOffsetInBytes] = cubeVertex[k + 4];
            colorView[2 + colorOffsetInBytes] = cubeVertex[k + 5];
            colorView[3 + colorOffsetInBytes] = cubeVertex[k + 6];

            positionOffsetInFloats += vertexSizeInFloats;
            colorOffsetInBytes += vertexSizeInBytes;
            k += 7;
        }
        gl.bufferData(gl.ARRAY_BUFFER, realBuffer, gl.STATIC_DRAW);
    }
    function setupCubeAxisBuffers() {
        let axisVertex = [
            //x轴xyz, rgba
            0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0,
            2.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0,

            //y轴xyz, rgba
            0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 1.0,
            0.0, 2.0, 0.0, 0.0, 1.0, 0.0, 1.0,

            //z轴xyz, rgba
            0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0,
            0.0, 0.0, 2.0, 0.0, 0.0, 1.0, 1.0,
        ];

        cubeAxisBuffer = gl.createBuffer();
        gl.bindBuffer(gl.ARRAY_BUFFER, cubeAxisBuffer);
        gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(axisVertex), gl.STATIC_DRAW);
    }
    function drawAxis() {
        gl.bindBuffer(gl.ARRAY_BUFFER, axisBuffer);
        let axisPositionIndex = gl.getAttribLocation(shaderProgram, 'aVertexPosition');
        let axisColorIndex = gl.getAttribLocation(shaderProgram, 'aVertexColor');
        let FSIZE = Float32Array.BYTES_PER_ELEMENT;

        gl.enableVertexAttribArray(axisPositionIndex);
        gl.vertexAttribPointer(axisPositionIndex, 3, gl.FLOAT, false, FSIZE * 7, 0);

        gl.enableVertexAttribArray(axisColorIndex);
        gl.vertexAttribPointer(axisColorIndex, 4, gl.FLOAT, false, FSIZE * 7, FSIZE * 3);

        gl.drawArrays(gl.LINES, 0, 6);

    }
    function drawCubeAxis() {
        gl.bindBuffer(gl.ARRAY_BUFFER, cubeAxisBuffer);
        let axisPositionIndex = gl.getAttribLocation(shaderProgram, 'aVertexPosition');
        let axisColorIndex = gl.getAttribLocation(shaderProgram, 'aVertexColor');
        let FSIZE = Float32Array.BYTES_PER_ELEMENT;

        gl.enableVertexAttribArray(axisPositionIndex);
        gl.vertexAttribPointer(axisPositionIndex, 3, gl.FLOAT, false, FSIZE * 7, 0);

        gl.enableVertexAttribArray(axisColorIndex);
        gl.vertexAttribPointer(axisColorIndex, 4, gl.FLOAT, false, FSIZE * 7, FSIZE * 3);

        gl.drawArrays(gl.LINES, 0, 6);
    }

    function drawCube() {
        let numberOfPoint = 36; //总节点数
        let FLOATSIZE = Float32Array.BYTES_PER_ELEMENT; //每个元素4个字节
        let UINTSIZE = Uint8Array.BYTES_PER_ELEMENT; //每个元素1个字节
        let vertexSizeInBytes = 3 * FLOATSIZE + 4 * UINTSIZE;//每个顶点所占字节数

        gl.bindBuffer(gl.ARRAY_BUFFER, cubeBuffer);

        gl.enableVertexAttribArray(gl.getAttribLocation(shaderProgram, 'aVertexPosition'));
        gl.vertexAttribPointer(gl.getAttribLocation(shaderProgram, 'aVertexPosition'), 3, gl.FLOAT, false, vertexSizeInBytes, 0);

        gl.enableVertexAttribArray(gl.getAttribLocation(shaderProgram, 'aVertexColor'));
        gl.vertexAttribPointer(gl.getAttribLocation(shaderProgram, 'aVertexColor'), 4, gl.UNSIGNED_BYTE, true, vertexSizeInBytes, 3 * FLOATSIZE);

        gl.drawArrays(gl.TRIANGLES, 0, numberOfPoint);
    }


    function setupBuffers() {
        setupAxisBuffers();
        setupCubeBuffers();
        setupCubeAxisBuffers();
    }

    function draws() {

        if (timer > 0) {
            if (rotateCube && !rotateCamera) {
                thetaCube += 1;
            }else if (!rotateCube && rotateCamera) {
                thetaCamera += 1;
            }else if (rotateCube && rotateCamera) {
                thetaCube += 1;
                thetaCamera += 1;
            }
        }


        radius = 8;
        var x = Math.cos(glMatrix.toRadian(thetaCamera)) * radius;
        var z = Math.sin(glMatrix.toRadian(thetaCamera)) * radius;

        radius2 = 2;
        var x2 = Math.cos(glMatrix.toRadian(thetaCube)) * radius2;
        var z2 = Math.sin(glMatrix.toRadian(thetaCube)) * radius2;

        gl.viewport(0.0, 0.0, canvas.width, canvas.height);
        gl.clearColor(0.0, 0.0, 0.0, 1.0);
        gl.enable(gl.DEPTH_TEST);
        gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);

        mat4.perspective(projectionMatrix, glMatrix.toRadian(60), canvas.width / canvas.height, 0.1, 150);
        mat4.identity(mVMatrix);
        //alert(mat4.str(mVMatrix));
        mat4.lookAt(mVMatrix, [x, 8, z], [0, 0, 0], [0, 1, 0]);
        //alert(mat4.str(mVMatrix));
        uploadModelViewMatrixToShader();
        uploadProjectionMatrixToShader();

        drawAxis();

        pushMvMatrixStack();
        let cameraMatrix = mat4.create();
        mat4.targetTo(cameraMatrix, [x2, 2.0, z2], [0.0, 0.0, 0.0], [0.0, 1.0, 0.0]);
        mat4.multiply(mVMatrix, mVMatrix, cameraMatrix);
        uploadModelViewMatrixToShader();
        drawCube();
        drawCubeAxis();
        popMvMatrixStack();

        if (timer > 0) {
            timer = window.requestAnimationFrame(draws);
        }
    }
    $('#myButton').on('click', function () {
        if (timer < 0) {
            rotateCube = true;
            startAnimate();
        } else if (timer > 0) {
            if (rotateCamera && !rotateCube) {
                rotateCube = true;
            }else if (rotateCamera && rotateCube) {
                rotateCube = false;
            }else if (!rotateCamera && rotateCube) {
                rotateCube = false;
                endAnimate();
            }
        }
    });
    $('#myButton2').on('click', function () {
        if (timer < 0) {
            rotateCamera = true;
            startAnimate();
        } else if(timer > 0){
            if (rotateCube && !rotateCamera) {
                rotateCamera = true;
            }else if(rotateCube && rotateCamera){
                rotateCamera = false;
            } else if (!rotateCube && rotateCamera) {
                rotateCamera = false;
                endAnimate();
            }
        }
    });

    function popMvMatrixStack() {
        if (mvMatrixStack.length > 0) {
            mVMatrix = mvMatrixStack.pop();
        } else {
            alert('mvMatrixStack为空')
        }
    }

    function pushMvMatrixStack() {
        let copyToPush = mat4.create(mVMatrix);
        mvMatrixStack.push(copyToPush);
    }

    function uploadModelViewMatrixToShader() {
        let mvMatrixIndex = gl.getUniformLocation(shaderProgram, 'uMVMatrix');
        gl.uniformMatrix4fv(mvMatrixIndex, false, mVMatrix);
    }

    function uploadProjectionMatrixToShader() {
        let projectionMatrixIndex = gl.getUniformLocation(shaderProgram, 'uProjectMatrix');
        gl.uniformMatrix4fv(projectionMatrixIndex, false, projectionMatrix);
    }


    $(window).load(function () {
        loadGlMatrix();
        loadGl();
        loadShader();
        setupBuffers();
        draws();
    });

    function startAnimate() {
        timer = 1;
        draws();
    }

    function endAnimate() {
        timer = -1;
        window.cancelAnimationFrame(timer);
    }
</script>
</body>
</html>