2018.11.29
- 人×技術
WebGL x 歪曲収差
歪曲収差
歪曲収差は、ザイデル収差の一種であり、要約してしまえば、像を陣笠に歪ませる効果と言える。今回は、写像に対し、この歪曲収差を反映させる実装、およびその結果を示す。
中心座標をcxとcy対象座標をpxとpyとした場合、中心からの距離dは
で求まる。
また、単位半径の半球面で考えると、対象座標の奥行pzは
になることがわかる。
奥行に対する角度θは
になるため、xy平面における半径rを
と仮定する。
距離dのx成分dxとy成分dyから、xy平面における角度ϕは
になる。
この時点で、xy平面における半径と角度が判明しているため、極座標系で示すことができる。
最終的には、極座標系ではなく、直交座標系で考えればよいので
により、歪曲収差後の座標px'とpy'が求まる。
以上の計算から
を
のように歪ませることが期待できる。
実装
通常のカメラ映像をバッファにレンダリングしておき、そのバッファに対して画像処理を施す、いわゆるポストエフェクトとして実装する。今回の歪曲収差効果において、頂点パイプラインでは、通常の MVP 変換行列をかけているだけであり、画素パイプラインで前述のアルゴリズムに従い計算を行う。下記は、WebGL (GLSL) の実装例になる。
頂点処理
varying vec2 vUv;
void main() {
vUv = uv;
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
画素処理
varying vec2 vUv;
uniform sampler2D inputBuffer;
void main() {
vec2 coord = vUv * 2.0 - 1.0;
float d = length(coord);
if (d > 1.0) {
gl_FragColor = vec4(texture2D(inputBuffer, vUv).rgb * 0.25, 1.0);
return;
}
float r = atan(d, 1.0 - dot(coord, coord) * 0.5) / 3.1415926;
float phi = atan(coord.y, coord.x);
coord = vec2(cos(phi), sin(phi)) * r;
gl_FragColor = texture2D(inputBuffer, coord + 0.5);
}
結果
下記のリンクで WebGL (GLSL) の実装例の結果が確認できる。