はじめに
勾配を計算することで法線ベクトルを計算するケースはいくつか存在します.自分が使用するケースとしてはレイマーチングでのライティングや、拡散方程式などの数値解析の境界条件で使用されるノイマン境界条件などでも使用されたりします.
そこでこの記事ではなぜスカラー場の勾配をとると法線ベクトルが求められるのかを記述していきます.
勾配と法線の関係
${f(x, y)}$で与えられている平面スカラー場Dについて考える.${P{_0}(x{_0}, y{_0})}$を通る等位曲線を$C$とし、$x = x(s), y = y(t)$をする.↓ピンクで塗られている曲線が等位曲線
ここで等位曲線Cの方程式について考える.(Cはどの点に置いても同じ値、$f(x{_0}, y{_0})$という定数をとる)
$$
P(t) = f(x(t), y(t)) = f(x{_0}, y{_0}) \tag{1.1}
$$
(1.1)の両辺を変数$t$で微分を行うと
$$
\frac {\partial f}{\partial x} {\cdot} \frac{dx}{dt} + \frac {\partial f}{\partial y} {\cdot} \frac{dy}{dt} = 0 \tag{1.2}
$$
(1.2)は2つのベクトル$ [ \frac{\partial f}{\partial x}, \frac{\partial f}{\partial y}] $と$ [\frac{dx}{dt} , \frac{dy}{dt}] $の内積を表現している.$ [\frac{dx}{dt} , \frac{dy}{dt}] $は等位曲線上の接線を示しており,この
またベクトルとの内積の値が0になっていることから2つのベクトルが直行していることがわかる.故に、勾配を示す$ [ \frac{\partial f}{\partial x}, \frac{\partial f}{\partial y}] $は法線を示していると言える
サンプルソース
参考までにですが、コンピュータ上では正確な微分演算は出来ないので以下のように微少区間ずらした値との差分で計算を行います.
vec3 normal(vec3 p) {
float EPSILON = 0.0001;
return normalize(vec3(
phi(vec3(p.x + EPSILON, p.y, p.z)) - phi(vec3(p.x - EPSILON, p.y, p.z)),
phi(vec3(p.x, p.y + EPSILON, p.z)) - phi(vec3(p.x, p.y - EPSILON, p.z)),
phi(vec3(p.x, p.y, p.z + EPSILON)) - phi(vec3(p.x, p.y, p.z - EPSILON))
));
}