零基础入门 WebGL:用代码绘制你的第一个三角形

433 阅读3分钟

1. WebGL基础概念

WebGL(Web Graphics Library)是一个JavaScript API,运行在浏览器中的图形库,允许在支持HTML5的浏览器中直接绘制3D图形,而无需安装任何插件。WebGL基于OpenGL ES 2.0,能为Web开发者提供强大的图形渲染功能,广泛应用于游戏、数据可视化、虚拟现实等领域。它可以让我们在网页中实现硬件加速的2D和3D图形渲染。WebGL不仅支持绘制图像,还能实现复杂的着色、纹理映射、光照效果等。

  • WebGL与HTML5 Canvas:WebGL依赖于HTML5中的<canvas>元素。它是通过JavaScript调用底层图形API,进行图形渲染的。
  • 着色器:WebGL使用着色器来定义图形如何渲染。通常有顶点着色器和片段着色器两种类型,前者处理顶点数据,后者处理每个像素的颜色。
  • 缓冲区和顶点数据:WebGL需要通过缓冲区传递顶点信息,帮助渲染引擎计算出最终的图形。

2. 环境搭建

2.1 创建一个HTML文件

首先,创建一个简单的HTML文件,里面包含一个<canvas>元素,用来绘制图形。

<!DOCTYPE html>
<html lang="zh">
    <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>WebGL入门教程</title>
        <style>
            body {
                margin: 0;
            }
            canvas {
                display: block;
            }
        </style>
    </head>
    <body>
        <canvas id="webgl-canvas"></canvas>

        <script src="app.js"></script>
    </body>
</html>

2.2 设置WebGL上下文

接下来,我们需要在JavaScript中获取WebGL渲染上下文,并设置好画布的大小。

// 获取canvas元素
const canvas = document.getElementById('webgl-canvas');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;

// 获取WebGL上下文
const gl = canvas.getContext('webgl');

// 检查浏览器是否支持WebGL
if (!gl) {
    alert("WebGL未被支持!");
}

3. 绘制一个简单的三角形

接下来,我们绘制一个简单的三角形,并将其渲染到页面上。

3.1 创建顶点数据

我们需要定义一个三角形的三个顶点。每个顶点包含两个坐标:xy,这两个坐标决定了三角形的位置。

const vertices = new Float32Array([
    0.0,  0.5,   // 顶点1 (x, y)
   -0.5, -0.5,   // 顶点2 (x, y)
    0.5, -0.5    // 顶点3 (x, y)
]);

3.2 编写着色器代码

WebGL需要顶点着色器和片段着色器来控制图形的渲染。下面是一个简单的着色器代码:

顶点着色器(vertex shader)

const vertexShaderSource = `
    attribute vec2 a_position;
    void main() {
        gl_Position = vec4(a_position, 0.0, 1.0);
    }
`;

片段着色器(fragment shader)

const fragmentShaderSource = `
    precision mediump float;
    void main() {
        gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);  // 设置颜色为红色
    }
`;

3.3 编译和链接着色器

我们需要将着色器代码编译为WebGL可以执行的程序,并将它们链接到一起。

/**
 * 创建着色器
 * @param {number} type - gl.VERTEX_SHADER or gl.FRAGMENT_SHADER
 * @param {string} source - 着色器源代码
 * @return {WebGLShader} - 创建的着色器对象
 */
function createShader(type, source) {
    const shader = gl.createShader(type); // 创建着色器
    gl.shaderSource(shader, source); // 设置着色器源代码
    gl.compileShader(shader); // 编译着色器

    if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
        console.error('Shader编译失败:', gl.getShaderInfoLog(shader));
        gl.deleteShader(shader);
        return null;
    }
    return shader;
}

/**
 * 创建WebGL程序对象
 * @param {string} vertexShaderSource - 顶点着色器源代码
 * @param {string} fragmentShaderSource - 片元着色器源代码
 * @return {WebGLProgram} - 创建的程序对象
 */
function createProgram(vertexShaderSource, fragmentShaderSource) {
    const vertexShader = createShader(gl.VERTEX_SHADER, vertexShaderSource);
    const fragmentShader = createShader(gl.FRAGMENT_SHADER, fragmentShaderSource);

    const program = gl.createProgram();
    gl.attachShader(program, vertexShader);
    gl.attachShader(program, fragmentShader);
    gl.linkProgram(program);

    if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
        console.error('程序链接失败:', gl.getProgramInfoLog(program));
        return null;
    }
    return program;
}

const program = createProgram(vertexShaderSource, fragmentShaderSource);
gl.useProgram(program);

3.4 创建缓冲区并传递顶点数据

我们需要将顶点数据传递给WebGL,创建一个缓冲区并将其绑定。

// 创建缓冲区
const vertexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);

// 获取顶点位置属性位置 a_position 在顶点着色器源代码中定义
const positionLocation = gl.getAttribLocation(program, 'a_position');
gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(positionLocation);

3.5 清空画布并绘制三角形

设置清空画布的背景色,并绘制三角形。

// 清空画布
gl.clearColor(0.0, 0.0, 0.0, 1.0);  // 背景色为黑色
gl.clear(gl.COLOR_BUFFER_BIT);

// 绘制三角形
gl.drawArrays(gl.TRIANGLES, 0, 3);

3.6 效果

image.png