下面主要介绍了WebGL和wasm,是除了html,css,js以外Web标准所支持的另外两个大件
前者实现复杂的图形处理,后者提供高效的代码迁移以及代码执行效率
首先,浏览器里的游戏是怎么做到这种交互又显示不同的画面的?
试想用我们的前端三件套实现一下.好像可以用canvas来实现,但是实现的过程会很复杂,代码量会很大
所以对这种图形渲染,实际上是交给了图形渲染引擎
我们可以通过引擎提供的js接口来执行我们的渲染过程
而我们要介绍的WebGL的本质就是OpenGL的js接口
那OpenGL又是什么呢?好像疑问越牵扯越多,不急,先了解一下图形渲染的原理
实际开发中,我们也不会直接使用WebGL,只是了解一下原理
内嵌于浏览器中,无需安装插件和库就可以使用
借助系统显卡来在浏览器里更流畅地展示3D 场景和模型了,还能创建复杂的导航和数据视觉化
可被用于创建具有复杂3D 结构的网站页面,例如:
这是Flutter ( Google 推出的应用开发框架)的图形渲染层次架构图.
注意 : WebGL 与OpenGL 平级,只是B/S 和C/S 架构的区别,所以等同于下图的OpenGL
所以WebGL的本质就是将浏览器要处理的图形经过翻译交给我们的GPU来执行
本质上,它其实是通过GLSL (OpenGL Shading Language)语言来实现的,跟JS一样,不过各殊其职罢了
与我们需要构建整个图像不同,在利用WebGL构造时,我们只需要告诉它一些点线面的关系,它就能自动处理,渲染出图形
具体过程如下,我们称这套流程为"渲染管线"
可以看到二者的对比
HTML
<body>
<canvas id="canvas"></canvas>
<script>
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
ctx.fillStyle = '#00F';
ctx.fillRect(0, 0, 600, 600);
</script>
</body>
html
<body>
<canvas id="canvas" width="600" height="600"></canvas>
<script src="webgl.js"></script>
</body>
webgl.js
function main(){
var canvas = document.getElementById('canvas');
var gl = canvas.getContext('webgl');
gl.clearColor(0, 0, 255/255, 1.0);
gl.clear(gl.COLOR_BUFFER_BIT);
}
main();
在2017年,OpenGL发布了其最终版本4.6,并在同一年,Khronos宣布不再推出新的OpenGL版本,而将专注于Vulkan(又称为glNext)和其他技术的发展.随着OpenGL停止更新,新一代图形API,如Vulkan、Metal、D3D12等相继发布,同时新的Web图形API WebGPU也即将问世.在此过程中,WebGL毫无疑问将退出历史舞台.
OpenGL已不再适应现代GPU架构
早期的GPU是一组固定的、仅具有基本功能的硬件,几乎没有可编程性.随着应用开发者不断突破这些非可编程系统的功能极限,GPU厂商也进行了技术突破.现代GPU已经演变成可以处理大量数据、支持异步并行计算的性能“怪兽”.
由于OpenGL是在计算机图形学的早期发布的,其全局状态机类似的设计已经与现代GPU架构脱节,无法充分发挥GPU的最优能力.而WebGL的设计来源于OpenGL子集标准,因此也面临相同的问题.
WebGL 仍将持续很长时间
尽管WebGPU距离我们越来越近,从发布的演示中可以看出,在多个方面都大幅优于WebGL.但可以预见的是,在未来很长一段时间内,WebGL仍然是前端图形应用开发的主要选择:
即WebAssembly是一种用于在 Web 浏览器中运行的低级字节码格式.它旨在提供一种高性能的、可移植的执行环境,使得各种语言能够在浏览器中运行,而不受到 JavaScript 引擎的限制.
如cpp代码
#include <emscripten.h>
extern "C" {
EMSCRIPTEN_KEEPALIVE
int add(int a, int b) {
return a + b;
}
}
Emscripten 是一个工具链,作用是通过LLVM 来编译生成asm.js 、WebAssembly 字节码,目的是让你能够在网页中接近最快的速度运行C 和C++ ,并且不需要任何插件.
安装好装Emscripten 后,我们可以通过以下命令将这段C++ 程序编译为wasm 程序:
emcc add.cpp -s WASM=1 -O3 --no-entry -o add.wasm
得到字节码
00 61 73 6D 01 00 00 00 01 17 05 60 00 01 7F 60
00 00 60 01 7F 00 60 01 7F 01 7F 60 02 7F 7F 01
7F 03 07 06 01 04 00 02 03 00 04 05 01 70 01 02
02 05 06 01 01 80 02 80 02 06 0F 02 7F 01 41 90
88 C0 02 0B 7F 00 41 84 08 0B 07 82 01 09 06 6D
65 6D 6F 72 79 02 00 19 5F 5F 69 6E 64 69 72 65
63 74 5F 66 75 6E 63 74 69 6F 6E 5F 74 61 62 6C
65 01 00 03 61 64 64 00 01 0B 5F 69 6E 69 74 69
61 6C 69 7A 65 00 00 10 5F 5F 65 72 72 6E 6F 5F
6C 6F 63 61 74 69 6F 6E 00 05 09 73 74 61 63 6B
53 61 76 65 00 02 0C 73 74 61 63 6B 52 65 73 74
6F 72 65 00 03 0A 73 74 61 63 6B 41 6C 6C 6F 63
00 04 0A 5F 5F 64 61 74 61 5F 65 6E 64 03 01 09
07 01 00 41 01 0B 01 00 0A 30 06 03 00 01 0B 07
00 20 00 20 01 6A 0B 04 00 23 00 0B 06 00 20 00
24 00 0B 10 00 23 00 20 00 6B 41 70 71 22 00 24
00 20 00 0B 05 00 41 80 08 0B
直接在在vscode里运行下面这段js代码
a = 2;
b = 4;
WebAssembly.instantiate(new Uint8Array(`
00 61 73 6D 01 00 00 00 01 17 05 60 00 01 7F 60
00 00 60 01 7F 00 60 01 7F 01 7F 60 02 7F 7F 01
7F 03 07 06 01 04 00 02 03 00 04 05 01 70 01 02
02 05 06 01 01 80 02 80 02 06 0F 02 7F 01 41 90
88 C0 02 0B 7F 00 41 84 08 0B 07 82 01 09 06 6D
65 6D 6F 72 79 02 00 19 5F 5F 69 6E 64 69 72 65
63 74 5F 66 75 6E 63 74 69 6F 6E 5F 74 61 62 6C
65 01 00 03 61 64 64 00 01 0B 5F 69 6E 69 74 69
61 6C 69 7A 65 00 00 10 5F 5F 65 72 72 6E 6F 5F
6C 6F 63 61 74 69 6F 6E 00 05 09 73 74 61 63 6B
53 61 76 65 00 02 0C 73 74 61 63 6B 52 65 73 74
6F 72 65 00 03 0A 73 74 61 63 6B 41 6C 6C 6F 63
00 04 0A 5F 5F 64 61 74 61 5F 65 6E 64 03 01 09
07 01 00 41 01 0B 01 00 0A 30 06 03 00 01 0B 07
00 20 00 20 01 6A 0B 04 00 23 00 0B 06 00 20 00
24 00 0B 10 00 23 00 20 00 6B 41 70 71 22 00 24
00 20 00 0B 05 00 41 80 08 0B
`.trim().split(/[\s\r\n]+/g).map(str => parseInt(str, 16))
)).then(({instance}) => {
const { add } = instance.exports
console.log('a + b =', add(a, b))
})
可以得到
a + b = 6
实际上,unity在build WedGL时,就是导出的wasm以保持高性能
可以看下面的导出步骤自行尝试,或者导出目录里面可以看到wasm文件
打开 Unity 项目,点击导航栏的 “File”,选择下拉菜单中的 “Build Settings”.
在打开的对话框中,切换平台为 WebGL,点击左边的 “WebGL”,然后选择右下角的 “Switch Platform”.如果是第一次导出 WebGL,Unity 可能会要求下载相应的组件包.确保勾选需要导出的所有场景.
在左下角点击 “Player Settings”,以更改 WebGL 平台专属的导出设置.
在 “Other Settings” 子菜单中,更改以下设置:
在 “Publish Settings” 子菜单中,更改以下设置:
Tip: 使用 Brotli 压缩后打包出来的文件大小会优于使用 Gzip 打包出来的文件大小,但代价是更长的打包等待时间.
确保项目路径没有中文字符(在某些条件下有中文也可以,这可能涉及到 Unity 版本问题,建议在出错时再进行更改).
点击 “Build and Run”,等待一段(较长的)时间.区别在于,“Build and Run” 会启动一个本地服务器,可以预览 WebGL 嵌入页面的效果,但打包时间不会有显著区别.在 Debug 阶段建议使用 “Build and Run”,要移植到网站上时只需使用 “Build” 然后取用核心文件.