削除された内容 追加された内容
ゲームプログラミングからOpenGLに関する部分を分割しました。
 
GL_MODELVIEW行列、 GL_PROJECTION行列などの説明を追加しました。
65 行
ここで,グラフィックボードなどの機器が用意できないなどの理由で全ての計算をCPUに行わせる場合のことを述べます.この場合は基本的にグラフィックボードが提供する機能を1つ1つプログラムしていくことになります.残念な事に,この場合のプログラムは更に高度([[w:3D]]レンダリング、[[w:レイトレーシング]]などを参照)になり,自力で全てを実装することは困難です.また、必要となるプログラムの量も多いため,いずれにしろそれらを書くことは時間がかかる作業となります.実際には,このような場合には[[w:en:Mesa 3D]]などのライブラリを使うのが1つの手段です.Mesaは、OpenGLが提供する機能を実際にプログラムしたもので、1つ1つプログラムする手間が省けます.Mesaは[[w:オープンソース]]ライセンスで配布されているので自由に手に入れて使うとよいでしょう.<!-- Mesaの作者はすごい。 -->
 
ここまでで3Dの計算を行う方法について述べました.ここでは実際にOpenGLのプログラムを扱います.OpenGLのチュートリアルはWeb上で公開されているので,紹介します.(OpenGL Redbook http://fly.srk.fer.hr/~unreal/theredbook/ )また、OpenGLの詳細な規定は、http://www.opengl.org/documentation/specs/ で入手できます。
 
OpenGLを利用して計算を行うのですが、OpenGLが行うのはあくまで計算であり,画面への描画では無いことに注意が必要です.画面への描画はOpenGLでの計算結果に従って描画を扱うプログラムが行います.Linuxでは描画は[[w:X Windows System]]が行い,Mac OS Xでは、[[w:quartz]]が行います.そのため、結果の描画を行うためには,描画を行うプログラムに,OpenGLを利用することを知らせる必要があります.
107 行
このプログラムを実行すると,黒い背景の中に白い3角形が描かれるはずです。
:[[画像:gl_tri.png]]
 
上のプログラムの結果を説明するにはいくつかの事柄を説明する必要があります。まず、上のプログラム内で,
glBegin(), glEnd()
という関数が使われています。この関数はその中で指定された事柄(主に頂点に関する事柄)を記録させます。記録できる事柄は頂点の位置や色などがあります。頂点の位置を指定するには
glVertex3f()
を使うことができます。ここでこの関数名はOpenGLに特徴的な事柄をいくつか含んでいます。最後の3fがそれでこれはそれぞれこの関数が"3つ"の引数を取ることと、その型が"GLfloat"であることです。ここでGLfloatはほとんどの場合float型のtypedefになっています。これ以降にもこの種の関数名は何度か出てきます。glVertex3fは、3つの引数によってそれぞれ3次元の座標を指定します。<!-- この関数はglBeginとglEndの間でしか使えません。 -->
 
さて、ここまでで上のGLプログラムの1-5行が、3つの座標を指定したことがわかります。実際にそれらの座標をどう使うかについてはglBegin()の引数が使われます。ここではGL_LINE_LOOPを使ったので,指定された座標は指定された順に直線でつながれます。
 
ここまでで、上のプログラム中で座標(0,0,0),(0,1,0),(0,0,1)が指定され,これらが直線でつながれることがわかりました。これは3次元中で3角形を描くことがわかります。次の問題は,この三角形がどのようにディスプレイに投影されるかです。
 
OpenGLは3次元中に指定された座標の2次元中での位置を定めるために2つの行列を利用します。ここで、OpenGLでは行列を"扱う"場所は1つしか用意しなくてもいいことが定められています。もちろん、値を保存しておく場所は複数あるのですが,これらの値を変更するのに使う領域は1つです。そのため、これらの行列を使い分けるには,これらを所定の場所に呼び出す必要があります。ここで行列を指定するには,glMatrixMode()関数を使います。この関数は1つの引数を取り、その値で行列を指定します。2次元中での位置を指定するのに使う行列はそれぞれGL_MODELVIEW, GL_PEROJECTIONで指定されます。これらの行列の初期値は4x4の[[w:単位行列]]です。また、実際に使われるのはこれらの積であるので,値を変更するのは片方の行列だけでもあらゆる変換を指定することは可能です。<!-- 意味があるかはわからないが ... 。 -->
 
ここで2つの行列のそれぞれについてその性質を述べます。GL_MODELVIEW行列はそれぞれの頂点の座標を変更するのに利用します。実際にはこの行列は
glRotatef(), glScalef(), glTranslatef()
の3つの関数から利用されます。 これらの関数は順に,座標を"回転", "拡大縮小", "平行移動"します。
*例
 
次に、GL_PROJECTION行列について述べます。OpenGLでは、頂点の座標についてこれらの行列をかけた後(-1, -1, -1), (1,1,1)で指定される立方体内にある図形を描きます。このため、例えば(0,0,10)にある図形は一般には描かれません。しかし、図形を3次元中に描くときの事情で、これらの位置を自由に指定できないと不便です。GL_PROJECTION行列は"描画される範囲を広げる"目的で利用されます。また、この行列は、"遠くにあるものほど小さく見える"という状況を扱うためにも利用されます。
 
まず、"描画される範囲を広げる"場合について行列の指定の仕方を説明します。実際には範囲を広げているのでは無く,"(-1,-1,-1)(1,1,1)内に入るように、遠くにあるものを近くに持ってきている"のが正しいのですが、どちらにしろ結果は同じです。これを指定するにはglOrtho()関数を利用します。glOrtho関数は6つの引数を取り,それぞれ描画する立方体(一般には直方体)を指定する座標を取ります。引数は順に
glOrtho(left, right, bottom, top, near, far)
と呼ばれ,描画される直方体は(left, bottom, near)(right, top, far)で指定されます。このとき、glOrthoを利用しないときは
glOrtho(-1, 1, -1, 1, -1, 1)
が指定されたときと同じ結果になることがわかりますが、実際にはこの指定は4x4の単位行列を返すので指定を省略したときと結果は同じになります。対応する行列は
*行列
となります
 
次に、"遠くにあるものほど小さく見える"の場合について説明します。これを指定するためには,いくつかの変数が必要になります。まず、"物体を観察するもの"が(0,0,0)にあるとします。次に,遠くの物体が縮小される割合を指定します。これは、投影された後のx座標とy座標に対応して2つのパラメータが必要です。更に,見える方向がz方向で無い場合を扱うために2つのパラメータが必要となります。最後に,上で指定した角度の方向に実際に描画するz座標の範囲を指定します。これらを全て指定すると、描画される領域は角錐([[w:en:frustum]])になります。
*図
実際にこの領域を指定するにはglFrustum関数を利用します。glFrustum関数は6つの引数を取りますが,それぞれの引数は
glFrustum(left, right, top, bottom, near, far)
で与えられる名前をもっており、縮小される割合を定める四角形がl, r, t, b、四角形の位置がn、描画される範囲がfで定められます。glFrustumで与えられる行列は
*行列
です。<!-- この行列がどのように上で解説した変換を行うかを次に説明します。 -->