利用顶点位移进行VR畸变校订

    VR开发的最大挑战之一是对高帧率与高分辨率结合的要求。咱们经过把顶点转化为“镜头空间”,删除了须要全屏渲染的纹理,这样就能够大规模提升手机性能。程序员

下面的技术使用谷歌的Cardboard Unity SDK进行开发,应用于Cardboard Design Lab(CDL),然而,利用透镜畸变效果,给与适当的失真系数去构成顶点着色器,而且SDK容许禁止渲染纹理,这样一样的方法能够适用于任何VR系统。算法

Google公司的Cardboard Design Lab,在Google Play这个场景中可能使用了惟美的处理,但其实是很是细化。编辑器

一些背景


在审查这个技术以前,重要的是要了解大多数的VR渲染是如何处理的。对于为何咱们须要镜头畸变,以及典型实施的来历,能够查看Oculus rift documentation这一部分。函数

镜头畸变

VR应用的镜头畸变阻碍了头戴式显示器(HMDs)的玻璃透镜的物理畸变,从而获得一个无明显失真图像的宽视野。性能

在大多数VR软件中,反畸变是经过将每一个照相机渲染成一个单独的渲染目标来执行,而后将后处理效果的图像进行扭曲。不管是在一个像素着色器,或者经过将渲染目标投影到一个扭曲的网格上,都将最终输出渲染到屏幕上。测试

本文演示了一种技术,在场景中的每一个对象都在顶点着色以前执行渲染,从而消除对单独渲染目标的需求。渲染目标的消除同时几乎消除掉移动设备上的热问题,并容许在全分辨率上MSAA增长2至4倍也不会对散热或目标帧率有显着影响。优化

值得注意的是,我不是第一个想到这一点的人,但据我所知,Cardboard Design Lab是第一个使用这种技术开发VR应用的。此外在项目开始的时候,谷歌的团队已经作了顶点变形版本的雏形,最终成为代码是包含在今天的SDK。this

因此充分证实,我会由于坚持顶点变形为基础的镜头校订可以在生产应用中工做而受到你们的好评,它对于在谷歌已经写CGine文件的一些性能算法工程师是一种喜讯。我写这篇文件是由于(A)它确实能使用,(B)但愿更多的开发者使用它使VR应用变得更好;(C)引擎开发者实现正向渲染仍然很棒,MSAA仍然很可怕,依靠全屏后处理对核心功能有不良影响。操作系统

问题

在开发一个移动VR应用中,有3个主要的考虑因素影响工程成果,这些因素或多或少约束着什么是可能的。设计

  1. 帧率
  2. 可视化分辨率
  3. 散热

帧率

帧率是咱们比较熟悉的。在整场游戏中30-60帧是广泛能够接受的。在VR中,60帧是一个最低限度,并且你们有共识是一个好的VR体验帧率要在90-120帧之间。

固然,在移动设备上,咱们能够作得最好。许多设备设置最大帧率是60帧,因此我使用60做为本文的其他部分的参照。

当一个VR体验低于60帧,效果是立竿见影的。头部跟踪不出现'保持'的显示时,用户会迷失方向,而且体验更可能出现模拟器问题。瞬时性能问题(如背景资料加载、操做系统的通知和垃圾回收)引发短暂但极度的不适,而持续的低帧率(30~60)随着时间的推移可能有不适的表现。许多用户没法自主肯定一个体验是运行在45帧仍是60帧;然而,在咱们对低帧率的测试中,用户因为各类各样的除了帧率的特征更可能感到恶心。对于这个缘由,在我看来,VR体验在30帧是危害极大的,低于30帧是毫无心义的。

 

将一个可视化的帧时间整合显示到测试版本对于调试是必不可少的。只要确保调试自己没有以这样的方式实现,从而致使GC分配或没必要要的开销就能够。上图:帧率显示使用环形缓冲区和调用原GL的单绘制。在Unity中顶点调用不要使用GUI系统!

