WebGL线段绘制:掌握三种线段图元类型

42 阅读3分钟

线段图元的三种类型

WebGL提供了三种不同的线段绘制模式,每种都有其独特的用途和特点:

1. 基本线段(LINES)

每条线段都需要明确指定两个端点,线段之间相互独立。

// 每两个点构成一条独立线段
// [v1, v2] 构成第一条线段
// [v3, v4] 构成第二条线段
gl.drawArrays(gl.LINES, 0, 4); // 绘制2条线段

特点: 每次需要2个顶点来绘制1条线段,线段之间不相连。

2. 带状线段(LINE_STRIP)

线段首尾相连,形成连续的线条。

// [v1, v2] 第一条线段
// [v2, v3] 第二条线段(使用前一线段的终点作为起点)
// [v3, v4] 第三条线段
gl.drawArrays(gl.LINE_STRIP, 0, 4); // 绘制3条相连的线段

特点: 除了第一条线段需要2个点,后续每个点都会与前一个点形成新线段。

3. 环状线段(LINE_LOOP)

在带状线段的基础上,自动连接最后一个点和第一个点。

// [v1, v2], [v2, v3], [v3, v4], [v4, v1] 形成闭合环
gl.drawArrays(gl.LINE_LOOP, 0, 4); // 绘制闭合的四边形边框

特点: 形成闭合的环状线条,非常适合绘制轮廓。

交互式线段绘制实现

让我们通过一个鼠标点击绘制线段的示例来理解这些概念:

screenshot_2026-02-12_15-07-11.gif

JavaScript交互代码

// 存储点击位置的数组
var positions = [];

// 监听鼠标点击事件
canvas.addEventListener('mouseup', function(e) {
    var x = e.offsetX;  // 获取相对于canvas的X坐标
    var y = e.offsetY;  // 获取相对于canvas的Y坐标
    
    // 将点击坐标添加到数组
    positions.push(x);
    positions.push(y);
    
    // 更新缓冲区数据
    gl.bufferData(
        gl.ARRAY_BUFFER,
        new Float32Array(positions),
        gl.DYNAMIC_DRAW
    );
    
    // 重新绘制
    render();
});

// 渲染函数
function render() {
    // 清空画布
    gl.clearColor(0.0, 0.0, 0.0, 1.0);
    gl.clear(gl.COLOR_BUFFER_BIT);
    
    // 根据需要选择不同的线段模式
    // 绘制基本线段(每次需要2个点绘制1条线)
    gl.drawArrays(gl.LINES, 0, positions.length / 2);
    
    // 或绘制带状线段(连续连接所有点)
    // gl.drawArrays(gl.LINE_STRIP, 0, positions.length / 2);
    
    // 或绘制环状线段(连接所有点并闭合)
    // gl.drawArrays(gl.LINE_LOOP, 0, positions.length / 2);
}

着色器程序

顶点着色器和片元着色器与之前三角形的例子类似,只是处理的顶点数据用于绘制线段:

// 顶点着色器
precision mediump float;
attribute vec2 a_Position;
attribute vec2 a_Screen_Size;

void main() {
    // 将屏幕坐标转换为WebGL坐标系统
    vec2 position = (a_Position / a_Screen_Size) * 2.0 - 1.0;
    position.y = -position.y; // 翻转Y轴
    gl_Position = vec4(position, 0.0, 1.0);
}
// 片元着色器
precision mediump float;
uniform vec4 u_Color;

void main() {
    gl_FragColor = u_Color;
}

三种线段模式的实际应用

基本线段(LINES)适用场景

  • 绘制独立的直线段
  • 连接特定的点对
  • 路径规划中的独立路段

带状线段(LINE_STRIP)适用场景

  • 绘制连续的路径
  • 手写轨迹绘制
  • 曲线轮廓绘制

环状线段(LINE_LOOP)适用场景

  • 绘制封闭图形的边框
  • 凸多边形轮廓
  • 环形路径

性能考虑

// 使用STATIC_DRAW适用于不经常改变的数据
gl.bufferData(gl.ARRAY_BUFFER, data, gl.STATIC_DRAW);

// 使用DYNAMIC_DRAW适用于经常改变的数据
gl.bufferData(gl.ARRAY_BUFFER, data, gl.DYNAMIC_DRAW);
  • STATIC_DRAW:数据只设置一次,多次使用
  • DYNAMIC_DRAW:数据多次更新,多次使用
  • STREAM_DRAW:数据少量修改,少量使用

实践建议

  1. LINES模式:每次点击两个点后才能看到一条线段,适合绘制独立的线段对
  2. LINE_STRIP模式:每次点击都会延续之前的线条,适合连续绘制
  3. LINE_LOOP模式:在LINE_STRIP基础上自动闭合,适合绘制封闭形状

掌握了这三种线段绘制模式,你就可以创建各种线条效果,从简单的几何图形到复杂的路径可视化都能轻松实现!