WebGL - 繪圖模式

你好,未來的 WebGL 巫師們!? 今天,我們將要深入 WebGL 的刺激世界,探索繪圖模式。作為你們友好的鄰居計算機老師,我在這裡引導你們進行這次旅行,即使你們之前從未寫過一行代碼。所以,拿起你的虛擬畫筆,讓我們創造一些數字化的傑作吧!

WebGL - Modes of Drawing

mode 參數

在我們開始繪圖之前,讓我們來介紹我們節目的明星:mode 參數。把它當成魔杖,告訴 WebGL 如何連接點(或者在我們的例子中,頂點)來創造不同的形狀和圖案。

在 WebGL 中,當我們調用 gl.drawArrays()gl.drawElements() 函數時,我們需要指定一個 mode 參數。這個參數就像給連接點益智遊戲的指示——它告訴 WebGL 如何連接我們定義的點。

以下是 WebGL 中可用的不同繪圖模式的表格:

模式 描述
gl.POINTS 為每個頂點繪製一個單點
gl.LINES 在每對頂點之間繪製一條線
gl.LINE_STRIP 繪製一條連續的線,連接頂點
gl.LINE_LOOP 與 LINE_STRIP 相似,但會關閉形狀
gl.TRIANGLES 為每三個頂點繪製一個三角形
gl.TRIANGLE_STRIP 繪製一組連接的三角形
gl.TRIANGLE_FAN 繪製一個類似扇形的連接三角形

如果現在這些看起來很混亂,別擔心。我們將在接下來的例子中一一探討它們!

範例 - 繪製三條平行線

我們從一個簡單的例子開始:繪製三條平行線。這將幫助我們了解 mode 參數在實際中是如何工作的。

// 首先,設定我們的 WebGL 環境
const canvas = document.getElementById('myCanvas');
const gl = canvas.getContext('webgl');

// 接下來,定義我們的頂點著色器
const vertexShaderSource = `
attribute vec2 a_position;
void main() {
gl_Position = vec4(a_position, 0.0, 1.0);
}
`;

// 以及我們的片段著色器
const fragmentShaderSource = `
precision mediump float;
void main() {
gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); // 紅色
}
`;

// 創建和編譯著色器(現在不必擔心,我們會在未來的課程中詳細介紹)
const vertexShader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vertexShader, vertexShaderSource);
gl.compileShader(vertexShader);

const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fragmentShader, fragmentShaderSource);
gl.compileShader(fragmentShader);

// 創建一個程序並將著色器鏈接到它
const program = gl.createProgram();
gl.attachShader(program, vertexShader);
gl.attachShader(program, fragmentShader);
gl.linkProgram(program);
gl.useProgram(program);

// 定義我們線的位置
const positions = new Float32Array([
-0.8, -0.8,  // 線 1 開始
-0.8,  0.8,  // 線 1 結束
-0.3, -0.8,  // 線 2 開始
-0.3,  0.8,  // 線 2 結束
0.2, -0.8,  // 線 3 開始
0.2,  0.8   // 線 3 結束
]);

// 創建一個緩存並將位置放入其中
const positionBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
gl.bufferData(gl.ARRAY_BUFFER, positions, gl.STATIC_DRAW);

// 告訴 WebGL 如何讀取緩存並將其屬性分配給 a_position
const positionAttributeLocation = gl.getAttribLocation(program, 'a_position');
gl.enableVertexAttribArray(positionAttributeLocation);
gl.vertexAttribPointer(positionAttributeLocation, 2, gl.FLOAT, false, 0, 0);

// 清除畫布
gl.clearColor(0.0, 0.0, 0.0, 1.0);
gl.clear(gl.COLOR_BUFFER_BIT);

// 繪製線條
gl.drawArrays(gl.LINES, 0, 6);

現在,讓我們分解這個過程:

  1. 我們設定 WebGL 環境並定義著色器。現在不必過於關心這些;我們會在未來的課程中詳細介紹。

  2. 我們創建一個程序並將著色器鏈接到它。這就像準備我們的數字畫筆。

  3. 我們定義我們線的位置。每條線由兩個點(它的開始和結束)定義,每個點由兩個坐標(x 和 y)定義。所以,我們有三條線共六個點。

  4. 我們創建一個緩存並將我們的位置放入其中。這就像將颜料裝上畫筆。

  5. 我們告訴 WebGL 如何讀取這個緩存並將其與頂點著色器中的 a_position 屬性關聯。

  6. 最後,我們調用 gl.drawArrays(gl.LINES, 0, 6)。這裡發生了魔法!

  • gl.LINES 是我們的模式。它告訴 WebGL 在頂點對之間繪製線條。
  • 0 是我們位置數組中的起始索引。
  • 6 是我們要考慮的頂點數量(記住,我們有三條線共六個點)。

