Mozilla工程师展示如何将WebGL应用移植到WebVR
文章相关引用及参考:mozilla
本文来自Manish Goregaokar
(映维网 2018年09月14日)在数个月前,我将一款Pathfinder演示应用程序移植到WebVR。那是一次有趣的经历,而我感觉自己在将WebGL应用移植到WebVR的过程中学到了一推事情。我认为这些经验教训应该会对大家有所帮助,尤其是缺乏Web编程经验的WebVR新人。
Pathfinder是一款用Rust语言编写的基于GPU的字体光栅化器,它包含一个在服务器端运行Rust代码的演示应用程序,但都在TypeScript网站的WebGL中完成所有的GPU工作。
我们有一个展示Mozilla Monument的3D演示作品,将其作为演示3D文本光栅化的一种方式。我希望做的事情是将其转换为WebVR应用程序,支持你通过移动头部来浏览纪念碑,而非使用键盘的方向键。
我在着手研究这个问题的时候相当熟悉OpenGL和WebGL,但对VR或WebVR几乎没有任何知识背景。三年前我编写了一个Android Cardboard应用程序,但也就仅此而已。
我希望这篇文章能够为类似的开发者提供帮助。
1. 什么是WebVR
WebVR是一组用于在Web上编写VR应用程序的API。它允许我们请求跳转到VR模式,这时我们就可以直接将影像渲染到VR显示器,而不是渲染到平面浏览器。当用户使用Cardboard或Daydream等设备时,用户需要将智能手机塞进头显之中。
WebVR API有助于切换至或离开VR模式,获取姿态信息,在VR中渲染,以及处理设备输入。新的WebXR Device API规范正在对一系列的事项进行优化。
2. 我需要什么设备来支持WebVR吗?
理想情况下,一款优秀的VR设备可以更容易地测试你的工作,但根据你需要的分辨率,Daydream或Cardboard已经足够。你甚至可以在没有头显的情况下进行测试,不过画面看起来会很怪异和出现扭曲。
对于本地测试,Chrome提供了一个非常有用的WebVR API模拟扩展。你可以使用其中的开发者工具面板来调整姿态,而且你可以获得无扭曲的显示。
火狐支持WebVR,而在启动一定的flag情况下,Chrome Canary同样予以支持。这个polyfill应该能兼容更多的浏览器。
3. 工作原理
我认为在我开始的时候,不理解这部分内容是我产生许多困惑和错误的根源。API的核心基本上是“将某些内容渲染到画布,然后再变出魔术”,而我当时无法确定魔法是如何产生。
基本上,有一些我们应该做的事情,然后浏览器(或polyfill)同样有一些额外的工作需要完成。
一旦我们进入VR模式,只要设备请求帧,就会触发回调。在这个回调中,我们可以访问姿态信息。利用姿态信息,我们可以确定每只眼睛应该看到的内容,并以某种形式将其提供给WebVR API。
WebVR API期望的事情是,我们将每个眼睛的视图渲染至画布,水平分割(当我们初始化它时,这个画布将传递给API)。这是我们这一边要做的事情,然后浏览器(或polyfill)完成剩下的工作。它将使用我们渲染的画布作为纹理,并且对于每只眼睛,它会扭曲渲染的一半以适当地使用设备中的透镜。例如,Daydream和Cardboard的扭曲遵循这个polyfill中的代码。
值得注意的是,作为应用程序开发者,我们不必担心这一点,因为WebVR API将会为我们处理它。我们只需要将每只眼睛的未扭曲视图渲染至画布,左边视图到左半边,右边视图到右半边,而浏览器将处理其余的视图。
4. 移植WebGL应用
webvr.info和MDN提供了一些很好的资源。webvr.info有一堆简洁的样本,如果你像我一样,捣鼓它们能够帮助你更好地学习。
4.1 进入VR模式
首先,我们需要访问VR显示器并进入VR模式:
我们需要添加一个Event Handler,用于进入/退出VR:
进入VR本身:
4.2 在VR中渲染
现在我们已经进入VR,下一步是什么?在上面的代码片段中,我们有一个render()调用,它正在完成大部分的艰苦工作。由于我们从一个现有的WebGL应用程序开始,我们已经有了这样的功能:
所以,我们首先要进一步处理两只眼睛的渲染:
这看起来很好,但请注意我们是为双眼渲染相同的影像,而且根本没有处理头部运动。为了实现这一点,我们需要使用WebVR从VRFrameData对象提供的透视图和视图矩阵。
VRFrameData对象包含一个姿态构件,其中包含所有头部姿态信息(位置,方向,甚至是速度和加速度)。但为了在渲染时正确定位camera,VRFrameData提供了我们可以直接使用的投影和视图矩阵。我们可以这样做:
在图形中,我们经常发现我们需要处理模型,视图和投影矩阵。模型矩阵定义了我们希望在空间坐标中渲染的对象位置,视图矩阵定义了camera空间和世界空间之间的变换,而投影矩阵则处理剪辑空间和camera空间之间的变换。有时候我们会处理其中一些组合,比如“模型-视图”矩阵。
你可以在webvr.info的立体渲染示例中看到立方体群代码使用这些矩阵。
我们的应用程序很可能已经具备模型/视图/投影矩阵的概念。如果没有,我们可以在顶点着色器中使用视图矩阵预乘我们的位置。我们的代码看起来将是这样:
这应该能解决问题。现在移动头部应该能触发场景中的移动。你可以通过这个演示应用程序看到代码的应用,它是利用本文提及的技术来将一个旋转三角形WebGL应用程序转换为WebVR兼容的三角形浏览应用程序。
如果我们有进一步的输入,我们可能需要使用Gamepad API来设计一个适用于典型VR控制器的VR界面,但这超出了本文的范围。