OpenGL(Mesa)の最初のプログラム

Jun Mizutani 10/1/98

OpenGL自体は 3Dグラフィックライブラリですから,X上で動作するプログラムを作成するためには, その体裁を整えるために Xのプログラムがしなくてはならないウインドウの生成,初期化, キーボードやマウスのイベントの処理の面倒は見てやる必要があります.したがって,例えば Xlib を使用して3Dグラフィックの簡単な例をOpenGLで作成しても,すぐに数百行になってしまいます.

そこで GLUTライブラリが活躍します.OpenGLの外側で必要となるウインドウの初期化, イベントの処理,OpenGLを使用した基本的な立体の生成などを担当します.

Microsoft Windows 95/NT用のGLUTライブラリもあり,ウインドウシステムの差を吸収 して移植性にすぐれたプログラムを作成することができます.

GLUTライブラリを使用すると X11 のプログラムに必要な初期化などの面倒な部分が 不要になります.コメントを除けば 50行ほどで最低限のプログラムを作成できますが, 今後の拡張が容易なように若干の無駄な部分も含めたプログラムを示します. また静止画の生成ではPOV-Rayのようなレイトレーシングソフトにはかなわないので,すべて動く絵 (アニメーション)をサンプルにする予定です.

どうしても最初のうちは OpenGLではなく GLUTライブラリ等の部分の比率が多くなります. 小さなプログラムであるほど,ウインドウシステムに依存した前処理の比率が多くなるためです. 下記のサンプル中の //11111111111111111111..のような数字のコメントに 囲まれた部分は今後のサンプルで変更する可能性のある部分です.


ソース(EUC)はここです.


/* ---------------------------------------------------
  Mesa and Glut Sample glprg_01.c
          Jun Mizutani  3/1/98
  サンプルプログラム その1
      キーボードとマウス入力
      ウィンドウのサイズ変更
      アイドル時間を利用した画面の更新
 ---------------------------------------------------*/

#include <GL/glut.h>
#include <stdlib.h>

//111111111111111111111111111111111111111111111111111111111111111111
GLfloat rotation;  // 回転角
GLfloat rate;      // 回転速度

//------------------------------------------------------------------
//  このプログラム特有の初期化処理
//------------------------------------------------------------------
void Init()
{
    rotation = 10.0;
    rate = 2.0;
}

//------------------------------------------------------------------
//  このプログラム特有のアニメーション処理
//------------------------------------------------------------------
void animation()
{
    rotation += rate;
    while (rotation < 0.0) rotation += 360.0;
    while (rotation > 360.0) rotation -= 360.0;
}
//111111111111111111111111111111111111111111111111111111111111111111

//------------------------------------------------------------------
//  glutDisplayFuncで指定したコールバック関数 
//  glutPostRedisplayの後か,再描画が必要な場合に呼ばれる.
//------------------------------------------------------------------
void display(void)
{
    // カラーバッファの消去
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glLoadIdentity();             // モデルビュー行列の初期化
//222222222222222222222222222222222222222222222222222222222222222222
    glColor3f(1.0, 0.8, 1.0);     // 色の指定
    // 視線の設定(モデルビュー行列の設定)
    //        _____eye_____  ____center___  ______up_____
    gluLookAt(0.0, 0.0, 4.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
    
    // 立方体の描画
    glRotatef(rotation * 1.5, 1.0, 1.0, 1.0);
    glutSolidCube(1.2);  
//222222222222222222222222222222222222222222222222222222222222222222
    glFlush();
}

//------------------------------------------------------------------
//  glutReshapeFuncで指定したコールバック関数 
//  ウィンドウの生成時とサイズ変更時に呼ばれる.
//  視野の初期化処理
//------------------------------------------------------------------
void reshape(int w, int h)
{
    // ビューポートの設定
    glViewport(0, 0, (GLsizei) w, (GLsizei) h);
    glMatrixMode(GL_PROJECTION);  // 投影行列を指定
    glLoadIdentity();             // 投影行列の初期化
//333333333333333333333333333333333333333333333333333333333333333333
    // 視野角,アスペクト比の設定(投影行列の設定)
    // left, right, bottom, top, near, farでビューボリュームを指定
    glFrustum(-1.0, 1.0, -1.0, 1.0, 1.5, 20.0);
//333333333333333333333333333333333333333333333333333333333333333333
    // 投影行列の設定終了,この後はモデルビュー行列を使用する
    glMatrixMode(GL_MODELVIEW);   // モデルビュー行列を指定
}

//------------------------------------------------------------------
//  glutIdleFuncで指定したコールバック関数
//    他にイベントがない時(暇な時)に呼び出される.
//    アニメーション処理の定石
//------------------------------------------------------------------
void idle(void)
{
    animation();
    glutPostRedisplay(); //  glutDisplayFuncで指定した関数を呼ぶ
    glutSwapBuffers();   // glFlushが内部で呼ばれる
}

//------------------------------------------------------------------
//  glutKeyboardFuncで指定したコールバック関数
//  key には ASCIIコードが設定される
//  x, y にはキー入力時のマウス座標が設定されている
//------------------------------------------------------------------
void keyboard(unsigned char key, int x, int y)
{
//444444444444444444444444444444444444444444444444444444444444444444
    switch(key) {
        case 27  : exit(0); break;               // ESC キーで終了
        case 'z' :
        case 'Z' : rate -= 1.0; idle(); break;
        case 'X' :
        case 'x' : rate += 1.0; idle(); break;
    }
//444444444444444444444444444444444444444444444444444444444444444444
}

//------------------------------------------------------------------
//  glutMouseFuncで指定したコールバック関数
//  button : GLUT_LEFT_BUTTON,GLUT_MIDDLE_BUTTON,GLUT_RIGHT_BUTTON
//  state  : GLUT_UP, GLUT_DOWN
//  x, y にはウィンドウを基準としたマウス座標が設定されている
//------------------------------------------------------------------
void mouse(int button, int state, int x, int y)
{
//555555555555555555555555555555555555555555555555555555555555555555
   // 修飾キー(Shift,Ctrl,Alt)の状態取得方法
   int m = glutGetModifiers();
   switch(m) {
      case GLUT_ACTIVE_SHIFT : /* Shift */  break;
      case GLUT_ACTIVE_CTRL :  /* Ctrl  */  break;
      case GLUT_ACTIVE_ALT :   /* Alt   */  break;
   }
//555555555555555555555555555555555555555555555555555555555555555555
}

//------------------------------------------------------------------
//  光源の設定 
//------------------------------------------------------------------
void LightSource()
{
//666666666666666666666666666666666666666666666666666666666666666666
    GLfloat mat_specular[] =   { 0.0, 1.0, 0.0, 1.0 };
    GLfloat mat_shininess[] =  { 90.0 };
    GLfloat light_position[] = { 1.0, 1.0, 4.0, 0.0 };
    GLfloat light_ambient[] =  { 0.0, 0.0, 0.5, 1.0 };
//666666666666666666666666666666666666666666666666666666666666666666

    glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
    glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);
    // 0番光源の位置指定
    glLightfv(GL_LIGHT0, GL_POSITION, light_position);
    // 環境光の指定
    glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient);
    // 照明を有効に
    glEnable(GL_LIGHTING);
    // 0番光源を有効に
    glEnable(GL_LIGHT0);
   // デプスバッファを有効に
   glEnable(GL_DEPTH_TEST);
}