運行這段代碼,瞧!你應該會在黑色背景上看到三條紅色平行線。恭喜你,你剛剛創作了你的第一個 WebGL 繪圖!?

繪圖模式

既然我們已經看到了 gl.LINES 的作用,讓我們來探索一些其他的繪圖模式。我們將使用之前的設置,但更改我們的位置和繪圖模式。

gl.POINTS

讓我們從最簡單的模式開始:gl.POINTS。這個模式為每個頂點繪製一個單點。

// ... (之前的設置代碼)

const positions = new Float32Array([
-0.5, 0.5,
0.0, 0.0,
0.5, -0.5
]);

// ... (緩存設置代碼)

gl.drawArrays(gl.POINTS, 0, 3);

這將在畫布上繪製三個紅色點。簡單吧?

gl.LINE_STRIP

現在,讓我們嘗試 gl.LINE_STRIP。這個模式繪製一條連續的線,連接每個頂點。

// ... (之前的設置代碼)

const positions = new Float32Array([
-0.5, 0.5,
0.0, -0.5,
0.5, 0.5
]);

// ... (緩存設置代碼)

gl.drawArrays(gl.LINE_STRIP, 0, 3);

你應該會看到一個 V 形狀的線條,連接這三個點。

gl.LINE_LOOP

gl.LINE_LOOPLINE_STRIP 相似,但它會關閉形狀,將最後一個頂點連接到第一個頂點。

// ... (之前的設置代碼)

const positions = new Float32Array([
-0.5, 0.5,
0.0, -0.5,
0.5, 0.5
]);

// ... (緩存設置代碼)

gl.drawArrays(gl.LINE_LOOP, 0, 3);

這將繪製一個三角形的外框。

gl.TRIANGLES

現在,讓我們來填充形狀,使用 gl.TRIANGLES。這個模式為每三個頂點繪製一個三角形。

// ... (之前的設置代碼)

const positions = new Float32Array([
-0.5, -0.5,
0.5, -0.5,
0.0, 0.5
]);

// ... (緩存設置代碼)

gl.drawArrays(gl.TRIANGLES, 0, 3);

你應該會看到一個實心的紅色三角形。

gl.TRIANGLE_STRIP

gl.TRIANGLE_STRIP 要複雜一些。它繪製一組連接的三角形,每個三角形與前一个三角形共享兩個頂點。

// ... (之前的設置代碼)

const positions = new Float32Array([
-0.5, -0.5,
0.5, -0.5,
-0.5, 0.5,
0.5, 0.5
]);

// ... (緩存設置代碼)

gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);

這將繪製兩個連接的三角形,形成一個矩形。

gl.TRIANGLE_FAN

最後,讓我們看看 gl.TRIANGLE_FAN。這個模式繪製一個扇形,所有三角形共享第一個頂點作為公共點。

// ... (之前的設置代碼)

const positions = new Float32Array([
0.0, 0.0,    // 中心點
0.5, 0.0,    // 點 1
0.35, 0.35,  // 點 2
0.0, 0.5,    // 點 3
-0.35, 0.35  // 點 4
]);

// ... (緩存設置代碼)

gl.drawArrays(gl.TRIANGLE_FAN, 0, 5);

這將繪製一個看起來像四分之一圓的形狀。

至此,我們已經探索了 WebGL 中的所有繪圖模式。記住,掌握這些模式的關鍵在於練習。嘗試組合不同的模式,改變顏色,玩弄頂點位置。在你知道之前,你將能夠輕鬆地創建複雜的 WebGL 场景!

在我們的下一次課程中,我們將深入探討著色器,並學習如何為我們的繪圖添加一些魅力,如顏色和紋理。在此之前,祝所有未來的 WebGL 藝術家們編程愉快!??‍??‍?

Credits: Image by storyset