【元宇宙】iOS16将支持WebXR!一起来撸个WebVR华容道吧

2022-06-20 23:21:03 浏览数 (1)

【元宇宙】iOS16将支持WebXR!一起来撸个WebVR华容道吧

1. 背景:浏览器的革命WebXR

6月7日凌晨,苹果举行了2022年的WWDC全球开发者大会,在iOS16-Beta开发者预览版中,Safari已支持WebXR标准api。早在2018年,Chrome79 和 Firefox Reality 就已支持 WebXR 标准,而苹果可能是出于对自家 App Store 的保护,迟迟未跟进,被业内人士指责"拖累WebXR技术发展的最大障碍"。

那什么是WebXR呢?说到VR大家一定不会陌生,前几年短暂火爆后一度遇冷,很大程度上是由于高昂的硬件成本限制了技术的普及。从去年 Facebook 改名 Meta,元宇宙概念将 VR 推向了新的高度,再加上近两年硬件设备价格的不断下探,从过去的动辄上万到现在的 6 Dof 设备才不到2000,字节旗下初露头角的pico今年甚至定下了180w台的销售目标,我们不难发现,VR正在迅速普及

再说回WebXR的概念,可以简单理解为 WebXR = Web VR AR ?R,由W3C发布于2019年。与传统VR技术不同,WebXR 技术不需要下载任何应用程序或插件,将VR体验搬到浏览器中。伴随着 5G网络HMD头显价格下探 以及 平台应用生态的成熟,我们有理由相信,一场交互的革命要来了,我们搬砖人也有了更好的动力来学习 WebXR 技术。

在端午节期间,我收到了因上海疫情延误的520礼物,pico-neo3-256G,拿到手后迫不及待地摸索了一阵。本文将和大家一起在 pico 中从零开发一个VR版华容道,敲开元宇宙的大门。

2. 方案设计:兼容多终端降低获客门槛

WebXR 的定义最早可以追溯到 2014 年,前Mozilla工程总监 Vladimir Vukicevic 构思了 WebVR API 的概念,这是一个 JavaScript API,特点是 兼容PC、移动设备、VR等各种设备,无需下载和安装即可在浏览器运行 3D VR 内容。

兼容是WebXR的一大亮点,通过降级体验,能够扩大用户群体:

  • 对于少数的VR一体机用户:可以支持6Dof 手柄的身临其境的完美体验
  • 对于部分cardboard盒子用户:可以降级支持3Dof 基于凝视(gaze)的交互体验,能够胜任一些相对轻松的场景
  • 对于广大的PC/手机设备用户:可以支持基础的裸眼3D效果 鼠标/触摸操作,交互效果也远胜普通的2D场景

说回本文的WebVR华容道,华容道游戏来源于三国故事《诸葛亮智算华容,关云长义释曹操》,玩家在一个5×4的棋盘上布置蜀国五虎上将和四卒围困曹操,共计10个棋子,通过滑动棋子帮助曹操移动到出口位置逃走。

虽然华容道玩起来没那么容易,但其整体交互相对简单,作为第一个入门元宇宙的demo再合适不过了,整体开发过程大致分为下面5个步骤:场景搭建、棋盘渲染、棋子拖动交互、触发奖励开宝箱、自动求解算法。

分析一下,不难看出,涉及到的交互只有两处:棋子拖动点击按钮自动求解。为了兼容更多的终端设备,在VR设备中,用户是通过手柄的扳机键抓取(triggerdown)动作实现棋子的移动、按钮的点击,在cardboard中通过凝视(gaze)来选择并触发棋子选择移动和按钮的点击,而PC/移动端设备中需要通过click/touch操作来交互。由于两种降级方案之前已经摸索过,加上刚拿到设备,所以趁着兴奋劲先把VR设备端的手柄交互实现。

在浏览器中打开时,默认是裸眼3D模式,而如果要将手机插入到cardboard设备中,可以通过点击页面右下脚的 VR 按钮,如下图所示:

点击后进入双目VR模式。

3. 技术概览:使用世界上最好的语言开发WebXR

众所周知,JavaScript 是世界上最好的语言。很幸运,WebXR就是使用的这最好的语言来进行开发的,而且开发门槛也足够低,并不需要使用复杂的WebGL,一次编码即可在多个主流VR平台上运行,因此,WebVR一度被认为具有推动VR应用规模的潜力。

3.1 浏览器现状

市面上的几个主流浏览器中,Chrome从2018年的79版本就开始全面支持WebXR,Mozilla在2014年成立Mixed Reality团队,在2018年还发布了AR/VR头显专用浏览器Firefox Reality。从目前的兼容性来看,最大的阻碍还是iOS的safari,随着 ios16的普及,WebXR的兼容性将不再是个问题。

