3 GLUTを使ったグラフィックス

今までのプログラムの出力は,文字のみであった.ここでは,図のOpenGLを使ったコンピュ ーターグラフィックスの基礎を学習する.

3.1 GLUTとは

GLUTを説明する前に,OpenGLを説明する必要があるだろう.OpenGLはコンピューターグラ フィックスで有名なシリコングラフィックス社が開発したコンピューターグラフィックス のAPI(Application Program Interface)である.プログラマーはOpenGLの関数をコールす るだけで,簡単にコンピューターグラフィックスの作成ができる.

OpenGLは,WindowsのDirectXと同じようなものである.DirectXはWindowsでしか使えない が,OpenGLはどのようなOSでも使える.WindowsやMacintosh,Unixでも,同じように OpenGLを使って,コンピューターグラフィックスの作成が可能である.

GLUTはOpenGLのユーティリティツールキットで,OpenGLの初期化やウィンドウ操作,イベ ント処理などを簡単に記述することができる.OpenGLを実際に使うと,結構面倒な部分が あり,それを簡単にしたものと思えば良い.

3.1.1 参考とすべきWEBページと図書

GLUTを使ったプログラムは,和歌山大学の床井浩平先生の "GLUTによる「手抜き」OpenGL入門"が大変参考になる.ここで の講義で分からないところがあれば,床井先生のWEBページを見ると良い.

また,床井先生の著書「GLUTによるOpenGL入門」 [2]も分かりやす くて良い.GLUTを使う場合,まず最初にそろえるべき書籍である.ここでの講義もこの書 籍を元に作成している.

3.2 二次元グラフィックス

いろいろ説明するよりも,実際のプログラムとその結果を見た方がわかりやすいであろう. 図2がGLUTを使って,作成したウィンドウである.そのプログラムの ソースをリスト2に示す.


   1 #include <stdio.h>
   2 #include <GL/glut.h>
   3 
   4 void draw(void);                            // プロトタイプ宣言
   5 void set_color(void);
   6 
   7 //====================================================================
   8 // main関数
   9 //====================================================================
  10 int main(int argc, char *argv[])
  11 {
  12 
  13   glutInit(&argc, argv);                    // GLUT 初期化
  14   glutInitDisplayMode(GLUT_RGBA);           // 表示モードの指定
  15   glutCreateWindow("Yamamoto's window");    // windowをタイトルを付けてを開く
  16   glutDisplayFunc(draw);                    // イベントにより呼び出し
  17   set_color();                              // 塗りつぶす色指定
  18   glutMainLoop();                           // GLUTの無限ループ
  19 
  20   return 0;
  21 }
  22 
  23 //====================================================================
  24 // ウィンドウを塗りつぶす
  25 //====================================================================
  26 void draw(void)
  27 {
  28   glClear(GL_COLOR_BUFFER_BIT);
  29   glFlush();                           // 描画
  30 }
  31 
  32 //====================================================================
  33 // 色の指定
  34 //====================================================================
  35 void set_color(void)
  36 {
  37   glClearColor(1.0, 0.0, 0.0, 1.0);  //赤緑青と透明度
  38 }


\fbox{\textgt{実行結果}}         図2のウィンドウが作成される.
図 2: リスト2のプログラムの実行結果.赤く塗りつぶされた ウィンドウが表示される.
\includegraphics[keepaspectratio, scale=1.0]{figure/red_window.eps}


3.2.1 どのように動作するか

GLUTを使ったプログラムは,イベント駆動型のプログラムになる.これまで学習してきた プログラムは,プログラムで書かれた順序通りに処理を行っていた.それに対して,イベ ント駆動型のプログラムは,イベント--キーボードやマウスの操作--によって,処理を 行う.

リスト2の例では,作成した赤く塗りつぶされたウィンドウの再描 画が必要なときに,draw()関数が実行される.たとえば,他のウィンドウに隠れて いて,それが前に出るときである.実際にその関数が実行されることを確かめることがで きる.リスト2 の27行目と28行目の間に,

	printf("function draw() has been called.\n");

を書き加える.そして,プログラムを実行させる.赤く塗りつぶされたウィンドウを操作 すると,端末に
function draw() has been called.
function draw() has been called.
function draw() has been called.
function draw() has been called.
function draw() has been called.

