本文为 《程序员》 原创文章,未经允许不得转载,更多精彩文章请订阅 2017年《程序员》
作者:张乾,上海渲图信息科技有限公司CEO。曾任职于腾讯上海研发部,负责次时代游戏引擎的研究与开发工作,目前主要从事VR/AR以及轻量化Web3D的应用与平台开发,热爱图形与渲染。
责编:屠敏,关注 VR/AR 等领域,寻求报道或者投稿请发邮件tumin@csdn.net,另有「CSDN VR 开发群」,技术之路,我们共同进步,欢迎开发者加微信tm_forever_miss申请入群,务必备注姓名+公司+职位。
引用
导语:随着硬件和软件技术的发展,产业界对虚拟现实(Virtual Reality)用户体验产生了重大期望。技术的进步也使我们可能通过现代浏览器借助开放Web平台获得这种用户体验。这将帮助Web成为创建、分发以及帮助用户获得虚拟现实应用和服务生态系统的重要基础平台。
引言2016年最令科技界激动的话题,莫过于VR会如何改变世界。一些电影已开始涉足VR,让用户不仅能看到3D影像,更能以“移形换影”之术身临其境,带来前所未有的沉浸式观影体验;此外,游戏领域也开始VR化,用户再也不用忍受游戏包里单一的场景。这些酷炫效果带来了巨大想象空间,VR正在走近人们的生活。然而现实是,除了偶尔体验下黑科技的奇妙外,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应用,有下面三种方式:
第一种方法是使用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框架 <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>
上述代码在A-Frame中执行的效果如图1所示。
使用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 function var 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); }
最后,程序运行的效果如图2所示,可以直接在手机上通过VR模式并配合Google Cardboard即可体验无需下载的VR内容[3]。
上述示例中的代码实现可从[4]中下载。
经验与心得通过上述介绍我们基本可以实现一个具有初步交互体验的Web端VR应用,但这只是第一步,单纯技术上的实现距离真正的可工程化还有一定差距。因为最终工程化之后面向用户的产品必须比技术原型要考虑更多具体的东西,比如渲染的质量、交互的流畅度、虚拟化的沉浸度等,这些都最终决定用户是否会持续使用产品、接受产品所提供的服务等,所以将上述技术在工程化应用之前还有很多的优化与改进工作要做。以下是个人在做Web端VR应用过程中体会的一些心得经验,分享出来供读者参考。
许多人将即将过去的2016称为VR元年,在这一年中VR的确经历了突飞猛进的发展,体现在技术与生态等各个方面。在新的2017年,相信VR必将会有更大的发展与进步,作为技术工作者,我们更应该从自身的技术专长作为出发点,参与到新技术对社会与生活的变革中来。
参考链接[1] http://kripken.github.io/emscripten-site/
[2] https://aframe.io/
[3] http://www.shxt3d.com/webvr/index.html
[4] https://github.com/bugrunnerzhang/hellowebvr.git
[5] https://mozvr.com/
了解最新移动开发、VR/AR 干货技术分享,请关注 mobilehub 微信公众号(ID: mobilehub)。了解最新移动开发、VR/AR 干货技术分享,请关注 mobilehub 微信公众号(ID: mobilehub)。