3.2 框架选择

WebXR 领域相关的前端技术主要包括:WebGLcanvasThree.jsA-Frame,他们之间的关系大致如下图所示:

  • WebGL:涉及3D就不得不提 WebGL,WebGL 是 OpenGL ES 在浏览器端的实现,可以理解其为 OpenGL 的子集,其功能非常强大,甚至可以操作前端的每一个像素点,且支持 GPU 调用,但写起来异常复杂,学习成本很高
  • Three.js:作为前端最著名的 3D 库,将繁琐的 WebGL API 进行了封装和优化,方便调用
  • A-Frame:这是本文的主角,是 Mozilla 团队在 2015 年开源的一款做 WebVR 的框架,使用各种组件用很少的代码构建出丰富的3D世界。

其他的框架,如 Pixi.js、Babylon.js 等各有适合的场景,对于 WebVR 初学者来说,用好 A-Frame 和 Three.js 就足够啦。

3.3 A-Frame框架介绍

接下来隆重介绍下 A-Frame 框架,A-Frame 是一个构建VR/AR应用的网页开发框架,场景绘制使用 HTML 写法使其上手十分简单,其核心思想是基于 Three.js 提供一个声明式、可扩展、组件化的编程结构。A-Frame 使用的是 ECS 架构,即 entity-component-system(实体-组件-系统) 架构,遵循 组合模式好于继承和层次结构 的设计原则,灵活性很强,详情可以参考文档:链接。

3.3.1 ECS 实体-组件-系统 架构简述

实体:对应一个物体,也可以看作是若干组件的集合,在 A-Frame 中使用 <a-entity> 标签表示一个实体。

代码语言:html复制
<!-- 空实体 -->
<a-entity />
<!-- 给实体添加"几何模型"和"材料"两个组件,使其具有形状和外观-->
<a-entity geometry="primitive: box;" material="color: red;" />

组件:对应一个可重用的功能模块,以 html 标签属性的形式插入实体中,如上面的 geometrymaterial。除框架提供的组件外,开发者需要开发自定义组件,如华容道中触发宝箱动画的动画控制组件。

代码语言:html复制
<script>
// VR华容道触发宝箱动画控制组件
AFRAME.registerComponent('animation-control', {
  schema: {
    target: { type: 'selector', default: '' }, // 执行模型目标
    clip: { type: 'string', default: '' }, // 选择动画集
    duration: { type: 'string', default: '3' }, // 持续时间
    loop: { type: 'string', default: 'once' }, // 循环方式
  },
  init() {
    const { target, clip, duration, loop } = this.data;
    const model = target;
    this.el.addEventListener('click', () => {
      model.removeAttribute("animation-mixer");
      model.setAttribute("animation-mixer", AFRAME.utils.styleParser.stringify({clip, duration, loop}));
    });
  }
});
</script>
<a-entity animation-control></a-entity>

系统:为组件提供全局服务和管理,如公共方法和属性

3.3.2 架构优势

ECS 架构在 3D 和 VR 游戏开发领域更具优势,大名鼎鼎的 Unity 游戏引擎就是采用 ECS 架构,相比 OOP(面向对象),最大的区别在于 使用组合而非继承的方式 构建复杂类,这种使用最小耦合来集成复杂功能的方式更适合游戏项目的开发。

除了ECS,A-Frame使用 HTML 标记语言来构建3D场景,相比于其他游戏引擎,不仅上手简单,还巧妙地利用了浏览器web环境得天独厚的优势,如丰富的dom的操作api、强大的css选择器、完善的 npm 生态、typescript,甚至是 MVVM 框架如 vue、react 的使用,都能极大地简化编码操作。

4. 调试方案实践:打造沉浸式debug体验

工欲善其事,必先利其器。对于场景搭建、基础的js调试,浏览器配合模拟器已经足够了,但是涉及到复杂的手柄交互,浏览器就力不从心了,这里介绍几个本人搭建开发环境中总结的经验。

4.1 工程搭建

不用多说,npm webpack ts 已经是前端标配,使用 devServer 在本地 4096 端口启动服务,然后浏览器访问 http://localhost:4096/index.html 即可。

4.2 使用浏览器插件模拟VR设备交互

对于简单的交互,用 WebXR-emulator-extension 浏览器插件即可轻松搞定,后续的配置主要是针对真机调试的。

4.3 配置localhost的https证书

