
↑App Storeに並んでるVRアプリなどを見るとこんな感じで樽型に補正してたりする。これVRゴーグルのレンズに対する補正らしい。

↑確かに真っ直ぐな線をレンズを通してみると少し凹んで見える。わかりにくい写真だけどねえ。
とりあえずこういうのに対して膨らますような補正をするもんらしい。
カメラ キャリブレーションとは - MATLAB & Simulink - MathWorks 日本
↑ここにレンズの補正に関する式があるので、それをMetalのシェーダーに実装してみた。
なお、ここでは半径方向の歪みに対してのみ処理を行うことにする(レンズと被写体は並行にあるだろうってことで)。
Metalのフラグメントシェーダーで単に相応の座標のテクスチャを表示するならこんな感じ(テクスチャ画像はtex2Dとしてもらって、テクスチャの座標はin.texCoordとしてもらってる)。
{
constexpr sampler quad_sampler;
half4 texcolor = tex2D.sample(quad_sampler, in.texCoord);
float4 color = float4(texcolor.r,texcolor.g,texcolor.b, 1.0);
return half4(color);
}
これを補正するようにして、、、
{
float k1 = 0.040;
float k2 = 0.004;
float2 texCoord = in.texCoord;
float texX = texCoord.x*2.0-1.0;//-1から1に変換
float texY = texCoord.y*2.0-1.0;
float r2 = pow(texX,2.0)+pow(texY,2.0);
float kk = (1.0 + k1 * r2 + k2* pow(r2,2.0));
float xx = texX * kk;
float yy = texY * kk;
float2 fCoord = float2((xx+1.0)/2.0 , (yy+1.0)/2.0);
if ( (fCoord.x < 0.0)||(fCoord.x > 1.0)||(fCoord.y < 0.0)||(fCoord.y > 1.0) ) {
return half4(0,0,0,1.0);
}
constexpr sampler quad_sampler;
half4 texcolor = tex2D.sample(quad_sampler, fCoord);
float4 color = float4(texcolor.r,texcolor.g,texcolor.b, 1.0);
return half4(color);
}
テクスチャ画像の座標は0から1だけど、変換の中心はテクスチャ画像の中心なのでそこがゼロになるように修正して、補正して、さらに元に戻して得るべきテクスチャ画像の座標を得ている。画像の端っこの方は正しく表示されないためそこは黒を表示させてる。それからk3は考慮外。

↑とりあえず樽型に歪み補正ができてる。
けど、だよ。
手持ちのVRゴーグルのレンズにあう歪み係数k1,k2を得るのはなかなか面倒。
そもそもVRゴーグルの種類によってこの係数が変わるならどうしようもないしなあ。
そう思うとこの補正、テキトウにやるしかないよな。うーん、もうしなくてもいいかって気もしてきたわ。