OpenGLとは
計算機序論2, 
www.kameda-lab.org 
2004/09/03
    
    OpenGLとは
    
      - 三次元グラフィックス・ライブラリ(二次元グラフィックスも可能) 
      
- 高速な描画が可能 
      
- ハードウェア化が比較的簡単 (SGIのワークステーション, PCのグラ 
      フィックスカード等)
      
最近ではWWW上に様々な解説が公開されていたりするので、興味のあ
    る人は自分で探して使い方を追求してみましょう。また、各関数の説
    明に限って言えば、man ページも役に立ちます。活用してください。
    (2004/09/03)
    
    描画のための基本
    
    色の指定
 
    ワイヤー, ポリゴンの色を RGB モードで指定する関数群は,
    glColor*() です. glColor*() は, glColor3f() や glColor4fv() などい 
    くつかの関数をまとめた表現です. (* には, 接尾子が付きます. )
    
    glColor3f(float r, float g, float b)
    glColor4f(float r, float g, float b, float a)
    glColor3fv(float *rgb)
    glColor4fv(float *rgba)
      : 
     
    このように, 最初の接尾子が 3 のものが, RGB の値を指定するもので 
    , 4 が, RGB に加えてα値(透過係数) も指定するものです. 2 番目の接尾 
    子は, 引数の型を指定するものです. f は float を, dは, double を 
    表します. 3番目の接尾子vが付いているものは, 配列のポインタで指定する 
    ものです.
    ワイヤーやポリゴンは, glColor*() 関数で指定した色で表示されます 
    . 色の設定は, ポリゴン単位で行う必要はなく, 再度, glColor*() 関数で 
    カレントカラーを変更するまで, 同じ色でポリゴン等を描画します.
    プリミティブ
    プリミティブとは, 基本物体のことです. OpenGL では, ポリゴンやワイ 
    ヤー・フレーム等を指します. プリミティブは, 次のような手順で表示しま 
    す. 
    
        glBegin( タイプ );
            glVertex{2,3,4}{s,i,f,d}[v] (.....);
            glVertex{2,3,4}{s,i,f,d}[v] (.....);
                   :
        glEnd();
     
    プリミティブの頂点リストの開始と終了を示す関数が, glBegin() と 
    glEnd() です. glBegin() の引数には, GL_LINES(ライン), GL_POLYGON(ポ
    リゴン)等のタイプを指定します. プリミティブの頂点を指 定する関数が
    , glVertex*() です. glColor*() の時と同じように, 引数の 種類によって
    使用する関数が異なります. glVertex*() は, glVertex2f() や 
    glVertex3fv() などいくつかの関数をまとめた表現です. (* には, 接尾子
    が付きます. )
    
    glVertex2f(GLfloat x, GLfloat y)
    glVertex3f(GLfloat x, GLfloat y, GLfloat z)
    glVertex2fv(GLfloat *coords)
    glVertex3fv(GLfloat *coords)
      : 
        
    このように, 最初の接尾子が 2 のものが, 二次元の座標(x,y)を指定す 
    るもので, 3 が, 三次元の座標(x,y,z) を指定するものです. 2 番目の接尾 
    子は, 引数の型を指定するものです. f は float であり, dは, double を 
    表します. 3番目の接尾子 v が付いているものは, 配列のポインタで指定す 
    るものです.
    なお, 頂点は glBegin() と glEnd() の間に指定しなければなりません .
    ワイヤー・フレーム
    ワイヤー・フレームとは, 物体を線(ワイヤー)で表現するものです. 単 
    純であることから描画が速く, アニメーションのプレビューなど, 速度を要 
    求される場面によく利用されます.
    GL_LINES と GL_LINE_LOOP の違いは, 終点から始点に線を結ぶかど う
    かの違いです.
    
    glBegin(GL_LINES);       /* ラインの開始宣言 */
      glVertex3fv(ax1);      /* 第1頂点を指定 */
      glVertex3fv(ax2);      /* 第2頂点を指定 */
    glEnd();                 /* ラインの終了宣言 */
    
    glBegin(GL_LINE_LOOP);   /* GL_LINES と GL_LINE_LOOP の違いは, */
      glVertex3fv(ax3);      /* 終点から始点を結ぶかどうかです.    */
      glVertex3fv(ax2);      /* GL_LINE_LOOP は終点から始点を結び  */
      glVertex3fv(ax4);      /* ます.                              */
    glEnd();
        
    ポリゴン
    ポリゴンは, あくまでも一平面ですから, ポリゴンを構成するすべての 
    頂点が,同一平面上になければなりません. もし, 同一平面上にない場合は 
    , 面が正しく表示されません. 
    
    glColor3fv(blue);       /* ポリゴン・カラーの設定 */
    glBegin(GL_POLYGON);    /* ポリゴン開始宣言 */
      glVertex3fv(v1);      /* 第1頂点    箱の一つの面は,  */
      glVertex3fv(v2);      /* 第2頂点    正方形であるから */
      glVertex3fv(v3);      /* 第3頂点    頂点が4つになり */
      glVertex3fv(v4);      /* 第4頂点    ます.            */
    glEnd();                /* ポリゴン終了宣言 */
        
    
    GLUTを使ったプログラムの流れ
    
     GLUTを使ったプログラミングでは,main関数が,似たもの
    (ほとんど同じような形式)になります.
    いったん形式を覚えておくと,ずっと使い回しができるでしょう.
    
