WebGL - 基础:初学者的友好入门
你好,未来的 WebGL 大师们!我很高兴能成为你们在这激动人心的 WebGL 世界之旅中的向导。作为一位有着多年计算机图形学教学经验的人,我迫不及待地想与你们分享 WebGL 的魔法。别担心你编程新手——我们将从头开始,一步步建立我们的知识体系。那么,拿起一杯咖啡(或者茶,如果你喜欢的话),让我们开始吧!
什么是 WebGL?
在我们深入研究细节之前,先来了解一下 WebGL 是什么。WebGL(Web 图形库)是一个强大的 JavaScript API,它允许我们在网页浏览器中创建令人惊叹的 3D 图形。这就像在你的指尖拥有一个迷你电影工作室!
将 WebGL 想象成你网页浏览器和计算机图形硬件之间的桥梁。它让我们能够利用 GPU(图形处理单元)的力量,以流畅的性能渲染复杂的 3D 场景。酷吧?
WebGL - 坐标系统
现在,让我们来谈谈 WebGL 坐标系统。想象你站在一个巨大的、无形的 3D 立方体的中心。这基本上就是 WebGL 坐标系统的样子!
笛卡尔坐标系
WebGL 使用一个 3D 笛卡尔坐标系。这和你可能在数学课上学习过的 2D 系统类似,但多了一个维度:
- X 轴:水平(左到右)
- Y 轴:垂直(下到上)
- Z 轴:深度(后到前)
这里有一个简单的例子来帮助你形象化:
// 定义一个顶点(三维空间中的点)
var vertex = [
0.5, // X 坐标
0.7, // Y 坐标
0.0 // Z 坐标
];
在这个例子中,我们定义了一个点,它从中心稍微向右(0.5)和向上(0.7),并且正好在屏幕表面上(0.0)。
剪切空间
WebGL 有一个特点是它使用了一个特殊的坐标范围,称为“剪切空间”。所有坐标都必须在每个轴上介于 -1.0 和 1.0 之间。超出这个范围的所有内容都会被“剪切”(不会绘制)。
// 剪切空间右上角的点
var cornerPoint = [1.0, 1.0, 0.0];
// 将被剪切(不可见)的点
var clippedPoint = [1.5, 0.5, 0.0];
WebGL 图形
现在我们理解了坐标系统,让我们来谈谈 WebGL 是如何实际绘制东西的。
基本图形
WebGL 使用简单的基本图形称为“图元”来绘制所有内容。主要有三种类型:
- 点
- 线
- 三角形
下面是一个总结这些图元的表格:
图元 | 描述 | 使用场景 |
---|---|---|
点 | 单个像素 | 粒子效果、星星 |
线 | 点之间的直线 | 线框、图表 |
三角形 | 三点形状 | 大多数 3D 模型、地形 |
让我们看看如何定义一个简单的三角形:
var triangleVertices = [
0.0, 0.5, 0.0, // 顶点
-0.5, -0.5, 0.0, // 左下角点
0.5, -0.5, 0.0 // 右下角点
];
这段代码定义了一个三角形的三点。每个点由三个数字表示(x, y, z)。
缓冲区
要将我们的三角形显示在屏幕上,我们需要使用一种叫做“缓冲区”的东西。将缓冲区想象成一个容器,它保存我们的顶点数据并将其发送到 GPU。
下面是如何创建和填充缓冲区的方法:
// 创建缓冲区
var buffer = gl.createBuffer();
// 绑定缓冲区(使其成为活动的)
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
// 用我们的三角形数据填充缓冲区
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(triangleVertices), gl.STATIC_DRAW);
如果现在这些看起来有点令人困惑,别担心。我们会在接下来的内容中详细解释!
着色器程序
现在我们来到了真正激动人心的部分:着色器!着色器是运行在你 GPU 上的特殊程序。它们就像处理你 3D 场景中每个顶点和像素的小型工厂。
着色器类型
WebGL 中主要有两种着色器:
- 顶点着色器:处理你 3D 场景中的每个顶点
- 片段着色器:决定每个像素的颜色
下面是每种着色器的简单示例:
// 顶点着色器
attribute vec4 a_position;
void main() {
gl_Position = a_position;
}
// 片段着色器
precision mediump float;
void main() {
gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); // 明亮的红色
}
顶点着色器决定每个点(顶点)应该在屏幕上的位置。片段着色器然后填充这些点之间的所有像素。
编译和链接着色器
要使用我们的着色器,我们需要编译它们并将它们链接到一个程序中:
// 创建着色器程序
var program = gl.createProgram();
// 附加并编译着色器
var vertexShader = createShader(gl, gl.VERTEX_SHADER, vertexShaderSource);
var fragmentShader = createShader(gl, gl.FRAGMENT_SHADER, fragmentShaderSource);
gl.attachShader(program, vertexShader);
gl.attachShader(program, fragmentShader);
// 链接程序
gl.linkProgram(program);
这个过程就像编译和链接一个普通程序,但发生在 GPU 上!
OpenGL ES 着色语言变量
最后,让我们来谈谈在 OpenGL ES 着色语言(我们的着色器所使用的语言)中使用的一些特殊变量。
属性
属性是顶点着色器中使用的输入变量。它们通常包含关于每个顶点的数据,如位置或颜色。
attribute vec4 a_position;
一致变量
一致变量是全局变量,对所有顶点和片段都保持不变。它们非常适合用于转换矩阵或光照信息。
uniform mat4 u_modelViewMatrix;
易变变量
易变变量是从顶点着色器传递到片段着色器的变量。它们在顶点之间进行插值。
varying vec4 v_color;
下面是一个总结这些变量类型的表格:
变量类型 | 使用在 | 目的 |
---|---|---|
属性 | 顶点着色器 | 每个顶点的输入数据 |
一致变量 | 两者 | 全局数据 |
易变变量 | 两者 | 从顶点着色器传递到片段着色器的数据 |
就是这样!我们已经涵盖了 WebGL 的基础知识,从坐标到着色器。记住,学习 WebGL 就像学习绘画一样——需要练习和耐心。如果一开始所有内容都不容易理解,不要气馁。继续尝试,很快你就能在浏览器中创建令人惊叹的 3D 图形了!
祝编程愉快,未来的 WebGL 大师们!
Credits: Image by storyset