Google VR平台 Daydream:一起来做白日梦吧


Google在2016年5月的I/O开发者大会上发布了DaydreamVR 平台,在Android N的SDK里也集成了部分Daydream相关的源码。

想做DaydreamAR开发的同学,得先配齐硬件:一台支持Daydream的手机,以及VR头盔。

Google官网(https://vr.google.com/daydream/phones/)上公布的目前已确认支持Daydream的手机有:Google Pixel、Pixel XL、联想的Moto Z、华为的Mate 9 Pro、中兴Axon 7和华硕 ZenFone AR手机。


Daydream要求显示的延时在20ms以内,delay过长会很容易导致眩晕。这个delay的定义是从人的头部移动开始到头显设备(HMD)的光学信号映射到人眼上面全部的等待时间(latency time)。

要达到20ms的要求,Daydrem手机对硬件要求也比较高:包括sensor、显示屏、CPU及GPU等。高通确认他们只在高通8996或8998平台上跑通过;另外,华为Mate9因为使用LCD屏,而不是OLED,所以也不在列表中。

不过,话说高通8996或8998的手机也还真不便宜,专门整一台也不是随便的事。好在Android手机升级到N之后也能跑Daydream APP,只是跑得不够好,要想跑得好,得打上google一堆patch,还有平台厂商发布的库。所以,特别有兴趣的同学得开始准备攒钱了。。。

 

SDK方面,Daydream为应用开发者分别提供了Unity、Unreal 4、Android和iOS平台的SDK。

相关资料:

Google Daydream开发者网址:https://vr.google.com/daydream/developers/

GoogleVR SDK for Androidgit clonehttps://github.com/googlevr/gvr-android-sdk.git


SDK里附带了几个sample,看看里面附带的TreasureHunt代码,发现似乎和我们以前用OpenGL ES写的应用差不多嘛。


以前要画一个3D图,得先自己定义一个MySurfaceView类继承自GLSurfaceView,在这里可以重载一些和用户输入事件有关的方法,并设置自定义的渲染器Render,该渲染器执行真正的渲染任务。


如上图,自定义的渲染器需实现GLSurfaceView.Renderer的3个接口:

  • onSurfaceCreated() :在开始渲染的时候被调用。
  • onSurfaceChanged():该方法在surface大小改变时被调用。
  • onDrawFrame():每帧更新时该方法都会被调用。

TreasureHunt 这个例子大致也是这样做的,同样自定义一个render来处理渲染任务,只是没有处理手柄的事件。不同的是,这个Render需要实现GvrView.StereoRenderer接口,还需要继承GvrActivity。

SDK定义一个继承自Activity的GvrActivity,它用来处理和手柄交互及渲染相关的事情。

GvrView.StereoRenderer和GLSurfaceView.Render很相似,只是多了3个接口:



  • onNewFrame():画面更新时更新模型位置信息。
  • onDrawEye():画面更新时需要分别画左、右眼内容;由于左、右眼的观察位置不同,调onNewFrame()后需要调两次onDrawEye(),下发实际的draw call。上面的onDrawFrame()相当于分成了两步:onNewFrame()和onDrawEye()。
  • onRendererShutdown():应该是结束VR立体渲染模式时调用。

 

Talk is cheap, show me the code. 说了这么多,接下来就看看怎么把一个传统的APP改成Daydream APP吧。

手上有一个之前用openGL画的地月系,在Moto Z上跑起来是这样子:


下面动手开始修改:

1.    AndroidManifest.xml

首先followGoogle 文档在AndroidManifest.xml中添加相关属性。(参考:https://developers.google.com/vr/daydream/guides/vr-manifest)


加上enableVrMode属性后,在启动该应用时,系统会自动切到Vr 模式。

  • 一般需要强制VR应用为横屏模式,并且为全屏显示。
  • VR APP需要运行在Android N上。
  • android:configChanges="orientation|keyboardHidden|screenSize"并非必须指定。
  • 如果应用支持Daydream或 Cardboard,则需指定相应的category。

2.    build.gradle

在build.gradle中添加相应的依赖库。

目前最新的版本是1.20.0。


SDK中libraries列出了完整的列表:


我们这个例子比较简单,没有使用到audio、controller等模块,因此只添加了base这一个库。

 

3.    MainActivity.java

接下来就是如何修改源码了。

 

1) 定义gvr_view

在layout中加上:


在MainActivity::onCreate()里会加载这个layout。

 

2) 修改MainActivity的继承关系

public class MainActivity extends GvrActivity implementsGvrView.StereoRenderer

3)在onNewFrame()中设置camera的视角位置。



camera视角信息对左右眼都是一样的,所以在onNewFrame()更新。这里设置固定的视角位置。

headTransform.getHeadView(headView,0);用来获取头盔的转向信息,然后传进vertex shader,使得旋转头盔时画面有移动的效果。后面并没有用到headView,所以画面一直在屏幕中间。

4)在onDrawEye()中发draw call

需要根据把左右眼观察位置分别计算:


上面projMatrix= eye.getPerspective(Z_NEAR,Z_FAR); 用来设置透视投影,这里只指定了观察点距近平面和远平面的距离,left、right、top、right参数封装在API里,应该是和屏幕宽高值相关。


这里视角位置要同时考虑camera和eye的信息。通过eye.getEyeView()获取眼睛的位置信息,然后乘以在onNewFrame()里设置的camera视角位置,再传给顶点渲染器作进一步计算。

 

代码大致就改完了,Moto Z上跑起来是这样:


呐,左右两幅图就出来了,这两幅图大致是一样的,稍微有些偏差,毕竟还得拼成3D呢,另外左右眼的视角位置也略有差别。当然这里不仅仅是同一幅图画两次这么简单,在帧率不够的时候,可以使用异步时间扭曲技术(Asynchronous Timewarp)来减少latency。举个栗子,画出一帧内容后,再根据最新的pose信息或者预测的pose,造出下一帧内容。在三星的Gear VR上就引进了这个技术。

附上源码,https://github.com/may627/VrEarthMoon

 

       这里只作了个简单的例子,还有很多东西都没有考虑,比如头盔转动时移动画面、立体音效、和手柄的交互等,值得继续深入探究。







  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值