uniformSphere
一様分布に従う乱数 $ u_1・$ u_2を用意し、 $ \phi = 2 \pi u_1
$ \sin(\theta) = 1 - 2 u_2
$ \cos(\theta) = \sqrt{1 - \sin^2(\theta)}
$ \vec v = \left( \begin{matrix} \cos(\theta) \cos(\phi) \\ \cos(\theta) \sin(\phi) \\ \sin(\theta) \end{matrix} \right)
$ \theta の値域を$ [0, \pi] ととるか$ \left[ -\frac{\pi}{2}, \frac{\pi}{2} \right] ととるかで$ \sin(\theta)と$ \cos(\theta)が入れ替わるが、どっちでも良い
上の式は$ \left[ -\frac{\pi}{2}, \frac{\pi}{2} \right] で考えてるほう
球内部
さらに、球内部にも一様に分布させたい場合は、
もうひとつ一様乱数$ u_3を用意し、それの立方根をかけてやる $ r = \sqrt[3]{u_3}
$ \vec v' = r \vec v
Observable
https://gyazo.com/88b793e680db4b67bcc1999b83bf7fc7
GLSL
code:glsl
vec3 uniformSphere(vec2 xi) {
float phi = xi.x * TAU;
float sinTheta = 1.0 - 2.0 * xi.y;
float cosTheta = sqrt(1.0 - sinTheta * sinTheta);
return vec3(
cosTheta * cos(phi),
cosTheta * sin(phi),
sinTheta
);
}
考え方
$ \theta を$ \left[ -\frac{\pi}{2}, \frac{\pi}{2} \right] の一様分布にしちゃうと、極付近に分布が偏っちゃう
ある$ \thetaが与えられたときに$ \phiを連続的に動かしていって、円周の長さがどうなるかを考えると、
$ \theta = 0のときは円周の長さが$ 2 \piなのに対して、$ \thetaを$ \frac{\pi}{2}(あるいは$ -\frac{\pi}{2})へと近づけていくにつれて円周の長さは短くなっていく
$ r = 2 \pi \cos(\theta)ですねえ
確率密度関数で表現すると$ f(\theta) = \frac{1}{2} \cos(\theta)になってほしい 累積分布関数にすると、$ F(\theta) = \frac{1}{2} \sin(\theta) + \frac{1}{2} 逆関数法を使って、$ U = \frac{1}{2} \sin(\hat{\Theta}) + \frac{1}{2}となってくれれば良い じゃあ$ \sin(\theta) を$ [-1, 1] で作ってやればいいんじゃね?
(実は$ \thetaを直接求める必要がありません、なんと)
さらに、$ \cos(\theta) = \sqrt{1 - \sin^2(\theta)}と求められる
オケー
球内部
球の面積が$ 4 \pi r^2なので、
確率密度関数で$ f(r) = 3 r^2になってほしい
累積分布関数にすると、$ F(\theta) = r^3
逆関数法を使って、$ U = \hat R^3 を満たすような$ \hat R は$ \sqrt[3]{u}
オケー
Blackleの手法
code:glsl
vec3 uniformSphere( vec3 xi ) {
return normalize( tan( xi * 2.0 - 1.0 ) );
}
正確ではないが、ライブコーディング文脈だとモンテカルロ積分とかをしない限りは全然これで良い https://gyazo.com/1dadca060a85fdbe54446a9eabff21fc