OpenGLとは
計算機序論2,
www.kameda-lab.org
2006/09/08
OpenGLによるグラフィックス描画
- 三次元グラフィックス・ライブラリ(二次元グラフィックスも可能)
- 高速な描画が可能
- ハードウェア化が比較的簡単 (SGIのワークステーション, PCのグラフィックスカード等)
- 公式サイト:OpenGL
最近ではWWW上に公式文書を含め様々な解説が公開されているので、興味のある人は自分で探して使い方を追求してみましょう。
また、各関数の説明に限って言えば、man ページも役に立ちます。活用してください。
描画のための基本
色の指定
ワイヤー、ポリゴンの色を 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を使ったプログラムの流れ
グラフィックの描画を行うライブラリとして有名なものにOpenGLがあります。
本授業ではこれを用いますが、そのOpenGLライブラリをさらに使いやすくするために、
GLUT(GL utility)ライブラリというものも本授業では同時に使います。
ここでは、特にそのGLUTについて使い方を簡単に説明します。
ライブラリとは?
|
簡単に言えば「他の誰かが貴方のために役に立つ関数をいくつか用意してくれている」ものです。
当然、どんな関数を書いてくれたかは書いた人たちの資料を見なくてはわかりません。
多くの場合、manページにその説明があります。
OpenGLライブラリの場合、見分けやすいように関数名は全てglという2文字から始まっています。
GLUTライブラリの場合、見分けやすいように関数名は全てglutという4文字から始まるようになっています。
ライブラリで用意された関数のことをライブラリ関数と呼ぶことがあります。
|
GLUTを使ったプログラミングでは、main関数が、似たもの(ほとんど同じような形式)になります。
これまでのC言語でのプログラムとは雰囲気が違いますが、ユーザーとのインタラクションを
行うプログラミングでは時々このような形が出てきます。
いったん形式を覚えておくと、あとあと便利だと思います。
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の初期化をしています。「おまじない」と思って下さい。興味のある人は man glutInit で調べてみましょう。
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つの関数はこの順番で実行されるというものではありません。
あるイベントが起こったときにどの関数が実行されるかを定義しています。
イベントとは?
|
ここでは、ユーザがプログラムに対して引き起こした1つの簡単な動作をいいます。
ユーザが操作できるのはキーボードかマウスですから、ユーザイベントはこのどちらかを介して発生します。
他には、タイマーなどもイベントの1種と考えられます。
|
glutDisplayFunc(display);
はウィンドウに描画イベントが起こったときに、 システムに display() を呼び出してもらうようお願いしています。
なお、 display() 自体はユーザがプログラミングしておきます。
glutReshapeFunc(reshape);
はウィンドウのサイズ変更が生じたときに rehape() を呼び出してもらうように指定しておきます。
つまり、マウスでウィンドウのサイズを変えたりすると reshape() が呼び出されます。
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 の知識がある程度必要。
このライブラリは, Microsoft系OS では利用できない。
- GLUT ライブラリ
- "glut" で始まる。
GLを利用するときに現在標準的に使われている便利なライブラリ。
Microsoft系OSでも利用可能であるため, このライブラリを使用すれば,ほぼ同じプログラムを UNIX と Windowsで動かすことができる。
この他にもOpenGLに関連した以下のような補助ライブラリがありますが、授業では取り扱いません。
- GLUI ライブラリ:
- glutライブラリを用いて作られたGUI用のライブラリ。
一般的なGUIボタンなどだけでなく、トラックボールのような外見の回転用GUIなどもVer2.0から追加された。
GLUTを元に作られているので、Windowsでも同じGUIで動かすことができる。3L504の計算機には標準では載っていない。
- AUX ライブラリ:
- 関数名が, "aux" で始まるもの。
近年はあまり使われていない。
GLX を使わなくてもイベント処理を 行うことができる。
複数の Window を開くことができない等の欠点がある。
3L504の計算機には標準では載っていない。
- TK ライブラリ:
- 関数名が, "tk" で始まるもの。
AUX ライブラリより低レベルのライブラリであり, AUX ライブラリは, この TK ライブラリで作られている。
ただし, OpenGL を用いてイベント操作やウィンドウ操作など, 複雑な処理を行うには, 結局 Xlib や Motif を使うほうがよい可能性もあります。
Mesaに基づくプログラミング環境
Mesa
正確には、工シスサテライトのLinuxにはOpenGLライブラリと全く互換である
Mesa (http://www.mesa3d.org) と呼ばれるライブラリが用意されています。
ライブラリ関数の名前と機能はOpenGLと全く同じです。
gl.h libGL.a
glu.h libGLU.a
glx.h
glut.h libglut.a
コンパイル
% gcc sample.c -o sample -I(OpenGL関係のヘッダディレクトリパス) -L(OpenGL関係のライブラリディレクトリパス) -lX11 -Xmu -lXi -lGL -lGLU -lglut -lm
ないしは、本授業用に用意したMakefile という設定ファイルを作業ディレクトリに用意した上で、makeコマンドを利用することもできる。
(参照)
% make sample
より深みにハマりたい人へ
C言語によるプログラミング解説については、UNIX対応を謳っている解説書であれば自分に合ったものを選べばいいでしょう。
OpenGLの参考書としては、バイブルとも呼ばれる "Opengl Programming Guide: The Official Guide to Learning Opengl, Version 1.4" (通称Open GL 赤本)があります(Version 2.0もリリースされました)。
CG、特にリアルタイム処理を意識したCGに興味があるのなら一度手に取ってみてください。
英文ですが、それほど難しい文章ではないので、英語の勉強にもなります(高いですが‥)。
日本語翻訳版もあります(翻訳版はバージョンが古いですが、基礎原理を学ぶだけなら支障ありません)。
Yoshinari Kameda: 2004/09/05-
Yuichi Nakamura: Fri Aug 27 18:07:24 JST 1999