紧接上文
WebVR扩展了WebGL的标准,增加了HMD、PS等组件,让开发者可以在H5上开发VR程序。高级VR设备往往拥有了比手机更高精度的传感器、显示器、GPU等,让用户可以更加真实的感受虚拟世界。本节是《Html5的局》最后一节,我们手把手的写一段VR代码,感受WebVR的便捷。
本次Demo所需二维码
用户可以本地启动HTTP服务,将URL填写到播放路径
3D地球
环境准备
- Three.js 到http://www.threejs.org下载最新源码,这里使用three.min.js作为渲染引擎。
- TrackballControls.js,在three.js的源码里面可以找到,作为交互控制器。
纹理准备
- 地球纹理,在网上可以找到最新的地图纹理,最好使用4k,比较清晰
- 星空纹理,虽然可以使用粒子系统来模拟星空,简单起见,使用4k纹理图
准备空白的html
我们会将所有JS代码写在单独的index.js中,因此index.html只是提供JS运行的环境,这一步为代码迁移到WebVRSDK做准备。代码如下:
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>WebGL Earth</title>
<style>
body { margin: 0; overflow: hidden; background-color: #000; }
</style>
</head>
<body>
<script src="three.min.js"></script>
<script src="TrackballControls.js"></script>
<script src="index.js"></script>
</body>
</html>
index.js核心代码
- 渲染器,使用WebGL渲染three.js中的3D对象
- 加载器,使用XMLHttpRequest或者Image,异步加载图片纹理
- 摄像机,模拟观察者的位置和方向,从不同角度来观看3D世界
- 控制器,接受用户点击、触摸、鼠标等事件,控制摄像机的参数,实现人机交互
- 材料,任何3D对象,是由骨骼和图像组成,材料就像油漆,粉刷过的对象更加真实
- 几何,3D对象的结构描述,这里只用球状几何
- 场景,用来管理所有需要展示的3D对象,以及他们之间的层级和关系
代码如下
var w = window.innerWidth;
var h = window.innerHeight;
var renderer = new THREE.WebGLRenderer(); // 创建渲染器
renderer.setSize(w, h); // 设置渲染器为全屏
document.body.appendChild(renderer.domElement); // 将渲染器添加到body上
var loader = new THREE.TextureLoader(); // 创建纹理加载器,用于异步加载图片
var camera = new THREE.PerspectiveCamera(45, w / h, 0.01, 1000);// 创建摄像机,表示人眼的方向
camera.position.x = 4;
var controls = new THREE.TrackballControls(camera); // 创建控制器,用来控制摄像机
var earth_mate = { map : loader.load('earth_map.jpg'), side : THREE.FrontSide }; // 地球的表面,一张4096x2048的图片
var earth_mesh = new THREE.Mesh(new THREE.SphereGeometry(1.5, 32, 32), new THREE.MeshBasicMaterial(earth_mate));// 地球的模型,直径1.0,经纬各32切片
var stars_mate = { map : loader.load('stars_map.png'), side : THREE.BackSide }; // 星空的表面,一张4096x2048的图片
var stars_mesh = new THREE.Mesh(new THREE.SphereGeometry(100, 16, 16), new THREE.MeshBasicMaterial(stars_mate));// 星空的模型,直径100,经纬各32切片
var scene = new THREE.Scene(); // 创建场景
scene.add(earth_mesh); // 添加地球
scene.add(stars_mesh); // 添加星空
scene.add(new THREE.AmbientLight(0xFFFFFF));// 创建环境光
animate();
function animate() {
requestAnimationFrame(animate); // 下一帧回调
earth_mesh.rotation.y += 0.002; // 绕Y轴旋转
controls.update(); // 控制器更新
renderer.render(scene, camera); // 刷新整个视图
}
用浏览器打开index.html
代码见附件:3D地球.zip
一个3D地球已经出现在了浏览器页面上。
我们可以双指上下滑动,来缩放地球
可以点击拖动,改变摄像机的视角
在手机的WebVRSDK上,可以使用三指滑动,改变摄像机的位置
从Native到H5
代码量进一步减小
- 核心代码仅有30行,我们就实现了3D地球,只是缩放、旋转、平移。
- 无需编译,所见即所得,只要能够编辑文本,就可以写代码
- 所见即所得,浏览器页面直接刷新,妈妈再也不用担心打包慢的问题了(C++编译尤其慢)
- 运行时调试,程序员都懂得。
门槛进一步降低
- 阅读three.js后,发现3D引擎的原理也挺简单的,以前只要提到3D游戏引擎,感觉很高深的样子。
- 分工更加灵活,框架可以*切换,类似的3D框架在上一篇文章中已经列举,有兴趣的同学可以学习
从3D到VR
传感器由屏幕转交给HMD
屏幕、鼠标等传统人机交互,已经无法满足VR设备的输入,HMD会提供更加人性化的输入,但缺少了键盘,VR的I/O也成了难事。
定时器由VREffect触发
VR对于视频帧的刷新精度,要求更高,不同的WebVR标准表现不一样,可以简单的认为effect.requestAnimationFrame等同于window.requestAnimationFrame
3D地球升级为VR地球
只需要修改几行代码,就可以轻松的打开VR模式
环境准备
- VREffect.js,检查&兼容WebVR的运行环境,控制VR模式的开启与否
- VRControls.js,监听HMD返回的信息,并及时的操控camera来调整视角
- WebVR.js,人性化的展示WebVR的信息和按钮
修改代码
切换为VR控制器
var controls = new THREE.TrackballControls(camera);
改为:
var controls = new THREE.VRControls(camera);
切换帧管理器
requestAnimationFrame(animate);
effect.requestAnimationFrame(animate);
增加VR特效器
// 将renderer的任务,封装为VREffect,由VR来控制双屏显示
var effect = new THREE.VREffect(renderer);
使用VR特效器渲染场景
effect.render(scene, camera);
增加VR检测
if (WEBVR.isAvailable() === true) {
document.body.appendChild(WEBVR.getButton(effect));
setTimeout(function() {
effect.requestPresent(); // 请求双屏显示
}, 1);
}
VR效果展示
由于附件只能上传一个,只放置了3D地球的源码,VR地球的源码和3D地球,除了index.js不一样,其他都一样,在线地址如下,自己下载一看即可。
这里放出二维码和在线链接地址,由于部分浏览器是没有兼容WebGL和WebVR,看到的效果可能不一致。
手机上,已经集成到最新的WebVRSDK中,用手机安装即可看到。
3D地球
浏览器点击: 3D地球
VR地球
浏览器点击: VR地球
如何使用WebVRSDK
WebVRSDK不支持Dom
WebVRSDK核心只有400k,集成了JS引擎、WebGL、WebVR、WebVideo、WebAudio、图像处理、网络处理等,如果参加Dom的支持,那和浏览器还是有什么差异?
WebVR如何加载已开发的H5工程
将核心的index.js所在的URL拷贝到APP的输入框,点击打开即可
写法上有何差异
由于不支持Dom,所以加载JS的任务需要写在JS中,目前有两种写法可以支持,二者都是同步方式加载,不支持异步。
使用内置API加载外部JS资源
window.loadFile = window.__execute || function() {}; // WebVRSDK不支持Dom,所以需要自定义函数,加载JS资源。浏览器则不需要。
window.loadFile('three.js'); // 加载当前目录的three.js
window.loadFile('promise.js'); // 加载当前目录的promise.js
window.loadFile('RollerCoaster.js'); // 加载当前目录的RollerCoaster.js
window.loadFile('WebVR.js'); // 加载当前目录的WebVR.js
window.loadFile('VREffect.js'); // 加载当前目录的VREffect.js
window.loadFile('VRControls.js'); // 加载当前目录的VRControls.js
使用标准JS加载JS资源
var script = document.createElement("label");
script.src = 'http://xxxx.js';// 绝对路径
// 或者
script.src = 'xxx.js';//相对路径
WebVRSDK的目标
性能的极致
现在主流的手机,都是多核心CPU、支持大型3D游戏的GPU。
如果要把硬件性能发挥到极致,我认为使用C/C++,或者汇编,往往能够最大化的“榨干”硬件,但这是不现实的,因为开发效率和维护成本太高了。
所以,WebVRSDK为了追求性能的机制,底层完全使用C/C++编写,直接封装硬件最底层的API,并暴露给JS接口,实现H5的标准。
以上Demo都可以在浏览器上开发、调试、运行,运行性能可以对比IE、Chrome、Safari、FireFox,红米3也可以达到60FPS的帧率
灵活的开发方式
- WebVRSDK提供的只是运行环境,开发、调试完全可以在PC的浏览器上完成,开发规则除DOM不支持外,完全遵守WebGL、WebVR、WebVideo等标准
2.不挑剔渲染引擎
支持2D的pixi.js
支持3D的three.js
甚至自定义的JS引擎
。。。
WebVRSDK的未来
提供底层API运行时支持
经过数据测试(简单测试,每种开发语言都有自的优缺点,勿喷)
JS运行速度对比Java,慢10倍,甚至更多;
Java运行速度对比C/C++,慢5~10倍
JS语言作为技术底层,如何提高性能呢?
我们大胆的提出假设,JS在大规模数据计算时的性能不足,是否可以由C/C++来弥补呢?
比如,矩阵的变换和算法,针对目前向量、矩阵、四元数、欧拉角等,数学算法已经很固定,我们是否可以大胆的提出"WebTransform"标准,将这些常用的算法,用C/C++编写后,暴漏给JS,让JS只要传数据就可以瞬间获取结果?
开放平台
我们已经走到了WebVR技术的前沿,目前主流的浏览器,特别是在移动端能够支持的,还没有正式支持,即使已经支持的浏览器,性能也比较差。这点,是WebVRSDK的优势。
WebVR的发展,背后是IT巨头的博弈,毕竟谁也不愿意在同一个维度去竞争,这是时代给我们的机遇和挑战,目前VR购物、看片、游戏等场景不断增多,硬件发展又无法跟上的时候,我们技术人员是否可以做点什么呢?
下一回
Html5的局,到此结束,我也该整理整理思路。