VR虚拟现实技术分享

近几年VR技术大热,各种VR设备层出不穷。我来站在自己的角度简述一下当下VR的情况。

什么是VR?

VR、AR、MR有什么区别?

一般来讲,VR指的是纯虚拟的世界,用户需要带上不透明眼罩将看到的真实世界完全替换成计算机构建的三维世界。AR则不需要戴眼罩,或者带上半透明玻璃眼罩,用户透过眼罩仍然可以看到真实世界,计算机在半透明眼罩上精心地构建新的物理,使得用户看起来好像是真实世界多出一个物理一样。

从技术实现角度来说,两者都需要关注人和世界的交互,即感应人的动作。但VR不需要关注真实世界是什么样的,而AR由于需要在真实世界嵌入虚拟事物,需要在图像上对真实世界有着足够的理解。

上面是VR和AR的区别。下面说说我对MR的理解。

MR可以看做是AR的高级版。初级阶段AR的应用主要是基于现实世界物理增加标签或附属物,真正世界的物体仍然是真实世界的物体,虚拟物理都是新的物体,虽然是遵循真实世界的物理法则的,不过并不会替换真实世界中的原有物体。比如我有一个草坪,AR眼镜帮我在草坪上添了一棵树。

而高级阶段AR的应用,真实世界的一些物体会被精心地替换成虚拟世界,用户不会再看到这个物理的原本面貌,而被完全的替换掉了。这样的体验称作是MR。比如我有一个草坪,MR眼镜把草坪换成了水池。

从应用角度来看,VR适合于娱乐体验,比如游戏、电影;AR适合于标签实物、地图导航、工业设计;MR可以应用到很多工程、辅助操作领域。

VR内容

依据用户所看到的内容来分,大题来讲分为类,一类是VR视频,一类是纯虚拟世界。我们先要知道VR内容是怎么制作出来的,再去体会不同VR体验上的区别。

全景视频 panorama

VR视频大多是定点位置视频。这一类视频是360°全景摄像机拍摄的视频。和平面视频不同的是,这是一个球面视频。 在视频中的时候,你可以上下左右看,但是不能自由移动。 也就是说你个人的位置移动(比如向前走了一步)不会对所见世界中的物体的成像产生任何影响,每个物体依然是以同样的角度对着你。 也就是说观看全景视频时,VR设备只会捕捉你的视角变换动作,而不会捕捉你的移动。 Ref: http://vrplayer.tv/

3D虚拟世界

Unity3D构建的虚拟世界,任何一个可见的物体都是实时渲染出来的,因此你可以左顾右看、任意移动,你所看到的任何物体也会因为你视线位置或角度的变化而变化。 3D技术其实已经比较成熟了,正如已经风靡很多年了的游戏CS、极品飞车。

VR技术

虚拟世界

构建动画制作的3D虚拟世界需要3D引擎构建虚拟世界的各个物体。 构建全景视频则需要采集真实世界的点点滴滴,然后重放到VR视频中。

摄像头

在VR中,摄像头就是我们的眼睛,虚拟世界要对摄像头,也就是我们视线的变化做出反应。 将我们的眼睛加入到虚拟世界,也就是说,我们的眼睛(眼睛所对应的动作)是在VR世界中的一个最重要的交互方式。

虚拟世界的摄像头

拍摄全景视频的摄像机

运动感应、空间定位

运动感应主要靠传感器技术。

空间定位可以靠空间传感器定位、也可以靠视觉定位。

交互方式

彻底虚拟的世界叫Dream,而不叫Virtual Reality。 之所以称作Reality,是因为我们在这个世界中,能够以同现实世界一样的交互方式来应对这个VR世界。 先来想一想我们和真实世界的交互方式:用脚走,眼睛看,耳朵听,用嘴说,手碰,鼻子闻。当然还有更精细的,比如皮肤的感觉、用脚踢、用胳膊蹭等等。 以目前的技术和场景要求,VR设备做到了眼睛、耳朵、手势、走动这四种交互方式。

眼睛的交互

这是最重要的交互方式。前面说摄像头也提到了。需要做的是用设备将屏幕和双眼以舒适、无缝的方式融合在一起。

耳朵的交互

声音的立体声技术也早已非常成熟,根据空间定位来反馈出不同空间感的声音也是容易做到的。

手的交互

