第 8 章 形状の表現
8.4 隠面消去
8.4.2 背面カリング
このプログラムを実行すると、最初は図 123 (a) のように正しい六面体のように描かれます。
しかし、この六面体を回転させると、途中で正しい六面体として表示されなくなります。
図 123 六面体を一回転させた時の表示
そこで、六面体が図 123 (d) の向きにある時、六面体の各面をデータの順で描くと、図 124 の ようになります。このように多面体の各面をデータの順に重ね書きしていくだけでは、面の見え 隠れが正しく表現できません。
図 124 図 123 (d) を一面ずつ描画
そこで、六面体の各面に表裏を設定します。多面体のデータの面の表裏は、その面を構成する 頂点の順番で表すことができます。多面体の表を向いている面を見た時、その面の頂点が左回り に並んでいれば、その面は視点に対して表を向けているとします (図 125)。
(a) (b) (c) (d) (e) (f)
図 125 面に表裏を設定する
このとき、視点から裏側が見えている面を描かないようにすれば、立方体のような凸多面体の 場合は、このような問題を避けることができます (図 127)。この処理を、背面カリング (Backface Culling) といいます。
三角形の場合、この判定は次のようにして行うことができます。左手系の座標系において、三 角形の頂点のスクリーン上の位置ベクトルを P0、P1、P2 とし、P0 から P1 に向かうベクトルを V1、P0 から P2 に向かうベクトルを V2 とするとき、V1、V2 の外積V1×V2 の Z 成分が正なら P0、P1、P2 は左回り (表面)、負なら右回り (裏面) になっています。
図 126 三角形の表裏判定
l メインプログラム (main.cpp) の変更点
OpenGL にはこの判定機能が組み込まれており、以下の設定により有効にすることができます。
int main() {
《省略》
// 背景色を指定する
glClearColor(1.0f, 1.0f, 1.0f, 0.0f);
// 背面カリングを有効にする
glFrontFace(GL_CCW);
V1⇥V2= (dx1, dy1,0)⇥(dx2, dy2,0) = 0,0, dx1dy2 dx2dy1
V2=P2 P0= (dx2, dy2,0) V1=P1 P0= (dx1, dy1,0)
P0
P1
P2
V1
V2
dx1dy2 dx2dy1
8<
:
>0
= 0
<0
:表を向いている
:裏を向いている
:つぶれている(見えない)
glCullFace(GL_BACK);
glEnable(GL_CULL_FACE);
// プログラムオブジェクトを作成する
const GLuint program(loadProgram("point.vert", "point.frag"));
《省略》
// ウィンドウが開いている間繰り返す
while (glfwWindowShouldClose(window) == GL_FALSE) {
《省略》
} }
n サンプルプログラム step25
void glFrontFace(GLenum mode)
視点に対して表側を向いている面 (表面) の条件を引数 mode に指定します。
mode
GL_CCW なら見て頂点が左回り (反時計回り、Counterclockwise) の面を表とし、GL_CW な
ら頂点が右回り (時計回り、Clockwise) の面を面とする。デフォルトは GL_CCW。
void glCullFace(GLenum mode)
表面を削除するか、裏面を削除するかを引数 mode に指定します。
mode
表面を削除するなら GL_FRONT、裏面を削除するなら GL_BACK。デフォルトは GL_BACK。
これらの設定の後、glEnable(GL_CULL_FACE) を実行すれば、背面カリングが有効になります。
背面カリングを無効にするには glDisable(GL_CULL_FACE) を実行します。
補足:背面カリングのデフォルト値
デフォルトでは背面カリングは無効になっています。また、デフォルトでは glFrontFace() が
GL_CCW、glCullFace() が GL_BACK になっているので、多面体の外から面を見たときに頂点が
左回りになっていれば、glEnable(GL_CULL_FACE) だけで背面カリングが有効になります。
図 127 背面カリングを行なった場合
(a) (b) (c) (d) (e) (f)