PyOpenGL 4

ライトとマテリアル

ライトとマテリアルの設定をしてみましょう。

#!env python

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


vertex = [
    [ -1.0, -1.0, 1.0 ],
    [ 1.0, -1.0, 1.0 ],
    [ -1.0, 1.0, 1.0 ],
    [ 1.0, 1.0, 1.0 ],
    [ -1.0, 1.0, -1.0 ],
    [ 1.0, 1.0, -1.0 ],
    [ -1.0, -1.0, -1.0 ],
    [ 1.0, -1.0, -1.0 ]]

face = [
    [ 0, 1, 3, 2 ],
    [ 2, 3, 5, 4 ],
    [ 4, 5, 7, 6 ],
    [ 6, 7, 1, 0 ],
    [ 1, 7, 5, 3 ],
    [ 6, 0, 2, 4 ]]

normal = [
    [ 0.0, 0.0,1.0 ],
    [ 0.0, 1.0, 0.0 ],
    [ 0.0, 0.0, -1.0 ],
    [ 0.0, -1.0, 0.0 ],
    [ 1.0, 0.0, 0.0 ],
    [ -1.0, 0.0, 0.0 ]]

light0p = [ 0.0, 3.0, 5.0, 1.0 ]
light1p = [ 5.0, 3.0, 0.0, 1.0 ]
lightColor = [ 0.5, 0.5, 0.5, 1.0 ]
greenColor = [ 0.0, 1.0, 0.0, 1.0 ]

angleX = 0.0
angleY = 0.0


def resize(w, h):
    glViewport(0, 0, w, h)
    glMatrixMode(GL_PROJECTION)
    glLoadIdentity()
    gluPerspective(30.0, w/h, 1.0, 100.0)
    glMatrixMode(GL_MODELVIEW)


def draw():
    global angleX, angleY

    glClearColor(0.0, 0.0, 1.0, 0.0)
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)

    glLoadIdentity()
    gluLookAt(3.0, 4.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0)

    glLight(GL_LIGHT0, GL_POSITION, light0p)
    glLight(GL_LIGHT1, GL_POSITION, light1p)

    glRotated(angleX, 1.0, 0.0, 0.0)
    glRotated(angleY, 0.0, 1.0, 0.0)

    glMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, greenColor)

    glBegin(GL_QUADS)
    for j in range(0, 6):
        glNormal3dv(normal[j])
        for i in range(0, 4):
            glVertex(vertex[face[j][i]])
    glEnd()

    glFlush()
    glutSwapBuffers()


def keyboard(key, x, y):
    global angleX, angleY
    if key=='q':
        sys.exit()
    elif key=='h':
        angleY += 1.0
        glutPostRedisplay()
    elif key=='j':
        angleX += 1.0
        glutPostRedisplay()

glutInit(sys.argv)
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH)
glutInitWindowSize(320, 320)
glutCreateWindow("PyOpenGL 13")

glutDisplayFunc(draw)
glutReshapeFunc(resize)
glutKeyboardFunc(keyboard)

glClearColor(0.0, 0.0, 1.0, 0.0)
glEnable(GL_DEPTH_TEST)
glEnable(GL_CULL_FACE)
glCullFace(GL_BACK)

glEnable(GL_LIGHTING)
glEnable(GL_LIGHT0)
glEnable(GL_LIGHT1)
glLight(GL_LIGHT1, GL_DIFFUSE, lightColor)
glLight(GL_LIGHT1, GL_SPECULAR, lightColor)

glutMainLoop()

スクリプト解説

