WebGL - 着色器:初學者指南

親愛的编程新手們!今天,我們將踏上一段令人興奮的旅程,進入 WebGL 着色器的世界。別擔心如果你之前從未寫過一行代碼——我將成為你在這個計算機图形的五彩繽紛景觀中的友好導遊。

WebGL - Shaders

着色器是什麼?

在我們深入之前,讓我們先了解著色器是什麼。想象你正在畫一幅畫。畫布是你的電腦屏幕,而着色器就像神奇的畫筆,告訴計算機如何精確地為每個像素上色。酷炫吧?

數據類型

在着色器的世界中,我們有一些特殊的數據類型來工作。讓我們看看它們:

數據類型 描述 示例
float 單精度浮點數 3.14
vec2 二維向量 vec2(1.0, 2.0)
vec3 三維向量 vec3(1.0, 2.0, 3.0)
vec4 四維向量 vec4(1.0, 2.0, 3.0, 4.0)
mat2 2x2 矩陣 mat2(1.0, 2.0, 3.0, 4.0)
mat3 3x3 矩陣 mat3(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0)
mat4 4x4 矩陣 mat4(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0)

別擔心這些看起來讓人覺得overwhelming——我們會一步步使用它們!

定語

定語就像我們放在變量上的特殊標籤。它們告訴着色器如何對待這些變量。這裡是主要的幾種:

定語 描述
attribute 每個頂點改變的輸入值
uniform 對所有頂點都保持不變的輸入值
varying 從頂點着色器傳遞到片段着色器的值

頂點着色器

頂點着色器就像我們3D模型的骨骼。它計算我們模型中的每個點(頂點)應該在屏幕上的哪裡。這裡有一個簡單的頂點着色器:

attribute vec3 aVertexPosition;
uniform mat4 uModelViewMatrix;
uniform mat4 uProjectionMatrix;

void main(void) {
gl_Position = uProjectionMatrix * uModelViewMatrix * vec4(aVertexPosition, 1.0);
}

讓我們分解一下:

  1. 我們聲明了一個名為 aVertexPositionattribute —— 這是我們頂點的位置。
  2. 我們有兩個 uniform 矩陣 —— 它們幫助我們定位並將我們的3D模型投影到2D屏幕上。
  3. main 函數中,我們計算我們頂點的最終位置。

片段着色器

如果頂點着色器是骨骼,那麼片段着色器就是皮膚。它決定每個像素的颜色。這裡有一個簡單的片段着色器:

precision mediump float;

void main(void) {
gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}

這個着色器將所有東西都染成了紅色!vec4(1.0, 0.0, 0.0, 1.0) 表示完全是紅色,沒有綠色,沒有藍色,並且完全不透明。

儲存和編譯着色器程序

現在我們已經寫好了我們的着色器,我們需要告訴 WebGL 關於它們的信息。這是我們如何在 JavaScript 中做到這一點:

function getShader(gl, id) {
const shaderScript = document.getElementById(id);
if (!shaderScript) return null;

const str = shaderScript.text;
let shader;

if (shaderScript.type === "x-shader/x-fragment") {
shader = gl.createShader(gl.FRAGMENT_SHADER);
} else if (shaderScript.type === "x-shader/x-vertex") {
shader = gl.createShader(gl.VERTEX_SHADER);
} else {
return null;
}

gl.shaderSource(shader, str);
gl.compileShader(shader);

if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
alert(gl.getShaderInfoLog(shader));
return null;
}

return shader;
}

這個函數做了幾件事:

  1. 它在 HTML 文檔中找到我們的着色器代碼。
  2. 它創建了正確類型的着色器(頂點或片段)。
  3. 它編譯着色器並檢查錯誤。

結合程序

最後,我們需要將我們的頂點和片段着色器結合成一個程序:

const shaderProgram = gl.createProgram();
gl.attachShader(shaderProgram, vertexShader);
gl.attachShader(shaderProgram, fragmentShader);
gl.linkProgram(shaderProgram);

if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {
alert("Could not initialize shaders");
}

gl.useProgram(shaderProgram);

這段代碼創建了一個程序,附加了我們的着色器,鏈接程序,並告訴 WebGL 使用它。

這就是全部!你剛剛踏入了 WebGL 着色器的世界。記住,就像學習任何新語言一樣,這需要練習。如果一開始沒有馬上明白——別氣餒——持續嘗試,很快你就能在網頁瀏覽器中創造出令人驚奇的3D圖形!

在我多年的教學經驗中,我見過無數學生從完全的初學者變成了着色法師。其中一個學生甚至用這些技能為她的畢業專案創建了一個虛擬藝術画廊——想象一下在網頁瀏覽器中漫步一個3D博物館!

那麼,你將用你的新着色器技能創造什麼呢?唯一的限制是你的想象力!未來的图形大師們,快樂編程!

Credits: Image by storyset