通过GoogleVR来了解VR到底是什么

GoogleVR

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

不过对于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世界是如果构建的。

相关推荐
CCTV果冻爽1 小时前
Android 源码集成可卸载 APP
android
秋月霜风2 小时前
mariadb主从配置步骤
android·adb·mariadb
Python私教3 小时前
Python ORM 框架 SQLModel 快速入门教程
android·java·python
编程乐学4 小时前
基于Android Studio 蜜雪冰城(奶茶饮品点餐)—原创
android·gitee·android studio·大作业·安卓课设·奶茶点餐
problc5 小时前
Android中的引用类型:Weak Reference, Soft Reference, Phantom Reference 和 WeakHashMap
android
IH_LZH5 小时前
Broadcast:Android中实现组件及进程间通信
android·java·android studio·broadcast
去看全世界的云5 小时前
【Android】Handler用法及原理解析
android·java
机器之心5 小时前
o1 带火的 CoT 到底行不行?新论文引发了论战
android·人工智能
机器之心6 小时前
从架构、工艺到能效表现,全面了解 LLM 硬件加速,这篇综述就够了
android·人工智能
AntDreamer6 小时前
在实际开发中,如何根据项目需求调整 RecyclerView 的缓存策略?
android·java·缓存·面试·性能优化·kotlin