どこのサイトでも、初めてのコマンドラインプログラムは「Hello 〇〇!!」, GUI プログラムの場合はウィンドウの作成。
「なぜ?」と聞かれると少し困りますが、プログラムの内容自体が簡単, 結果が分かりやすい形で眼に見える、という2つの理由だと“自分”は考えています。
では本題に。
ライブラリの導入のページでも軽く書きましたが、このページでは OpenGL の学習用に「GLUT」を使います。
まず、OpenGL 用の関数には、使用するライブラリごとに関数名の先頭に特徴があります。
このサイトでは3種類だけ登場すると思います
- 先頭が gl…… となっている OpenGL ライブラリ関数。これが OpenGL 関数の基礎。
- 先頭が glu…… となっている OpenGL ユーティリティ関数。gl 関数よりも少し高水準な関数セットで、例えば曲面を描画する関数などがある。
- 先頭が glut…… となっている OpenGL ユーティリティツールキット関数。主に GUI プログラムをつくるための設定を行なう関数(ウィンドウを作ったり)のライブラリ。
ただ、GLUT はそれなりに簡単にマルチプラットフォームの GUI プログラムが作れる代わりに、
どの OS にも共通するような機能だけが用意されているため、「この機能が欲しいな……」と
思っても GLUT のライブラリには用意されていないことが多々あります。
そのため、“自分”の場合は完成版のプログラムに GLUT を使いません。
なので、GLUT については出来るだけ深い部分には踏み込まないようにはします。
glut 関数については、解説を読まずにコピペしても OK と思う。
インクルードするヘッダは、glut.h のみ。
普通は GL フォルダに入っていると思うので、GL フォルダをインクルード対象として登録しておき、GL/glut.h をインクルードすれば OK です。
gcc を使うなら makefile を書いておけば楽でしょう。
ただし、Mac OS X の場合は少し違うので、こちらの解説を見てください。
※ ちなみに glut.h の中では、 gl.h, glu.h という、gl 関数, glu 関数のライブラリを使うのに必要なヘッダファイルが既にインクルードされているので、glut.h だけで済むわけです。
ついでに注意。
OpenGL, GLUT の関数は C 言語で書かれているので、引数に関数を渡す場合、渡す側の関数が引数を取らないなら、宣言の部分できちんと「void」を明記する必要があります。C++ に慣れてしまった人は注意。
それでは、最初はウィンドウを生成するだけのプログラムのコードを。
gl1_1.c (空ウィンドウを表示するだけ)
[表示・非表示]
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
|
#include <GL/glut.h>
/* ディスプレイへの描画処理について記述 */
void display(void)
{
/* とりあえず今は空 */
}
/* 個々のプログラム独自に行なうべき初期化 */
void myInit(void)
{
glutCreateWindow("OpenGL"); // ウィンドウの生成
glutDisplayFunc(display); // 画面描画関数(自分自身で定義)をイベントとして登録
}
int main(int argc, char* argv[])
{
/* 初期化 */
glutInit(&argc, argv); // GLUT 関数を使用するための初期化
myInit(); // プログラマ定義の初期化
/* イベント待機状態に入る */
glutMainLoop(); // イベント待ち状態に入る
return 0;
}
|
実行結果はこちら
myInit の内容を main 関数に直接書けばコードの量は少し減らせますが、後々のプログラムで myInit のところに色々な設定を記述するため、蛇足かもしれませんが myInit 関数を記述しています。
さて、太字で示した関数の解説でも。
- void glutInit(int *argcp, char* argv[])
GLUT ライブラリの初期化を行なう。GLUT を使用する際には必ず必要。
一応書いておくと、main 関数の引数を「int argc, char* argv[]」とすると、argc にはコマンドライン引数の数, argv[] にはコマンドライン引数の文字列が格納されます。
なお、argv[0] にはコマンド名, argv[argc] には NULL が入っていることが保証されています。
引数には コマンドライン引数 argc のアドレスと、argv をそのまま渡してやれば大丈夫です。
-
int glutCreateWindow(char* name)
ウィンドウの生成を行なう。引数の name はウィンドウのタイトルとして使われる。
返り値にはウィンドウの id 。1 から始まる整数である。
-
void glutDisplayFunc(void (*func) (void))
ディスプレイへの描画を行なうための関数を、イベントハンドラとして登録する。
引数にはなんだかわかりにくいものが書かれていますが、これは「関数ポインタ」というものです。
関数名の後ろに「*」を付けてから()で囲んでいる以外は、普通の関数宣言の形と同じですね。
が、ここでは関数ポインタの詳しい説明は書かないので、最低限「引数, 返り値ともに void の関数の名前を、引数として渡せばいいんだ」とだけ思えば十分です。
-
void display(void)
ここにディスプレイへの描画を行なうための処理をまとめて記述しておく。
今回は空なので、真っ黒の画面が表示されているだけですが。
-
void glutMainLoop(void)
登録しておいたイベントの処理を行なうループへと入る。GLUT を使用するなら必ず必要。
どんなプログラムでも、上に挙げた 5 つの関数は使うと思うので覚えておくと楽かもです。コピペでもいいですが。
これだけでは寂しいので、もう少しいろいろな設定を加えてみましょうか。というか gl 関数、まだ紹介してないし
今度はウィンドウサイズやウィンドウの背景色を決めたりもしてみましょう。
なお、ページの1番最初のソースコードは基本的に全文を貼りますが、それ以降のプログラムコードについては、変更した部分のみを書くようにします。
gl1_2.c (ウィンドウを表示するだけだが、少し設定を加えてみる)
[表示・非表示]
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
|
~インクルードファイル 変更なし~
/* ディスプレイへの描画処理について記述 */
void display(void)
{
glClear(GL_COLOR_BUFFER_BIT); // OpenGL が使用するバッファのクリア
glClearColor(0.0, 0.0, 1.0, 1.0); // ウィンドウの背景色(画面消去色)を青に設定
glutSwapBuffers(); // バッファの入れ替え
}
/* 個々のプログラム独自に行なうべき初期化 */
void myInit(void)
{
/* ウィンドウ生成前に行なうべき設定 */
glutInitWindowSize(800, 600); // ウィンドウサイズの設定
glutInitWindowPosition(200, 200); // 表示位置の設定
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE); // ディスプレイモードの設定
glutCreateWindow("OpenGL"); // ウィンドウを生成
/* イベント発生時に呼び出される関数の登録 */
glutDisplayFunc(display); // 画面描画関数を登録
}
~main 関数 変更なし~
|
実行結果はこちら。
-
void glutInitWindowSize(int width, int height)
ウィンドウサイズの初期値を設定する。
単位は px(ピクセル) 。幅は width, 高さは height の部分に整数値(プラスの値)で指定。
何も設定しなかった場合のウィンドウサイズは、幅 300px, 高さ 300px となる。
-
void glutInitWindowPosition(int x, int y)
ウィンドウ表示位置の初期値を設定する。単位は px(ピクセル) 。
ディスプレイ左上を原点とし、横方向 x, 縦方向 y の整数値(プラスの値)で指定した位置にウィンドウの左端が表示される。
何も設定しなかった場合の表示位置は、(-1, -1) である。
-
void glutInitDisplayMode(unsigned int mode)
ディスプレイモードを設定する。まあ glut で画面表示のために使用する機能の設定だと考えてもいいでしょう。
引数には、使用するオプションを表す定数を「|」で区切りながら並べていく。
ちなみに、“自分”が使う可能性があるオプションは次の 5 つ。
glutInitDisplayMode で指定できるモード
GLUT_RGBA | RGBAカラーを使えるようにする |
GLUT_DOUBLE | 「ダブルバッファリング」を行なうようにする |
GLUT_DEPTH | 「Z バッファ」を使えるようにする |
GLUT_ACCUM | 「アキュームレーションバッファ」を使えるようにする |
GLUT_STENCIL | 「ステンシルバッファ」を使えるようにする |
ダブルバッファリングはこのページの下の方で説明します。
また、下側 3 つのオプションに関係する「〇〇バッファ」については、後々のプログラムで使うときになったら説明します。
今は、特別な機能を使うために必要な領域(つまりバッファ)を確保しておく、と考えておけばいいです。
ステンシルバッファは使わないかもだが。
-
void glClear(GLbitfield mask)
OpenGL で画面描画のために使用しているバッファのクリアを行なう。
引数には、クリアを行なうバッファを表す定数を「|」で区切りながら並べていく。
glClear の引数に用いる定数
GL_COLOR_BUFFER_BIT | カラーバッファ |
GL_DEPTH_BUFFER_BIT | Z バッファ |
GL_ACCUM_BUFFER_BIT | アキュームレーションバッファ |
GL_STENCIL_BUFFER_BIT | ステンシルバッファ |
-
void glClearColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)
ウィンドウの背景色を設定する。
値は 0.0 ~ 1.0 の小数で、引数は、R(赤成分), G(緑成分), B(青成分), A(不透明度) の順番である。
「RGB カラー」がわからない方は、こちらのページなどを参考にどうぞ。
-
void glutSwapBuffers(void)
ダブルバッファリングモードの時、ウィンドウのバッファを交換する。
「ダブルバッファリング」とは、画面の書き換えをスムーズにするため、2 個の画面描画用のバッファを使うことです。
ちなみに、「バッファ」は一時的にデータを置いておく場所のことで、便利な「そこら辺の手の届く場所」というやつです。
ようやく gl 関数も 2 つほど出てきました。
とは言え、これからは基本的に gl 関数のみを紹介していくことになります。
もちろん必要あるときには glut 関数を紹介しますが、最終的には GLUT を使わないので、あまり覚える必要はない。
この先、立方体の表示や, アニメーションのデバッグをしたい時なんかに紹介するかも。
長くなりましたが、最後にこのページで登場した OpenGL 関数の一覧を。
- glut の初期化
- ウィンドウに関する設定
- その他の glut 関数
- gl 関数
2. 図形の表示へ