拥抱元宇宙:通过GoogleVR来了解VR到底是什么

GoogleVR

GoogleVR是google出的VR库,随着google在VR方面的尝试失败,这套SDK也不再维护了,github(https://github.com/googlevr/gvr-android-sdk )上的更新停留在三年前了。

不过对于Android开发者来说,通过这套SDK来了解VR非常方便,所以在这个系列的一开始,我打算通过GoogleVR来带大家先了解一下VR。

使用GoogleVR很简单,只要依赖几个库即可,如下:

java 复制代码
implementation 'com.google.vr:sdk-base:1.180.0'
implementation 'com.google.vr:sdk-panowidget:1.180.0'
implementation 'com.google.vr:sdk-videowidget:1.180.0'

Panorama

Panorama就是全景图,上面的sdk-panowidget库就是用来展示全景图的,使用起来非常简单。

首先在页面中添加VrPanoramaView,如下:

xml 复制代码
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".PanoViewFragment">

    <com.google.vr.sdk.widgets.pano.VrPanoramaView
        android:id="@+id/vr_pano"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>

然后通过它的loadImageFromBitmap来加载图片即可,比如我们使用官方DEMO中的一张神庙图片andes.jpeg

将它放到assets目录下,然后通过下面代码加载即可:

kotlin 复制代码
val option = VrPanoramaView.Options()
var bitmap = BitmapFactory.decodeStream(assets.open("andes.jpeg"))
option.inputType = VrPanoramaView.Options.TYPE_STEREO_OVER_UNDER
_binding?.vrPano?.loadImageFromBitmap(bitmap, option)

在生命周期中做相应的处理即可,如下:

kotlin 复制代码
override fun onResume() {
    super.onResume()
    _binding?.vrPano?.resumeRendering()
}

override fun onPause() {
    super.onPause()
    _binding?.vrPano?.pauseRendering()
}

override fun onDestroyView() {
    super.onDestroyView()
    _binding?.vrPano?.shutdown()
}

这样我们就可以看到全景图了,效果如下:

可以看到随着我们手机的移动,画面也会跟着移动,就好像是真的在现场似的。

这时候我们点击下面眼镜那个图标就会进入vr眼睛的模式,效果如下:

将手机放入vr眼镜中就可以身临其境的看到神庙了。

单通道和双通道

上面我们可以看到原图是上下两个部分,这两个部分基本一样,这是为什么?

因为上图是双通道全景图,上下其实不一样,是专门的摄像机模拟人的左右眼拍摄的两张不同的照片,然后以上下的形式放在了一起。

这样当我们切换到VR眼镜的模式的时候,两个眼镜的部分就会展示不同的图片,这样模拟了人眼的模式,就会有景深和立体的感觉,更加真实。

所以我们在上面加载图片的时候type设置为TYPE_STEREO_OVER_UNDER。这个type还有另外一个值TYPE_MONO,即单通道。

单通道就是一个摄像头拍摄的全景图,如下:

代码都一样,只不过加载的时候将type改成TYPE_MONO即可。运行效果如下:

这个与双通道的差距不大,然后来看看VR眼镜效果:

小伙伴可能就有疑问了,不是只有一个通道么,那么左右眼显示的是一个图片么?

大家仔细观察可以发现,虽然展示的是一个图片,但是明显偏移及角度不同,Google通过计算的方式来模拟双眼的感觉。在VR眼镜中可以感受到,确实有那么一点立体感,但是明显没有双通道那么真实,因为双眼看一个物体的角度不同成像也是不同的,单通道毕竟只有一张图片。

原理

实际上是将全景图映射渲染到球的内壁上,我们则在球的内部观察,这样我们上下左右都可以看到相应的景象(与地球仪正好相反,地球仪是将地图渲染到球的外壁,我们在外部观察)。上面其实可以看到全景图越靠近两侧拉伸越大,因为最终要收缩成球。

而进入VR眼镜模式的时候,左右眼就会分别绘制,也就是说实际上是两个球绘制不同的图片。

下面我们会讲视频也是一样的原理。

Video

只看图片太low了,还可以播放全景视频(全景视频是通过全景相机拍摄的视频)。上面sdk-videowidget库就用来播放视频的。

首先定义一个布局,添加VrVideoView:

xml 复制代码
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".VrVideoFragment">

    <com.google.vr.sdk.widgets.video.VrVideoView
        android:id="@+id/vr_video"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>

然后通过它就可以播放全景视频了,流程跟图片差不多,代码如下:

kotlin 复制代码
var options = VrVideoView.Options()
options.inputFormat = VrVideoView.Options.FORMAT_DEFAULT
options.inputType = VrVideoView.Options.TYPE_STEREO_OVER_UNDER
_binding?.vrVideo?.loadVideoFromAsset("congo.mp4", options)

_binding?.vrVideo?.setEventListener(object : VrVideoEventListener() {
    override fun onLoadSuccess() {
        super.onLoadSuccess()
        _binding?.vrVideo?.playVideo()
    }

    override fun onLoadError(errorMessage: String?) {
        super.onLoadError(errorMessage)
    }

    override fun onClick() {
        super.onClick()
    }

    override fun onDisplayModeChanged(newDisplayMode: Int) {
        super.onDisplayModeChanged(newDisplayMode)
    }

    override fun onCompletion() {
        super.onCompletion()
    }

    override fun onNewFrame() {
        super.onNewFrame()
    }
})

这里我们通过VrVideoView的loadVideoFromAsset来播放assets目录下的视频资源,也可以通过它的loadVideo来播放本地资源和网络资源。

VrVideoView也包含一些视频的常规操作,比如play、pause、seek等等,大家自行查阅源码即可。

然后在生命周期中做一些处理即可:

kotlin 复制代码
override fun onResume() {
    super.onResume()
    _binding?.vrVideo?.resumeRendering()
}

override fun onPause() {
    super.onPause()
    _binding?.vrVideo?.pauseRendering()
}

override fun onDestroyView() {
    super.onDestroyView()
    _binding = null
    _binding?.vrVideo?.shutdown()
}

在上面的例子中我们使用的官方demo中的一段视频,最终效果如下:

可以看到因为是视频,所以真实感更加强烈,再来看看AR效果:

单通道双通道

与图片一样,视频也有单通道和双通道两种模式,比如上面例子中的congo.mp4就是双通道视频,所以type是VrVideoView.Options.TYPE_STEREO_OVER_UNDER,双通道视频与双通道图片原理一样,左右眼分别录制两个视频然后上下拼在一起;而单通道就是全景相机录制一个视频,type是VrVideoView.Options.TYPE_MONO,下面来看看一个单通道视频的效果:

也是那种身临其境的感觉,再来看看VR效果:

与图片的原理差不多,也是通过计算的方式将一个视频模拟出双眼的效果,带上眼镜就会发现还是很逼真的。

总结

通过这两个demo我们就基本掌握来GoogleVR sdk的用法,主要目的还是了解一下VR到底是什么。下一篇文章我们来着重讲一讲如何渲染一个VR场景,介绍一下VR世界是如果构建的。

相关推荐
chaoyuanl1 天前
适配购物中心的优质 XR 游乐项目推荐
大数据·人工智能·科技·xr·vr
山顶夕景3 天前
【VR】 A CLIP-Hitchhiker’s Guide to Long Video Retrieval
vr·多模态·图片·clip·视频检索
东方-教育技术博主11 天前
论文全文翻译_通过VR课堂适应性反馈提升职前教师注意能力
json·vr
EQ-雪梨蛋花汤12 天前
【Unity笔记】VR 一体机画面锯齿、模型边缘闪烁、接缝抖动排查:MSAA、Mipmap、Render Scale、Z-Fighting 全流程记录
笔记·unity·vr
_helen_52013 天前
unreal engine 虚拟现实 + airsim
游戏引擎·vr·虚幻
云和恩墨15 天前
数据库一体机简史:从ODA到zData X,命名之中的玄机
数据库·vr
图扑软件15 天前
WebGIS 零碳智能港口态势感知与 VR 远控系统
物联网·自动化·vr·webgl·数字孪生·3d 渲染
世优科技虚拟人1 个月前
VR大空间成文旅研学新宠:山海经、西游记、吴哥窟三大IP项目实探
vr·mr·虚拟体验·vr大空间
DolitD1 个月前
点盾云新增VR加密功能:一机一码,让VR内容分发安全可控
安全·vr·视频