在本地编辑器中编写代码并实时在VR设备中生效是不是听起来很棒?不难想到开发机和VR设备连接在同一个路由器上,VR浏览器通过IP 端口访问开发机,如 http://192.168.31.88:4096/index.html,但是对 WebXR api 来说,https 是前置必须项,因此需要为 localhost 本地环境配置 https 证书。

关于 https 的介绍与原理,网上详尽的介绍有很多,最后都要落地为两个文件:cert-filekey-file,而常用的 Let's Encrypt 却无法为 localhost 申请证书,这里推荐使用 go 编写的 mkcert 工具简化 openssl 晦涩难懂的命令行操作:

代码语言:shell复制
$ brew install mkcert
# 为本地环境安装 CA
$ mkcert -install
$ mkcert local.csxiaoyao.test

根据命令行提示,将生成的两个文件拷贝到项目根目录下,并修改 webpack 的 devServer 配置。

代码语言:javascript复制
devServer: {
  port: 4096,
  hot: true,
  // https
  allowedHosts: [
    '*',
    'localhost',
    'local.csxiaoyao.test',
  ],
  https: {
    key: fs.readFileSync('./local.csxiaoyao.test-key.pem'),
    cert: fs.readFileSync('./local.csxiaoyao.test.pem'),
  },
},

4.4 关闭防火墙、配置静态IP和路由器host

配置完本地证书,就得用域名访问了,https://local.csxiaoyao.test:4096,在这之前还得配置下 host,让 DNS 能找到开发机,应该是可以在VR设备中安装安卓 host 修改工具来配置,此处偷个懒,直接修改家中路由器 host,添加一条记录:192.168.31.88 local.csxiaoyao.test。为了避免开发机动态IP发生变化,可以顺手为开发机分配一个静态IP,如 192.168.31.88,如果发现开发机访问不通,可以检查下防火墙配置。

4.5 VR头显访问本地工程并支持热更新

至此,试试VR设备浏览器访问 https://local.csxiaoyao.test:4096,并且 webpack 的 websocket 连接会主动热更新,nice!

4.6 错误日志输出

对于错误日志的收集,建议写一个 debug 组件用于输出,当然也可以用 vConsole,缺点是VR模式下看不到,得退出来查看。

4.7 投屏画面避免频繁穿戴设备

在实际开发中发现,每次修改代码后穿戴设备切换有些麻烦,而且脱下时间久了设备会强制重新定位,我的方法是将VR设备投屏,并遮住面部传感器,插上电源,让VR设备一直工作。写完代码,操作手柄调试,观看投屏,Perfect!

5. 场景搭建:从建模到动画

5.1 使用 A-Frame编辑器可视化搭建

由于本人美术能力有限,所以整体看起来比较丑,望谅解

A-Frame 自带一个功能强大的场景编辑器,在任意引入了 A-Frame 的页面中使用 ctrl alt i 快捷键即可打开。可以在编辑器中搭建地面、四面墙壁、房顶、棋盘盒,并导出参数到 html 源码中。

5.2 布光

本案例的华容道棋盘放置在一个 10m x 10m 的密闭房间内,框架会默认添加 ambient(环境光) / directional(平行光) 两个光源,由于密闭空间内默认灯光并不适用,所以将灯光重置为一个 ambient(环境光) 和一个头顶正上方的point(点光源)。

5.3 模型&材质

VR的世界里离不开各种模型,作为第一个demo,本案例导入的模型较少,包括:7个棋子模型、1个宝箱模型、1个古装人物模型,其中,宝箱、古装人物模型包含动画序列。

模型的格式有很多种,目前 A-Frame 支持比较好的模型格式为 gltf(glb)obj,更推荐使用 gltfglb 格式的模型,因为它包含的信息种类丰富,但是冗余很少,所以体积容量小,就像是模型界的 JPG,非常适合在 WebXR 这类 web 场景中使用。

关于建模工具,市面上有很多,本人最熟悉的还是 C4D,用它来 展 UV贴图 非常顺手!

本案例中的棋子模型是从零开始开发的,而其余的两个复杂模型都是从 sketchfab.com 上下载,因为载入 C4D 后有一些兼容问题,所以做了一些面的修补。而导入后的模型默认是素模,还需要新建材质来贴图。关于模型、材质和贴图,有很多门道,本人也不够专业,这里就不展开讨论了。

5.4 动画

gltf 模型支持关键帧动画,可以C4D中制作并导出,宝箱的开箱动画如下所示。而 A-Frame 动画的播放则需要借助 animation-mixer 组件实现,详情可以参考组件文档。

6. 棋盘绘制