不幸的是,目前不多有可用的移动VR应用程序能够始终在60帧运行,而且桌面应用程序有严格的硬件要求。这些反作用致使VR的最佳作法过于保守。我看过很多文章说“VR用户的移动老是很差,而运动的某些类型如向视图方向的运动是有问题,设计良好的60帧跑步运动能够给绝大多数用户带来愉悦感。因为过山车的普及,VR应用程序能够足够被证实,运动是值得研究的。

关键点:低于60帧率可让一个很好的体验变的使人做呕,甚至体验用户和开发者可能没法正确识别缘由。

可视化分辨率

可视化分辨率是指如何让一个场景细节“可视”。在VR,这是一个物理屏幕分辨率、渲染缓冲区的分辨率、MSAA水平、物理镜头放大和各类后期处理效果(如透镜畸变)的组合。

咱们须要多少分辨率?我读过不少不一样的数字,但我对事物使用Michael Abrash近似,如每只眼4K×4K(90度视野)与当前的显示器相配,和16K×16K(180度视野)与视网膜分辨率相配。

显然,没有移动设备是能够作到,可是若是忽略一些,仍然有作到的。三星Galaxy S6推出每只眼2560×1440像素或1280×1440像素。在边缘进行一些损失计算,这大约是1024×1024或1K(是4K的16分之一)。

如今我敢确定,Michael Abrash给的那些数字就是意味着4K×4K的MSAA打开,产生一个糟糕的16K可视分辨率,但原理是相同的,MSAA会帮助你。

关键点:抗混叠是很是重要的,即便昂贵。我喜欢在高端手机追求4x的MSAA。打破你的正向渲染吧。

简而言之,我知道推迟渲染的人有各类各样的后处理图像保真技术。就我我的而言,我认为,移动到后处理图像保真使一代游戏看起来很糟糕,但回到主题,这篇文章的重点是从移动传输中删除全屏渲染纹理,虽然他们是那么昂贵。原本的目的是后处理AA须要一个全屏渲染纹理。在Unity,正向渲染是很是快的。我最后一次检查UE4时并无正向渲染模式,更糟糕的是,当我问及CG水平材质定制时我被讽刺的告知“你有源”–仿佛从新编译引擎对于垂死之人是一个可行的开发策略。这就是说,我对于若是史人正在为它努力也不会感到惊讶。

散热

散热是指设备的热输出。做为游戏开发者,我熟知在移动上的几个常见的性能瓶颈,以频率为顺序依次为:GPU填充率、CPU(一般绘制调用),CPU-GPU内存带宽,GPU的顶点处和糟糕的特定设备的驱动程序问题,就像无穷无尽的GPU处理。

大部分时间这些都是不相关的问题。即便是在CPU充分利用的状况下,开发者仍然能够继续添加对CPU的使用。然而,手机是小的,处理器大可能是在同一个地方,这意味着热是一个全程问题。

为了保持手机远离融化,或爆炸,或融化和爆炸,当手机产生太多的热量时将减小处理器的权限,放缓一切。当你想到硬件工程参与后能够很可靠的作到,但帧率不能够,这就让人很惊讶。热调节不是设计用来平衡性能和热的,它的目的是为了节省你的手机。当它第一次开始,一个很好流畅的60帧一般会降低到40帧如下。当它实现了之后手机仍然是热的,它在相比较大的增量上减小权力。若是你的VR应用是散热有限的,这将不是一个很好的体验。

使热很是具备挑战性的缘由是由于很难知道是什么是形成热,忽然一切都是相关的。若是你能够减小每一个函数调用的汇编指令,也许你能够假定每一个指令的一些恒定的热因子,但这没有考虑到你的硬件效率或设备内部的物理结构,或应用程序的控制之外的因素,如后台进程,或者wifi等等。

