WebGL 概念和基礎(chǔ)入門(mén)
本文首發(fā)于政采云前端團(tuán)隊(duì)博客:WebGL 概念和基礎(chǔ)入門(mén)
https://www.zoo.team/article/webglabout

WebGL 是什么
對(duì)于 WebGL 百度百科給出的解釋是 WebGL 是一種 3D 繪圖協(xié)議,而對(duì)此維基百科給出的解釋卻是一種 JavaScript API。由于 WebGL 技術(shù)旨在幫助我們?cè)诓皇褂貌寮那闆r下在任何兼容的網(wǎng)頁(yè)瀏覽器中開(kāi)發(fā)交互式 2D 和 3D 網(wǎng)頁(yè)效果,我們可以將其理解為一種幫助我們開(kāi)發(fā) 3D 網(wǎng)頁(yè)的繪圖技術(shù),當(dāng)然底層還是 JavaScript API。
WebGL 發(fā)展史
WebGL 的發(fā)展最早要追溯到 2006 年,WebGL 起源于 Mozilla 員工弗拉基米爾·弗基西維奇的一項(xiàng) Canvas 3D 實(shí)驗(yàn)項(xiàng)目,并于 2006 年首次展示了 Canvas 3D 的原型。這一技術(shù)在 2007 年底在 FireFox 和 Opera 瀏覽器中實(shí)現(xiàn)。2009 年初 Khronos Group 聯(lián)盟創(chuàng)建了 WebGL 的工作組最初的工作成員包括 Apple、Google、Mozilla、Opera 等。2011 年 3 月 WebGL 1.0 規(guī)范發(fā)布,WebGL 2 規(guī)范的發(fā)展始于 2013 年,并于 2017 年 1 月最終完成,WebGL 2 的規(guī)范,首度在 Firefox 51、Chrome 56 和 Opera 43 中被支持。
WebGL 中的基本概念
WebGL 運(yùn)行在電腦的 GPU 中,因此需要使用能在 GPU 上運(yùn)行的代碼,這樣的代碼需要提供成對(duì)的方法,每對(duì)方法中的一個(gè)叫頂點(diǎn)著色器而另外一個(gè)叫做片元著色器,并且使用 GLSL 語(yǔ)言。將頂點(diǎn)著色器和片元著色器連接起來(lái)的方法叫做著色程序。
頂點(diǎn)著色器:頂點(diǎn)著色器的作用是計(jì)算頂點(diǎn)的位置,即提供頂點(diǎn)在裁剪空間中的坐標(biāo)值 
片元著色器:片元著色器的作用是計(jì)算圖元的顏色值,我們可以將片元著色器大致理解成網(wǎng)頁(yè)中的像素 數(shù)據(jù)獲取方式:在前面我們提到了頂點(diǎn)著色器和片元著色器的概念,而頂點(diǎn)著色器和片元著色器這兩個(gè)方法的運(yùn)行都需要有對(duì)應(yīng)的數(shù)據(jù),接下來(lái)我們一起來(lái)了解一下著色器獲取數(shù)據(jù)的四種方式: 屬性和緩沖:緩沖是發(fā)送到 GPU 的一些二進(jìn)制數(shù)據(jù)序列,通常情況下緩沖數(shù)據(jù)包括位置、方向、紋理坐標(biāo)、頂點(diǎn)顏色值等。當(dāng)然你可以根據(jù)自己的需要存儲(chǔ)任何你想要的數(shù)據(jù)。屬性用于說(shuō)明如何從緩沖中獲取所需數(shù)據(jù)并將它提供給頂點(diǎn)著色器。 全局變量:全局變量在著色程序運(yùn)行前賦值,在運(yùn)行過(guò)程中全局有效。全局變量在一次繪制過(guò)程中傳遞給著色器的值都一樣。 紋理:紋理是一個(gè)數(shù)據(jù)序列,可以在著色程序運(yùn)行中隨意讀取其中的數(shù)據(jù)。一般情況下我們?cè)诩y理中存儲(chǔ)的大都是圖像數(shù)據(jù),但你也可以根據(jù)自己喜歡存放除了顏色數(shù)據(jù)以外的其它數(shù)據(jù) 可變量:可變量是一種頂點(diǎn)著色器給片元著色器傳值的方式
小結(jié)
WebGL 只關(guān)心兩件事:裁剪空間中的坐標(biāo)值和顏色值。使用 WebGL 只需要給它提供這兩個(gè)東西。因此我們通過(guò)提供兩個(gè)著色器來(lái)做這兩件事,一個(gè)頂點(diǎn)著色器提供裁剪空間坐標(biāo)值,一個(gè)片元著色器提供顏色值。
WebGL 工作原理
了解完 WebGL 的一些基本概念,我們可以一起來(lái)看看 WebGL 在 GPU 上的工作都做了些什么。正如我們之前了解到的 WebGL 在 GPU 上的工作主要分為兩個(gè)部分,即頂點(diǎn)著色器所做的工作(將頂點(diǎn)轉(zhuǎn)換為裁剪空間坐標(biāo))和片元著色器所做的工作(基于頂點(diǎn)著色器的計(jì)算結(jié)果繪制像素點(diǎn))。假如我們需要繪制一個(gè)三角形,此時(shí) GPU 上進(jìn)行的工作便是先調(diào)用三次頂點(diǎn)著色器計(jì)算出三角形的 3 個(gè)頂點(diǎn)在裁剪空間坐標(biāo)系中的對(duì)應(yīng)位置,并通過(guò)變量 gl_Position 保存在 GPU 中,然后調(diào)用片元著色器完成每個(gè)頂點(diǎn)顏色值的計(jì)算,并通過(guò)變量 gl_FragColor 將對(duì)應(yīng)的顏色值存儲(chǔ)在 GPU 中。完成這些工作后我們已經(jīng)得到了繪制三角形所需的像素點(diǎn),最后便是光柵化三角形了。
原生 WebGL API 繪制三角形
前面我們已經(jīng)學(xué)習(xí)了 WebGL 的發(fā)展史、基本概念和工作原理等內(nèi)容,接下來(lái)我們就該實(shí)踐出真知了,所以我們來(lái)看看如何通過(guò) WebGL 在網(wǎng)頁(yè)中繪制一個(gè)簡(jiǎn)單的三角形。我們知道 WebGL 作為一種 3D 繪圖技術(shù)本身就是依托于 HTML5 中的 canvas 元素而存在的,所以在正式開(kāi)始繪制之前我們需要進(jìn)行一系列的準(zhǔn)備工作:
首先我們需要?jiǎng)?chuàng)建一個(gè) canvas 元素作為繪制三角形所需的畫(huà)布,并完成瀏覽器對(duì) canvas 元素兼容性的測(cè)試。
function webglInit () {
const canvasEl = document.createElement('canvas'); // canvas 元素創(chuàng)建
canvasEl.width = document.body.clientWidth; // 設(shè)置 canvas 畫(huà)布的寬度
canvasEl.height = document.body.clientHeight; // 設(shè)置 canvas 畫(huà)布的高度
document.body.append(canvasEl); // 將創(chuàng)建好的 canvas 畫(huà)布添加至頁(yè)面中的 body 元素下
// 接下來(lái)我們需要判斷瀏覽器對(duì)于 WebGL 的兼容性,如果瀏覽器不支持 WebGL 那么我們就不需要再進(jìn)行下去了
if(!canvasEl.getContext("webgl") && !canvasEl.getContext("experimental-webgl ")) {
alert("Your Browser Doesn't Support WebGL");
return;
}
// 如果瀏覽器支持 WebGL,那么我們就獲取 WebGL 的上下文對(duì)象并復(fù)制給變量 gl
const context = (canvasEl.getContext("webgl"))
? canvasEl.getContext("webgl")
: getContext("experimental-webgl");
/*
設(shè)置視口 context.viewport(x, y, width, height);
x: 用來(lái)設(shè)定視口的左下角水平坐標(biāo)。默認(rèn)值:0
y: 用來(lái)設(shè)定視口的左下角垂直坐標(biāo)。默認(rèn)值:0
width: 用來(lái)設(shè)定視口的寬度。默認(rèn)值:canvas 的寬度
height: 用來(lái)設(shè)定視口的高度。默認(rèn)值:canvas 的高度
當(dāng)你第一次創(chuàng)建 WebGL 上下文的時(shí)候,視口的大小和 canvas 的大小是匹配的。然而,如果你重新改變了canvas的大小,你需要告訴 WebGL 上下文設(shè)定新的視口,因此這里作為初次創(chuàng)建這行代碼可以省略
*/
context.viewport(0, 0, context.canvas.width, context.canvas.height);
return context;
}準(zhǔn)備好了 canvas 畫(huà)布下一步就可以開(kāi)始畫(huà)三角形了,正如我們平常畫(huà)畫(huà)一般,我們需要準(zhǔn)備畫(huà)三角形所需的頂點(diǎn)即頂點(diǎn)著色器,以及三角形對(duì)應(yīng)的填充色即片元著色器
const gl = webglInit();
// 創(chuàng)建頂點(diǎn)著色器 語(yǔ)法 gl.createShader(type) 此處 type 為枚舉型值為 gl.VERTEX_SHADER 或 gl.FRAGMENT_SHADER 兩者中的一個(gè)
const vShader = gl.createShader(gl.VERTEX_SHADER)
// 編寫(xiě)頂點(diǎn)著色器的 GLSL 代碼 語(yǔ)法 gl.shaderSource(shader, source); shader - 用于設(shè)置程序代碼的 webglShader(著色器對(duì)象) source - 包含 GLSL 程序代碼的字符串
gl.shaderSource(vShader, `
attribute vec4 v_position;
void main() {
gl_Position = v_position; // 設(shè)置頂點(diǎn)位置
}
`)
gl.compileShader(vShader) // 編譯著色器代碼
const fShader = gl.createShader(gl.FRAGMENT_SHADER)
gl.shaderSource(fShader, `
precision mediump float;
uniform vec4 f_color;
void main() {
gl_FragColor = f_color; // 設(shè)置片元顏色
}
`) // 編寫(xiě)片元著色器代碼
gl.compileShader(fShader) // 編譯著色器代碼前面我們已經(jīng)完成了頂點(diǎn)著色器和片元著色器的配置,做好了一切繪制前的準(zhǔn)備工作接下來(lái),接下來(lái)我們就需要?jiǎng)?chuàng)建一個(gè)程序用來(lái)連接我們的頂點(diǎn)著色器和片元著色器完成最終的三角形繪制工作。
// 創(chuàng)建一個(gè)程序用于連接頂點(diǎn)著色器和片元著色器
const program = gl.createProgram()
gl.attachShader(program, vShader) // 添加頂點(diǎn)著色器
gl.attachShader(program, fShader) // 添加片元著色器
gl.linkProgram(program) // 連接 program 中的著色器
gl.useProgram(program) // 告訴 WebGL 用這個(gè) program 進(jìn)行渲染
const color = gl.getUniformLocation(program, 'f_color')
// 獲取 f_color 變量位置
gl.uniform4f(color, 0.93, 0, 0.56, 1) // 設(shè)置它的值
const position = gl.getAttribLocation(program, 'v_position')
// 獲取 v_position 位置
const pBuffer = gl.createBuffer()
// 創(chuàng)建一個(gè)頂點(diǎn)緩沖對(duì)象,返回其 id,用來(lái)放三角形頂點(diǎn)數(shù)據(jù),
gl.bindBuffer(gl.ARRAY_BUFFER, pBuffer)
// 將這個(gè)頂點(diǎn)緩沖對(duì)象綁定到 gl.ARRAY_BUFFER
// 后續(xù)對(duì) gl.ARRAY_BUFFER 的操作都會(huì)映射到這個(gè)緩存
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
0, 0.5,
0.5, 0,
-0.5, -0.5
]), // 三角形的三個(gè)頂點(diǎn)
// 因?yàn)闀?huì)將數(shù)據(jù)發(fā)送到 GPU,為了省去數(shù)據(jù)解析,這里使用 Float32Array 直接傳送數(shù)據(jù)
gl.STATIC_DRAW // 表示緩沖區(qū)的內(nèi)容不會(huì)經(jīng)常更改
)
// 將頂點(diǎn)數(shù)據(jù)加入的剛剛創(chuàng)建的緩存對(duì)象
gl.vertexAttribPointer( // 告訴 OpenGL 如何從 Buffer 中獲取數(shù)據(jù)
position, // 頂點(diǎn)屬性的索引
2, // 組成數(shù)量,必須是 1,2,3 或 4。我們只提供了 x 和 y
gl.FLOAT, // 每個(gè)元素的數(shù)據(jù)類(lèi)型
false, // 是否歸一化到特定的范圍,對(duì) FLOAT 類(lèi)型數(shù)據(jù)設(shè)置無(wú)效
0, // stride 步長(zhǎng) 數(shù)組中一行長(zhǎng)度,0 表示數(shù)據(jù)是緊密的沒(méi)有空隙,讓 OpenGL 決定具體步長(zhǎng)
0 // offset 字節(jié)偏移量,必須是類(lèi)型的字節(jié)長(zhǎng)度的倍數(shù)。
)
gl.enableVertexAttribArray(position);
// 開(kāi)啟 attribute 變量額,使頂點(diǎn)著色器能夠訪(fǎng)問(wèn)緩沖區(qū)數(shù)據(jù)
gl.clearColor(0, 1, 1, 1) // 設(shè)置清空顏色緩沖時(shí)的顏色值
gl.clear(gl.COLOR_BUFFER_BIT) // 清空顏色緩沖區(qū),也就是清空畫(huà)布
// 語(yǔ)法 gl.drawArrays(mode, first, count); mode - 指定繪制圖元的方式 first - 指定從哪個(gè)點(diǎn)開(kāi)始繪制 count - 指定繪制需要使用到多少個(gè)點(diǎn)
gl.drawArrays( gl.TRIANGLES, 0, 3 )
配合 HTML 文件運(yùn)行上述代碼后我們可以在網(wǎng)頁(yè)中看到如圖所示的三角形,且三角形大小根據(jù)瀏覽器窗口大小自適應(yīng)。
可以看到僅僅是繪制一個(gè)簡(jiǎn)單的三角形我們就已經(jīng)寫(xiě)了一大長(zhǎng)串的 JS 代碼,如果真的用原生 WebGL API 編寫(xiě)一個(gè)動(dòng)態(tài)的 3D 交互式網(wǎng)頁(yè),那么開(kāi)發(fā)成本可見(jiàn)是極其昂貴的。
WebGL 原生 API 開(kāi)發(fā)的不足
上面原生 WebGL API 繪制三角形的例子,充分向我們展示了使用原生 WebGL API 開(kāi)發(fā) 3D 交互式網(wǎng)頁(yè)存在的問(wèn)題。盡管從功能上而言原生 WebGL API 可以滿(mǎn)足我們?nèi)我鈭?chǎng)景的開(kāi)發(fā)需要但是,其開(kāi)發(fā)和學(xué)習(xí)的成本極其昂貴。對(duì)于 WebGL 的初學(xué)者而言是極度不友好的,我們需要配置頂點(diǎn)著色器用于計(jì)算繪制頂點(diǎn)所在的位置,而這對(duì)于開(kāi)發(fā)者而言需要一定的數(shù)學(xué)基礎(chǔ)熟悉矩陣的運(yùn)算,同時(shí)也要有空間幾何的概念熟悉 3D 物體的空間分布。而場(chǎng)景的光照,紋理等的設(shè)計(jì)也都需要對(duì)顏色的配置有自己的見(jiàn)解。所以為了給初學(xué)者降低難度,下面我將介紹一些 WebGL 開(kāi)發(fā)的常用框架。
幾種 WebGL 開(kāi)發(fā)的框架
Three.js Three.js 是 WebGL 的綜合庫(kù),其應(yīng)用范圍比較廣泛,美中不足的一點(diǎn)是,Three.js 庫(kù)沒(méi)有比較全面詳細(xì)的官方文檔,對(duì)于使用者而言不是特別友好 Cesium.js Cesium.js 是專(zhuān)用于 3D 地圖開(kāi)發(fā)的 WebGL 庫(kù),其擁有較為全面的 3D 地圖開(kāi)發(fā) API,對(duì)于需要開(kāi)發(fā) 3D 地圖的開(kāi)發(fā)者而言是一個(gè)不錯(cuò)的選擇,但針對(duì)其他場(chǎng)景的應(yīng)用開(kāi)發(fā)覆蓋的就不是很全面了 Babylon.js Babylon.js 是一款國(guó)外應(yīng)用較廣泛的 WebGL 庫(kù),感興趣的小伙伴可以自己去了解一下,這里就不做詳細(xì)介紹了
Three.js 是一款運(yùn)行在瀏覽器中的 3D 引擎,你可以用它創(chuàng)建各種三維場(chǎng)景,同時(shí) Three.js 也是一個(gè)綜合性的 WebGL 庫(kù)。如果你需要進(jìn)行 3D 地圖網(wǎng)頁(yè)的開(kāi)發(fā)那就可以用到 Cesium.js 了,Cesium.js 是一款專(zhuān)用于地圖開(kāi)發(fā)的 WebGL 庫(kù)。而 Babylon.js 則是國(guó)外較火的 WebGL 庫(kù)。
基于 Three.js 繪制旋轉(zhuǎn)立方體
運(yùn)用 Three.js 繪制旋轉(zhuǎn)立方體的第一步同原生 WebGl 一樣,首先便是要準(zhǔn)備 Three.js 運(yùn)行所需的環(huán)境。
// 創(chuàng)建 renderer 變量用于存儲(chǔ)渲染器對(duì)象
var renderer;
// initThree 函數(shù)用來(lái)初始化 Three.js 運(yùn)行所需的環(huán)境
function initThree() {
// 同原生 WebGL 環(huán)境搭建過(guò)程一樣,Three.js 也需要先設(shè)置畫(huà)布 canvas 元素的大小
width = document.getElementById('canvas-frame').clientWidth; // 設(shè)置寬度屬性為瀏覽器窗口寬度
height = document.getElementById('canvas-frame').clientHeight; // 設(shè)置高度屬性為瀏覽器窗口高度
// 新建一個(gè) WebGL 渲染器并賦值給 renderer 變量
renderer = new THREE.WebGLRenderer({
antialias: true
});
// 設(shè)置畫(huà)布大小為瀏覽器窗口大小
renderer.setSize(width, height);
// 將畫(huà)布元素掛載到頁(yè)面
document.getElementById('canvas-frame').appendChild(renderer.domElement);
// 設(shè)置清空畫(huà)布的顏色為白色
renderer.setClearColor(0xFFFFFF, 1.0);
}接下來(lái)不同于原生 WebGL 需要準(zhǔn)備頂點(diǎn)著色器和片元著色器,Three.js 需要準(zhǔn)備的是相機(jī)。Three.js 繪制 3D 網(wǎng)頁(yè)所需的 3 大基本要素便是 相機(jī)、場(chǎng)景和物體,當(dāng)然如果有需要設(shè)置明暗效果我們還需要加入第 4 要素光源,光源并不一定需要設(shè)置,但是相機(jī)、場(chǎng)景和物體是一定有的。
// 創(chuàng)建 camera 變量用于存儲(chǔ)相機(jī)對(duì)象
var camera;
// 初始化相機(jī)函數(shù) Three.js 中相機(jī)的類(lèi)型有好幾種可以根據(jù)具體需要進(jìn)行選擇這里我們要?jiǎng)?chuàng)建的是一個(gè)旋轉(zhuǎn)的立方體所以采用的是透視相機(jī),而如果需要?jiǎng)?chuàng)建 3D 陰影效果的場(chǎng)景則需要使用正交相機(jī)
function initCamera() {
/*
創(chuàng)建透一個(gè)視相機(jī)的實(shí)例語(yǔ)法 PerspectiveCamera( fov : Number, aspect : Number, near : Number, far : Number )
fov - 視角
aspect - 物體的長(zhǎng)寬比
near - 相機(jī)近點(diǎn)截圖
far - 相機(jī)遠(yuǎn)點(diǎn)截圖
*/
camera = new THREE.PerspectiveCamera(45, width / height, 1, 10000);
camera.position.x = 0; // 設(shè)置相機(jī)在三維空間坐標(biāo)中 x 軸的位置
camera.position.y = 10; // 設(shè)置相機(jī)在三維空間坐標(biāo)中 y 軸的位置
camera.position.z = 5; // 設(shè)置相機(jī)在三維空間坐標(biāo)中 z 軸的位置
camera.up.x = 0;
camera.up.y = 0;
camera.up.z = 1;
camera.lookAt(new THREE.Vector3(0,0,0));// 設(shè)置相機(jī)的觀(guān)察點(diǎn)
}上一步我們完成了相機(jī)的設(shè)置,下面我們來(lái)準(zhǔn)備 Three.js 繪制 3D 網(wǎng)頁(yè)所需的第二要素場(chǎng)景。
// 創(chuàng)建 scene 變量用于存儲(chǔ)場(chǎng)景對(duì)象
var scene;
// initScene 函數(shù)創(chuàng)建一個(gè)場(chǎng)景并賦值給 scene 變量
function initScene() {
scene = new THREE.Scene();
}準(zhǔn)備好了相機(jī)和場(chǎng)景下面我們就需要設(shè)置拍攝的物體了,完成物體的繪制后將其添加到場(chǎng)景中。
// 創(chuàng)建一個(gè) cube 變量用于存放幾何立方體
var cube;
// initObject 函數(shù)就是我們創(chuàng)建場(chǎng)景的核心了
function initObject() {
// 首先創(chuàng)建一個(gè)一個(gè)幾何類(lèi)的實(shí)例并賦值給 geometry 變量
var geometry = new THREE.BoxGeometry(1, 1, 1);
// 然后創(chuàng)建一種材質(zhì)的實(shí)例 MeshBasicMaterial 材質(zhì)的構(gòu)造函數(shù)能夠創(chuàng)建一種簡(jiǎn)單的不受場(chǎng)景燈光效果影響的材質(zhì)
var material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
// Mesh 是一種三角形網(wǎng)格基本單元的構(gòu)造函數(shù),類(lèi)似于我們?cè)?nbsp;WebGL 中的片元著色器它用于連接幾何體和材質(zhì)
cube = new THREE.Mesh( geometry, material );
// 最后將創(chuàng)建好的幾何立方體添加到場(chǎng)景中
scene.add(cube);
}到這里我們已經(jīng)完成了 Three.js 繪制 3D 網(wǎng)頁(yè)所需的基本配置,當(dāng)然如果有需要對(duì) 3D 網(wǎng)頁(yè)的明暗效果,燈光顏色做處理的我們還可以在場(chǎng)景中加入燈光的配置,這里由于我們的旋轉(zhuǎn)立方體對(duì)于燈光并未有什么特殊的要求,所以我們便直接進(jìn)入最后一步場(chǎng)景的渲染。
// render 函數(shù)提供了瀏覽器的循環(huán)渲染功能
function render() {
cube.rotation.x += 0.01;
cube.rotation.y += 0.01;
renderer.render(scene, camera);
requestAnimationFrame(render);
}
// 最后將 Threee.js 環(huán)境初始化,場(chǎng)景創(chuàng)建,相機(jī)創(chuàng)建渲染器創(chuàng)建以及渲染初始化等函數(shù)合成到一起執(zhí)行我們就完成了一個(gè)旋轉(zhuǎn)立方體的繪制
function threeStart() {
initThree();
initCamera();
initScene();
initObject();
render();
}
document.addEventListener('DOMContentLoaded',function(){
threeStart();
});Three.js 的旋轉(zhuǎn)立方體的繪制還需要配合 HTML 文件使用才能看到效果
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script type="text/javascript" src="../utils/three.js"></script>
<style type="text/css">
div#canvas-frame {
border: none;
cursor: pointer;
width: 100%;
height: 600px;
background-color: #EEEEEE;
}
</style>
</head>
<body>
<div id="canvas-frame"></div>
</body>
</html>配合 HTML 文件運(yùn)行上述代碼后我們可以在網(wǎng)頁(yè)中看到,一個(gè)旋轉(zhuǎn)的綠色立方體
小結(jié)
通過(guò)對(duì)比我們發(fā)現(xiàn)盡管我們通過(guò) Three.js 創(chuàng)建了更為復(fù)雜的場(chǎng)景,但是代碼量相對(duì) WebGL 原生 API 繪制三角形時(shí)反而要少了。由此可見(jiàn)對(duì)于初學(xué)者而言,直接使用 WebGL 原生 API 進(jìn)行 3D 網(wǎng)頁(yè)的開(kāi)發(fā),顯然是不合適的。這時(shí)候我們就可以借助像 Three.js 這樣的 WebGL 封裝庫(kù)進(jìn)行開(kāi)發(fā)。相較之原生 API 的開(kāi)發(fā),這類(lèi)第三方封裝好的 WebGL 庫(kù)大大降低了我們的開(kāi)發(fā)成本,同時(shí)也能幫助我們開(kāi)發(fā)出更加炫酷的頁(yè)面效果。當(dāng)然也不是說(shuō)原生 API 不好,畢竟如果有能力學(xué)透 WebGL 原生 API 的開(kāi)發(fā)還是能夠幫助我們?cè)陂_(kāi)發(fā) 3D 網(wǎng)頁(yè)的時(shí)候?qū)崿F(xiàn)更加隨心所欲的功能,且 Three.js 本身的文檔并不是特別完善所以想要順利的使用同樣需要摸透 WebGL 原生 API。
總結(jié)
WebGL 技術(shù)出現(xiàn)的時(shí)間并不算短,然而盡管能夠開(kāi)發(fā)出擁有炫酷效果的 3D 網(wǎng)頁(yè)卻一直未能大火,現(xiàn)今應(yīng)用的最多的也不過(guò)是 3D 網(wǎng)頁(yè)游戲的開(kāi)發(fā)。這其中很大一部分的原因便是受到網(wǎng)速發(fā)展的制約,在當(dāng)今這個(gè)快節(jié)奏的社會(huì)中人們對(duì)于網(wǎng)頁(yè)加載速度的忍耐度是極低的,一個(gè) WebGL 開(kāi)發(fā)的 3D 網(wǎng)頁(yè)動(dòng)輒需要三四秒的打開(kāi)時(shí)間對(duì)用戶(hù)而言無(wú)疑是極度不友好的。但是相信隨著 5G 通信技術(shù)的發(fā)展,網(wǎng)絡(luò)通信技術(shù)飛速發(fā)展下,WebGL 技術(shù)的明天可能會(huì)迎來(lái)新的發(fā)展契機(jī)。
看完兩件事
如果你覺(jué)得這篇內(nèi)容對(duì)你挺有啟發(fā),我想邀請(qǐng)你幫我兩件小事
1.點(diǎn)個(gè)「在看」,讓更多人也能看到這篇內(nèi)容(點(diǎn)了「在看」,bug -1 ??)