//------------------------------------------------------------------
//  メイン関数
//  
//------------------------------------------------------------------
int main(int argc, char** argv)
{
    Init();
//777777777777777777777777777777777777777777777777777777777777777777
    // デフォルトのウィンドウサイズを指定
    glutInitWindowSize(480, 360); 
    // デフォルトのウィンドウ位置を指定
    glutInitWindowPosition(100, 100);
//777777777777777777777777777777777777777777777777777777777777777777
    // GLUTライブラリの初期化,-display等のオプションの処理
    // glutInitが認識したオプションはargc, argvから除かれる.
    glutInit(&argc, argv);
    // ディスプレイモードの指定,ダブルバッファ,デプスバッファ,
    // アキュムレイトバッファ,ステンシルバッファ付のウィンドウなど.
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
    // ウィンドウ名を指定してウィンドウ生成
    glutCreateWindow(argv[0]);
//888888888888888888888888888888888888888888888888888888888888888888
    // ウィンドウの背景色を指定
    glClearColor(0.3, 0.3, 0.1, 0.0);
//888888888888888888888888888888888888888888888888888888888888888888
    // 光源の設定
    LightSource();
//999999999999999999999999999999999999999999999999999999999999999999
    // シェイディングモードを指定
//    glShadeModel(GL_SMOOTH);
    glShadeModel(GL_FLAT);
//999999999999999999999999999999999999999999999999999999999999999999
    // 再描画が必要な場合に呼び出す関数を指定
    glutDisplayFunc(display);
    // ウィンドウサイズが変更された場合に呼び出す関数を指定
    glutReshapeFunc(reshape);
    // イベントがないアイドル時に呼び出す関数を指定
    glutIdleFunc(idle);
    // キー入力された場合に呼び出す関数を指定
    glutKeyboardFunc(keyboard);
    // マウスボタンイベント発生時に呼び出す関数を指定
    glutMouseFunc(mouse);
    // GLUTのメイン関数,指定したコールバック関数を呼び出す
    glutMainLoop();

    return 0;
}

上記のサンプル中で gl で始まる関数はOpenGLの関数,gluで始まる関数はOpenGLのユーティリテイ関数, glut で始まる関数は GLUTライブラリの関数です. メイン関数中の最後の glutMainLoop()は呼び出すとプログラムの終了まで無限ループする関数です.

glutMainLoop()の前にある以下の関数は,

メイン関数中では何もしませんが,マウス,キーボードなどのイベント が発生した場合に glutMainLoop()の内部から呼びだす関数を登録するための関数です.


[CONTENTS] [PREVIOUS] [NEXT]

[HOME]


ご意見・ご感想は,mizutani.jun@nifty.ne.jp まで.