面法線と頂点法線_3DCG
面法線と頂点法線
面法線
ポリゴン(三角形)は、3つの頂点の並びにより「面から垂直に出るベクトル」が計算できます。これが「面法線」といわれるものです。
これは、3頂点をv0/v1/v2とした場合に
VECTOR3 vv1, vv2, n; vv1 = v1 - v0; vv2 = v2 - v1; Vec3Cross(&n, &vv1, &vv2); Vec3Normalize(&n, &n);
として求まります。「Vec3Cross」は外積を求める関数、「Vec3Normalize」はベクトルを正規化して長さを1.0にする関数です(よく使うベクトル・行列計算関数を参照)。
この「面法線」は、光の計算をするとき(正反射するときなど)に利用されます。また、面が表を向いているか裏を向いているかの判定でも利用されます。
たとえば、方向ベクトルV(v.x, v.y, v.z)があり、面の法線がN(n.x, n.y, n.z)のときに、ベクトルVの進行方向にて面が表を向いているかどうかは
A = -(v.x * n.x + v.y * n.y + v.z * n.z);
のAが0.0以上の場合に法線Nを作る面は面を向いていると判断できます。これは、
cosθ = V1 * N / (|V1| * |N|)
の角度を求める式(「|V1|」はベクトルV1の長さを求める、の意味)のベクトルの長さは共に1.0なので分母を消して、
cosθ = V1 * N
つまり、ベクトルの内積を求めることで2ベクトルが作る角度が求まる、ということを利用したものです(V1をベクトルNと同じ向きにするために「-V1 * N」としている)。
cos-90°〜cos0°〜cos90°の範囲の場合は結果はプラスになります。
頂点法線
面法線とは別に、頂点ごとに法線を持たせます。これを「頂点法線」と言います。これは、グローシェーディングにて「滑らかにシェーディングする」ために利用されます。これも面法線と同じく計算で求まります。
計算としては、以下の手順で行われます(オブジェクト単位で計算)。
- 個々のポリゴンの面法線を計算
- 頂点ごとに共有するポリゴン番号を配列化して格納(1つの頂点を複数のポリゴンが共有している、という状態)
- 頂点ごとの共有するポリゴンの法線をすべて加算していく
- 加算後、頂点の加算した法線を正規化する
この結果、各頂点ごとに法線が入ります。これがそれぞれ頂点法線となります。
スムージング角度
シェーディングにてこの頂点法線を利用すると(頂点以外の座標では補間することになります)それこそ滑らかになりますが、たとえばサイコロのような立方体の場合は頂点法線は使ってはいけません。このときは面法線を採用します。
このように時と場合によって「面法線」「頂点法線」の利用を使い分けますが、「スムージング角度」としてマテリアルのパラメータ(またはオブジェクト自身のパラメータ)を持たせることが多いようです。
スムージングの角度を最大45°としたときの面の表面のとある座標位置での面法線をN、頂点法線をVNとして考えてみます。
c1 = N.x * VN.x + N.y * VN.y + N.z * VN.z; c2 = cos(45 * 3.1415926535 / 180.0);
「c1 >= c2」のときは頂点法線を採用します。「c1 < c2」のときは面法線を採用します。スムージング角度が大きいほどスムーズになり、スムージング角度が小さいとフラットなシェーディングになります。
Future's Laboratory 技術格納庫 2004-2013 Yutaka Yoshisaka.