为何这对于VR是独特的?其余一些移动应用要求高分辨率3D渲染一个恒定的60帧4x MSAA–除此以外,VR应用渲染场景两次(每只眼一次),大多数SDK默认渲染一个高分辨率渲染纹理进行畸变。事实证实,渲染纹理在性能和产生的热量方面是很是费钱的。

在Gear VR发布的时候,约翰·卡马克提到了相关散热的问题。不幸的是,这不是一个能够很快消失的问题。

关键点:若是你的性能好几分钟,而后就莫名其妙地暴跌(以致于你的手机烫手),请检查日志中的热警告。

顶点位移镜头校订

当项目开始时,Cardboard Unity SDK的默认渲染方式是渲染成一个16位的渲染纹理不用MSAA。即便在这些设置下,许多低端设备在几分钟内就遇到了热限制。GearVR使用了一个相似的管道,也遇到了相同的局限性。不管使用什么SDK,在手机上绘制全分辨率渲染纹理是会占用性能的。

切换到顶点位移VR后,CDL渲染成32位全屏缓冲区(减小色带)–根据设备利用2x-4x MSAA,而且通常维持60帧。

此外,经过对“镜头空间”场景畸变,咱们避免了变形的渲染对象的分辨率损失(或经过渲染一个更高分辨率的缓冲区而其相应渲染时间的浪费)。这是一种有效的像Nvidia公司最近发布的多分辨率的阴影,但它是免费的,而且它能够在一个6年的智能手机上运行。

上图:使用标准的渲染纹理技术渲染的121顶点平面。

下图:121顶点平面采用顶点位移,2x MSAA,没有渲染纹理。UV图像来自

http://www.pixelcg.com/blog/?p=146

 

 

从上面两个渲染中心进行双线性放大。

左:标准渲染纹理技术

右:顶点位移

如何使用

目前Unity的Cardboard SDK中有一个CG,其中包含一个名为CardboardDistortion.cginc文件。它包含了一个方法,这个方法用Brown–Conrady模型进行径向畸变校订将一个世界空间的顶点转换为反镜头畸变屏幕空间(‘镜头空间’)。

使用这个功能,看起来像是一个简单的固体颜色材质。请注意,我已经禁用了在桌面和在编辑器中使用条件编译的效果。在编辑器中执行反镜头畸变,使编辑的场景至关具备挑战性。

CGPROGRAM
#pragma vertex VertexProgram
#pragma fragment FragmentProgram
#include "CardboardDistortion.cginc"

struct VertexInput {
float4 position : POSITION;
};

struct VertexToFragment {
half4 position : SV_POSITION;
};

VertexToFragment VertexProgram (VertexInput vertex){
VertexToFragment output;

#if SHADER_API_MOBILE

///easy as that.
output.position = undistortVertex(vertex.position);
#else

///this is how a standard shader works
output.position = mul(UNITY_MATRIX_MVP, vertex.position);
#endif

return output;
};

fixed4 _Color;
fixed4 FragmentProgram (VertexToFragment fragment) : COLOR{
return _Color;
}
ENDCG

要求

这看起来很容易,你可能会想知道为何每一个人不在每一个平台上这样作。为何有人为渲染纹理而感到烦恼?为何咱们不把全部的东西都放在“镜头空间”。

镜头畸变是非线性的,所以,反透镜畸变也是非线性的。当咱们对顶点着色处的顶点变形时,它们之间的线仍然是一条线,事实上,它应该是一个弯弧,当你经过一个弯曲的镜头看一条弧线时,它看起来像是一条线。当你经过一个弯曲的镜头看一条直线时,你会看到一个立方体与弯曲的边缘,总体的但可能不是你想要的。

上图:121个顶点的平面。下图:4个顶点的四边形。注意:非线性畸变是与平面被保留,但不与四边形。

这样作的结果是,若是顶点间隔相距甚远(在屏幕空间),咱们将结束校订太多畸变,当咱们转动咱们的头时最终图像将显示为'经',这就绝不奇怪用户有愤怒的倾向了。

