webgl 11.动画

webgl 11.动画_第1张图片
animation.gif

动画需要循环绘制并在绘制的过程中不断改变位置,由于人眼的视觉停留看起来就像动画。

之前都用 setInterval 实现循环调用函数,但这个函数有个缺点是在 inactive 的 tab 中也会被调用影响性能。所以后来又加了一个新的方法 requestAnimationFrame(func) 这个方法会在浏览器 redraw(重绘) 页面的时候调用一次。

var tick = function () {
    draw();
    requestAnimationFrame(tick);
};
tick();

可以这样实现循环调用 tick 函数。一般显示器刷新频率是 60fps (frame per second), 意味着 1 秒钟刷新 60 次,1秒=1000毫秒, 1000毫秒/60 约等于 16.7毫秒 , 所以 tick 函数大约每隔 16.7 毫秒会调用一次。

// vertex shader
var VERTEX_SHADER_SOURCE =
    'attribute vec4 a_Position;\n' +
    'uniform mat4 u_ModelMatrix;\n' +
    'void main() {\n' +
    '   gl_Position = u_ModelMatrix * a_Position;\n' +
    '}\n';

// fragment shader
var FRAGMENT_SHADER_SOURCE =
    'void main() {\n' +
    '   gl_FragColor = vec4(1.0,0.0,0.0,1.0);\n' +
    '}\n';

var canvas = document.getElementById("canvas");
var gl = canvas.getContext('webgl');
gl.clearColor(0.0, 0.0, 0.0, 1.0);

if (!initShaders(gl, VERTEX_SHADER_SOURCE, FRAGMENT_SHADER_SOURCE)) {
    alert('Failed to init shaders');
}

var vertices = new Float32Array([
    0.0, 0.5,
    -0.5, -0.5,
    0.5, -0.5
]);

initVertexBuffers(gl, vertices);

var u_ModelMatrix = gl.getUniformLocation(gl.program, 'u_ModelMatrix');

var ANGLE_STEP = 45.0;
var currentAngle = 0.0;
var modelMatrix = new Matrix4();

var g_last = Date.now();
function animate(angle) {
    var now = Date.now();
    var elapsed = now - g_last;
    g_last = now;

    var newAngle = angle + (ANGLE_STEP * elapsed) / 1000.0;
    return newAngle %= 360;
}

function draw() {
    modelMatrix.setRotate(currentAngle, 0, 0, 1);
    gl.uniformMatrix4fv(u_ModelMatrix, false, modelMatrix.elements);

    gl.clear(gl.COLOR_BUFFER_BIT);
    gl.drawArrays(gl.TRIANGLES, 0, 3);
}

var tick = function () {
    currentAngle = animate(currentAngle);
    draw();
    requestAnimationFrame(tick);
};
tick();

function initVertexBuffers(gl, vertices) {
    var vertexBuffer = gl.createBuffer();
    if (!vertexBuffer) {
        console.log('Failed to create buffer object');
        return -1;
    }

    gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
    gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);

    var a_Position = gl.getAttribLocation(gl.program, 'a_Position');
    gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, 0, 0);
    gl.enableVertexAttribArray(a_Position);
}

animate 函数的意思 1 秒钟大约旋转 45 度,tick 中调用了 animate , animate 也是约 16.7 毫秒调用一次

查看源码

你可能感兴趣的:(webgl 11.动画)