WebGL - 基礎:初学者的友好導入
你好,未來的 WebGL 巫師們!我很興奮能成為你們在 WebGL 世界的驚險旅程中的導遊。作為一個教了多年計算機圖形的人,我迫不及待地想與你們分享 WebGL 的魔法。別擔心你們對編程是新手——我們會從頭開始,一步步建立我們的知識。那麼,來一杯咖啡(或者如果你喜歡,一杯茶),讓我們開始吧!
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 使用稱為基本元素的簡單形狀來繪製一切。三種主要類型是:
- 點
- 線
- 三角形
以下是一個總結這些基本元素的表格:
基本元素 | 描述 | 使用案例 |
---|---|---|
點 | 單個像素 | 粒子效果、星星 |
線 | 點之間的直線 | 線框、圖表 |
三角形 | 三點形狀 | 多數 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 变量
Uniform 变量是在所有顶点和片段中保持不变的全局变量。它们对于转换矩阵或光照信息等东西非常有用。
uniform mat4 u_modelViewMatrix;
Varying 变量
Varying 变量是在顶点着色器到片段着色器之间传递数据的变量。它们在顶点之间进行插值。
varying vec4 v_color;
以下是一個總結這些變量類型的表格:
變量類型 | 使用在 | 用途 |
---|---|---|
属性 | 顶点着色器 | 每個顶点的输入数据 |
Uniform | 两者 | 全局数据 |
Varying | 两者 | 从顶点传递到片段着色器的数据 |
这就对了!我們已經涵蓋了 WebGL 的基礎,從坐標到着色器。記住,學習 WebGL 就像學習繪畫一樣——它需要練習和耐心。如果一開始一切都不夠清晰,不要氣餒。持續實驗,很快你們就會在瀏覽器中創造出令人驚奇的 3D 圖形!
祝編程愉快,未來的 WebGL 大師們!
Credits: Image by storyset