主に、生成された形状の法線を計算する3つの方法があります。
分析法線
場合によっては、法線を生成するのに十分な表面情報があります。たとえば、球上の任意の点の法線を計算するのは簡単です。簡単に言えば、関数の導関数を知っているときは、法線も知っています。
分析法線を使用できるほどケースが狭い場合、おそらく精度の点で最高の結果が得られます。ただし、この手法はあまりうまくスケーリングしません。分析法線を使用できない場合も処理する必要がある場合、一般的な場合を処理する手法を維持し、分析的なものを完全に削除する方が簡単かもしれません。
頂点法線
2つのベクトルの外積は、それらが属する平面に垂直なベクトルを与えます。したがって、三角形の法線を取得するのは簡単です。
vec3 computeNormal(vec3 a, vec3 b, vec3 c)
{
return normalize(crossProduct(b - a, c - a));
}
さらに、上記の例では、外積の長さはabc内の面積に比例します。したがって、複数の三角形で共有される頂点の平滑化された法線は、外積を合計し、最後のステップとして正規化することで計算できます。
vec3 computeNormal(vertex a)
{
vec3 sum = vec3(0, 0, 0);
list<vertex> adjacentVertices = getAdjacentVertices(a);
for (int i = 1; i < adjacentVertices; ++i)
{
vec3 b = adjacentVertices[i - 1];
vec3 c = adjacentVertices[i];
sum += crossProduct(b - a, c - a);
}
if (norm(sum) == 0)
{
// Degenerate case
return sum;
}
return normalize(sum);
}
クワッドを使用している場合、使用できる素晴らしいトリックがあります。クワッドabcdにcrossProduct(c - a, d - b)
は、クアッドが実際に三角形である場合にうまく処理できます。
イニゴquilezトピックに関するいくつかの短い記事を書いた:巧妙なメッシュの正規化、および通常の面積のn辺のポリゴンを。
偏微分からの法線
法線は、フラグメントシェーダーで偏微分から計算できます。背後の計算は同じですが、今回は画面スペースで行われます。Angelo Pesceによるこの記事では、テクニック:Normals without normalsについて説明しています。