読者です 読者をやめる 読者になる 読者になる

VR 研究記

3D技術の経験を活かして、VRに挑戦するおっさんの奮闘記

【Shaderプログラミング】雪を降らせる手法について Part.4

年度跨ぐ際にいろいろ大変でした。
年度末に急に振られた、ノベルゲーム勉強会。

まったく、経験が無いのに教えろと言う無茶振りw
何とか乗り越えました。
(その方、よくプログラミング出来るみたいでしたよ。)

終わったことは、どうでもいいとして・・・
内積の説明に入りましょう。

心身ともにボロボロなパンダですクマーーーーーー。。。
(猫熊なので、語尾がクマでも間違いではないのだw)

前回のおさらい

前回は、ベクトルの足し算を図で表現することで、イメージしやすく表現してみました。
ベクトルの足し算は、量の総和です。
方向も合わせて考えることが、重要なんですよ。

【Shaderプログラミング】雪を降らせる手法について Part.3 - VR 研究記


では、ベクトルの内積に入ろうと思います。
まずは、内積を証明する前に必要な余弦定理の証明を示します。

懐かしいと思いますが、定義は以下の通りです。

  a^2 = b^2 + c^2 + 2bc \cos \theta

パンダでも分かる余弦定理

余弦定理とは、直角三角形ではない三角形からある角度θ挟む線分の終点通しを結んだとき、その線分の長さを求める式のことです。
実際に何に使うのやら、まったく用途の分からない式ですが、まぁ通過点と思って見てくだせぇ。

点Oを原点にして、角θを挟んで広がる線分OAと線分OBがあります。
線分OA,線分OBの長さは、それぞれb, cと定義します。
線分ABの長さaを求めるために順番に解説します。

f:id:subrutm:20170414221719p:plain

まず、点Aから線分OBに向かって垂直なる線を引き線分OBとの交点をHとします。
線分AHの長さと線分HBの長さが分かれば、 a^2が出ることは分かりますよね。

じゃあ、線分AHの長さを算出してみましょう。
下の絵の通り、三角形OAHを出してみました。

f:id:subrutm:20170414222735p:plain

ここで、分かっているのは、線分OAの長さbと角θのみです。
角θを使って \sin \thetaを計算してみましょう。

 \sin \theta = \frac{|AH|}{b}
 |AH| = b \sin \theta

f:id:subrutm:20170414223726p:plain

次に、線分HBの長さを算出したいけど、このままでは算出できないね。
線分OBの長さがcだと分かっているので、全体から、|OH|を引けば出せるかもしれないよ。

ってことで、線分|OH|を算出します。
線分OAの長さbと \thetaが分かるので、 \cos \thetaを使って以下のように表現します。

 \cos \theta = \frac{|OH|}{b}
 |OH| = b \cos \theta

最終的に求めたいのは、線分HBの長さで線分OBの長さはcであるから、
 |HB| = c - b \cos \theta

f:id:subrutm:20170414225338p:plain

最終的な目的は、線分ABの長さaを求めることなので、三角関数の定理より
 a^2 = |HA|^2 + |HB|^2

それぞれ、算出した長さを代入すると、こうなります。
 a^2 = (b \sin \theta)^2 + (c - b \cos \theta)^2
これを展開して、
 a^2 = b^2 \sin^2 \theta + (c^2 + b^2 \cos^2 \theta - 2bc \cos \theta)
 a^2 = b^2 (\sin^2 \theta + \cos^2 \theta) + c^2 - 2bc \cos \theta
 (\sin^2 \theta + \cos^2 \theta) = 1より
 a^2 = b^2 + c^2 - 2bc \cos \theta となる。

前出の定理になりました。
この知識を踏まえて、ベクトルの内積とは何かを解剖しましょう。

パンダの内積 (パンダ関係ないぞw)

いよいよ本題の内積です。
これを通してイメージ掴んでくださいな

ベクトルの内積って \vec{a}(a_1,a_2)と\vec{b}(b_1,b_2)があるとすると \vec{a}・\vec{b} = (a_1 * b_1) + (a_2 * b_2)になるよって習いましたよね?
だから、それ何に使うの?どういう意味なの?って突込みには一切触れずに、式だけ覚えましたよね?

んじゃ、今回はそれを解き明かしましょう。

まず、 \vec{0}ではない、 \vec{OA} = \vec{a}, \vec{OB} = \vec{b}を用意します。

f:id:subrutm:20170415001225p:plain

この三角形は、どこかで見ましたね?
そう、余弦定理です。
余弦定理とtの関係から内積とは『何か』を見たいと思います。

三角形OABについて、余弦定理を見てみましょう。
 \vec{|BA|}^2 = \vec{|OA|}^2 + \vec{|OB|}^2 - 2\vec{|OA|}\vec{|OB|}\cos \theta
 (|\vec{a} - \vec{b}|)^2 = \vec{|a|}^2 + \vec{|b|}^2 - 2\vec{|a|}\vec{|b|}\cos \theta
 (\vec{|a}|^2 + \vec{|b|}^2 - 2\vec{a}\vec{b}) = \vec{|a|}^2 + \vec{|b|}^2 - 2\vec{|a|}\vec{|b|}\cos \theta
 (-2\vec{a}\vec{b}) = -2\vec{|a|}\vec{|b|}\cos \theta
 \vec{a}・\vec{b} = \vec{|a|}\vec{|b|}\cos \theta (0≦ \theta≦180)

ここで、 \vec{a}(a_1,a_2)と\vec{b}(b_1,b_2)と定義して余弦定理に代入してみましょう。
 (a_1 - b_1)^2 + (a_2 - b_2)^2 = (a_1^2 + a_2^2) + (b_1^2 + b_2^2) - 2\vec{a}・\vec{b}
 a_1^2 + b_1^2 - 2a_1b_1 + a_2^2 + b_2^2 - 2a_2b_2 = (a_1^2 + a_2^2) + (b_1^2 + b_2^2) - 2\vec{a}・\vec{b}
 - 2(a_1b_1 + a_2b_2) = - 2\vec{a}・\vec{b}
 a_1b_1 + a_2b_2 = \vec{a}・\vec{b}となる。

成分で見ると、内積 \vec{a}・\vec{b} = a_1b_1 + a_2b_2

まとめ

結局、内積の正体は数式でのみでしか表現できそうに無い。
ただし、数式の関係からベクトルから、 \cos \thetaを求めて、角度の算出等に役立ちそうだというのは理解できると思う。

では、次回は【内積】を使って、シェーダープログラミングを書いてみることにしよう。

Let's try it.

シリーズ一覧:
【Shaderプログラミング】雪を降らせる手法について Part.1 - VR 研究記
【Shaderプログラミング】雪を降らせる手法について Part.2 - VR 研究記
【Shaderプログラミング】雪を降らせる手法について Part.3 - VR 研究記