资讯专栏INFORMATION COLUMN

VR大潮来袭 ---前端开发能做些什么

mikyou / 2594人阅读

摘要:通过佩戴的分离式头显浏览连接在主机端的网页,现支持的浏览器主要是火狐的和设置的谷歌。的概念大概就如此,这次我们将采用的方式来测试我们的场景,现在踏上我们的开发之旅。

WebVR即web + VR的体验方式,我们可以戴着头显享受沉浸式的网页,新的API标准让我们可以使用js语言来开发。本文将介绍如何快速开发一个WebVR网页,在此之前,我们有必要了解WebVR的体验方式。

WebVR体验模式


WebVR的体验方式可以分为VR模式和裸眼模式

VR模式

1.Mobile VR

如使用cardboard眼镜来体验手机浏览器的webVR网页,浏览器将根据水平陀螺仪的参数来获取用户的头部倾斜和转动的朝向,并告知页面需要渲染哪一个朝向的场景。

2.PC VR

通过佩戴Oculus Rift的分离式头显浏览连接在PC主机端的网页,现支持WebVR API的浏览器主要是火狐的 Firefox Nightly和设置VR enabled的谷歌chrome beta。

裸眼模式

除了VR模式下的体验方式,这里还考虑了裸眼下的体验浏览网页的方式,在PC端如果探测的用户选择进入VR模式,应让用户可以使用鼠标拖拽场景,而在智能手机上则应让用户可以使用touchmove或旋转倾斜手机的方式来改变场景视角。
WebVR的概念大概就如此,这次我们将采用cardboard + mobile的方式来测试我们的WebVR场景,现在踏上我们的开发之旅。

准备工作

测试工具:智能手机 + cardboard式头显 + chrome beta 60+(需开启WebVR选项)

如果你练就了裸眼就能将手机双屏画面看成单屏的能力也可以省下头显。

技术和框架:three.js for WebGL

Three.js是构建3d场景的框架,它封装了WebGL函数,简化了创建场景的代码成本,利用three.js我们可以更优雅地创建出三维场景和三维动画,这里我使用的是0.86版本。
如果想了解纯WebGL开发WebVR应用以及WebVR具体环境配置,可以参考 webvr教程--深度剖析。

需要引入的js插件:

1.three.min.js
2.webvr-polyfill.js 由于WebVR API还没被各大主流浏览器支持,因此需要引入它来解决兼容性问题。

3D场景构建

首先我们创建一个HTML文件




    
    
    webVR-helloworld
    






接下来编写js脚本,开始创建我们的3d场景。

1.创建场景

Three.js中的scene场景是绘制我们3d对象的整个容器

var scene = new THREE.Scene();
2.添加相机

Three.js中的camera相机代表用户的眼睛,我们通过设置FOV确定视野范围,

//定义一个60°的视角,视线范围在1到1000的透视相机
var camera = new THREE. new THREE.PerspectiveCamera(60,window.innerWidth/window.innerHeight,1,1000);
scene.add(camera);
3.添加渲染器

Three.js的渲染器用来渲染camera所看到的画面

//初始化渲染器 antialias参数为ture表示开启抗锯齿策略
var renderer = new THREE.WebGLRenderer({ antialias: true } );
//设置渲染器渲染尺寸
renderer.setSize(window.innerWidth,window.innerHeight);
//设置渲染背景为白色
renderer.setClearColor(0xeeeeee);
//将渲染场景的canvas放入body标签里
document.body.appendChild(renderer.domElement);
4.添加一个立方体网格
// 创建立方体
var geometry = new THREE.CubeGeometry( 10,10,10);
var material = new THREE.MeshLambertMaterial( { color: 0xef6500,needsUpdate: true,opacity:1,transparent:true} );
var cube = new THREE.Mesh( geometry, material );
cube.position.set(0,100,-50);
cube.rotation.set(Math.PI/6,Math.PI/4,0);
scene.add(cube);
5.启动动画

动画渲染的原理:渲染器的持续调用绘制方法,方法里动态改变物体的属性。
旧版的three.js需要手动调用requestAnimationFrame()方法递归的方式来渲染动画,新版three.js已经封装了该属性,因此只需要通过渲染器renderer.animate(callback)

function update() {
    //让立方体旋转
    cube.rotation.y += 0.01;
    //渲染器渲染场景,等同于给相机按下快门
    renderer.render(scene, camera);
}
renderer.animate(update);//启动动画

至此,我们已经绘制了一个简单的3d场景并且让它动了起来,接下来,我们需要让我们的场景可以支持WebVR模式。

WebVR场景开发

WebVR网页开发的基本原理是通过WebVR API获取VR动态数据(VR Display frameData),渲染器根据VR数据来分别绘制左右屏场景,具体步骤如下:

使用navigator.getVRDisplays获取vr设备示例

vrdisplay是vr设备的实例,我们需要将它传给当前运行的renderer渲染器。

