WebGL - 魔方旋轉
你好,未來的WebGL大師們!今天,我們將踏上一段令人興奮的旅程,進入3D圖形的世界。在本教程結束時,你將能夠使用WebGL創建一個旋轉的魔方。這不是很酷嗎?讓我們一起來看看!
了解基礎知識
在我們開始像DJ一樣旋轉魔方之前,讓我們先了解一下一些基本概念。
什么是WebGL?
WebGL(Web圖形庫)是一個JavaScript API,讓我們能在網頁瀏覽器中渲染3D圖形。這就像是給你的瀏覽器一副3D眼鏡!
為什麼選擇魔方?
你可能會想,"我們為什麼從魔方開始?" 嘿,親愛的學生們,魔方就像是3D圖形的"Hello World"。它足夠簡單,讓我們能夠理解,但同時也足夠複雜,教導我們重要的概念。而且,有誰不愛一個好魔方呢?
設置我們的WebGL環境
HTML畫布
首先,我們需要一個舞台,讓我們的魔方在上面表演。在WebGL中,這個舞台叫做畫布。讓我們來設定它:
<canvas id="glcanvas" width="640" height="480">
你的瀏覽器不支持HTML5畫布
</canvas>
這會創建一個640x480像素的畫布。如果你看不到它,別擔心 - 現在它就像是一個無形的舞池。
初始化WebGL
現在,讓我們讓WebGL準備好開始派對:
var canvas = document.getElementById('glcanvas');
var gl = canvas.getContext('webgl');
if (!gl) {
console.log('WebGL不支持,轉而使用experimental-webgl');
gl = canvas.getContext('experimental-webgl');
}
if (!gl) {
alert('你的瀏覽器不支持WebGL');
}
這段代碼獲取我們的WebGL環境。如果你的瀏覽器不支持WebGL,那就好比在VHS播放器上播放DVD - 根本行不通!
創建我們的3D魔方
定義頂點
魔方有8個角落(頂點)。我們需要告訴WebGL這些角落在哪里:
var vertices = [
// 正面
-1.0, -1.0, 1.0,
1.0, -1.0, 1.0,
1.0, 1.0, 1.0,
-1.0, 1.0, 1.0,
// 背面
-1.0, -1.0, -1.0,
-1.0, 1.0, -1.0,
1.0, 1.0, -1.0,
1.0, -1.0, -1.0,
// 顶面
-1.0, 1.0, -1.0,
-1.0, 1.0, 1.0,
1.0, 1.0, 1.0,
1.0, 1.0, -1.0,
// 底面
-1.0, -1.0, -1.0,
1.0, -1.0, -1.0,
1.0, -1.0, 1.0,
-1.0, -1.0, 1.0,
// 右面
1.0, -1.0, -1.0,
1.0, 1.0, -1.0,
1.0, 1.0, 1.0,
1.0, -1.0, 1.0,
// 左面
-1.0, -1.0, -1.0,
-1.0, -1.0, 1.0,
-1.0, 1.0, 1.0,
-1.0, 1.0, -1.0
];
每一組三個數字代表我們魔方的一個角落在三維空間中的位置。這就像是給WebGL一張我們魔方的地圖!
創建緩存
現在,我們需要把這些數據發送到GPU:
var vertexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
這就像是把我们的魔方打包進一個行李箱(緩存)然後發送到GPU。
Shaders - WebGL的魔法師
頂點Shader
頂點Shader負責定位我們的頂點:
var vertexShaderSource = `
attribute vec3 aVertexPosition;
uniform mat4 uModelViewMatrix;
uniform mat4 uProjectionMatrix;
void main(void) {
gl_Position = uProjectionMatrix * uModelViewMatrix * vec4(aVertexPosition, 1.0);
}
`;
這個Shader將每個頂點和我們的變換矩陣應用到一起。這就像是魔法師移動我們魔方的角落!
片段Shader
片段Shader負責給我們的魔方上色:
var fragmentShaderSource = `
void main(void) {
gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);
}
`;
這個簡單的Shader將所有東西染成白色。這就像是給我们的魔方上了色!
編譯和鏈接Shaders
現在我們需要編譯我們的Shaders並將它們鏈接到一個程序中:
function getShader(gl, source, type) {
var shader = gl.createShader(type);
gl.shaderSource(shader, source);
gl.compileShader(shader);
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
alert('編譯Shader時發生錯誤:' + gl.getShaderInfoLog(shader));
return null;
}
return shader;
}
var vertexShader = getShader(gl, vertexShaderSource, gl.VERTEX_SHADER);
var fragmentShader = getShader(gl, fragmentShaderSource, gl.FRAGMENT_SHADER);
var shaderProgram = gl.createProgram();
gl.attachShader(shaderProgram, vertexShader);
gl.attachShader(shaderProgram, fragmentShader);
gl.linkProgram(shaderProgram);
if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {
alert('無法初始化Shader程序:' + gl.getProgramInfoLog(shaderProgram));
}
gl.useProgram(shaderProgram);
這就像是教導我們的魔法師(Shaders)他們的技巧,然後把他們放到舞台上!
讓我們的魔方旋轉
設置旋轉
要讓我們的魔方旋轉,我們需要在時間上更新它的旋轉角度:
var cubeRotation = 0.0;
function render(now) {
now *= 0.001; // 轉換為秒
const deltaTime = now - then;
then = now;
cubeRotation += deltaTime;
drawScene();
requestAnimationFrame(render);
}
這個函數會被反覆調用,每次更新我們魔方的旋轉。
繪製場景
現在讓我們把所有東西合起來,繪製我們旋轉的魔方:
function drawScene() {
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
const projectionMatrix = mat4.create();
mat4.perspective(projectionMatrix, 45 * Math.PI / 180, gl.canvas.clientWidth / gl.canvas.clientHeight, 0.1, 100.0);
const modelViewMatrix = mat4.create();
mat4.translate(modelViewMatrix, modelViewMatrix, [-0.0, 0.0, -6.0]);
mat4.rotate(modelViewMatrix, modelViewMatrix, cubeRotation, [0, 1, 1]);
gl.uniformMatrix4fv(gl.getUniformLocation(shaderProgram, 'uProjectionMatrix'), false, projectionMatrix);
gl.uniformMatrix4fv(gl.getUniformLocation(shaderProgram, 'uModelViewMatrix'), false, modelViewMatrix);
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 36);
}
這個函數清除畫布,設置我們的視角,應用我們的旋轉,最後繪製我們的魔方。
結論
这就是了,各位!我們使用WebGL創建了一個旋轉的3D魔方。記住,掌握WebGL就像學習擲飛鏢 - 它需要練習,但一旦你掌握了它,你就能做出令人驚奇的事情!
這裡是一個我們使用的主要方法的總結:
方法 | 描述 |
---|---|
gl.createBuffer() |
創建一個新的緩存對象 |
gl.bindBuffer() |
將緩存對象绑定到一個目標 |
gl.bufferData() |
創建並初始化緩存對象的數據存儲 |
gl.createShader() |
創建一個Shader對象 |
gl.shaderSource() |
設置Shader對象的源代碼 |
gl.compileShader() |
編譯Shader對象 |
gl.createProgram() |
創建一個程序對象 |
gl.attachShader() |
將Shader對象附加到程序對象 |
gl.linkProgram() |
鏈接程序對象 |
gl.useProgram() |
設置當前程序為當前渲染狀態的一部分 |
gl.clear() |
清除緩存到預設值 |
gl.uniformMatrix4fv() |
為當前程序指定一個4x4矩陣的值 |
gl.drawArrays() |
從數組數據渲染原始 |
繼續練習,繼續編程,很快你就能在瀏覽器中創建出令人驚奇的3D圖形。編程愉快!
Credits: Image by storyset