と表示されるであろう.再描画が必要なときに,draw()関数が呼び出されたことが 分かるだろう.

リスト2のプログラムは,無限ループglutMainLoop();の中で, イベントが起きるのを待っており,そのイベントに応じた処理を自動的に行っている.こ れを今までのプログラミングスタイルで記述するとなると大変面倒なことになる.GLUTを 使うと自動的に,イベントの処理を行う.プログラマーは,イベントと処理の内容を記述 するだけでよい.さまざまな面倒な処理は,GLUTが自動的に行うのである.プログラマー は,楽ができる仕組みとなっている.

3.2.2 Makefileをつかおう

ところで,リスト2(paint_out.c)をコンパイルして実行ファイルを 作成するためには,次のようにコマンドを打ち込む必要がある [2].
gcc -o paint_out -I/usr/X11R6/include -Wall paint_out.c -L/usr/X11R6/lib \
-lglut -lGLU -lGL -lXmu -lXi -lXext -lX11 -lm

GLUTのライブラリーを使うため,その記述が必要である.

プログラムを直す毎にこの長いコマンドを打ち込むのはうんざりする.このようなときに, makeを使う.makeについては,教科書 [1]のpp.34-36に記述しているの詳細 は述べない.また,いろいろなWEBページにも解説があるので,それを見ると良いだろう.

私がリスト2(paint_out.c)をコンパイルしたときのMakefileをリス ト3に示す.ソースファイルとMakefileを同じディレクトリーに置い て,「make」と打ち込めば,実行ファイルができる.「make clean」とすれ ば,実行ファイルを削除できる.他のファイルをコンパイルしたい場合は,Makefile中の SRCの横のファイル名を書き直せば良い.

Makefileの大体の部分は,見れば分かるであろう.注意すべきことは,行頭 に[Tab]を打ち,スペースを空けずにコマンド--リスト3では gccrm--を書くことである.[Tab]の代わりにスペースで記述してはならな い.想像がつくと思うが,#があると,そこから行末までコメント文になる.

   1 CFLAGS = -I/usr/X11R6/include -Wall
   2 LIBS = -L/usr/X11R6/lib -lglut -lGLU -lGL -lXmu -lXi -lXext -lX11 -lm
   3 SRC = paint_out.c      # ここにソースファイル名を書くだけ
   4 
   5 #---- 実行ファイルを作成するコマンド ----------
   6 $(SRC:.c=):$(SRC)
   7 	gcc -o $(SRC:.c=) $(CFLAGS) $(SRC) $(LIBS)
   8 
   9 #---- make clean で実行ファイルを削除できる --------
  10 clean:
  11 	rm $(SRC:.c=)

3.2.3 2次元図形の例

二次元グラフの作図の例を示す.いろいろな二次元グラフの作図命令は,床井さんの "GLUTによる「手抜き」OpenGL入門"2次元図形を描くを見よ.ここでは,2つの例を示すにとどめる.

3.2.3.1 折れ線による描画