int main (int argc, char **argv) {
  /* glutの初期化 */
  glutInit (&argc, argv);
  /* ウィンドウを開く */
  glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB); /* モード設定 */
  glutInitWindowSize (400, 400);                /* ウィンドウの大きさ */
  glutInitWindowPosition (100, 100);            /* ウィンドウの位置 */
  glutCreateWindow (argv[0]);                   /* ウィンドウの生成 */
  glClearColor (0.0, 0.0, 0.0, 0.0);   /* ウィンドウ全体を書き直すときの色 */
  glShadeModel (GL_FLAT); /* シェーディングのモデル(理解しなくて良い) */
  glutDisplayFunc (display);  /* 表示関数の登録 */
  glutReshapeFunc (reshape);  /* 画面設定関数の登録 */
  glutKeyboardFunc (keyfunc); /* キー入力処理関数の登録 */
  glutMainLoop ();            /* 実行 */
  return 0;
}
    まずは,最初から.
    
  glutInit (&argc, argv);
    
    glutの初期化をしています.「おまじない」と思って下さい。
    
  glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB); /* モード設定 */
  glutInitWindowSize (400, 400);                /* ウィンドウの大きさ */
  glutInitWindowPosition (100, 100);            /* ウィンドウの位置 */
  glutCreateWindow (argv[0]);                   /* ウィンドウの生成 */
    
    ウィンドウに関する命令です。画面の左上(100, 100)に幅400,高さ400の
    ウィンドウを開きます. このウィンドウ内にOpenGLコマンドによって
    描画することになります。
    
  glClearColor (0.0, 0.0, 0.0, 0.0);   /* ウィンドウ全体を書き直すときの色 */
  glShadeModel (GL_FLAT); /* シェーディングのモデル(理解できなくて良い) */
    
    最初の行は書き直されるときにバックの色が黒になるようにします.
    2行目は描画する際の濃淡のつけ方を指定します.
    時間があれば授業で説明しますが,
    とりあえずは,「おまじない」と思って下さい。
    
  glutDisplayFunc (display);  /* 表示関数の登録 */
  glutReshapeFunc (reshape);  /* 画面設定関数の登録 */
  glutKeyboardFunc (keyfunc); /* キー入力処理関数の登録 */
        
    この3つの関数はこの順番で実行されるというものではありません。
    あるイベントが起こったときにどの関数が実行されるかを定義しています。
    
  glutDisplayFunc(display);
    
    はウィンドウに描画イベントが起こったときに、
    display()が呼び出されるようシステムにお願いしています。
    
  glutReshapeFunc(reshape); 
    
    はウィンドウのサイズ変更が起こったときに呼び出される関数が
    rehape()であることを指定しています。
    マウスでウィンドウのサイズが変えられたりするとreshape()が呼び出されます.
    
  glutKeyboardFunc (keyfunc); 
  glutMouseFunc   (mousefunc);
    
    はキーボードやマウスによって入力があったときに呼び出される関数が,
    各々,keyfunc(), mousefunc()になるように指定しています。
    キーボードのキーが押されたときや,
    マウスのボタンが押されたり離されたりしたときにこれらの関数が呼ばれます.
     keyfunc()そのものはユーザが記述するのですが,宣言部分は
    
    void keyfunc (unsigned char key , int x, int y) 
    
    という形で引数をとらなければなりません。
    呼ばれるときには,システムによって、
    key: 押されたキーのコード(文字)と,
    x,y: キーが押された時のマウスカーソルの位置(Xウィンドウ中での位置) 
    が与えられます.
  
  
    mousefunc()は,
    
    void mousefunc (int button, int status, int x, int y)
    
    という形になります.
    buttonには,左ボタン,中ボタン,右ボタンを区別するための数が入り,
    左ボタン: button => GLUT_LEFT_BUTTON,
    中ボタン: button => GLUT_MIDDLE_BUTTON,
    右ボタン: button => GLUT_RIGHT_BUTTON
    となります.
    statusには,押されたか,離されたかを区別するための数が入ります. 
    押した場合: status => GLUT_DOWN,
    離した場合: status => GLUT_UP
    になります.
    x,y はkeyfuncと同様,マウスカーソルの位置です.
  
  
    最後に,
    
  glutMainLoop();
    
    が実行されると、プログラムはその場で無限ループを実行しはじめます。
    ループが無限にまわるあいだ、(上で行った定義に基づいて)イベントが
    起こるのを待ち続け、生じたイベントに合わせて指定された関数を
    呼び出してます。実行が済むと、また無限ループに戻ります。
    
    OpenGLのライブラリ
    実習用の計算機に標準でインストールされている 
    OpenGL 関連ライブラリには , 以下のものがあります。
    
      - GLライブラリ: 
      
