Web端VR初介绍
目前,虽然VR硬件的发展已经走上了快车道,但内容却非常单薄。一部VR电影的成本相当高昂,VR游戏也不逊色。内容创作成本的居高不下,导致了VR的曲高和寡。要想脱下那一层高冷的贵族华裳,飞入寻常百姓家,VR尚需解决内容供给这一难题。以HTML5为代表的Web技术的发展,或将改变这一僵局。目前,最新的Google Chrome和Mozilla Firefox浏览器已经加入面向HTML5技术的WebVR功能支持,同时各方也正在起草并充实业界最新的WebVR API标准。基于Web端的这些虚拟现实标准将进一步降低VR内容的技术创作成本及门槛,有利于世界上最大的开发者群体—HTML5(JavaScript)开发者进入VR内容创作领域。这不仅是Web技术发展历程上的显著突破,也为VR造就了借力腾飞的契机。
Web端VR的优势
Web可降低VR体验门槛
Web技术不仅使创作VR的成本更加低廉,而且大大降低技术门槛。Web VR依托于WebGL技术的高速发展,利用GPU执行计算以及游戏引擎技术针对芯片级的API优化,提高了图形渲染计算能力,大大降低开发者进入VR领域的门槛,同时Web VR还可以更好地结合云计算技术,补足VR终端的计算能力,加强交互体验。
可以肯定,Web扩展了VR的使用范围,广告营销,全景视频等领域已经涌现一批创新案例,很多生活化的内容也纳入了VR的创作之中,如实景旅游、新闻报道、虚拟购物等,其内容展示、交互都可以由HTML5引擎轻松创建出来。这无疑给其未来发展带来更多想象空间。
Web开发者基数庞大
除了技术上的实现优势,Web还能给VR带来一股巨大的创新动力,因为它拥有着广泛的应用范围与庞大的开发者基数,能帮助VR技术打赢一场人民战争,让VR不再只是产业大亨们的资本游戏,而是以平民化的姿态,进入广大用户日常生活的方方面面。
相信假以时日,VR应用会像现在满目皆是的App一样,大量的VR开发者借助于Web端开发的低门槛而大量进入,同时各种稀奇古怪的创意层出不穷,虚拟现实成为电商商家必须的经营手段等。若到了这个阶段,VR离真正的繁荣也就不远了。
开发Web端的VR内容
接下来我们通过实践操作来真正制作一些Web端的VR内容,体验WebVR的便捷优势。我们知道,许多VR体验是以应用程序的形式呈现的,这意味着你在体验VR前,必须进行搜索与下载。而Web VR则改变了这种形式,它将VR体验搬进了浏览器,Web+VR = WebVR。在进入实践之前,下面先来分析一下WebVR实现的技术现状。
WebVR 开发的方式
在Web上开发VR应用,有下面三种方式:
HTML5+ Java Scnipt + WebGL + WebVR API
传统引擎 + Emscripten[1]
第三方工具,如A-Frame[2]
第一种方法是使用WebGL与WebVR API结合,在常规Web端三维应用的基础上通过API与VR设备进行交互,进而得到对应的VR实现。第二种是在传统引擎开发内容的基础上,比如Unity、Unreal等,使用Emscripten将C/C++代码移植到Java Scnipt版本中,进而实现Web端的VR。第三种是在封装第一种方法的基础上,专门面向没有编程基础的普通用户来生产Web端VR内容。在本文中我们主要以第一和第三种方法为例进行说明。
WebVR草案
WebVR是早期和实验性的JavaScript API,它提供了访问如Oculus Rift、HTC Vive以及Google Cardboard等VR设备功能的API。VR应用需要高精度、低延迟的接口,才能传递一个可接受的体验。而对于类似Device Orientation Event接口,虽然能获取浅层的VR输入,但这并不能为高品质的VR提供必要的精度要求。WebVR提供了专门访问VR硬件的接口,让开发者能构建舒适的VR体验。
WebVR API目前可用于安装了Firefox nightly的Oculus Rift、Chrome的实验性版本和Samsung Gear VR的浏览器。
使用A-Frame开发VR内容
如果想以较低的门槛体验一把WebVR开发,那么可以使MozVR团队开发的A-Frame框架。A-Frame是一个通过HTML创建VR体验的开源WebVR框架。通过该框架构建的VR场景能兼容智能手机、PC、 Oculus Rift和HTC Vive。MozVR团队开发A-Frame框架的的是:让构建3D/VR场景变得更易更快,以吸引Web开发社区进入WebVR的生态。WebVR要成功,需要有内容。但目前只有很少一部分WebGL开发者,却有数以百万的Web开发者与设计师。A-Frame要把3D/VR内容的创造权力赋予给每个人,其具有如下的优势与特点:
A-Frame能减少冗余代码。冗余复杂的代码成为了尝鲜者的障碍,A-Frame将复杂冗余的代码减至一行HTML代码,如创建场景则只需一个<a-scene> 标签。
A-Frame是专为Web开发者设计的。它基于 DOM,因此能像其他Web应用一样操作3D/VR内容。当然,也能结合box、d3、React等JavaScript 框架一起使用。
A-Frame让代码结构化。Three.js代码通常是松散的,A-Frame在Three.js之上构建了一个声明式的实体组件系统(entity-component-system)。另外,组件能发布并分享出去,其他开发者能以 HTML的形式进行使用。
代码实现如下:
// 引入A-Frame框架<script src="./aframe.min.js"></script><a-scene> <!-- 定义并创建球体 --> <a-sphere position="0 1 -1" radius="1" color="#EF2D5E"></a-sphere> <!-- 定义交创建立方体 --> <a-box width="1" height="1" rotation="0 45 0" depth="1" color="#4CC3D9" position="-1 0.5 1"></a-box> <!-- 定义并创建圆柱体 --> <a-cylinder position="1 0.75 1" radius="0.5" height="1.5" color="#FFC65D"></a-cylinder> <!-- 定义并创建底板 --> <a-plane rotation="-90 0 0" width="4" height="4" color="#7BC8A4"></a-plane> <!-- 定义并创建基于颜色的天空盒背景--> <a-sky color="#ECECEC"></a-sky> <!-- 设置并指定摄像机的位置 --> <a-entity position="0 0 4"> <a-camera></a-camera> </a-entity></a-scene>
使用Three.js开发VR内容
上文中我们提到另外了一种更加靠近底层同时更加灵活生产WebVR内容的方法,就是直接使用WebGL+WebVR的API。这种方法相对于A-Frame的优势在于可以将VR的支持方便地引入到我们自己的Web3D引擎中,同时对于底层,特别是渲染模块可以做更多优化操作从而提升VR运行时的性能与体验。
如果没有自己的Web3D引擎也没有关系,可以直接使用成熟的渲染框架,比如Three.js和Babylon.js等,这些都是比较流行且较为出色的Web3D端渲染引擎(框架)。接下来就以Three.js为例,说明如何在其上制作WebVR内容。
首先,对于任何渲染程序的三个要素是相似的,即是建立好scene、renderer、camera。设置渲染器、场景以及摄像机的操作如下:
var renderer = new THREE.WebGLRenderer({antialias: true}); renderer.setPixelRatio(window.devicePixelRatio); document.body.appendChild(renderer.domElement); // 创建Three.js的场景 var scene = new THREE.Scene(); // 创建Three.js的摄像机 var camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 0.1, 10000); // 调用WebVR API中的摄像机控制器对象,并将其与主摄像机进行绑定 var controls = new THREE.VRControls(camera); // 设置为站立姿态controls.standing = true; // 调用WebVR API中的渲染控制器对象,并将其与渲染器进行绑定 var effect = new THREE.VREffect(renderer); effect.setSize(window.innerWidth, window.innerHeight);// 创建一个全局的VR管理器对象,并进行初始化的参数设置 var params = { hideButton: false, // Default: false. isUndistorted: false // Default: false. }; var manager = new WebVRManager(renderer, effect, params);
上述代码即完成了渲染前的初始化设置。接下来需要向场景中加具体的模型对象,主要操作如下所示:
function onTextureLoaded(texture) { texture.wrapS = THREE.RepeatWrapping; texture.wrapT = THREE.RepeatWrapping; texture.repeat.set(boxSize, boxSize); var geometry = new THREE.BoxGeometry(boxSize, boxSize, boxSize); var material = new THREE.MeshBasicMaterial({ map: texture, color: 0x01BE00, side: THREE.BackSide }); // Align the skybox to the floor (which is at y=0). skybox = new THREE.Mesh(geometry, material); skybox.position.y = boxSize/2; scene.add(skybox); // For high end VR devices like Vive and Oculus, take into account the stage // parameters provided. setupStage(); } // Create 3D objects. var geometry = new THREE.BoxGeometry(0.5, 0.5, 0.5); var material = new THREE.MeshNormalMaterial(); var targetMesh = new THREE.Mesh(geometry, material); var light = new THREE.DirectionalLight( 0xffffff, 1.5 ); light.position.set( 10, 10, 10 ).normalize(); scene.add( light ); var ambientLight = new THREE.AmbientLight(0xffffff); scene.add(ambientLight); var loader = new THREE.ObjectLoader(); loader.load('./assets/scene.json', function (obj){ mesh = obj; // Add cube mesh to your three.js scene scene.add(mesh); mesh.traverse(function (node) { if (node instanceof THREE.Mesh) { node.geometry.computeVertexNormals(); } }); // Scale the object mesh.scale.x = 0.2; mesh.scale.y = 0.2; mesh.scale.z = 0.2; targetMesh = mesh; // Position target mesh to be right in front of you. targetMesh.position.set(0, controls.userHeight * 0.8, -1); });
最后的操作便是在requestAnimationFrame设置更新。在animate的函数中,我们要不断地获取HMD返回的信息以及对camera进行更新。
// Request animation frame loop functionvar lastRender = 0;function animate(timestamp) { var delta = Math.min(timestamp - lastRender, 500); lastRender = timestamp; // Update VR headset position and apply to camera. //更新获取HMD的信息 controls.update(); // Render the scene through the manager. //进行camera更新和场景绘制 manager.render(scene, camera, timestamp); requestAnimationFrame(animate); }
经验与心得
通过上述介绍我们基本可以实现一个具有初步交互体验的Web端VR应用,但这只是第一步,单纯技术上的实现距离真正的可工程化还有一定差距。因为最终工程化之后面向用户的产品必须比技术原型要考虑更多具体的东西,比如渲染的质量、交互的流畅度、虚拟化的沉浸度等,这些都最终决定用户是否会持续使用产品、接受产品所提供的服务等,所以将上述技术在工程化应用之前还有很多的优化与改进工作要做。以下是个人在做Web端VR应用过程中体会的一些心得经验,分享出来供读者参考。
引擎的选用。如果是使用已有的WebGL引擎,则可参考[5]中的文档来进行VR SDK集成。这里边需要做到引擎层与VR SDK层兼容,以及VR模式与引擎的工具部分的整合,也可以参考桌面引擎如Unity3D和Unreal在VR SDK集成上的开发模式。如果选用第三方的WebGL引擎则有Three.js或Babylon.js等可选,这些主流的WebGL引擎都已经(部分功能)集成了VR SDK。
调试的设备。调试Web端的VR应用同样需要有具体的VR设备的支持。对于桌面WebM内容还是要尽量使用HTC Vive或Oculus等强沉浸感VR设备。对于移动Web应用,由于Android平台上的各浏览器的差异较大,表现也会不太一致,所以建议使用iOS设备进行开发与调试,但是在最终发布前仍要对更多的Andnoid设备进行适配性测试与优化。
性能的优化。在Web端做三维的绘制与渲染,性能还是主要瓶颈,因而要尽可能的提高实时渲染的性能,这样才能有更多资源留给VR部分。目前的WebVR在渲染实时中并没有像桌面VR SDK一样可以调用众多的GPU底层接口做诸如Stereo rendering等深层次的优化,因而对性能的占用还是较多。
已知的问题。目前,WebVR仍然不太稳定,还会有诸多的Bug,比如某些情况下会有设备跟踪丢失的情况,而且效率也不是太高。大多数WebVR应用可以作为后期产品的储备和预研,但要推出真正可供用户使用并流畅体验的产品,还是有较长的路要走。
我们不妨来一起来看看一个VR DEMO的开发历程究竟是怎样的。
下面把大家可能会关心的开发环节简单介绍一下:
1、关于开发一个具有一定体量的VR DEMO需要的时间
60天前在我们的会议室的桌子上摆了一本叫《UNITY从入门到精通的书》,我们也搞不清楚这个开发时间是不是好事,是否容易被人认为是另一种“中国速度”搞出来的玩意。
后来我们换成了UE引擎,当然UE有可能会挺高兴的,你看我们的引擎多高效,效果多好,蓝图多么便捷,商城资源多么的好用……
另外需要指出的是其实这60天的时间不是零基础开始的,我们这个团队岁数偏大,基本都30+了,都有十年的基础三维美术经验积累,并且长期扮演乙方角色,导致在技术落地和时间观念上比较好。加上这个是自己在创作东西,大家投入的状态比较彻底。所以我说这是一段奇特而幸福的时光,当然付出的代价也是很大的,这期间我们没有接任何新的业务单子。
2、关于开发VR用什么引擎
其实用什么真的不重要,之前也看到知乎上面大神们的各种机灵文章探讨VR开发是用UE还是UNITY,意见几乎是一边倒的倾向于UNITY,类似用UE就会掉坑里……但我们研究了一阵觉得我们还是适合用UE,然后现在也还相对幸福地活着,《小马过河》的故事都读过吗?
我回忆了一下我们之前用的工具:MAX和MAYA。这俩都好,看你干什么用,如果是做建筑动画,就用MAX,因为快;做角色为主的动画电影,就用MAYA,动作模块好用,利于团队协同。
另外其实现在UE已经特别用心在做,看他的官方教程,商城一看就是下了很大的功夫,而且蓝图这个工具也特别合适偏视觉的团队去使用。
但看UE官方的公众号每次的阅读量都少得感人,与国内这么火热的VR题材形成有趣的反差,真不知道都在关注什么号。
还有个比较大的问题就是UE会的人比较少,我们只能花时间自己去摸索,现成的人不好找,这种方式叫死磕。
3、CG团队开发VR的优势和劣势
我觉得我们的优势还是在视觉设计上,比如我们认为不同的场景,作为交互工具的Vive手柄也应该有不同的主题,于是就出现了各种漂亮的手柄,我觉得都可以上官方商城了。
现在国内做VR内容开发的出身我觉得可以分成几种:
第一种是技术门槛相对较低的全景视频 ,这个大部分出身是之前搞实拍的,之前的名头一般是导演。
第二种是游戏公司,优势是在程序以及工作流程上和VR比较类似,容易在技术上转型,但尴尬的是如果想追求视觉效果的话最好是做次世代游戏的,但国内现在基本上都是移动端的网游路数,做次世代又以外包加工为主业。
第三种是之前CG行业的,就是我们这种,优势是对视觉比较有追求,国外有一些现在做得还挺好的团队之前也都是这个路子,但需要在技术上做一定的升级和转型,但好在底层的原理是类似的,一说都能明白。
第四种是程序猿团队,优势是能开发出来比较牛X的代码,写自己想要的shader,弄出来自己想要的功能,需要使劲的地方是怎么把东西弄好看了。
最后还有一种是说自己是做VR的。
4、UE引擎的蓝图
蓝图是UE专门为了提高工作效率开发的一个可视化模块编程,这个东西对我们的帮助很大,没有它我们的DEMO出不来。
举一个栗子:
DEMO后半程出现的你的双臂变成了翅膀,你挥动翅膀飞向苍穹,来到一片水天一色的盐湖,翅膀化为漫天飘散的羽毛……好浪漫的场景。
实现这个东西就需要借助蓝图的帮助,当然我们这个标注非常接地气,能看懂的一定能看懂。
总之,这是个全蓝图的DEMO,没有写一行代码,听起来不够高大上?其实UE开发蓝图是为什么呢,不就是让你把精力放到对最终效果帮助更大的事上吗,适合你团队的流程就是对的流程。
5、另一个技术点:PBR流程
PBR流程说起来还是游戏行业借鉴了CG行业引入的,但惭愧的是我们在CG行业后期因为项目类型的原因连UV都很少去展。
PBR材质系统可以让物体在引擎中表现出更加真实的质感与丰富的细节,这也是这一世代游戏引擎的通用材质系统,美术师在工作时以更符合现实世界光照原理的逻辑绘制贴图,调节材质。基于这一系统的Substance Tools系列工具软件将贴图、材质、shader等系统由原本的多软件工具协作整合成一个完整的系统,同时灵活的工作流极大地节省了制作时间,方便系列化贴图材质的迭代与更新,让材质贴图工作环节更直观,高效。
使用软件Substance painter,这个流程比我们早年PS和MAX展平贴图之间来回倒腾好了很多。
技术很重要,但面对一个新的视听体验方式,创作Very重要,更是VR体验设计的难点。
7、关于VR体验的选题
我们选的这个其实是个比较冷门的题材,现在能看到的大部分VR是打枪题材,我觉得我们好像对文化题材更感兴趣,再加上我们有几位同事都是航空迷,就选了这个题材。
我们注意到在STEAM上有个国外团队做的阿波罗登月的体验,就下载下来学习了一下,但我们认为他给我们的是一些错误的经验,这个团队我认为是一帮闷瓜工程师,太闷了,受不了。文化输出是个我们比较擅长的东西,这可能和之前的工作经历有点关系,而且应该用新的技术做点有意义的东西吧,打怪必须要有,但要是都打怪就不对了。
我自己的总结是,题材最好是你自己喜欢的,有深入研究的,然后又是适合VR表达的就是好的题材。
8、VR的叙事语言会和之前有什么不同
从创作角度来说,之前导演手里攥着摄像机,让你看哪就看哪,还有蒙太奇什么的逗你琢磨;但在VR的世界里,你就是临场参与者,导演需要引导你去看他希望你看的、参与的。
从2008年开始我们参与策划执行了好些现场活动,我觉得这个经验其实和VR是有相通之处的,在一个很大的空间中,在哪闹动静,哪给光,如何引导视线,推动情节发展,都是个有讲究、好玩的事情。
所以我觉得VR的视觉语言不是影片路子,而是个现场活动或表演的路数。
从技术流程上来说,原来的合成和剪辑岗位退休了,但是呢,又没有全退,还在但只是换了个平台,UE里居然加了非线编辑,也可以有后期滤镜什么的,真是有趣。
9、关于流程和分工
前后大致有20个左右的人参与,大部分的人员会集中在三维美术素材这个岗位,和游戏开发的人员分布类似。有一位导演,我们正直的朴岸老师来统筹整个事,在艺术上做把握,然后我和其他同事会一起配合从技术流程上往前推。
从根上说,可能开始这个选题有点大了,好处是对整个试听语言的探讨会更充分和深入,坏处就是导致要做的资源特别多,虽然我们在过去的十年中是个特别擅长做大体量,贩卖伟大的团队。但在有限的时间内会导致有些资源精度做得还是不够到位,如果时间再多点就会更好。 预计有可能爬不出来的坑居然很幸运的没遇到,总是逢凶化吉,比如开始觉得这么多物件最后肯定会卡成翔,但通过合理的加载和隐藏居然在帧率上还好,就是其实引擎的承载力比我们想象的要好。