效果演示

使用说明

主要代码如下:

var canvas = document.getElementById('webgl-canvas');
var gl = canvas.getContext('webgl');

if (!gl) {
    console.log('WebGL not supported, falling back on experimental-webgl');
    gl = canvas.getContext('experimental-webgl');
}

if (!gl) {
    alert('Your browser does not support WebGL');
}

var vertices = [
    -0.5, -0.5, -0.5,
    0.5, -0.5, -0.5,
    0.5, 0.5, -0.5,
    -0.5, 0.5, -0.5,
    -0.5, -0.5, 0.5,
    0.5, -0.5, 0.5,
    0.5, 0.5, 0.5,
    -0.5, 0.5, 0.5
];

var indices = [
    0, 1, 2, 0, 2, 3,
    4, 5, 6, 4, 6, 7,
    0, 4, 7, 0, 7, 3,
    1, 5, 6, 1, 6, 2,
    0, 1, 5, 0, 5, 4,
    2, 3, 7, 2, 7, 6
];

var vertex_buffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vertex_buffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);

var index_buffer = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, index_buffer);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), gl.STATIC_DRAW);

var vertCode = `
            attribute vec3 coordinates;
            attribute vec3 aVertexNormal;
            uniform mat4 modelViewMatrix;
            uniform mat4 projectionMatrix;
            varying vec4 vColor;
            void main(void) {
                gl_Position = projectionMatrix * modelViewMatrix * vec4(coordinates, 1.0);
                vec3 lightDirection = normalize(vec3(0.0, 0.0, 1.0));
                float brightness = max(dot(aVertexNormal, lightDirection), 0.0);
                vColor = vec4(brightness * 0.5 + 0.5, brightness * 0.5 + 0.5, 1, 1.0);
            }
        `;

var vertShader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vertShader, vertCode);
gl.compileShader(vertShader);

var fragCode = `
            precision mediump float;
            varying vec4 vColor;
            void main(void) {
                gl_FragColor = vColor;
            }
        `;

var fragShader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fragShader, fragCode);
gl.compileShader(fragShader);

var shaderProgram = gl.createProgram();
gl.attachShader(shaderProgram, vertShader);
gl.attachShader(shaderProgram, fragShader);
gl.linkProgram(shaderProgram);
gl.useProgram(shaderProgram);

var coord = gl.getAttribLocation(shaderProgram, 'coordinates');
gl.vertexAttribPointer(coord, 3, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(coord);

var normals = [
    // Front
    0, 0, -1,
    0, 0, -1,
    0, 0, -1,
    0, 0, -1,
    // Back
    0, 0, 1,
    0, 0, 1,
    0, 0, 1,
    0, 0, 1,
    // Top
    0, 1, 0,
    0, 1, 0,
    0, 1, 0,
    0, 1, 0,
    // Bottom
    0, -1, 0,
    0, -1, 0,
    0, -1, 0,
    0, -1, 0,
    // Right
    1, 0, 0,
    1, 0, 0,
    1, 0, 0,
    1, 0, 0,
    // Left
    -1, 0, 0,
    -1, 0, 0,
    -1, 0, 0,
    -1, 0, 0
];

var normalBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, normalBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(normals), gl.STATIC_DRAW);

var normalAttribute = gl.getAttribLocation(shaderProgram, "aVertexNormal");
gl.vertexAttribPointer(normalAttribute, 3, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(normalAttribute);

var modelViewMatrix = gl.getUniformLocation(shaderProgram, "modelViewMatrix");
var projectionMatrix = gl.getUniformLocation(shaderProgram, "projectionMatrix");

var angle = 0;
var modelView = mat4.create();
var projection = mat4.create();
var modelViewProjection = mat4.create();

(function animloop() {
    angle += 0.01;
    mat4.identity(modelView);
    mat4.translate(modelView, modelView, [0.0, 0.0, -7.0]);
    mat4.rotate(modelView, modelView, angle, [1, 1, 1]);
    gl.uniformMatrix4fv(modelViewMatrix, false, modelView);

    mat4.perspective(projection, Math.PI / 4, canvas.width / canvas.height, 0.1, 100);
    gl.uniformMatrix4fv(projectionMatrix, false, projection);

    gl.clearColor(0.5, 0.5, 0.5, 0.9);
    gl.clearDepth(1.0);
    gl.enable(gl.DEPTH_TEST);
    gl.depthFunc(gl.LEQUAL);
    gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);

    gl.bindBuffer(gl.ARRAY_BUFFER, vertex_buffer);
    gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, index_buffer);
    gl.drawElements(gl.TRIANGLES, indices.length, gl.UNSIGNED_SHORT, 0);

    gl.flush();
    requestAnimationFrame(animloop);
})();