- 関数名が, "gl" で始まる基本的な描画コマンド. 
      射影変換, 形状設定やライティングの設定等を行う.
      
- GLU ライブラリ: 
      
      
- 関数名が "glu" で始まるユーティリティ関数群.
       GL ライブラリ・関数を組み合わせて作られた, 有用なライブラリ .
      
- GLX ライブラリ: 
      
- 関数名が "glX" で始まる. 
      ウィンドウ操作やイベント操作に関する, 
      X Window System に依存するライブラリ. 
      利用するには, X の知識がある程度必要. 
      このライブラリは, Windows NT/95 では利用できない.
      
- GLUT ライブラリ
      
- "glut" で始まる. 
      現在標準的に使われている便利なライブラリ.
      Windows NT/95 でも利用可能であるため, 
      このライブラリを使用すれば, ほぼ同じプログラムを UNIX と 
      Windowsで動かすこと ができる.
    
この他にもOpenGLに関連した以下のような補助ライブラリが
    ありますが、授業では取り扱いません。      
      - GLUI ライブラリ:
      
- glutライブラリを用いて作られたGUI用のライブラリ.
      一般的なGUIボタンなど)だけでなく、
      トラックボールのような外見の回転用GUIなどもVer2.0から追加された.
      GLUTを元に作られているので、Windowsでも同じGUIで動かすことが
      できる。実験用計算機には標準では載っていない。
      
- AUX ライブラリ: 
      
- 関数名が, "aux" で始まるもの. 最近はほとんど使われていない.
      GLX を使わなくてもイベント処理を 行うことができる. 
      Windows NT/95でも利用可能であるため, 
      このライブ ラリを使用すれば, ほぼ同じプログラムを 
      UNIX と Windowsで動かすこと ができる. 
      複数の Window を開くことができない等の欠点がある .
      実験用計算機には標準では載っていない。
      
- TK ライブラリ: 
      
- 関数名が, "tk" で始まるもの. 
      AUX ライブラリより低レベルのライブラリであり, AUX ライブラリは, 
      この TK ライブラリで作られている.
    
ただし, OpenGL を用いてイベント操作やウィンドウ操作など, 
    複雑な処理を行うには, 結局 Xlib や Motif を使うほうがよい
    可能性もあります。
    プログラミング環境
    Mesa
    工シスサテライトのLinuxには既にOpenGL開発環境が
    インストールされている。
    これはMesa(
    http://www.mesa3d.orgと呼ばれるOpenGL互換の開発環境である。
    
    
      gl.h                            libGL.a
      glu.h                           libGLU.a
      glx.h                        
      glut.h                          libglut.a
      
    コンパイル
    
      % cc sample.c -o sample -I(OpenGL関係のヘッダディレクトリパス) -L(OpenGL関係のライブラリディレクトリパス) -lX11 -Xmu -lGL -lGLU -lgult
    
    ないしは、本授業用に用意したMakefileという設定ファイルを
    作業ディレクトリに用意した上で、
    makeコマンドを利用することもできる。
    (参照)
    
      % make PROG=sample
    
    
    より深みにハマりたい人へ
    
    C言語によるプログラミング解説については、UNIX対応を謳って
    いる解説書であれば自分に合ったものを選べばいいでしょう。
    OpenGLの参考書としては、バイブルとも呼ばれる "Opengl
    Programming Guide: The Official Guide to Learning Opengl,
    Version 1.4" (通称Open GL 赤本)があります。CG、特にリアルタ
    イム処理を意識したCGに興味があるのなら一度手に取ってみてくだ
    さい。英文ですが、それほど難しい文章ではないので、英語の勉強に
    もなります(高いですが‥)。日本語翻訳版もあります(翻訳版はバー
    ジョンが古いですが、基礎原理を学ぶだけなら支障ありません)。
Yoshinari Kameda: 2004/09/05-
Yuichi Nakamura: Fri Aug 27 18:07:24 JST 1999