发布日期:2024-12-12 浏览次数:
这个标题看上去很疯狂,而且笔者正试图让它变得更疯狂一些:没错,我们可不打算让用户还得专门插个手机进去播全景小电影——我们要做VR头盔,能duang地运行起一个PC端的正经VR游戏的那种!
然而,如今的虚拟现实头盔正呈现出OculusVR,HTCVive和PSVR三分天下之势,国内也有乐相、3Glasses、星轮等厂商投入重金攻关。笔者在这里突然自诩为“极客”,然而实际上又算是哪根葱呢?嘴上说要做一款正经的虚拟现实头盔,实际上却恐怕连入行的庙门都找不到才对吧:三星OLED屏的渠道有么,菲涅尔镜片长什么样认识么,屏幕分辨率和刷新率能达标么,Unity或者Unreal程序能写出一行么,以及渲染优化,工业设计,外观内衬,人体工学种种……至少,看起来这样繁多和艰险的任务,能在短短的一篇文章里解决么?
也许不能;不过,这并不代表我们就不去尝试一些事情。极客的准则首先是实践。然后才看它与我们理想中的结果还有多远。
传统的液晶显示屏大都是采用薄膜晶体管(ThinFilmTransistor,TFT)作为核心技术,在基板的背部设置光源主动控制屏幕上的各个像素,它的屏幕反应时间通常可以达到60-80ms左右。这样的延迟作为电脑和电视屏幕没有任何问题,但是作为头显设备显然是无法接受的。目前基本上也没有厂商会选择这种屏幕作为显示的载体。
IPS屏幕(In-PlaneSwitching)改变了液晶分子颗粒的排列方式,虽然本质上还是TFT屏幕的衍生品,但是拥有很好的清晰度和可视角度表现,甚至可以做到接近180度的视角。IPS屏幕的刷新率也远高于传统的TFT液晶屏,可以达到60Hz的水准,对于VR应用来说基本上差强人意。绝大部分国内头显厂商都使用了IPS屏幕作为自己方案的一部分。
OLED屏幕则是目前高质量VR头盔实现的首选(包括三大家和国内的乐相Deepoon),它具有自发光的特点,因此不需要额外的背光板,也改善了因此产生的余晖(Persistence)和拖影现象;同时它的反应时间很快,足以做到75Hz甚至更高的刷新率。但是OLED小尺寸屏幕做到更高的屏幕分辨率,目前难度还比较大,良品率较低;同时因为有源的AMOLED供电需求较高,通常需要大于8V的电压和稳定电流,因此电压管理的设计更为复杂,要找到稳定可靠的生产和供货渠道也更为困难(不过据说只要付给三星60万,就可以开启新世界的大门了)。
笔者并不想在这里挑战自己的财务底线,因此选择了更容易购买散件的IPS屏幕,并且为了能够得到更好的显示效果,显然至少要达到2K的屏幕分辨率(2560x1440)才能让观众感到满意。
从上图以及之前的OculusVR拆解图中,我们都可以看到一块与屏幕直接连接的电路板,它被称作驱动板。它负责与屏幕连接,将来自外部的数字视频信号通过HDMI或者MDL接口输入并转换到屏幕上显示,同时还要负责电压管理和保护。
对于OLED来说,复杂封闭的接口规格说明以及颇为棘手的电源管理问题,限制了很多国内厂家为它制作驱动板的能力;而IPS屏的驱动板使用则更为成熟,基本上可以直接连接电脑并作为扩展显示屏使用;或者烧录新的EDID信息,从而将屏幕识别为OculusDK1和DK2设备(前者已经开源),并且直接连入OculusVR接口和游戏内容。
显示和驱动的问题看起来有了眉目,另一个问题也是绝对不可忽视的,那就是镜片的选择。
VR头盔中的菲涅尔透镜隔在人眼和显示屏的中间,主要负责改变光路并产生画面的放大效果,尽可能与人眼的实际FOV(视场角度)相匹配,从而带来包裹感和沉浸感。然而透镜的色散效应会在边缘产生不正确的画面色差,透镜的形状也会极大影响画面的成像质量。这些问题不妨参考另一位老师发表过的文章(点击查看)。
除此之外,如何将这些设备连接到一起,形成一个外观和内里排布都足够合理的结构,以及与使用者头部的连接和固定方法。这些与工业设计密切相关的问题也都是相关从业者们所必须要关注和考虑的。当然了,选择三维打印外壳也是一个不错的主意,不过对于这样一次极客式的尝试而言,我们远不需要做到那么复杂。笔者选择了Cardboard作为示范的头盔外壳,并且将刚才的东西一股脑塞进去粘好,点亮!也许,这一切也许并不是那么具有山寨的气息?
看起来有一点进展了,至少现在有了一块可以用来看看日本小电影的袖珍屏幕。事实上,如果我们现在就能找到一些以左右眼分隔方式输出的视频的话,把它放大到全屏播放就可以看到正确的图像了!真是令人激动的成果啊,但是买点屏幕和驱动板就拉倒,这显然不应该是VR头盔的全部;至少,不能连最基本的交互行为都没有。
没错,我们下一步要解决的问题,就是让显示的画面能够跟随头部的旋转变化,让使用者真的可以有身临其境进行观察的感觉。既然是模拟头部的旋转姿态输出,自然少不了一个重要的参与者:惯性传感器(IMU)。
笔者在另一篇拙文中曾经提及IMU的实现原理,参见其中第(4)节:《成为VR的利器之前,运动捕捉技术是如何发展过来的?》
那么,我们从IMU传感器中能够得到什么样的数据呢?通常一个九轴的IMU传感器(包含三轴加速度计,陀螺仪与地磁传感器)可以输出如下所示的数据内容:
这显然无法用来表达任何的姿态信息,并且因为民用传感器的设备精度很低,直接采用陀螺仪(即角速度传感器)数据乘以时间间隔的结果,也基本上完全无法表达真实的转动情况。幸好,伟大的数学家们发明了SensorFusion(传感器融合)方法。
SensorFusion,顾名思义就是把各路并不精准的传感器数据合在一起,取得一个更好的整体结果值。事实上加速度计、陀螺仪和地磁传感器确实可以相互弥补弱点,从而有效地填补空白数据,从而得到反应更灵敏也更流畅的输出结果。
常见的SensorFusion算法主要包括KalmanFilter,Mahonyfilter以及Madgwickfilter等等,其基本共性是对输入的数据进行滤波和融合处理,得到平滑、低延迟、低抖动的结果数据(通常是世界坐标系下的旋转姿态值,欧拉角度或者四元数形式)。很显然,IMU本身的输出频率越高,最终结果的频率也就越高,这也是为什么GearVR会采用高达1000Hz频率的单一传感器作为姿态计算的依据,而不是手机本身的陀螺仪(根据手机品牌的不同,有些传感器的质量可能会很差,甚至被)的原因。国内厂商(例如焰火工坊等)也采取了类似的做法,以求整个SensorFusion和姿态计算过程高效且可控。
毫无疑问,如果选择九轴IMU作为姿态传感和输出设备,那么就可以直接得到使用者头部的世界旋转角度信息,进而控制内容的渲染以及交互。但是地磁传感器本身非常容易受到环境磁场的影响,例如附近有磁性的设备,抑或是铁制的桁架和管路,都可能改变地磁传感器的输出,进而产生一个错误的融合结果!此外,地磁传感器本身也需要预先进行标定,毕竟融合算法是需要对地磁数据进行归一化(取当地地磁最小和最大值,然后重映射到[0,1]区间)之后才能准确计算的,而北京和澳大利亚的磁场参数显然大相径庭。
另一种选择是放弃地磁传感器,转而采用仅包含三轴加速度计和陀螺仪的六轴IMU来计算相对旋转姿态。这样避免了标定和场地的限制,并且也有研究表明,单纯采用六轴IMU计算的响应速度更快,数据稳定后的抖动幅度更低。不过因为没有地磁数据作为参照,因此每次开机后头盔的初始姿态是无法预知的,因此也就无法确定游戏者是否一开始就能看到重要的三维提示信息,还是需要困惑地四处转头去寻找入口(如下图OculusVR的Demo场景,一个简单的Start按钮):
设备接口的选择也是有讲究的,USB无疑是目前最为常见的方案,事实上无论OculusVR还是HTCVive都选择使用USB接口来辅助供电和传递姿态信息。当然这一切在起步阶段都没有必要自己去制板和焊接,因此笔者根据上述的选择条件,在淘宝上毫不犹豫地相中了下图一款封装完整,物美价廉的IMU传感器模组:
它采用了九轴IMU传感器,数据通过UART转换到USB接口输出,并且已经做好了片上融合,即硬件已经通过SensorFusion算法计算得到了真实的世界旋转姿态,并且提供了简单的标定方案。因此现在要做的就是把这个传感器粘贴到纸质头盔的合适位置上,然后将姿态数据传递给自己的程序,及时改变当前用户观察的视角和渲染内容。
现在我们有了一个看起来像模像样的VR头盔,虽然一切都是硬纸壳子加上3M胶带组成,但它至少可以播放来自电脑的任意豪华分辨率的立体电影,并且通过简单的程序进行视角控制;最关键的是,整个系统的延迟似乎完全在我们能够接受的范围内——胜利在望了吗?那么随后我们要解决的,是显示内容开发的问题。
很显然,只是做了一个粗糙的影片播放器,这并不能满足一名极客的进取欲望。要让别人制作的游戏接入到我的头盔里面,然后构建自己的SDK开发接口和游戏内容平台,这也许才是我们内心的狂野独白——当然这并不是小小的一篇文章所能承载的庞大构想。不过至少,beat365登录现在才应该是有着十年图形学和底层渲染引擎开发经验的笔者发威的时间。
笔者选择自己熟悉的OpenSceneGraph开源引擎来做一个简单场景的渲染,为了确保它在山寨VR头盔里的显示是正确的,我们需要将场景画面重复渲染两次,分别对应人的左右眼所见的内容。大脑会根据这两幅画面在视网膜的成像,主动对比和生成具有强烈立体感的画面。然而人的双眼之间存在着一定的间隔,因此在观察同一个场景的时候会存在着方向上的偏差,也就是视差。使用程序执行渲染时,需要对左右眼的观察矩阵和投影矩阵做一个偏移处理,以模拟这个视差现象,从而欺骗大脑让它以为自己置身于虚拟世界。
我们现在把程序的画面全屏输出到VR头盔的显示屏上,再加上IMU的姿态输入来改变观察矩阵,看起来一切都很美了,只是感觉有点变形?没错,别忘了眼睛和显示屏之间的那个透镜,它很可能会造成桶形畸变(Barreldistortion)的现象,也就是说,靠近边缘的画面中,直线将不再以直线的形式出现,而是产生了弯曲变形。
简单来说,就是刚才渲染的场景不再直接输出到屏幕上,而是输出到一处显卡内存区域(Framebufferobject),然后对这张内存中的图像进行进一步的处理:包括处理失真,镜片引起的色散,改变对比度和亮度,修正色彩曲线,等等,就像是我们在Photoshop中做的一样。注意这里我们对原始输出的场景画面做了变形,从而与镜片的畸变参数进行匹配,在视野中得到正确无失真的结果。
现在再把画面接入到头盔中,是不是好了很多呢?当然了,如何处理失真,如何处理色散,这些都是与镜片以及显示屏的参数密切相关的,并非一个统一的数值。如果真的要完成某种VR头盔的生产流程的话,那么类似的校正参数计算和设置工作显然要在设备出厂的时候完成,交到消费者手中的显然应该是即插即用的成品了。
当然了,这样一副VR头盔能否让人有身临其境的感受,并不仅仅是把零件组合起来再编写程序那么简单。硬件的参数和工装设计,内容本身的渲染精细程度,以及因为这种精致渲染而带来的额外的计算延迟,都是影响体验品质的重要环节。
而所有这些细节的处理,是不能在短小的文章中统统得到体现的——如何在一个看起来很美的原型基础上实现真正可以商用和民用的VR头盔,以及如何确保每个环节的供应链和渠道畅通,产品大卖,这都不再是我们以极客范儿能够面对的问题了,那需要一支庞大而高效的团队去不断努力完善,就像如今VR行业众多创业公司们所追求的一样。
Cardboard硬纸外壳和镜片:19元,总觉得好像没这么贵才对啊,另外镜片也建议自己选配更好的菲涅尔透镜组。
这篇文章有自己的终点,但是钻研的道路事实上远远没有达到尽头。虚拟现实头盔是我们沉浸在全新世界的第一步,即取代了人们的视觉。但是无法与世界互动终究是十分无趣的,交互要如何来做,手柄?手套?动捕?空间定位?声音?手势?抑或其它稀奇古怪的方式,这又是一个完全不一样的命题,也是下一个VR热点话题的聚集地。
例如TimeWarp以及AsynchronousTimeWarp这样的算法,可以通过对当前渲染画面进行插值计算得到一些模拟的中间画面,避免因为帧速率不足而产生的抖动和迟滞感。不过这并非仙丹妙药,优化场景渲染速率以真正达到无延迟的画面随动才是正途。然而画面的优化往往又意味着渲染质量的降低,真实感随之下降。如何在其中权衡利弊,甚至投机取巧做一些戏法似的效果,这又是对众多内容开发者们的一个全新的挑战。
多说一句的话,笔者也曾经实现过一种基于单次渲染GBuffer数据然后在后处理阶段构建双目画面显示的方法,可以适用于各类开阔场景和没有复杂管道结构的室内场景,对效率的提升当然也是不言而喻的。
更多的脑洞还在开启当中,例如基于眼动追踪的渲染,可以基于NVIDIA的MultiRes架构将眼球聚焦位置之外的场景用低分辨率处理,从而减少像素着色过程的计算时间;又比如VR一体机的兴起,用高性能的移动开发板(例如TegraX1)与显示屏直接构成一体化的头盔,不再从电脑或者手机上输出场景画面,而是采用配套的SDK工具编写专属游戏。
总之,一切还远远没有到达尽头,未来很美,只愿越来越多的从业者们能够选择脚踏实地,从技术和产品化的角度更多地思考问题,让更多的原型产品和忽悠概念能够最终落到实处。