WebVR大潮來襲時,前端開發能作些什麼

WebVR大潮來襲時,前端開發能作些什麼?

 
 

WebVR即web + VR的體驗方式,咱們能夠戴着頭顯享受沉浸式的網頁,新的API標準讓咱們能夠使用js語言來開發。本文將介紹如何快速開發一個WebVR網頁,在此以前,咱們有必要了解WebVR的體驗方式。css

WebVR體驗模式


 

 
體驗WebVR的方式

WebVR的體驗方式能夠分爲VR模式和裸眼模式

 

VR模式

1.Mobile VRhtml

如使用cardboard眼鏡來體驗手機瀏覽器的webVR網頁,瀏覽器將根據水平陀螺儀的參數來獲取用戶的頭部傾斜和轉動的朝向,並告知頁面須要渲染哪個朝向的場景。前端

2.PC VRgit

經過佩戴Oculus Rift的分離式頭顯瀏覽鏈接在PC主機端的網頁,現支持WebVR API的瀏覽器主要是火狐的 Firefox Nightly和設置VR enabled的谷歌chrome beta。github

裸眼模式

除了VR模式下的體驗方式,這裏還考慮了裸眼下的體驗瀏覽網頁的方式,在PC端若是探測的用戶選擇進入VR模式,應讓用戶能夠使用鼠標拖拽場景,而在智能手機上則應讓用戶能夠使用touchmove或旋轉傾斜手機的方式來改變場景視角。
WebVR的概念大概就如此,此次咱們將採用cardboard + mobile的方式來測試咱們的WebVR場景,如今踏上咱們的開發之旅。web

準備工做


測試工具:智能手機 + cardboard式頭顯 + chrome beta 60+(需開啓WebVR選項)chrome

若是你練就了裸眼就能將手機雙屏畫面當作單屏的能力也能夠省下頭顯。canvas

技術和框架: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文件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0, shrink-to-fit=no">
    <title>webVR-helloworld</title>
    <style type="text/css">
    * {
        margin: 0;
        padding: 0;
    }
    html,body {
        height: 100%;
        overflow: hidden;
    }
    </style>
</head>
<body>
</body>
<script src="./vendor/three.min.js"></script>
<script src="./vendor/webvr-polyfill.js"></script>
<script></script>
</html>

 

接下來編寫js腳本,開始建立咱們的3d場景。

1.建立場景

Three.js中的scene場景是繪製咱們3d對象的整個容器

var scene = new THREE.Scene();

2.添加相機

 
Three.js的相機

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場景

至此,咱們已經繪製了一個簡單的3d場景而且讓它動了起來,接下來,咱們須要讓咱們的場景能夠支持WebVR模式。

WebVR場景開發


WebVR網頁開發的基本原理是經過WebVR API獲取VR動態數據(VR Display frameData),渲染器根據VR數據來分別繪製左右屏場景,具體步驟以下:

  1. 使用navigator.getVRDisplays獲取vr設備示例
     
    WebVR網頁分屏

    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));
}

 

這裏須要經過按鈕來控制當前的渲染模式:

  1. 當點擊按鈕時,根據display.isPresenting判斷當前是不是使用vr設備下進行渲染,若是false,進入2,不然true進入3
  2. 當前非VR模式,點擊按鈕進入VR模式,此時調用display.requestPresent()display.isPresenting被設置爲true,觸發window的vrdisplaypresentchange事件
  3. 當前爲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,後面開發流程將按以下圖結構來規範代碼:

 
WebVRApp類

第一步,構造函數先初始化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;
    // 建立光線、地面等
    ...
    // 建立立方體
    const geometry = new THREE.CubeGeometry(2, 2, 2);
    const material = new THREE.MeshLambertMaterial({ 
      color: 0xef6500,
    });
    this.cube = new THREE.Mesh( geometry, material );
    this.cube.position.set({ x: 0, y: 0, z: -4 });
    scene.add(this.cube);
  }
  // 動畫更新
  update() {
    const {scene,camera,renderer,clock} = this;
    const delta = clock.getDelta() * 60;
    // 啓動渲染
    this.cube.rotation.y += 0.1 * delta;
    renderer.render(scene, camera);
  }
  // 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);
  }
}
new WebVRApp();

 

 
demo示例

完整代碼: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

 

做者 | YoneChen來源 | https://www.jianshu.com/p/c9c03e14ba9d

相關文章
相關標籤/搜索