手持感应器将我们的手加入到虚拟世界,我们的手(手所对应的动作)是在VR世界的第二大交互方式。

嘴的交互

用户说的话要在虚拟世界有所反馈。这里自然就用到了语音识别、语义分析技术。

VR设备

当前的VR设备大体分为两类。一类是基于手机设备套上一个眼罩,其实这算是一种“假VR”,眼镜本身不带有任何电子原件;一类是独立的VR设备,需要连接到计算机上。这是真正的VR设备。

以手机为内容输出的VR眼罩

这类设备在硬件部之上是物理放大镜。 以Google Carboard项目为核心,产生了非常多的手机VR眼镜。 因为这类设备一般依托于手机,所以我在小标题上把这个写成是眼罩。 它们没有显示屏,主要结构是一个放大镜片,VR成像、动作感应都有手机来完成。

Google Cardboard

Cardboard VR 的门槛极低,以最简单的方式把VR眼镜平民化的普及开来。

Samsung Gear

另外一家是三星的Gear VR,这个眼镜相比google就贵多了,只兼容三星的少部分高分辨率手机。

Ref: https://developers.google.com/vr/concepts/vrview

以PC为内容输出的VR设备

这类VR设备在硬件本质上是浸入式显示器和各类传感器的结合。 其实这种设备才是真正的VR,因为他们有足够强大的显卡处理器、足够强大的传感器,加上合理的交互设计。 因此这种VR的体验算是浸入式,下面这三种是市面上最主要的产品。

Oculus Rift

HTC Vive

Sony PlayStation VR

VR开发

VR开发引擎

VR的开发都是基于3D开发引擎的构建出虚拟世界,然后在其中加入VR设备的交互逻辑。主流的3D开发引擎就是Unity和UE。

Unity3D

优点:配置简单,容易上手。官方社区Asset Store提供的素材丰富。文档丰富。

缺点:渲染效果不好。不支持编辑材质。

不开放源代码。

Unreal Engine

优点:渲染画质好。可以编辑材质。

缺点:不易上手,学习成本高。文档不如unity丰富。

UE4的私有协议:可以使用其源代码,盈利超过多少之后要缴纳一部分利润。

SteamVR SDK

在unity3D下steamVR SDK以plugin的形式提供了软件和VR硬件的交互。

SteamVR Plugin

这个插件由Steam开发。目前这个插件只支持Windows DX11.

The SteamVR SDK allows developers to target a single interface that will work with all major virtual reality headsets from seated to room scale experiences. Additionally, it provides access to tracked controllers, chaperoning, render models for tracked devices. SteamVR’s compositor allows you to preview your content in VR using Unity’s play mode, while leaving the normal game window to act as your companion screen on the main monitor.

Vive Input Utility

这个插件由HTC开发。 Vive Input Utility is an Unity plugin that allows developers to access Vive device status, including Vive Tracker.

HTC手柄上面有五种按键

	一、trigger       扳机键,就是手柄下面的那个类似扳机的按键。
	二、Touchpad          圆盘,手柄上面的那个特大的圆盘。
		GetTouch      通过手指触摸圆盘,就可以触发事件。
		GetPress         通过按下圆盘才可以触发事件。
	三、Grip       手柄两侧的椭圆形按键
	四、System         系统按键,圆盘下面的那个按键,
	五、ApplicationMenu         圆盘上面的那个按键。

Unity3D

这里我想专门立一章来讲Unity3D,毕竟真正上手VR开发主要是和Unity3D打交道。

Unity3D的开发平台可以是在windows和Mac。目标程序可以编译到所有主流的桌面、移动、游戏平台。

Unity开发是以资源为中心。资源包括material、texture、scripts、sound、custom editor。

几个核心元素

Scene

Scene是一个虚拟世界,或者说游戏场景。场景下的所有物体及其属性都包含在其中。

Components 基于组件的开发模式

Unity3D的模块都是以组件形式体现的。物体、属性、代码、材质等都是component。通常一个虚拟对象会由若干个组件结合而成。

Inspector

unity开发界面的左侧始终有个inspector的窗口。选中任何一个对象,其中包含的组件就会实时显示在Inspector窗口中。 The Inspector window is context sensitive and displays all the properties of any selected GameObject, Asset or Setting.

Material