棋盘的渲染其实是和棋局算法紧密相关的,本案例中棋盘使用一个二维数组来描述,-1 表示哨兵,用于界定边界,0 表示空格,1-10 对应了武将数组中的索引 1。在 A-Frame 中,将棋盘的坐标原点设定到左上角位置,由于每个棋子实例都会存储 type、top、left 信息,因此可以很方便地计算出每个棋子的坐标值,通过修改棋子实体的 position 组件属性,完成棋盘绘制。

7. 棋子拖动交互

在华容道中,棋子的拖动是受限的,只能是上下左右四个方向,并且必须整个棋子拖入值全为 0 的格子中,而棋子移动的触发在不同终端也是不同的。普通的PC/移动端,用户的操作是二维的,通过 mousedown/touchstart 和 mouseup/touchend 即可完成棋子的移动;而在VR设备中,用户的操作是三维的,控制棋子移动需要借助手柄,也就是激光发射器,通过监听激光与棋盘格的相交事件,以及用户触发的扳机 triggerdown / triggerup 事件,计算 Vector3 移动距离三维向量,触发棋子的移动动画。

8. 触发奖励开宝箱

每次在执行棋子移动后,都会判断曹操的位置是否到达棋盘最底部中间的位置,若到达该位置,游戏结束,并为宝箱模型实体添加 animation-mixer 组件来播放开箱动画,当看到这个古装人物模型的奖励,本文的WebVR华容道游戏就算结束了!(话说,我为了解开自己设置的这个默认关卡,挪棋子挪到手酸)

9. 自动求解算法

目前,网络上的华容道求解算法的讲解有很多,目前还没有数学方法来直接解决,只能依靠计算机穷举,利用 广度优先搜索 算法,获得最优解。华容道整体的计算量并不大,最复杂的图案需要127步完成,因为游戏一共有4类共10个棋子分布在 5x4 的棋盘上,全部的可能状态只有 65880 种,而且棋子的移动有空间限制并不灵活,导致图的规模进一步缩小。

游戏的求解过程就是棋局的搜索过程,每移动一个棋子就会生成一个新的棋局,对每一个棋局都要生成其所有的后续棋局,直到判断结果为解或后续棋局为空(死局),则结束。棋局的搜索空间是一个树状关系空间,广度优先搜索能够首先找到最优解,因为首先找到的解深度是最浅的。

为了进一步提高性能,需要把构造好的棋局缓存,本文采用的是 Zobrist 哈希算法来计算棋局的 key 值的。这是一种适用于棋类游戏的棋局编码方式,通过建立一个特殊的转换表,对棋盘上每一个位置的所有可能状态赋予一个绝不重复的随机编码,通过对不同位置上的随机编码进行异或计算,将复杂的棋局编码为一个整数类型哈希值,冲突率极低,可忽略不计,而且棋局变化时,不必对整个棋局重新计算哈希值,只需要计算发生变化的最小单元的状态变化即可。

在本案例中,玩家按下 resolve 按钮后,系统将立即算出最优解,并在棋盘中将棋子自动移动演化,直到曹操逃脱游戏结束。

10. 展望:营销,VR First!

目前,WebXR 无论在 Web 开发还是 VR 开发领域都是参与人数较少的一片蓝海。相关的资料,尤其是 A-Frame 框架除了官方文档外资料很少,网上搜到的大部分也是官方文档的搬运。WebVR华容道是本人业余时间正式接触VR半年来的第一个demo,如有不当之处欢迎指正交流。

WebVR的关键优势之一就是能够在网络、移动设备和 VR 平台上覆盖大量用户,其兴起更是为网络营销是创造了机遇,从前只能通过app使用的VR/AR功能,现在通过手机浏览器就能轻松开启,极大地降低了分享和使用门槛,前景十分广阔。

就像移动互联网时代终结PC时代,VR 是否能像移动应用一样成为主流,开辟一片新的天地?当用户厌倦了千篇一律的传统网页营销模式,或许行业里蹦出的一句"VR First"将彻底颠覆当前的营销活动设计和开发模式,那必将是激动人心的一刻。

11. 相关链接

WebXR模拟器浏览器插件

https://github.com/MozillaReality/WebXR-emulator-extension

A-Frame官方文档

https://aframe.io

A-Frame实体组件系统架构介绍

https://aframe.io/docs/1.3.0/introduction/entity-component-system.html

A-Frame更多优质组件

https://aframe.io/aframe-registry/

WebXR示例

https://immersive-web.github.io/webxr-samples/

3D模型资源

https://sketchfab.com/

sign.jpegsign.jpeg

0 人点赞