function initVR(renderer) {
    renderer.vr.enabled = true;
    navigator.getVRDisplays().then( function(display) {
        renderer.vr.setDevice(display[0]);
        const button = document.querySelector(".vr-btn");
        VRbutton(display[0],renderer,button,function() {
            button.textContent = "退出VR";
        },function() {
            button.textContent = "进入VR";
        });
    }).catch(err => console.warn(err));
}

这里需要通过按钮来控制当前的渲染模式:

当点击按钮时,根据display.isPresenting判断当前是否是使用vr设备下进行渲染,如果false,进入2,否则true进入3

当前非VR模式,点击按钮进入VR模式,此时调用display.requestPresent()display.isPresenting被设置为true,触发window的vrdisplaypresentchange事件

当前为VR模式,点击按钮退出模式,此时调用display.exitPresent()display.isPresenting被设置为false,触发window的vrdisplaypresentchange事件

/**  VR按钮控制
    * @param {VRDisplay} display VRDisplay实例
    * @param {THREE.WebGLRenderer} renderer 渲染器
    * @param {HTMLElement} button VR控制按钮
    * @param {Function} enterVR 点击进入VR模式时回调
    * @param {Function} exitVR 点击退出VR模式时回调
    **/
function VRbutton(display,renderer,button,enterVR,exitVR) {
    if ( display ) {
        button.addEventListener("click", function() {
            // 点击vr按钮控制`isPresenting`状态
            display.isPresenting ? display.exitPresent() : display.requestPresent( [ { source: renderer.domElement } ] );

        });

        window.addEventListener( "vrdisplaypresentchange", function() {
            // 是否处于vr体验模式中,是则触发enterVR,否则触发exitVR
            display.isPresenting ? enterVR() : exitVR();
        }, false );

    } else {
        // 找不到vr设备实例,则移除按钮
        button.remove();

    }
}

我们可以在vrdisplaypresentchange事件中根据isPresenting的值来改变按钮的UI,而three.js将根据isPresenting的值来决定是常规渲染还是vr模式渲染,在vr模式下,three.js将创建两个camera进行渲染。

代码优化

最后,将WebVR应用写成ES6 class,后面开发流程将按如下图结构来规范代码:

第一步,构造函数先初始化VR场景、相机和渲染器;第二步,在渲染之前调用start方法,在start方法里我们为场景创建3d物体;最后,调起renderer.animate(this.update)开启动画渲染,update方法里我们可动态操作物体属性,具体代码如下:

class WebVRApp {
    constructor() {
        // 初始化场景
        this.scene = new THREE.Scene();
        // 初始化相机
        this.camera = new THREE.PerspectiveCamera(60,window.innerWidth/window.innerHeight,0.1,1000);
        this.scene.add(this.camera);

        // 初始化渲染器
        this.renderer = new THREE.WebGLRenderer({ antialias: true } );
        this.renderer.setSize(window.innerWidth,window.innerHeight);
        this.renderer.setClearColor(0x519EcB);
        this.renderer.setPixelRatio(window.devicePixelRatio);
        document.querySelector(".main-page").appendChild(this.renderer.domElement);

        this.clock = new THREE.Clock();
        // VR初始化
        this.initVR();
        // 往场景添加3d物体
        this.start();
        // 窗口大小调整监听
        window.addEventListener( "resize", this.resize.bind(this), false );
        // 渲染动画
        this.renderer.animate(this.update.bind(this));
    }
    // 创建3d物体
    start() {
        const {scene,camera} = this;
        // 创建光线
        scene.add(new THREE.AmbientLight(0xFFFFFF));
        this.addLight();
        // 创建地面
        this.addGround(1000,1000);
        // 创建立方体
        this.addCube(2,2,2, 2,-1,-3);
    }
    // VR模式初始化
    initVR() {
        const {renderer} = this;
        renderer.vr.enabled = true;
        // 获取VRDisplay实例
        navigator.getVRDisplays().then( display => {
            // 将display实例传给renderer渲染器
            renderer.vr.setDevice(display[0]);
            const button = document.querySelector(".vr-btn");
            VRButton.init(display[0],renderer,button,() => button.textContent = "退出VR",() => button.textContent = "进入VR");
        }).catch(err => console.warn(err));
    }
    // 窗口调整监听
    resize() {
        const {camera,renderer} = this;
        // 窗口调整重新调整渲染器
        camera.aspect = window.innerWidth / window.innerHeight;
        camera.updateProjectionMatrix();
        renderer.setSize(window.innerWidth, window.innerHeight);
    }
    addCube(width=2,height=2,depth=2, posX,posY,posZ) {
        const {scene} = this;
        // 创建立方体
        const geometry = new THREE.CubeGeometry(width,height,depth);
        const material = new THREE.MeshLambertMaterial({ 
            color: 0xef6500,
            needsUpdate: true,
            opacity:1,
            transparent:true
        });
        const cube = new THREE.Mesh( geometry, material );
        cube.position.set({
            x: posX,
            y: posY,
            z: posZ
        });
        this.cube = cube;
        scene.add(cube);
    }
    addGround(width,height) {
        const {scene} = this;
        // 创建地平面
        const geometry = new THREE.PlaneBufferGeometry( width, height );
        const material = new THREE.MeshPhongMaterial( { color: 0xaaaaaa } );
        const ground = new THREE.Mesh( geometry, material );
        ground.rotation.x = - Math.PI / 2;
        ground.position.y = -10;
        scene.add(cube);
    }
    // 动画更新
    update() {
        const {scene,camera,renderer,clock} = this;
        const delta = clock.getDelta() * 60;
        // 启动渲染
        this.cube.rotation.y += 0.1 * delta;
        renderer.render(scene, camera);
    }
}
new WebVRApp();