Materials are used in conjunction with Mesh or Particle Renderers attached to the GameObject. They play an essential part in defining how your object is displayed. Materials include a reference to the Shader used to render the Mesh or Particles, so these Components can not be displayed without some kind of Material.

Shader

Prefabs

已经设计好,可以重用的物体。

Editor

创建一个物体

在菜单栏点击GameObject,就可以选择一种带有基本属性的GameObject,创建到当前Scene里。在Scene里单击这个新建的物体,可以在Inspector中看到它的属性,这时可以添加一个新的Component,比如一个属性Rigidbody带加入物理学属性,比如一个c#脚本来编写特定逻辑。

GameObject

虚拟世界的物体都是GameObject。

GameObject在一个Scene是有层级关系的,可以通过手工或代码来设置一个GameObject的父和子。父子物体之间的空间位置是相对的。

MonoBehaviour

MonoBehaviour是unity中所有代码的基类。

代码作为Gameobject的一个component,是被Gameobject加载的。代码中我们会设计物体的行为属性。

在自定义的类中我们通常会重写这几个基类函数:

	Awake:当一个脚本实例被载入时Awake被调用。我们大多在这个类中完成成员变量的初始化
	Start:仅在Update函数第一次被调用前调用。因为它是在Awake之后被调用的,我们可以把一些需要依赖Awake的变量放在Start里面初始化。 同时我们还大多在这个类中执行StartCoroutine进行一些协程的触发。要注意在用C#写脚本时,必须使用StartCoroutine开始一个协程,但是如果使用的是JavaScript,则不需要这么做。
	Update:当MonoBehaviour启用时,其Update在每一帧被调用。
	FixedUpdate:当MonoBehaviour启用时,其 FixedUpdate 在每一固定帧被调用。
	OnEnable:当对象变为可用或激活状态时此函数被调用。
	OnDisable:当对象变为不可用或非激活状态时此函数被调用。
	OnDestroy:当MonoBehaviour将被销毁时,这个函数被调用。

Mesh

3D Meshes are the main graphics primitive of Unity.

Mesh Renderer 网格渲染器 :一个3D模型的表面是由多个彼此相连的三角面构成。三维空间中,构成这些三角面的点以及三角形的边的集合就是Mesh。

Mesh Filter 网格过滤器 :网格过滤器 与 网格渲染器 联合使用,使模型显示到屏幕上。

重要的物体

Camera

Camera代表一个主人翁的视角。摄像机的个数和位置可以使任意的。

EventSystem

The EventSystem is responsible for processing and handling events in a Unity scene. A scene should only contain one EventSystem. 添加某些内置GameObject时会自动生成出一个EventSystem对象,里面主要有两个Components,分别是Event System和Standalone Input Module。其中Standalone Input Module是派生自BaseInputModule。

EventSystem负责管理,BaseInputModule负责输入,BaseRaycaster负责确定目标对象。

Event System 觸發流程: 1.使用者輸入(滑鼠、觸摸、鍵盤) 2.透過 Event System Manager 決定使用 Standalone 還是 Touch Input Module 3.決定使用的 Input Module 後,透過 Scene 中的 Raycasters 計算哪個元素被點中 4.傳送Event

编程语言

Unity3D支持开发语言是c#和JavaScript。

Mono C#

unity3d中的C#代码不是被VS编译器编译,而是用Mono。Mono是一个开源的.net实现,MonoDevelop是它的IDE。不过当前unity下默认Mono的.net版本比较低。

Mono版本和.net版本的对应

date mono version net version
2008-10-01 mono 2.0 .net 2.0 c# 3.0
2011-12-19 mono 2.10.8 .net 4.0 c# 4.0
2014-03-31 mono 3.4 .net 4.5 c#5.0
2016-06-08 mono 4.4.0 .net 4.6.1 c#6.0

Unity3D版本和所采用Mono版本的对应

Unity Version Mono Runtime/Compiler Version
3.5  
4.0  
4.3  
4.6  
5.0 2.0/2.0
5.3.5p8 2.0/4.4
5.4.0f1 2.0/2.0

C# 调用 Native plugin

unity支持以plugin的形式在C#代码里调用C/C++/OC所编的库。一般的引用方式是在C#中声明出库的名字和函数名。

	[DllImport ("PluginName")]
	private static extern float FooPluginFunction ();
*****
Written by Lu.dev on 04 May 2017