WebVR即web + VR的体验方式,本文介绍如何开发一个WebVR网页,在此之前,我们有必要了解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-polyfill.js

由于WebVR API还没被各大主流浏览器支持,因此需要引入webvr-polyfill.js来支持WebVR网页,它提供了大量VR相关的API,比如Navigator.getVRDisplay()获取VR头显信息的方法。

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中的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场景开发

使用navigator.getVRDisplays获取vr设备实例vrdisplay,我们需要将它传给当前运行的renderer渲染器,当点击按钮时可以进入VR模式,再次点击退出VR模式。

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,否则触发exitVRdisplay.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;// 创建光线、地面等...// 创建立方体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();

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

WebVR开发教程——标准入门相关推荐

  1. WebVR开发教程——深度剖析

    最近WebVR API 1.1已经发布,2.0草案也在拟定中,在我看来,WebVR走向大众浏览器是早晚的事情了,今天本人将对WebVR开发环境和开发流程进行深入介绍. WebVR与WebVR API ...

  2. SAP OData 开发教程 - 从入门到提高(包含 SEGW, RAP 和 CDP)

    文章目录 SEGW - Gateway Service Builder 使用 Restful ABAP Programming 编程模型(简称 RAP) 开发 OData 服务 使用 SAP Clou ...

  3. JavaFX开发教程——快速入门FX

    本文章主要针对JavaFX的入门内容进行讲解 创建项目 next 下一步的其他组件可以不用选 项目结构 HelloApplication-项目运行入口 HelloController-前后端交互类(跟 ...

  4. Swing开发教程从入门到实践(一)

    文章目录 开发工具 设置 实战示例 自定义组件 常用组件 总览 JFrame JDialog JPanel Layout布局 高级扩展 扩展皮肤 FlatLaf weblaf 扩展组件 自定义组件 S ...

  5. 微信小程序注册开发教程(入门)

    转眼到了17年,火了那么久的小程序的小程序终于在1月9号开放了,本着凑热闹的心态,打算感受一把.下面是一些大体的流程什么的,简单记录一下,可能不是很全了,想起来再添吧. 1.打开微信公众平台 ,选择立 ...

  6. 前端wxml取后台js变量值_微信小程序云开发教程WXML入门数据绑定

    同学们大家好,我是小伊同学,今天带领大家学习WXML部分一个重要的知识点,数据绑定. 简单来讲,数据绑定就是通过双重花括号将一个变量绑定到界面上. 首先,我们为什么要将变量绑定到页面上呢?因为在制作一 ...

  7. QCC305x系列开发教程(入门篇)之1.2-安装开发中需要配套软件

    目录 1.MDE安装 2.ADK_Toolkit安装 3.QACT安装 4.BlueSuite安装 5.GAIA_Client安装(安卓版) 查看全部文章:本系列文章全部汇总

  8. ❤️微信小程序 云开发 教程合集(视频+图文)免费❤️

    一.视频版 微信小程序云开发视频教程上线啦 二.图文版 (1)预备知识 1. 怎么注册开通个人微信小程序 2. 微信小程序云开发教程-互联网软件的运作模式 3.微信小程序云开发教程-云开发对微信小程序 ...

  9. truffle (ETH以太坊智能合约集成开发工具) 入门教程

    truffle (ETH以太坊智能合约集成开发工具) 入门教程 前言 在你了解区块链开发之前,你有必要了解区块链的一些基础知识,什么是DApp,DApp与传统app的区别, 什么是以太坊,以太坊中的智 ...

最新文章

  1. 识别网络应用所使用的协议Amap
  2. easyui 添加 自定义图标
  3. Examples osgparticleshader例子学习
  4. Flink从入门到精通100篇(十三)-Flink的入门教学
  5. 信息系统项目管理师论文指导(2/3)
  6. Codeforces 997D Cycles in Product (点分治、DP计数)
  7. 49 -算法 -LeetCode 107 107. 二叉树的层序遍历 II 栈队列vector
  8. paip.从HTML select 获取数据
  9. 新中大财务软件V5.08安装
  10. java根据车牌号获取车辆归属地
  11. java单点登录SSO教程(含源码和视频教程)
  12. AMAZEUI之iscroll 下滑刷新/上拉加载更多实例
  13. java-php-net-python-海鲜购物淘电商平台计算机毕业设计程序
  14. 区块链是什么通俗解释_区块链技术是什么?区块链的通俗解释原来是这样!
  15. DDOS防御----CENTOS 内核TCP参数优化
  16. 如何在APP中集成Google账户登录
  17. 元胞自动机交通模型【matlab实现】
  18. FastCAE工业仿真软件开源学院
  19. History of the Great Game
  20. win7官方原版iso镜像_Windows 10 v1909简体中文ISO镜像官方原版下载

热门文章

  1. 在uni-app里面怎么引入阿里矢量图标库?
  2. Golang 获取http状态码
  3. SAP SD 第一节 SD后台配置
  4. Gith黑窗口如何进入更深一级的文件夹
  5. 华为手环8添加门禁卡操作指导
  6. django+拉勾网招聘数据可视化
  7. adf测试 python_Python时间序列平稳检验--ADF检验
  8. 数据结构七大排序算法图解
  9. Android OpenGL ES 3.0 LUT 滤镜
  10. CS versus EE