WebGL - 繪圖模式
你好,未來的 WebGL 巫師們!? 今天,我們將要深入 WebGL 的刺激世界,探索繪圖模式。作為你們友好的鄰居計算機老師,我在這裡引導你們進行這次旅行,即使你們之前從未寫過一行代碼。所以,拿起你的虛擬畫筆,讓我們創造一些數字化的傑作吧!
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);
現在,讓我們分解這個過程:
-
我們設定 WebGL 環境並定義著色器。現在不必過於關心這些;我們會在未來的課程中詳細介紹。
-
我們創建一個程序並將著色器鏈接到它。這就像準備我們的數字畫筆。
-
我們定義我們線的位置。每條線由兩個點(它的開始和結束)定義,每個點由兩個坐標(x 和 y)定義。所以,我們有三條線共六個點。
-
我們創建一個緩存並將我們的位置放入其中。這就像將颜料裝上畫筆。
-
我們告訴 WebGL 如何讀取這個緩存並將其與頂點著色器中的
a_position
屬性關聯。 -
最後,我們調用
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_LOOP
與 LINE_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