GL_LINE_STRIPを使うと,頂点(vertex)を直線で結ぶ 図形を書くことができる.それを使って,グルグルを描くプログラム例をリスト 4に示す.これを見て分かるとおり,glBegin()glEnd()の間 に頂点を指定--glVertex()を使う--すれば,それらが直線で結ばれる.頂点の座 標は,glVertex(x座標,y座標)と指定する.ウィンドウの左下が$ (-1,\,-1)$で右上 が$ (1,\,1)$である.
   1 #include <stdio.h>
   2 #include <GL/glut.h>
   3 
   4 void draw(void);                            // プロトタイプ宣言
   5 void set_color(void);
   6 
   7 //====================================================================
   8 // main関数
   9 //====================================================================
  10 int main(int argc, char *argv[])
  11 {
  12 
  13   glutInit(&argc, argv);                    // GLUT 初期化
  14   glutInitDisplayMode(GLUT_RGBA);           // 表示モードの指定
  15   glutCreateWindow("Yamamoto's window");    // windowをタイトルを付けてを開く
  16   glutDisplayFunc(draw);                    // イベントにより呼び出し
  17   set_color();                              // 塗りつぶす色指定
  18   glutMainLoop();                           // GLUTの無限ループ
  19 
  20   return 0;
  21 }
  22 
  23 //====================================================================
  24 // 折れ線でグルグルを描く
  25 //====================================================================
  26 void draw(void)
  27 {
  28   glClear(GL_COLOR_BUFFER_BIT);
  29   glColor3d(0.0, 0.0, 1.0);            // 線の色指定(RGB) 青
  30   glBegin(GL_LINE_STRIP);              // 開始 頂点を直線で結ぶ
  31   glVertex2d(-0.9, -0.9);              // 頂点の指定
  32   glVertex2d(-0.9,  0.9);
  33   glVertex2d( 0.9,  0.9);
  34   glVertex2d( 0.9, -0.9);
  35   glVertex2d(-0.6, -0.9);
  36   glVertex2d(-0.6,  0.6);
  37   glVertex2d( 0.6,  0.6);
  38   glVertex2d( 0.6, -0.6);
  39   glVertex2d(-0.3, -0.6);
  40   glVertex2d(-0.3,  0.3);
  41   glEnd();                             // 終了
  42   glFlush();                           // 描画
  43 }
  44 
  45 //====================================================================
  46 // 色の指定
  47 //====================================================================
  48 void set_color(void)
  49 {
  50   glClearColor(0.9, 1.0, 1.0, 1.0);  //赤緑青と透明度
  51 }
図 3: リスト4のプログラムの実行結果.折れ線を使って,ぐるぐ るを描いている.
\includegraphics[keepaspectratio, scale=1.0]{figure/whirl.eps}

3.2.3.2 複数の図形の描画

描きたい図形の数だけglBegin()glEnd()を記 述すれば,複数の図形を描くことができる.
   1 #include <stdio.h>
   2 #include <GL/glut.h>
   3 
   4 void draw(void);                            // プロトタイプ宣言
   5 void set_color(void);
   6 
   7 //====================================================================
   8 // main関数
   9 //====================================================================
  10 int main(int argc, char *argv[])
  11 {
  12 
  13   glutInit(&argc, argv);                    // GLUT 初期化
  14   glutInitDisplayMode(GLUT_RGBA);           // 表示モードの指定
  15   glutCreateWindow("Yamamoto's window");    // windowをタイトルを付けてを開く
  16   glutDisplayFunc(draw);                    // イベントにより呼び出し
  17   set_color();                              // 塗りつぶす色指定
  18   glutMainLoop();                           // GLUTの無限ループ
  19 
  20   return 0;
  21 }
  22 
  23 //====================================================================
  24 // 折れ線でグルグルを描く
  25 //====================================================================
  26 void draw(void)
  27 {
  28   glClear(GL_COLOR_BUFFER_BIT);
  29 
  30   // ---- 三角形 ---------
  31   glColor3d(0.0, 0.7, 0.0);            // 線の色指定(RGB) 赤
  32   glBegin(GL_TRIANGLES);               // 開始 三角形
  33   glVertex2d(-0.7, -0.7);              // 頂点の指定
  34   glVertex2d( 0.0,  0.6);
  35   glVertex2d( 0.7, -0.7);
  36   glEnd();                             // 終了
  37 
  38   // ---- 四角形 ---------
  39   glColor3d(1.0, 0.0, 0.0);            // 線の色指定(RGB) 赤
  40   glBegin(GL_QUADS);                   // 開始 四角形
  41   glVertex2d(-0.7,  0.5);              // 頂点の指定
  42   glVertex2d(-0.7,  0.7);
  43   glVertex2d(-0.5,  0.7);
  44   glVertex2d(-0.5,  0.5);
  45   glEnd();                             // 終了
  46 
  47   glFlush();                           // 描画
  48 }
  49 
  50 //====================================================================
  51 // 色の指定
  52 //====================================================================
  53 void set_color(void)
  54 {
  55   glClearColor(0.9, 1.0, 1.0, 1.0);  //赤緑青と透明度
  56 }
図 4: リスト5のプログラムの実行結果.三角形と四角形の複数 の図形を描画している.
\includegraphics[keepaspectratio, scale=1.0]{figure/tri_sqr.eps}

ホームページ: Yamamoto's laboratory
著者: 山本昌志
Yamamoto Masashi
平成19年11月14日


no counter