iT邦幫忙

2021 iThome 鐵人賽

DAY 1
2
Modern Web

如何在網頁中繪製 3D 場景?從 WebGL 的基礎開始說起系列 第 1

Hello WebGL

大家好,大家都叫我西瓜。因為想轉職寫遊戲,而遊戲中會讓人第一個想到、也是能在第一瞬間吸引人的就是畫面了,筆者從事網站開發多年,也就順勢從 WebGL 開始學習,這系列文章將以做出範例的方式,跟大家分享這幾個月學習的心得

這系列文章假設讀者能夠看懂 Javascript,並且對於 Web 技術有基礎的了解

WebGL 是啥?為何是 WebGL?

簡單來說,WebGL 是一組在 Web 上操作 GPU 的 Javascript API,而 WebGL 絕大部分的 API 都可以找到 openGL 上對應的版本,且名字幾乎沒有差別,猜測制定 WebGL 標準時只打算做一層薄薄的包裝,這樣一方面瀏覽器可能比較好實做,但是也因此 WebGL 直接使用時是非常底層的,甚至偶爾會需要去算線性代數、矩陣的東西

看到這邊讀者們可能會想說:哇,我要來把 Tab 關掉了,洗洗睡。老實說,如果對於基礎原理沒有興趣,想要『快速』做出東西,這邊確實可以左轉 three.js 或是 babylon.js,筆者是基於下面這個因素決定學習 WebGL 的:

當你了解其原理時,比較不容易受到框架、潮流演進的影響

為什麼?在了解原理的狀況下,比較能知道框架幫你做了什麼,遇到變化比較大的需求的時候可能比較容易想到方法應對;前端技術更迭速度大家都知道,但是基礎原理是不會有太大的變化的;最後,透過 WebGL 學到的原理多多少少也能應用在其他平台上吧

筆者近期學習 WebGL 所使用的資源主要是 WebGL2 Fundamentals,這個網站上的教學寫的非常完整,從基礎一路到各個功能的實做,因此本次鐵人賽系列文章所提及的概念或多或少會與這個網站重疊,有興趣的讀者不妨交互參考看看;同時,如果有大大發現文章內容有誤,歡迎使用我的網站這邊的聯絡方式聯絡我改正,感謝!

準備開發環境

要製作範例,我們會需要編輯器,任何純文字編輯器皆可,接著透過瀏覽器執行網頁,理論上最新版 Chrome, Firefox, Edge 以及 Safari 都可以,WebGL 在這些瀏覽器都可以使用,筆者將使用 Chrome 示範;除此之外,我們需要一種方法讓瀏覽器讀取我們寫的網頁,這邊可以使用任何靜態網頁伺服器,例如:

  • Visual Studio Code Live Server,如果編輯器使用 Visual Studio Code,這會是最方便的選擇
  • nodeJS 的 http-server,安裝後在 commandline 上執行 http-server 會開啟網頁伺服器,以當前的工作目錄當成網站根目錄,預設把 port 開在 8080,可以透過 http://localhost:8080 打開網站,同時具有檢視資料夾的功能
  • ruby -run -ehttpd . -p8000: ruby 內建的網頁伺服器,與 http-server 類似,執行後 commandline 當前的工作目錄當成網站根目錄,-p8000 意思是 port 開在 8000,可以透過 http://localhost:8000 打開網站
  • python3 -m http.server / python -m SimpleHTTPServer: python 內建的網頁伺服器,預設把 port 開在 8000,可以透過 http://localhost:8000 打開網站

準備好開發用網頁伺服器,就可以來建立第一個範例的 HTML 檔案: 01-hello-webgl.html

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>01-hello-webgl</title>
</head>
<body>
  <canvas id="canvas"></canvas>
  <script type="module" src="01-hello-webgl.js"></script>
</body>
</html>

這邊可以看到有一個 <canvas id="canvas"></canvas>,這就是 WebGL 操作的『畫布』,WebGL 繪製的東西將透過這個元素呈現,另外 <script type="module" src="01-hello-webgl.js"></script>ES Module 的形式引入我們主要要寫的 Javascript: 01-hello-webgl.js

console.log('hello')

先這樣就好,使用瀏覽器透過網站伺服器打開 01-hello-webgl.html,並且按下 F12 或是右鍵檢視元件開啟開發者工具,接著應該可以在 Console 看到 hello 表示一切正常:

console-hello

為了確保之後對原始碼的更動在瀏覽器重整時使用更動後的版本,建議切換至 Network tab 關閉快取,以 Chrome 為例:

disable-cache

取得 WebGL instance

要取得 WebGL instance,我們透過 <canvas /> JS DOM API 的 .getContext() 並且傳入 'webgl' 來取得,像是這樣:

const canvas = document.getElementById('canvas');
const gl = canvas.getContext('webgl');
window.gl = gl;

第一行透過 id 取得元素,取得 gl 之後也設定到 window.gl 上方便在開發工具 Console 中玩轉:

window.gl

另一個常見的繪製 API 為 CanvasRenderingContext2D,這時要傳入的字串就變成 '2d': .getContext('2d'),在之後繪製文字的時候會需要這邊的幫忙

好歹畫點東西吧

老實說,我們距離繪製一些有意義的東西還有點遙遠,不過倒是可以先找個顏色填滿(事實上是清除)畫面讓第一天有點東西

首先要透過 gl.clearColor(red, green, blue, alpha) 設定清除用的顏色,這邊 red, green, blue, alpha 是介於 0 - 1 之間的浮點數,設定好之後,gl.clear(gl.COLOR_BUFFER_BIT) 進行清除,而 gl.COLOR_BUFFER_BIT 是用來指定清除顏色的部份,以筆者的主題色 #6bde99 / rgb(108 225 153) 為例,大概像是這樣:

gl.clearColor(108/255, 225/255, 153/255, 1);
gl.clear(gl.COLOR_BUFFER_BIT);

clear-color

雖然只是拿油漆工具填滿整張畫布,但是第一天至少讓畫面有點東西了,畫面上的綠色區塊就是 <canvas>,因為我們沒有設定長寬,在 Chrome 上預設的大小是 300x150

光是從 gl.clearColor / gl.clear 這兩個就可以感受到 WebGL 是來自另外一個世界的 API,在 GPU 這邊許多東西都是介於 0 到 1 之間的浮點數,而 gl.COLOR_BUFFER_BIT 更是體現跟底層溝通用的 bit flag

本篇的完整程式碼可以在這邊找到:

明天開始來繪製 GL 最常見的基本元素:三角形,並介紹繪製的基本流程


下一篇
畫一個三角形(上)
系列文
如何在網頁中繪製 3D 場景?從 WebGL 的基礎開始說起30

尚未有邦友留言

立即登入留言