はじめての OpenGL
OpenGL Utility Toolkit
OpenGL はシステムに依存しないレンダリングサービスを提供しています
しかし、ウィンドウを表示せずにグラフィックを描画することはできません
その部分はどうしても、システムに依存したコードを書かなければならないことになります
この問題は OpenGL Utility Toolkit、通称 GLUT を用いることで解決することもできます
システムの能力を発揮させるためには GLUT は役不足ですが
こうした解説の場で、システムに依存しないコードを書くためには十分です
この講座では、ソースが特定のシステムに依存しないようにするために GLUT を使います
GLUT は Mark Kilgard 氏が作成したウィンドウ・ツールキットです
すでに多くの環境に移植されており、Web から無料で手に入れることができます
これを使えば、ウィンドウの生成やイベント処理を抽象化することができます
Web から GLUT を入手し、各種システムに応じてライブラリをインストールしてください
OpenGL のコマンドには一定の命名規則が設けられています
まず、OpenGL コマンドはすべてが "gl" ではじまります
定義済み定数は GL_ ではじまり、すべてが大文字となります
また、OpenGL は従来の C 言語の標準型に対して typedef 名を定義しています
OpenGL の型と C 言語の型は次のような対応になっています
データ型 | C 言語 | OpenGL |
8ビット整数 | signed char | GLbyte |
8ビット符号なし整数 | unsigned char | GLubyte, GLboolean |
16ビット整数 | short | GLshort |
16ビット符号なし整数 | unsigned short | GLushort |
32ビット整数 | int, long | GLint, GLsizei |
32ビット符号なし整数 | unsigned int, unsigned long | GLuint, GLenum, GLbitfield |
32ビット浮動少数 | float | GLfloat, GLclampf |
64ビット浮動少数 | double | GLdouble, GLclampd |
OpenGL のコマンドは OpenGL で定義されている型を用いるので慣れる必要があります
OpenGL のコマンドや定義済み定数を使うには GL.H ヘッダファイルをインクルードしてください
ウィンドウを表示させるには GLUT を初期化しなければなりません
GLUT の初期化には glutInit() 関数を使います
void glutInit(int *argcp, char **argv);
argcp には main() 関数の argc パラメータへのポインタを
argv には main() 関数の argv パラメータへのポインタを指定します
これらの値は変更される可能性があります
次に、ウィンドウの位置とサイズを設定しましょう
ウィンドウの位置は glutInitWindowPosition() 関数で
サイズは glutInitWindowSize() 関数で設定します
void glutInitWindowPosition(int x, int y);
void glutInitWindowSize(int width, int height);
x にはウィンドウの X 座標を、y には Y 座標をそれぞれ指定します
width にはウィンドウの幅を、height には高さを指定します
これらの値は、ピクセル単位です
最後に、GLUT のディスプレイモードを設定します
ウィンドウモードは、ウィンドウのカラーモデルやバッファの設定を行うためのものです
これには glutInitDisplayMode() 関数を使います
void glutInitDisplayMode(unsigned int mode);
mode にはディスプレイモードを示すフラグの組み合わせを指定します
ここには、次のいずれかの定数を組み合わせて指定することができます
定数 | 解説 |
GLUT_RGBA | RGBA モード GLUT_RGBAも GLUT_INDEX も記述されないときのデフォルト |
GLUT_RGB | GLUT_RGBA と同じ |
GLUT_INDEX | カラーインデックス モード GLUT_RGBAも記述された場合,上書きする |
GLUT_SINGLE | シングルバッファ モード GLUT_DOUBLE もGLUT_SINGLEも記述されていない場合の デフォルトである |
GLUT_DOUBLE | ダブルバッファ モード GLUT_SINGLE も記述されていた場合,上書きする |
GLUT_ACCUM | アキュムレーション バッファ |
GLUT_ALPHA | カラーバッファにアルファ成分を加えること |
GLUT_DEPTH | デプス(Z)バッファを加えること |
GLUT_STENCIL | ステンシル・バッファを加えること |
GLUT_MULTISAMPLE | マルチサンプリングのサポート マルチサンプリングが利用できない場合は無視される ※マルチサンプリングを可能とするためには,OpenGL の クライアントとサーバーの両方が GLX_SAMPLE_SGIS エクステンションをサポートしていなければならない |
GLUT_STEREO | ステレオ・ウィンドウビットマスク |
この場では、デフォルトの GLUT_RGBA | GLUT_SINGLE を用いるため
glutInitDisplayMode() は必須ではありません
初期化が終われば、いよいよウィンドウの生成に取り掛かります
ウィンドウを作るには glutCreateWindow() 関数を呼び出します
この関数は、トップレベル ウィンドウを生成します
int glutCreateWindow(char *name);
name には、ウィンドウの名前を示す ASCII 文字列を指定します
関数は、他の関数で利用することができるウィンドウの識別子を表す数値を返します
ただし、この関数を呼び出した時点では、まだウィンドウは表示されません
プログラムは最後に glutMainLoop() 関数を呼び出します
この関数は、GLUT がイベント処理ループに入ることを表します
この関数を呼び出せば、トップレベル ウィンドウが破棄されるまで処理は戻ってきません
しかし、これだけではウィンドウが処理するべき基本的な処理を実現することができません
ウィンドウ領域が再描画されようとした時 GLUT は何をすればよいのかわからないでしょう
Windows プログラムで言うならば、ウィンドウ プロシージャが必要なのです
そこで、GLUT はコールバック関数を登録することでイベントを処理します
最低限、作らなければならないコールバック関数は、ディスプレイ コールバックです
この関数は、ウィンドウの再描画が必要であると判断された時に呼び出されます
ディスプレイ コールバックの登録は glutDisplayFunc() 関数を使います
void glutDisplayFunc(void (*func)(void));
func には、登録するディスプレイ コールバック関数へのポインタを指定します
ディスプレイ コールバックは表示されるどんなウィンドウにも登録されなければなりません
ディスプレイ コールバックを持たないウィンドウを表示しようとすれば、エラーが発生します
また、glutDisplayFunc() 関数に NULL を渡すことはできません
これは、いかなる方法でもディスプレイ コールバック関数を解除する方法がないことを表します
ディスプレイ コールバック関数では、少なくともウィンドウをクリアする必要があります
ここではじめて OpenGL コマンドを利用することができます
OpenGL では、すべてのピクセルの情報を保存する領域をバッファと呼び
ピクセルに関する1ビットの情報を保存するバッファをビットプレーンと呼びます
ビットプレーンには、RGBA か、カラー参照テーブルを参照する値が保存されます
多くの場合は、加法混色にアルファ値を加えた RGBA が用いられます
バッファのクリアには glClear() 関数を呼び出します
この関数は、指定したバッファを特定の色で消去してくれます
void glClear(GLbitfield mask);
mask には、現在の消去値でクリアする対象バッファを指定します
ここには、次の定数の組み合わせを指定することができます
定数 | 解説 |
GL_COLOR_BUFFER_BIT | カラー バッファ |
GL_DEPTH_BUFFER_BIT | デプス バッファ |
GL_ACCUM_BUFFER_BIT | アキュムレーション バッファ |
GL_STENCIL_BUFFER_BIT | ステンシル バッファ |
それぞれのバッファの役割や使用方法は後ほど解説します
この場では glClear() 関数を用いれば、バッファを初期化できることを知ってください
バッファを初期化するカラー情報は glClearColor()< 関数で指定できます
void glClearColor(
GLclampf red , GLclampf green ,
GLclampf blue , GLclampf alpha
);
red には赤、green は緑、blue は青、alpha はアルファ値そ指定します
これらは 0% 〜 100% の状態を float 型の 0.0 〜 1.0 で表します
すべてが 0 であれば黒であり、1 であれば白い状態になります
この場ではアルファ値を有効にしていないため、混合処理以外では alpha には 0 を指定しましょう
さて、これでバッファを初期化できるようになりました
デフォルトのディスプレイモーでは、単一のカラーバッファが用いられています
そこで、glClear() 関数には GL_COLOR_BUFFER_BIT 定数を指定します
#include <windows.h>
#include <GL/gl.h>
#include <GL/glut.h>
void disp(void) {
glClearColor(1 , 1 , 1 , 0);
glClear(GL_COLOR_BUFFER_BIT);
}
int main(int argc , char ** argv) {
glutInit(&argc , argv);
glutInitWindowPosition(100 , 50);
glutInitWindowSize(200 , 100);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGBA);
glutCreateWindow("Kitty on your lap");
glutDisplayFunc(disp);
glutMainLoop();
return 0;
}
このプログラムは GLUT と OpenGL を使ったウィンドウプログラムです
最初の #include は、実行するウィンドウシステムに応じて適切なヘッダを指定します
インクルードするべきヘッダファイルなど、細かい部分はシステムに依存します
この場合、main() 関数でトップレベル ウィンドウを初期化し、表示しています
その後、glutDisplayFunc() 関数で disp() 関数をディスプレイ コールバックとして登録し
glutMainLoop() でイベント処理に入っています
disp() 関数は、単純にウィンドウを白で消去しています
そうしなければ、ウィンドウが無効化されても、その部分が更新されません