WebGL - 基础:初学者的友好入门

你好,未来的 WebGL 大师们!我很高兴能成为你们在这激动人心的 WebGL 世界之旅中的向导。作为一位有着多年计算机图形学教学经验的人,我迫不及待地想与你们分享 WebGL 的魔法。别担心你编程新手——我们将从头开始,一步步建立我们的知识体系。那么,拿起一杯咖啡(或者茶,如果你喜欢的话),让我们开始吧!

WebGL - Basics

什么是 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 使用简单的基本图形称为“图元”来绘制所有内容。主要有三种类型:

  1. 线
  2. 三角形

下面是一个总结这些图元的表格:

图元 描述 使用场景
单个像素 粒子效果、星星
线 点之间的直线 线框、图表
三角形 三点形状 大多数 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 中主要有两种着色器:

  1. 顶点着色器:处理你 3D 场景中的每个顶点
  2. 片段着色器:决定每个像素的颜色

下面是每种着色器的简单示例:

// 顶点着色器
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