隠面消去
デプス バッファと距離
これまでの学習で、複数のオブジェクトを表示させることができるようになりました
しかし、複数のオブジェクトを表示させた場合、視点からの距離が問題となります
オブジェクトの絶対座標がなんであれ、オブジェクトがどのように表示されるかは
視点からの相対的な座標で決定されることに注目する必要があります
二つのオブジェクト A と B が重なりあって見えている場合
最後に描画したオブジェクトが、その前に描画したオブジェクトを上書きして手前に表示されます
これに、距離は関係ありません
実際に、「射影変換」の章の最初の、2つの三角形を表示するサンプルプログラムを書き換えて
青い三角形を後に描画すると、赤い三角形の手前にあるかのように表示されてしまいます
Z 座標で考えれば奥にあるはずのオブジェクトが手前にくるのは奇妙です
そこで、奥にあるオブジェクトを先に描画して、手前にあるオブジェクトを優先的に表示させる
という方法が考えられますが、これは2次元的な処理方法です
3次元の世界では、視点を変更し裏側から見ればその関係も逆転します
オブジェクトの絶対座標に関係なく、視点からの相対的な座標が重要なのです
Z 座標の関係上、他のオブジェクトに隠れてしまうオブジェクトを排除する必要があります
この処理を隠面消去と呼びます
通常、隠面消去を期待する場合はデプス バッファを利用することになります
デプスとは Z 座標のことで、Z バッファとも呼ばれます
デプス バッファは視界からの距離を保存し、ウィンドウのピクセルと関連付ける役割を持ちます
デプス バッファを有効にするには glutInitDisplayMode() で GL_DEPTH_BUFFER_BIT を指定します
ただし、これだけでは正しく処理されません
オブジェクトを描画する前に、デプス バッファを更新しなければなりません
デプスの更新は glEnable() で GL_DEPTH_TEST を指定します
#include <windows.h>
#include <GL/gl.h>
#include <GL/glut.h>
int width , height;
const GLfloat vertex[] = {
-0.9 , -0.9 , -2 , 0.9 , -0.9 , -2 , 0 , 0.9 , -2
};
void Draw(void);
void Draw() {
glDrawArrays(GL_POLYGON , 0 , 3);
glViewport(0 , 0 , width , height);
}
void disp( void ) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_DEPTH_TEST);
glPushMatrix();
glColor3f(1 , 0 ,0);
glTranslatef(-0.5 , 0 , 0);
Draw();
glPopMatrix();
glPushMatrix();
glColor3f(0 , 0 , 1);
glTranslatef(0.5 , 0 , -1);
Draw();
glPopMatrix();
glFlush();
}
void reshape(int w , int h) {
width = w; height = h;
disp();
}
int main(int argc , char ** argv) {
glutInit(&argc , argv);
glutInitWindowPosition(100 , 50);
glutInitWindowSize(400 , 300);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGBA | GLUT_DEPTH);
glutCreateWindow("Kitty on your lap");
glutDisplayFunc(disp);
glutReshapeFunc(reshape);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glFrustum(-1 , 1 , -1 , 1 , 2 , 10);
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3 , GL_FLOAT , 0 , vertex);
glutMainLoop();
return 0;
}
このプログラムは、赤い三角形を先に描画し、その後、青い三角形を描画しています
青い三角形は、赤い三角形の後ろ側にあるため、隠面消去されていることが確認できます