glLight(GL_LIGHT0, GL_POSITION, light0p)
ライトのパラメータの設定です。
0番目のライトの位置に light0p を指定します。
glLight() の引数は以下の様になります。
1番目の引数
設定するライトの番号 (GL_LIGHT0 〜 GL_LIGHTn)
2番目の引数
設定するパラメータの種類
GL_POSITION
ライトの位置
GL_DIFFUSE
ライトの拡散反射光色
GL_SPECULAR
ライトの鏡面光色
3番目の引数
2番目に指定した、パラメータの種類に設定する値
2番目の引数が、GL_POSITION であれば、 4つの要素を持つ配列になり、ライトの位置を指定します。
[ x, y, z, 1 ]
(x, y, z) の位置にある点ライト
[ x, y, z, 0 ]
(x, y, z) 方向の平行ライト
あるいは GL_DIFFUSE のときは、 4つの要素を持つ配列になり、拡散反射光色を指定します。
[ r, g, b, 1 ]
(r, g, b) の拡散反射光色
glLight() によるライトの位置 (GL_POSITION) の設定は、 視点の位置を設定(gluLookAt)した後に行う必要があります。
glLight(GL_LIGHT1, GL_POSITION, light1p)
1番目のライトの位置に light1p を指定します。
glMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, greenColor)
マテリアルの設定です。
1番目の引数
GL_FRONT
表に設定
GL_BACK
裏に設定
GL_FRONT_AND_BACK
表・裏に設定
2番目の引数
GL_AMBIENT
環境光反射係数
GL_DIFFUSE
拡散反射係数
GL_SPECULAR
鏡面反射係数
GL_EMISSION
発光係数
GL_SHININESS
ハイライト
GL_AMBIENT_AND_DIFFUSE
拡散反射係数と鏡面反射係数
GL_COLOR_INDEXES
インデックスカラーモード (GLUT_INDEX)のときのみ
3番目の引数
2番目の引数に対するパラメータ値です。
2番目の引数が、GL_SHININESS, GL_COLOR_INDEXES であれば1つ、それ以外は4つの要素([r, g, b, 1])を持つ配列です。
glNormal3dv(normal[j])
頂点に設定する法線ベクトルです。
glNormal(*normal[j])でも同じです。
glEnable(GL_LIGHTING)
陰影付けを有効にするために実行します。
無効にするには glDisable(GL_LIGHTING) を実行します。
陰影付けが有効になっていると、 glColor3d() などは無視されます。
glEnable(GL_LIGHT0)
0番目のライト (GL_LIGHT0) を有効にします。
このライトは必ず用意されています。
無効にして、ライトがあたらないようにするにはglDisable(GL_LIGHT0) を実行します。
glEnable(GL_LIGHT1)
1番目のライト (GL_LIGHT1) を有効にします。
glLight(GL_LIGHT1, GL_DIFFUSE, lightColor)
1番目のライトの拡散反射光色に lightColor を指定します。
glLight(GL_LIGHT1, GL_SPECULAR, lightColor)
1番目のライトの鏡面光色に lightColor を指定します。

ライトの移動

ライトの設定をどこで行なうかによって、移動•回転の仕方が変化します。

  1. glLoadIdentity()
  2. gluLookAt()
  3. glTranslated(), glRotated()
  4. glBegin(), glEnd()
1. 2. 間
ライトは視点と一緒に移動•回転
2. 3. 間
ライトの位置は、視点や図形の移動•回転によらず固定
3. 4. 間
ライトの位置は図形と一緒に移動•回転

法線描画関数

def dispNormal(vertex, face, normal):
    vers = [vertex[n] for n in face]
    v1 = [sum(x)/len(vers) for x in zip(*vers)]
    v2 = v1[:]
    v2 = [v+n for v,n in zip(v2, normal)]

    glDisable(GL_LIGHTING)
    glColor([1.0, 1.0, 1.0, 1.0])
    glBegin(GL_LINES)
    glVertex(v1)
    glVertex(v2)
    glEnd()
    glEnable(GL_LIGHTING)

上の関数をコピーして、draw関数内で以下のように呼び出す。

for j in range(0, len(face)):
    dispNormal(vertex, face[j], normal[j])

練習問題

  1. 前回の練習問題を参考にして、Maya の OBJ ファイルを読み込んで陰影表示ができるようにしてみましょう。
    ライトは、2つ以上設定してください。
    また、4キーでワイヤーフレーム表示、5でフラットシェーディング、6キーで陰影表示に切り換えることができるようにしてください。
    読み込むファイル名は、コマンドラインで指定します。
    # python pyopengl14.py cone.obj
    6 キーを押したとき

    4 キーを押したとき

    上図のOBJデータ
    (提出ディレクトリ)
    aa1001xx.py というファイル名で以下のフォルダにコピーしてください。
    Z:\10AA\プログラム技術研究4\pyopengl14

参考


Prev | Next
index | home
abetmhr@gmail.com