WebGL - 绘图模式
你好,未来的WebGL法师们!? 今天,我们将深入探索WebGL的绘图模式世界。作为你友好的邻里计算机老师,我将引导你完成这次旅程,即使你之前从未编写过一行代码。所以,拿起你的虚拟画笔,让我们来创作一些数字杰作吧!
模式参数(mode)
在我们开始绘制之前,让我们来谈谈我们节目的明星:mode
参数。把它想象成魔杖,告诉WebGL如何连接点(或者在我们的例子中,顶点)来创建不同的形状和图案。
在WebGL中,当我们调用gl.drawArrays()
或gl.drawElements()
函数时,我们需要指定一个mode
参数。这个参数就像给连线谜题下达指令一样——它告诉WebGL如何连接我们定义的点。
以下是WebGL中可用的不同绘图模式的表格:
模式 | 描述 |
---|---|
gl.POINTS | 为每个顶点绘制一个点 |
gl.LINES | 在每对顶点之间绘制一条线 |
gl.LINE_STRIP | 绘制一条连续的线连接顶点 |
gl.LINE_LOOP | 类似于LINE_STRIP,但闭合形状 |
gl.TRIANGLES | 每三个顶点绘制一个三角形 |
gl.TRIANGLE_STRIP | 绘制一个连接的三角形组 |
gl.TRIANGLE_FAN | 绘制一个扇形形状的连接三角形 |
如果现在这些看起来很令人困惑,不用担心。我们将边走边看,用例子来探索每一个模式!
示例 - 绘制三条平行线
让我们从一个简单的例子开始:绘制三条平行线。这将帮助我们理解mode
参数在实际中是如何工作的。
// 首先,让我们设置WebGL上下文
const canvas = document.getElementById('myCanvas');
const gl = canvas.getContext('webgl');
// 现在,让我们定义我们的顶点着色器
const vertexShaderSource = `
attribute vec2 a_position;
void main() {
gl_Position = vec4(a_position, 0.0, 1.0);
}
`;
// 以及我们的片段着色器
const fragmentShaderSource = `
precision mediump float;
void main() {
gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); // 红色
}
`;
// 创建并编译着色器(别担心,我们将在未来的课程中详细解释这些)
const vertexShader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vertexShader, vertexShaderSource);
gl.compileShader(vertexShader);
const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fragmentShader, fragmentShaderSource);
gl.compileShader(fragmentShader);
// 创建一个程序并链接着色器
const program = gl.createProgram();
gl.attachShader(program, vertexShader);
gl.attachShader(program, fragmentShader);
gl.linkProgram(program);
gl.useProgram(program);
// 定义我们的线条位置
const positions = new Float32Array([
-0.8, -0.8, // 线条1起点
-0.8, 0.8, // 线条1终点
-0.3, -0.8, // 线条2起点
-0.3, 0.8, // 线条2终点
0.2, -0.8, // 线条3起点
0.2, 0.8 // 线条3终点
]);
// 创建一个缓冲区并将位置放入其中
const positionBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
gl.bufferData(gl.ARRAY_BUFFER, positions, gl.STATIC_DRAW);
// 告诉WebGL如何读取缓冲区并将其属性分配给a_position
const positionAttributeLocation = gl.getAttribLocation(program, 'a_position');
gl.enableVertexAttribArray(positionAttributeLocation);
gl.vertexAttribPointer(positionAttributeLocation, 2, gl.FLOAT, false, 0, 0);
// 清除画布
gl.clearColor(0.0, 0.0, 0.0, 1.0);
gl.clear(gl.COLOR_BUFFER_BIT);
// 绘制线条
gl.drawArrays(gl.LINES, 0, 6);
现在,让我们分解一下:
-
我们设置了WebGL上下文并定义了我们的着色器。现在不要太担心这些;我们将在未来的课程中深入介绍着色器。
-
我们创建了一个程序并将我们的着色器链接到它。这就像准备我们的数字画笔。
-
我们定义了线条的位置。每条线由两个点(起点和终点)定义,每个点由两个坐标(x和y)定义。所以,我们的三条线总共有6个点。
-
我们创建了一个缓冲区并将我们的位置放入其中。可以把这想象成在画笔上装颜料。
-
我们告诉WebGL如何读取这个缓冲区并将其与顶点着色器中的
a_position
属性关联。 -
最后,我们调用
gl.drawArrays(gl.LINES, 0, 6)
。这就是魔法发生的地方!
-
gl.LINES
是我们的模式。它告诉WebGL在顶点对之间绘制线条。 -
0
是我们位置数组中的起始索引。 -
6
是要考虑的顶点数(记得,我们有6个点组成3条线)。
运行这段代码,瞧!你应该会在黑色背景上看到三条红色的平行线。恭喜你,你刚刚创建了你的第一个WebGL绘图!?
绘图模式
既然我们已经看到了gl.LINES
的实际应用,让我们探索一些其他的绘图模式。我们将使用之前的相同设置,但是更改位置和绘图模式。
gl.POINTS
让我们从最简单的模式开始:gl.POINTS
。这个模式为每个顶点绘制一个点。
// ... (之前的设置代码)
const positions = new Float32Array([
-0.5, 0.5,
0.0, 0.0,
0.5, -0.5
]);
// ... (缓冲区设置代码)
gl.drawArrays(gl.POINTS, 0, 3);
这将在你画布上绘制三个红色的点。简单吧?
gl.LINE_STRIP
现在,让我们试试gl.LINE_STRIP
。这个模式绘制一条连续的线,连接每个顶点到下一个。
// ... (之前的设置代码)
const positions = new Float32Array([
-0.5, 0.5,
0.0, -0.5,
0.5, 0.5
]);
// ... (缓冲区设置代码)
gl.drawArrays(gl.LINE_STRIP, 0, 3);
你应该会看到一条连接三个点的V形线。
gl.LINE_LOOP
gl.LINE_LOOP
与LINE_STRIP
相似,但它通过连接最后一个顶点回到第一个顶点来闭合形状。
// ... (之前的设置代码)
const positions = new Float32Array([
-0.5, 0.5,
0.0, -0.5,
0.5, 0.5
]);
// ... (缓冲区设置代码)
gl.drawArrays(gl.LINE_LOOP, 0, 3);
这将绘制一个三角形轮廓。
gl.TRIANGLES
现在,让我们转到填充形状的gl.TRIANGLES
。这个模式为每三个顶点绘制一个独立的三角形。
// ... (之前的设置代码)
const positions = new Float32Array([
-0.5, -0.5,
0.5, -0.5,
0.0, 0.5
]);
// ... (缓冲区设置代码)
gl.drawArrays(gl.TRIANGLES, 0, 3);
你应该会看到一个实心的红色三角形。
gl.TRIANGLE_STRIP
gl.TRIANGLE_STRIP
稍微复杂一些。它绘制一个连接的三角形组,其中每个三角形与前一个三角形共享两个顶点。
// ... (之前的设置代码)
const positions = new Float32Array([
-0.5, -0.5,
0.5, -0.5,
-0.5, 0.5,
0.5, 0.5
]);
// ... (缓冲区设置代码)
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
这将绘制两个连接的三角形,形成一个矩形。
gl.TRIANGLE_FAN
最后,让我们看看gl.TRIANGLE_FAN
。这个模式绘制一个扇形形状,其中所有三角形共享第一个顶点作为公共点。
// ... (之前的设置代码)
const positions = new Float32Array([
0.0, 0.0, // 中心点
0.5, 0.0, // 点1
0.35, 0.35, // 点2
0.0, 0.5, // 点3
-0.35, 0.35 // 点4
]);
// ... (缓冲区设置代码)
gl.drawArrays(gl.TRIANGLE_FAN, 0, 5);
这将绘制一个看起来有点像四分之一圆的形状。
就这样!我们已经探索了WebGL中的所有绘图模式。记住,掌握这些的关键是练习。尝试组合不同的模式,改变颜色,玩转顶点位置。在你意识到之前,你将能够轻松创建复杂的WebGL场景!
在下一课中,我们将更深入地研究着色器,并学习如何为我们的绘图添加颜色和纹理。在此之前,祝未来的WebGL艺术家们编程愉快!?????
Credits: Image by storyset