完整代码:github.com/YoneChen/WebVR-helloworld。

结语

目前,国外的谷歌、火狐、Facebook和国内百度已推出支持WebVR浏览器的版本,微软也宣布将推出自己的VR浏览器,随着后期5g网络极速时代的到来以及HMD头显的价格和平台的成熟,WebVR的体验方式将是革命性的,用户通过WebVR浏览网上商店,线上教学可进行“面对面”师生交流等,基于这种种应用场景,我们可以找到一个更好的动力去学习WebVR。

参考链接

responisve WebVR: 探讨WebVR在不同头显(HMD)的适配方案
MolizaVR example: 火狐WebVR示例
webvr-boilerplate: A starting point for web-based VR experiences that work on all VR headsets.
how to build webvr: How to Build VR on the Web Today

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/82306.html

相关文章

  • 5G浪潮来袭,程序员在风口中有何机遇

    摘要:通过阅读本文,你将了解到的优势即将燃爆的领域以及程序员在快速发展的产业中所需关注的技术。在没有堵车醉驾疲劳驾驶女性乘车等安全问题的未来,这将是极大的福利。 导读:本文共2894字,预计阅读时间为9分钟。通过阅读本文,你将了解到5G的优势、即将燃爆的领域以及程序员在快速发展的5G产业中所需关注的技术。 5G时代已经来临 随着中美5G主导权之战的持续发酵,5G时代正式拉开了序幕。最近,5G...

    NikoManiac 评论0 收藏0
  • 5G浪潮来袭,程序员在风口中有何机遇

    摘要:通过阅读本文,你将了解到的优势即将燃爆的领域以及程序员在快速发展的产业中所需关注的技术。在没有堵车醉驾疲劳驾驶女性乘车等安全问题的未来,这将是极大的福利。 导读:本文共2894字,预计阅读时间为9分钟。通过阅读本文,你将了解到5G的优势、即将燃爆的领域以及程序员在快速发展的5G产业中所需关注的技术。 5G时代已经来临 随着中美5G主导权之战的持续发酵,5G时代正式拉开了序幕。最近,5G...

    idealcn 评论0 收藏0
  • 人工智能融入“云”端

    摘要:去年月,阿里云宣布将设立阿里云广东研发中心,招募名云计算和人工智能工程师,推动前沿技术与广东产业融合。吴维刚表示,人工智能与云计算,两者不是同一事物,但是相互发展。近年来,随着互联网和移动互联网的蓬勃发展,大数据、云计算、人工智能、物联网等新技术也迎来了广阔的发展空间。去年,阿里云工业互联网全国总部正式在广州揭牌成立,阿里云将联合广东本地合作伙伴,共同打造服务全国的工业大脑。去年9月,华为与...

    yacheng 评论0 收藏0
  • 人工智能融入“云”端:人工智能是火箭,云计算是引擎

    摘要:去年月,华为与白云区签署云计算产业战略合作协议,将协同打造千亿元级新一代信息产业集群。融入智慧大脑人工智能是火箭云计算是引擎业内,大家将人工智能大数据以及云计算称为铁三角关系。吴维刚表示,人工智能与云计算,两者不是同一事物,但是相互发展。近年来,随着互联网和移动互联网的蓬勃发展,大数据、云计算、人工智能、物联网等新技术也迎来了广阔的发展空间。去年,阿里云工业互联网全国总部正式在广州揭牌成立,...

    骞讳护 评论0 收藏0
  • 飓风来袭,数据中心企业如何躲过这一劫?

    摘要:如果佛罗伦萨像长驱直入,那么即便内陆的数据中心也同样令人担忧。另外,油罐车无法为发电机输送柴油燃料,美国境内有几个数据中心失去了电力。其他数据中心不得不依靠备用电力长达一周。飓风来袭。美国所有公共云服务提供商和美国大型技术公司都未雨绸缪,进行各种布局,以确保其建筑物足够坚固以应对飓风构成的威胁。数据中心正在为名为佛罗伦萨的飓风做好准备,因为它位于南卡罗来纳州和北卡罗来纳州,并在未来几天向弗吉...

    不知名网友 评论0 收藏0

发表评论

0条评论

mikyou

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<