VR眼镜 开发 (九) Fov与头动矫正


软件Fov与设备fov匹配与调整对于vr和ar  而言都是核心的问题所在

市面上根据不同产品,对fov准确度的要求不同

1 以高通AR的vuforia为例几乎不用考虑Fov,sdk开发包封装了,而且手机屏幕显示方式fov影响不大。

2 常规的vr眼镜,fov匹配度会影响到体验效果,但也允许较大误差 ,毕竟用户佩戴Vr眼镜后体验到一点点不舒适,也说不清啥原因,比较好忽悠,有内容和立体感,基本舒适,不卡顿,对产品没太大影响。

3 微软为代表的AR眼镜, 对fov匹配要求高的离谱,头动角度姿态和空间坐标位置修正(人头转动可不是只有角度,还与脖子位移,走动,或跳动的情况下变化),对图像识别的准确度,空间定位的误差, 硬件性能,延时等要求很高,任何一个环节都不能拖后腿。以虚实叠加为代表,
用户移动自己的位置,通过透明镜片马上就能感觉到虚拟物体与显示场景中识别的mark是否产生视觉上的偏差,是否感觉到虚拟物体在视野中是晃动的还是绝对静止的。所以市面上还没有普及的ar眼镜百花盛放现象,技术门槛太高。(所以在holons出现以前,有很多虚拟现实怀疑论,要达到良好的视觉效果欺骗到用户眼睛,认为这种技术在现在是不可能实现。)
  (做Ar眼镜想纯粹用Cardboard而不自己搞算法和光学器件特性以及硬件性能修正匹配,这个就有不太可能成功了。。,看微软的巨额投入就知道了,与ar眼镜相比,做vr反倒容易多了,用户在封闭的vr场景里即便有较大的fov和头转角度 误差也基本感觉不到,唯一就是刷新率影响较大,即便更改Cardboard各个参数达不到理想状态,但也不会致命到无法量产给用户使用的程度,所以市面上vr产品便宜的一百块,贵的几千,参差不齐
 

 
android自带的Fov制定接口

(为简便开发,只考虑unity实现方式。重点关注是unity中实现,还是unity调用android插件实现,按照未来推出的unity支持Daydream开发版本看,估计这块也封装到下面了,也轮不到unity上特殊需求来自定义了。很多接口实现到了下层android平台或so库中,想要修改利用Cardboard现成的组件,只修改动unity平台接口,做适合自己公司自定义设备与镜片的畸形矫正,fov等的vr,ar眼镜的难度加大了,或者不可能了,还得具体看unity如何调用) 

 VR眼镜 开发 (九) Fov与头动矫正_第1张图片

头动姿态
 

封装到了so库的头动接口,没有slam修正位置,而是粗略的估算脖子的位置,获取视野中物体在头部坐标系的矩阵转化关系(对vr是可以,ar就不够精确了)
关键是新版本陀螺仪漂移修正代码被封装进库里去了,但可以获取头部和空间坐标的转化矩阵间接获得判断头的朝向
Head tracking is enabled by default, and will begin as soon as the gvr_context is created. The client should call gvr_pause_tracking()  and  gvr_resume_tracking()  when the app is paused and resumed, respectively.  


VR眼镜 开发 (九) Fov与头动矫正_第2张图片


 
 
   // This function will depend on your render loop's implementation.
  gvr_clock_time_point next_vsync  =   AppGetNextVsyncTime ();

  
const  gvr_mat4f head_view  =
      gvr_get_head_space_from_start_space_rotation
( gvr ,  next_vsync );
  
const  gvr_mat4f left_eye_view  =   MatrixMultiply (
      gvr_get_eye_from_head_matrix
( gvr ,  GVR_LEFT_EYE ),  head_view );
  
const  gvr :: Mat4f  right_eye_view  =   MatrixMultiply (
      gvr_get_eye_from_head_matrix
( gvr ,  GVR_RIGHT_EYE ),  head_view );
 

 
全景Vr (Vr View效果)

左右眼虽然分屏,但左眼却看到的右侧范围比右眼多,有点不符合人眼实际生理角度,观察久了眼睛发胀,但估计是全景图为增强立体效果而采取的折中办法
VR眼镜 开发 (九) Fov与头动矫正_第3张图片

 官方的Android工程 TreasureHunt demo 也是如此(谷歌技术雄厚不需要怀疑,这么做自然有这么做的道理),

所以也不管这些了,谷歌官方给了什么效果就用什么效果,专业领域的事应用程序员不需要关心,市面上产品都用的这个,竞争力在内容和交互上,没有大的资本和时间投入,改善
佩戴体验不会有很大区别。 国外投资几个亿,国内一个产品几百万不错了,关键在应用和内容,推广
VR眼镜 开发 (九) Fov与头动矫正_第4张图片


Cardboard在Android工程是继承GvrActivity方式实现VR,单独开发VR应用是无所谓的,但如果想和Vuforia结合有点奇怪,Vuforia在unity插件中是必须先启用它的Activity才能使用它的图像识别功能行(这点做得强势,融合很麻烦,但毕竟天下没有免费的午餐),vuforia android版本不太清楚,但如果非要同时使用它们的功能,能不能融进一个Activity得看具体情况。

但unity开发平台上已有cardboard老版本和vuforia工程合并的案例, 可能要融合manifest配置文件。 unity版本应该是不受限于GvrActivity的,不存在Activity的冲突问题。但不保证以后谷歌会搞出什么大的变动,至少DayDream未普及前结构一直在变,产品开发技术员是被牵着鼻子走


VR眼镜 开发 (九) Fov与头动矫正_第5张图片

VR眼镜 开发 (九) Fov与头动矫正_第6张图片



畸变矫正
(这个功能好像也在新版里从unity的shader编程中迁移到下面的so库中了,如果谷歌短时间内不提供设置参数的c#接口,未来在unity可能想用自己的镜片参数测试,估计得自己移植另想办法。再说一般山寨速成为目的的小公司谁会不用现成的吃饱了去自己整这些事)

gvr_compute_distorted_point(const gvr_context *gvr, const int32_t eye, const gvr_vec2f uv_in, gvr_vec2f uv_out)
void
Computes the distorted point for a given point in a given eye.
gvr_get_eye_from_head_matrix(const gvr_context *gvr,const int32_t eye)
gvr_mat4f
Gets the transformation matrix to convert from Head Space to Eye Space for the given eye.

gvr_compute_distorted_point

void  gvr_compute_distorted_point (
  
const   gvr_context   * gvr ,
  
const  int32_t eye ,
  
const   gvr_vec2f  uv_in ,
  
gvr_vec2f  uv_out
)

Computes the distorted point for a given point in a given eye.

The distortion inverts the optical distortion caused by the lens for the eye. Due to chromatic aberration, the distortion is different for each color channel.

Details
Parameters
gvr
Pointer to the gvr instance which will do the computing.
eye
The gvr_eye type (left or right).
uv_in
A point in screen eye Viewport Space in [0,1]^2 with (0, 0) in the lower left corner of the eye's viewport and (1, 1) in the upper right corner of the eye's viewport.
uv_out
A pointer to an array of (at least) 3 elements, with each element being a Point2f representing a point in render texture eye Viewport Space in [0,1]^2 with (0, 0) in the lower left corner of the eye's viewport and (1, 1) in the upper right corner of the eye's viewport.  uv_out[0] is the corrected position of  uv_in for the red channel uv_out[1] is the corrected position of  uv_in for the green channel  uv_out[2] is the corrected position of uv_in for the blue channel

gvr_distort_to_screen  新版本弃用的
void  gvr_distort_to_screen (
  
gvr_context   * gvr ,
  int32_t texture_id
,
  
const  gvr_buffer_viewport_list  * viewport_list ,
  
gvr_mat4f  head_space_from_start_space ,
  
gvr_clock_time_point  target_presentation_time
)

Performs postprocessing, including lens distortion, on the contents of the passed texture and shows the result on the screen.

Lens distortion is determined by the parameters of the viewer encoded in its QR code. The passed texture is not modified.

If the application does not call gvr_initialize_gl() before calling this function, the results are undefined.

Deprecated. This function exists only to support legacy rendering pathways for Cardboard devices. It is incompatible with the low-latency experiences supported by async reprojection. Use the swap chain API instead.

Details
Parameters
gvr
Pointer to the gvr instance which will do the distortion.
texture_id
The OpenGL ID of the texture that contains the next frame to be displayed.
viewport_list
Rendering parameters.
head_space_from_start_space
This parameter is ignored.
target_presentation_time
This parameter is ignored.

底层android和jni实现基本架构如上,后续重点:unity代码的实现,哪些部分可 制定化,哪些涉及到底层不方便修改,尤其谷歌的版本时刻更新,为盲目实现功能装逼,是否劳力伤财浪费时间有修改的意义,

你可能感兴趣的:(unity)