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

相关推荐
feathered-feathered19 小时前
Redis【事务】(面试相关)与MySQL相比较,重点在Redis事务
android·java·redis·后端·mysql·中间件·面试
Kapaseker20 小时前
三分钟搞懂 Kotlin Flow 中的背压
android·kotlin
柯南二号20 小时前
【大前端】【Android】把 Activity 重构成 MVVM 的对比示例
android·状态模式
某空m20 小时前
【Android】Glide的缓存机制
android·缓存·glide
某空m20 小时前
【Android】Glide的使用
android·glide
QING61820 小时前
Jetpack Compose 中的 ViewModel 作用域管理 —— 新手指南
android·kotlin·android jetpack
鹏多多20 小时前
flutter-使用EventBus实现组件间数据通信
android·前端·flutter
ShayneLee821 小时前
Nginx修改请求头响应头
android·运维·nginx
廋到被风吹走21 小时前
【数据库】【MySQL】高可用与扩展方案深度解析
android·数据库·mysql
恋猫de小郭21 小时前
Flutter 官方正式解决 WebView 在 iOS 26 上有点击问题
android·前端·flutter