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 軸:深度(後到前)

以下是一個簡單的例子來幫助你們形象化:

// 定義一個頂點(3D 空間中的一個點)
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. 三角形

以下是一個總結這些基本元素的表格:

基本元素 描述 使用案例
單個像素 粒子效果、星星
點之間的直線 線框、圖表
三角形 三點形狀 多數 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 变量

Uniform 变量是在所有顶点和片段中保持不变的全局变量。它们对于转换矩阵或光照信息等东西非常有用。

uniform mat4 u_modelViewMatrix;

Varying 变量

Varying 变量是在顶点着色器到片段着色器之间传递数据的变量。它们在顶点之间进行插值。

varying vec4 v_color;

以下是一個總結這些變量類型的表格:

變量類型 使用在 用途
属性 顶点着色器 每個顶点的输入数据
Uniform 两者 全局数据
Varying 两者 从顶点传递到片段着色器的数据

这就对了!我們已經涵蓋了 WebGL 的基礎,從坐標到着色器。記住,學習 WebGL 就像學習繪畫一樣——它需要練習和耐心。如果一開始一切都不夠清晰,不要氣餒。持續實驗,很快你們就會在瀏覽器中創造出令人驚奇的 3D 圖形!

祝編程愉快,未來的 WebGL 大師們!

Credits: Image by storyset