• WebGL编程指南10-通过组合变化绘制旋转三角形


    1.demo效果演示

    在这里插入图片描述

    2.动画效果原理

    在组合变换的基础上,实现动画差不多是顺利成章的事情,我们只需要利用浏览器提供的 requestAnimationFrame() 不断进行变换就可以实现动画,它的实质就是变换矩阵的不断相乘 。

    这里要注意:因为使用requestAnimationFrame的本质实际上是把回调函数交给浏览器来执行,具体什么时候执行,浏览器来决定,当系统负载较大,FPS比较低,可能导致requestAnimationFrame执行偏晚,导致每一帧绘制的时间间隔较长,动画不平滑流畅,所以我们把旋转角度与时间关系起来成比例关系,请看如下代码

    // 顶点着色器程序
    var VSHADER_SOURCE =
        `attribute vec4 a_Position;
        uniform mat4 u_xformMatrix;
        void main() {
            gl_Position = u_xformMatrix*a_Position;
    }`;
    
    // 片元着色器程序
    var FSHADER_SOURCE =
        `void main() {
    
    	gl_FragColor = vec4(1, 0, 0, 1);
    }`;
    
    const main = () => {
        //获取绘制dom
        const canvas = document.getElementById('webgl');
    
        //获取canvas上下文
        const gl = canvas.getContext('webgl');
    
        //初始化着色器
        if (!initShaders(gl, VSHADER_SOURCE, FSHADER_SOURCE)) {
            return console.log('Failed to initialize shaders.')
        }
        const initVertexBuffers = (gl) => {
            //类型化数组设置顶点坐标
            const vertices = new Float32Array([0, 0.5, -0.5, -0.5, 0.5, -0.5]);
    
            const n = 3;//点的个数
    
            //创建缓冲区对象
            const vertexBuffer = gl.createBuffer();
            if (!vertexBuffer) {
                console.log('Failed to create the buffer object');
                return -1
            }
    
            //将缓冲区对象绑定到目标
            gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
            //向缓冲区对象中写入数据
            gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
    
            const a_Position = gl.getAttribLocation(gl.program, 'a_Position');
    
            //将缓冲区对象分配给a_Position变量
            gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, 0, 0);
    
            //链接a_Position变量与分配给它的缓冲区对象
            gl.enableVertexAttribArray(a_Position);
    
            return n
        }
        const ANGLE_STEP = 45.0;
        let g_last = Date.now();
        let currentAngle = 0.0;
    
        const xformMatrix = new Matrix4();
        const u_xformMatrix = gl.getUniformLocation(gl.program, 'u_xformMatrix')
    
        //旋转函数
        const draw = (angle, xformMatrix, u_xformMatrix) => {
            xformMatrix.setRotate(angle, 0, 0, 1);
            // xformMatrix.translate(0.35, 0, 0)
            gl.uniformMatrix4fv(u_xformMatrix, false, xformMatrix.elements)
            //清空canvas
    
            gl.clear(gl.COLOR_BUFFER_BIT);
    
            //绘制一个点
            gl.drawArrays(gl.TRIANGLES, 0, 3);
        }
        //根据时间间隔计算旋转角度
        const animate = (angle) => {
            console.log('angle',angle)
            //计算距离上次调用经过多长时间
            const now = Date.now();
            const elapsed = now - g_last;
            g_last = now;
            return (angle + (ANGLE_STEP * elapsed) / 1000.0) % 360
        }
        //动画函数
        const tick = () => {
            currentAngle = animate(currentAngle);
            draw(currentAngle, xformMatrix, u_xformMatrix);
            requestAnimationFrame(tick)
        }
    
        tick()
    
    
        const n = initVertexBuffers(gl);
        if (n < 0) {
            console.error('n<0')
            return
        }
    
    
        //设置canvas的背景色
        gl.clearColor(0.0, 0.0, 0.0, 1.0);
    }
    main()
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
  • 相关阅读:
    C#源码 LIS实验室(检验科)信息系统源码 SaaS模式的Client/Server架构
    以“社交和品质”打通长线运营,UTONMOS打造真正的Web3.0链游破圈之作
    现在回头看,你有没有写过自己觉得比较愚蠢的代码?
    Ubuntu22.2下C语言编程实现,首次,最佳适应算法
    1330_硬件测试中的BCI测试
    LeetCode3. 无重复字符的最长子串
    【面试】揭秘面试背后的那点真实
    【CMN】Components组件汇总
    SA+ST表维护height+单调队列维护:CF1073G
    【gcc/g++】1.编译器, 编译过程和基本参数
  • 原文地址:https://blog.csdn.net/weixin_46773434/article/details/126834604