Distortion Correction
因为最近在搞畸变相关的东西,找了一些畸变的资料来研究,这个章节翻译自Oculus_SDK_OverView的5.6.2节,翻译中有一些个人添加的辅助信息,以括号标识,”注:”开头,以粗体表示,例如(注:以下为个人翻译,水平有限,欢迎指正).
在rift内部的光学透镜可以放大图像,来增大视场角.因此也产生一个径向的”枕型”畸变,如下图左图所示的那样扭曲的图像:
对于Oculus Rift DK,这样的畸变需要使用软件的办法实现”桶型”畸变来校正已经扭曲的图像,如上图中的右图.当这2种畸变同时生效时,”桶型”畸变将会抵消镜片所产生的畸变,图像中的线条将会变成直线.
“枕型”畸变和”桶型”畸变都可以用以下畸变函数来建模:
R = k0 * r + k1 * r^3 + k2 * r^5
这里可以看出,源采样半径’R’是基于原始半径’r’以及固定系数k0,k1,k2计算得出.这些固定系数与”桶型”畸变正相关.由于畸变的影响,像素被拉向镜片的中心,位移的增加,半径也随着增大.在Oculus SDK World示例当中,由以下像素着色器实现:
Texture2D Texture : register(t0);
SamplerState Linear : register(s0);
float2 LensCenter;
float2 ScreenCenter;
float2 Scale;
float2 ScaleIn;
float4 HmdWarpParam;
// Scales input texture coordinates for distortion.
float2 HmdWarp(float2 in01)
{
float2 theta = (in01 - LensCenter) * ScaleIn; // Scales to [-1, 1]
float rSq = theta.x * theta.x + theta.y * theta.y;
float2 rvector= theta * (HmdWarpParam.x + HmdWarpParam.y * rSq +
HmdWarpParam.z * rSq * rSq + HmdWarpParam.w * rSq * rSq * rSq);
return LensCenter + Scale * rvector;
}
float4 main(in float4 oPosition : SV_Position, in float4 oColor : COLOR,
in float2 oTexCoord : TEXCOORD0) : SV_Target
{
float2 tc = HmdWarp(oTexCoord);
if (any(clamp(tc, ScreenCenter-float2(0.25,0.5), ScreenCenter+float2(0.25, 0.5)) - tc))
return 0;
return Texture.Sample(Linear, tc);
};
这个着色器设计用来运行在一个屏幕一半的四边形上,输入的纹理跨越了左、右眼.输入的纹理坐标,以参数oTextCoord传入,范围从(0.0)到(1,1),其中(0,0)表示Oculus屏的左上角,(1,1)表示右下角.这就表示左眼的视图范围是(0,0)到(0.5,1),右眼的视图是从(0.5,0)到(1.1).
用HmdWarp来实现畸变功能,但是为了计算半径,需要把纹理坐标转换到[-1,1]的顶点坐标当中(注:这个转换过程需要看一下这篇文章).这就意味着有一些变量用来缩放和中心的坐标,来正确的应用畸变,这些变量如下:
- ScaleIn - 重新调整输入的纹理坐标到[-1,1]单元坐标反问,修正长宽比.
- Scale - 重新调整输出坐标,使它回到纹理坐标的范围内,并且增大缩放以支持”outside of the screen”
- lensCenter - 将纹理坐标移到镜头中心周围的畸变函数.
- HmdWarpParam - 存储畸变系数.
ScreenCenter- 在纹理坐标中,半屏纹理的中心.用来防止像素从一直眼睛泄漏到另一只眼睛中.
下图以数值说明左眼畸变功能的坐标范围.如蓝色矩形所示,如左眼的视图坐标那样.我们可以看到,畸变的中心向右移动了一部分,IPD变得更窄了.在7英寸的屏幕和64mm的IPD下,视图右移了0.1453个坐标单元(当然,不同情况下这个值就不一样了).
该图还说明了如何通过畸变函数映射采样坐标.一个畸变单元坐标点(0.5,0.6),如图绿色十字标识.它的半径是~0.61(注:这个0.61是0.5^2+0.6^2).这个也许会被映射到半径为0.68的畸变位置,如上图所示的红色十字.着色器会将像素往畸变的中心移动.如上图中的红色十字移动到绿色十字.位移量随着你的移动而增加.
从这方面讨论来看,在整个游戏场景运行期间”桶型”畸变需要在后台一直运行.这里有几个影响渲染情况:原始场景渲染需要在渲染目标上完成.
- 因为像素向中心畸变,渲染目标的场景需要大于最终的视图
- 视场角和图片缩放需要适配于畸变.
现在我们来讨论畸变缩放,渲染目标和视场角的调整,必须使Rift内的图像看起来是正确的.
本文链接:https://my.lmcjl.com/post/11457.html
4 评论