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 最常见的基本元素:三角形,并介绍绘制的基本流程


<<:  [DAY1] 新的一天,新的开始

>>:  前言与接下来的学习历程

[Tableau Public] day 2:认识 tableau public & 下载安装

日子来到了第二天,我们先去 tableau public 的官网看看吧! 注册帐号跟下载程序这两件事...

[经典回顾]资讯服务异常公关用语「 骇客攻击」

资料来源: [HITCON年会] 亲爱的,问题不一定是骇客造成的 保密防谍、人人有责 骇客语录 ...

风险暴露(risk exposure)

-ISO 31000 该问题的核心概念是如何定性或定量地分析风险,以确定风险敞口,以货币价值,得分...

Day 1-单元测试 (前言)

以往工作的经历,身边工程师对测试的认识 对於目前撰写程序的开发员来说,「测试」一词大多是不会感到陌生...

[Day5] 假想使用者之情境范例

接续我们在昨天所阐述的设计流程, 接着来看看这些设计流程是如何在实际运作的Action上被实践的。 ...