OpenGL覚え書き4 隠面消去

隠面消去を行うには、バックフェースカリング、奥行きソート法、スキャンライン法、zバッファ法などいくつかの手法が知られています。
zバッファ法は、ウインドウの各画素について投影面から物体の距離(デプス)の値が保存されたバッファを作成して、距離が大きい画素から描画する方法です。OpenGLでzバッファ法を利用して立体を表示させるためには次の3つのコマンドを実行します。
デプスバッファによる表示を指示するためのコマンド(フラグGLUT_DEPTHを引数に追加する)

glutInitDisplayMode(GLUT_RGBA  | GLUT_DOUBLE |GLUT_DEPTH)

デプスバッファを利用可能状態にするコマンド

glEnable(GL_DEPTH_TEST)

デプスを最大値に設定するコマンド(フラグGL_DEPTH_BUFFER_BITを引数に追加する)
描画前に全ての画素についてz座標を最大に設定しておきます。

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)


zバッファ法による隠面処理で四面体を描画した例です。原点に位置する物体をマウスで動かすことができます。

from OpenGL.GL import *
from OpenGL.GLUT import *
from OpenGL.GLU import *
from math import*
import sys

class AppBase:
    def __init__(self):
        self.__mouseX = 0
        self.__mouseY = 0
        self.__xrot = 0
        self.__yrot = 0
        
        glutDisplayFunc(self._draw)
        glutMouseFunc(self._mousePressed)
        glutMotionFunc(self._mouseDragged) 
        glutReshapeFunc(self._resize)
        
        glClearColor(0.0,0.0,0.0,0.0)
        glEnable(GL_DEPTH_TEST)
        
    def _draw(self):        
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
        #modeling transform
        glLoadIdentity()
        glRotatef(self.__xrot,1.0,0.0,0.0)
        glRotatef(self.__yrot,0.0,1.0,0.0)
        #draw x,y,z axis
        glBegin(GL_LINES);
        glColor3f(1.0,1.0,1.0)
        glVertex3f(-1,0,0)
        glVertex3f(1,0,0)
        glVertex3f(0,-1,0)
        glVertex3f(0,1,0)
        glVertex3f(0,0,-1)
        glVertex3f(0,0,1)
        glEnd()
        #draw solid model
        r = 0.4
        glBegin(GL_TRIANGLES)
        glColor3f(0.9,0.9,0.7)
        glVertex3f(0,r,0)
        glVertex3f(r,0,0)
        glVertex3f(0,0,r)
        glColor3f(0.7,0.7,1.0)
        glVertex3f(0,0,0)
        glVertex3f(r,0,0)
        glVertex3f(0,r,0)
        glColor3f(0.7,1.0,0.7)
        glVertex3f(0,0,0)
        glVertex3f(0,r,0)
        glVertex3f(0,0,r)
        glColor3f(1.0,0.7,0.7)
        glVertex3f(0,0,0)
        glVertex3f(r,0,0)
        glVertex3f(0,0,r)
        glEnd()
  
        glutSwapBuffers()
        
    def _mousePressed(self,button,state,x,y):
        if(state == GLUT_DOWN):
            glutIdleFunc(self._draw)
        else:
            glutIdleFunc(0)
        self.__mouseX = x
        self.__mouseY = y   
            
    def _mouseDragged(self,x,y):
        self.__xrot += y - self.__mouseY
        self.__yrot += x - self.__mouseX
        self.__mouseX = x
        self.__mouseY = y
    
    def _resize(self,width, height):
        glViewport(0, 0, width, height)
        glMatrixMode(GL_PROJECTION)
        glLoadIdentity()
        gluPerspective(15.0, float(width) / float(height), 3.0, 15.0)
        gluLookAt(0.0,0.0,5.0,0.0,0.0,-1.0,0.0,1.0,0.0)
        glMatrixMode(GL_MODELVIEW)

def main():
    glutInit(sys.argv)
    glutInitDisplayMode(GLUT_RGBA  | GLUT_DOUBLE |GLUT_DEPTH)
    glutInitWindowSize(600, 600)
    glutCreateWindow("PyOpenGL")
    
    app = AppBase()
    glutMainLoop()
    
main()