OpenGLの法線


by Ton Roosendaal



OpenGLによるライティング、法線、負のスケール



 デフォルトではOpenGLは負のスケールのObjectのライティングが苦手です。単に法線を反転し、シェーディングを反転しようと考えても―実際のライティング自身も反転し、Faceの「背面」と「前面」も入れ替わってしまいます。

この最初の画像はこれを表すもので、下の二つの球は通常のスケール、そして上の二つは負のスケールです。法線を反転し、前面・背面を入れ替えることで、反転したObjectの結果の外見はまだ「OK」です。



 このシチュエーションはOpenGLでDouble Sidedをライティングした時です。背面・前面が入れ替わった所為で、球が完全に黒くレンダリングされています。

負のスケールのObjectを使用する時、Blenderの"Double Sided"をOFFにすることが、通常の回避のアドバイスです。



 したがって、この問題の解決方法はObjectが「反転した」行列を持っているかどうか計算することです。幸運にも、ここにシンプルかつ信頼性の高い方法があります。


(blenkernel/intern/object.c の where_is_object()より)
/* set negative scale flag in object */ 
Crossf(vec, ob->obmat[0], ob->obmat[1]);
if( Inpf(vec, ob->obmat[2]) < 0.0 ) ob->transflag |= OB_NEG_SCALE;
else ob->transflag &= ~OB_NEG_SCALE;
これは単に変換行列の最初の二行の外積をとり、これを三行めと比べる(内積をとる)だけです。

描画中の前面・背面の決定を正しくしました。
if(ob->transflag & OB_NEG_SCALE) glFrontFace(GL_CW);
else glFrontFace(GL_CCW);
三つめの画像では4つのシチュエーションすべてにおいて正しいdouble-sideのライティングが行われています。

かなりの年月の後に、ついに…。