也许更糟的是,全部的顶点运动将增大对象之间的深度冲突问题。

幸运的是,解决方案很简单,咱们须要添加足够的顶点镶嵌,这样失真将再也不明显。事实证实,大多数高端移动设备可以在每帧的200000和800000个顶点之间渲染。不幸的是,咱们仍然须要渲染场景两次,因此咱们的顶点限制在100000和400000之间的顶点,此外,还取决于你想支持的设备。

你可能会认为,添加全部这些顶点会再次引发咱们的热故障,但现代手机有很是密集的屏幕,1920×1080是至关广泛的。1920×1080约有2百万像素只有少许的透支,咱们能够执行每帧1千万个着色器片断。若是咱们须要渲染成一个单独的渲染目标为畸变校订,它增长了另外的2百万像素,加上上下文切换不可忽略不计的成本和大量的纹理内存访问。

一个好成果

由于咱们必须大量增长场景的顶点数,咱们能够利用这一点。咱们能够在顶点程序中运行40万次计算照明,而不是在片断程序中运行约1000万次计算照明,这是计算的25倍下降(热切但愿)。因为咱们的顶点须要足够密集的非线性透镜畸变,照明也可能足够密集(这通常也是非线性)。

就像非线性畸变,顶点照明质量在很大程度上取决于顶点计数。左:使用顶点照明的4个顶点的四分之一是不能从点光源显示太多细节;右:一个具备121个顶点的平面是距离的一个合适近似。

这里请注意:我永远不会使用任何Unity的着色。我从不使用他们的天空盒。我只使用他们的照明引擎原型。在CDL的每一个着色器编写在CG/ ShaderLab(不使用表面着色器),和片断程序或从顶点着色器中读取颜色值而且显示它,或读两颜色值,访问纹理,经过一种颜色增长纹理并添加另一种颜色。保持片断程序很是简单,除去渲染纹理,减小透支使GPU多检查。

UI和2D

还有一个用来实现一个顶点位移管道,那就是处理二维元素,如用户界面。

既然咱们在VR,UI已是一个棘手的问题。为了维持正常的立体融合,UI须要在3D空间渲染,最好引用同一深度的3D对象(如网线须要对遮挡对象进行3D深度渲染)。

UI须要未失真和确保有足够数量的顶点,以及有意义的绘制UI元素,例如字母和纹理上镶嵌的是平面而不是四边形。镶嵌的确切数额将取决于屏幕上的UI元素的最大尺寸。

固然,任何一个被锁定的UI都会变形,但变形不会随着用户的头部旋转而改变,因此这种效果可能不太明显。

至少通常VR的接口是最好的处理背景,因此但愿利用顶点位移镜头校订不会出现大的障碍。

优化

顶点位移的最小偏差近似是在屏幕空间的顶点之间的距离的最小化,即为对象进一步远离相机,他们不须要太多的镶嵌,所以标准LoD技术是有用的。

这为优化提供了一个明确的机会,特别是对固定位置渲染。假如相机能够在一个场景中移动的状况下,优化变得更具挑战性。

最后的想法

坦率地说,我仍然感到震惊,这不是一个被普遍使用有极高硬件要求的发布桌面HMDs技术。基于镜头校订的顶点位移使智能手机渲染VR使 QHD(2560×1440)显示为60 帧高达4x MSAA。大多数现代的集成显卡至少应该可以集合多性能,而低到中等范围的专用显卡能够作得更好。我不但愿在个人英特尔HD 5000上玩前线VR,但我不相信HMD硬件当前做品能够很容易的获得一个更普遍的受众,而不须要SLI的支持。

关于Brian Kehrer

Brian是一个独立的游戏开发人员和图形程序员。他是Cardboard Design Lab的ustwo(奇幻冒险游戏)首席开发员,在那里他花了不少时间研究着色器。

相关文章
相关标签/搜索