21
20

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

WebGLのフラグメントシェーダを使ったミラーボール投影

Last updated at Posted at 2016-01-26

#はじめに
冬休みにThetaの360°画像にぼかしを入れるWebアプリSphereBlur.com作った際に、どのように360°写真を表示するのか悩んだ。編集ツールなので、引いた画面ではできるだけ広い範囲を表示したいが、単純に球体にテクスチャを貼り付けて、透視投影や平行投影をしても半球までしか表示できない。いろいろ悩んでいたら、どこかで見たこの絵
Hand with Reflecting Sphere
を思い出して、おおっ!これだっ!って思ったけど、後で調べたらTHETAのAndroid/iOSアプリの表示はミラーボール投影というものらしい・・・VR業界では常識なのかな?

#テクスチャを使ったミラーボール投影
というわけで、three.jsこのサンプルを参考にしてミラーボールの環境マッピングを試してみた。しかしこの場合、ポリゴンで構成された球、つまり多面体で反射した景色なので、ズームして回転した際にどうしても歪みが気になってしまう。そこで、自前でWebGLのフラグメントシェーダを書いてみることにした。

#デモ
https://horo-t.github.io/tmp/20151225/mirror_ball_view.html

#計算
ミラーボール反射はどうやって計算するのか考えてみる。
m1.png

図のように原点Oと視点Aの距離を$OA=1$と固定し、ミラーボールの半径をrとした場合を考え、原点Oからdの距離にある点Dとし、$\overrightarrow{AD}$方向の視線にどの方向からの光が反射するか($\overrightarrow{BR}$)を求めるために、まず$\alpha$を求める。

CB:OD=CA:OA

なので、

\begin{align}
\frac{CB}{OD}&=\frac{CA}{OA}\\
\frac{r \sin{\alpha}}{d}&=\frac{1-r\cos{\alpha}}{1}\\
r\sin{\alpha} + rd\cos{\alpha}&=d\\
\frac{1}{\sqrt{1+d^2}}\sin{\alpha}+\frac{d}{\sqrt{1+d^2}}\cos{\alpha}&=\frac{d}{r\sqrt{1+d^2}}\\
\cos{\beta}\sin{\alpha}+\sin{\beta}\cos{\alpha}&=\frac{d}{r\sqrt{1+d^2}}\\
\sin{(\alpha+\beta)}&=\frac{d}{r\sqrt{1+d^2}}\\
\cos{(\alpha+\beta)}&=\frac{\sqrt{r^2+r^2d^2-d^2}}{r\sqrt{1+d^2}}
\end{align}

ここから$\sin{\alpha}$、$\cos{\alpha}$を求めると、

\begin{align}
\sin{\alpha}&=\sin{(\alpha+\beta-\beta)}\\
&=\sin{(\alpha+\beta)}\cos{\beta}-\cos{(\alpha+\beta)}\sin{\beta}\\
&=\frac{d}{r\sqrt{1+d^2}}\frac{1}{\sqrt{1+d^2}}-\frac{\sqrt{r^2+r^2d^2-d^2}}{r\sqrt{1+d^2}}\frac{d}{\sqrt{1+d^2}}\\
&=\frac{d(1-\sqrt{r^2+r^2d^2-d^2})}{r(1+d^2)}\\
\cos{\alpha}&=\cos{(\alpha+\beta-\beta)}\\
&=\cos{(\alpha+\beta)}\cos{\beta}+\sin{(\alpha+\beta)}\sin{\beta}\\
&=\frac{\sqrt{r^2+r^2d^2-d^2}}{r\sqrt{1+d^2}}\frac{1}{\sqrt{1+d^2}}+\frac{d}{r\sqrt{1+d^2}}\frac{d}{\sqrt{1+d^2}}\\
&=\frac{\sqrt{r^2+r^2d^2-d^2}+d^2}{r(1+d^2)}
\end{align}

$\alpha$の値が求まると、後は簡単で、求めたい方向$\frac{\overrightarrow{BR}}{|BR|}$は、法線ベクトル$\frac{\overrightarrow{OB}}{|OB|}$に対する$\frac{\overrightarrow{AB}}{|AB|}$の反射なので、

\frac{\overrightarrow{BR}}{|BR|}=\frac{\overrightarrow{AB}}{|AB|}-2(\frac{\overrightarrow{AB}}{|AB|}\cdot\frac{\overrightarrow{OB}}{|OB|})\frac{\overrightarrow{OB}}{|OB|}

で求めることができる。

21
20
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
21
20

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?