具体的な図形の描き方は、glBegin()
で今から何をどんな描き方をするか指定し、次にglVertex*
を使って必要なだけ頂点座標を定義して、glEnd()
を呼ぶという方法になります。
1つの図形を書くため複数の関数を使うのは面倒に思えますが、このやり方だとどんな図形でもすっきりと書けるはずです。
glBegin(GL_TRIANGLES);
glVertex2f( 0.0, 0.5);
glVertex2f(-0.5, -0.5);
glVertex2f( 0.5, -0.5);
glEnd();
上の例では、三角形を描くために glBegin()
にGL_TRIANGLES
という引数を与え、三角形ですから最低3つの頂点位置を定義しました。 この頂点数はいくらでも定義できます。
しかし、引数で示された図形を描くために、示された頂点座標を順に使っていきます。たとえば先の例で頂点数が6つ定義されていれば、定義した順番に最初の3つの頂点を利用した三角形と、次の3つの頂点を利用した三角形が独立して描かれます。
このglBegin
の引数の種類を説明します。
GL_POINTS
頂点(点)を指定された座標にぽつんと描きます
GL_LINES
二つの頂点を結ぶ独立した線分を描きます、頂点数が6だとすると、1-2、3-4、5-6という3つの線分です。
GL_LINE_STRIP
頂点を順次結んでいく直線を描きます 頂点数が6だとすると、1-2-3-4-5-6という折れ線になります。
GL_LINE_LOOP
頂点を順次結んでいく直線を描くのはGL_LINE_STRIP
と変わりません。しかし、最初の頂点と最後の頂点も結び、多角形になります頂点数が6だとすると、1-2-3-4-5-6-1という多角形です。
ここまではいわゆる「ポリライン」です。以降が「ポリゴン」になります。
GL_TRIANGLES
独立した三角形を描き、内部を塗りつぶします頂点数が6だとすると、1-2-3、4-5-6という独立した2つの三角形です。
GL_TRIANGLE_STRIP
連続した三角形を描き、内部を塗りつぶします。解りにくいかも知れませんが 頂点数が6だとすると、1-2-3、2-3-4、3-4-5、4-5-6という3つの三角形です。
GL_TRIANGLE_FAN
三角形で扇形を描き、内部を塗りつぶします。頂点数が6だとすると、1-2-3、1-3-4、1-4-5、1-5-6という頂点1を中心とした複数の三角形で扇形を描こうとします。
GL_QUADS
独立した四角形を描き、内部を塗りつぶします 頂点数が8だとすると1-2-3-4、5-6-7-8の四角形を描きます。 ただし、図形の一部が凹んだような図形は描けません。
GL_QUAD_STRIP
ほぼ、GL_TRIANGLE_STRIP
と同じ事になります。すなわち、1-2-3、2-3-4でひとつの四角と見なすことができますが、2-3が対角線として描かれます。この2-3の部分が見えなくなります。
GL_POLYGON
任意の数の頂点を持った多角形を描き、内部を塗りつぶします。ただし、図形の一部が凹んだような図形は描けません。
GL_QUADS
やGL_POLYGON
で描けない図形がありますが、これを解決するためのひとつの方法として、図形を三角形や四角形で分割して描く方法があります。
頂点を定義する関数としてglVertexが出てきましたが、これらはglVertex2d
, glVertex2f
, glVertex2i
, glVertex2s
, glVertex3d
, glVertex3f
, glVertex3i
, glVertex3s
, glVertex4d
, glVertex4f
, glVertex4i
, glVertex4s
, glVertex2dv
, glVertex2fv
, glVertex2iv
, glVertex2sv
, glVertex3dv
, glVertex3fv
, glVertex3iv
, glVertex3sv
, glVertex4dv
, glVertex4fv
, glVertex4iv
, glVertex4sv
と色々な種類があります。
後ろにある2d
,2f
,3d
の意味はそれぞれ
x
, y
3だと x
, y
, z
d
だとdouble
, f
だとfloat
, V
はその型をもつ配列(VectorのV)になります。
三次元空間や二次元平面上に描画したオブジェクトを,次は実際にPCの画面上で表示する必要があります.そのためには,まず,実際のウインドウ環境を設定します.
glfwOpenWindow(width, height, red, green, blue, alpha, depth, stensil, flags)
glfwOpenWindow(640, 400, 0, 0, 0, 0, 0, 0, GLFW_WINDOW)
width
, height
: ウインドウのX軸ドット数,y軸ドット数red
, green
, blue
: 背景色をそれぞれの原色強度で定義.0,0,0で黒,1,1,1で白alpha
: αバッファのビット数(ここでは扱いません)depth
: depthバッファのビット数(ここでは扱いません)stensil
: stensilバッファのビット数(ここでは扱いません)flags
: GLFW_WINDOW
でウインドウをデスクトップウインドウとして開く次に,OpenGLではある座標空間内にある図形を,どういう位置からどういう方法で眺めるのかを自由に設定できます.
まず.どういう位置から図形をカメラで見ているというのを定義する必要があります.たとえば,カメラが動いてもオブジェクトに近づいても,オブジェクトが動いてカメラに近づいても,結果的には同じ絵になります(背景を除く).
言い換えると,カメラが動いてもオブジェクトが動いても,絵は変化します.このカメラと図形の相対位置をまとめて変化させるのがモデルビュー変換になります.
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
カメラとモデルの位置関係を示す変換行列設定をする.以下を指定しないと特に特別な変換はしない,デフォルトのまま
glScaled(0.4, 0.4, 0.4);
各座標軸上でのオブジェクトの倍率,いわゆるカメラと図形を近づける,遠ざける.1以上で拡大,1以下で縮小,-1で線対称に変換
glTranslated(-100.0, -100.0, 0.0);
各座標軸でのオブジェクトの平行移動量,カメラか図形を横方向,縦方向にずらしてから見る.
glRotated(15.0, 0.0, 0.0, 1.0)
最初は回転角度,次3つが回転方向を示すためのx, y, zベクトル.原点からこの点を通過する直線を軸として,左回りに回転する. カメラか図形を回転させて見ている.
次に,どういう方法でというのは,コンピュータ内で三次元的に図形を配置していても,PCの画面は二次元ですから,当然,カメラで撮影した写真のように二次元平面上に投影した形でしか見ることができません.これを射影と呼びます.自然の摂理では,遠くのものは小さく,近くの物は大きく見えます.これを遠近法だとか,透視射影と呼びます.もうひとつは正射影とよばれる遠近をまったく考慮しない投影法です.これら平面への写り方を定義するのが投影変換行列です.
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
投影法の変換行列設定をする.
glOrtho(0, 640, 0, 400, -1.0, 1.0);
使用するのは投影変換行列のうちの正射影用の変換行列(今回は二次元平面なので,遠近を全く考慮しないこの方法です)を使用します.
glOrtho(0, 640, 0, 400, -1.0, 1.0);
この0から640までと,0から400までの座標を平面に投影する
glOrtho(0, 640, 0, 400, -1.0, 1.0);
Z軸(奥行き方向)の座標をどこまで投影するかを設定する.今回は平面で関係ないので,デフォルトである-1から1までを指定してある.こうして定義された,「空間が投影されている平面」ができました.
この平面を一番最初に定義した実際のウインドウ上に表示させれば,我々が見る図形が決定します.これをビューポート変換といいます.
これには以下の方法を用います.
ビューポートの物理的な大きさ(画面上の縦横ドット数)を設定しなければなりませんが,今回は一番最初に定義したウインドウの大きさをそのままビューポートの大きさとします.これを行うためには,次の関数を用いて,開いているウインドウの縦横のドット数を取得します.
glfwGetWindowSize(x, y);
取得できたら次の関数を用いてビューポートの大きさを設定します.
glViewport(0, 0, x, y);
これが一般的ですが,たとえば開いているウインドウの一部分だけ,あるいはウインドウの大きさを超えてビューポートを開くこともできます.
最後に,ここで使用している座標系はすべて左下隅が0,0に対応することを覚えておいてください.以上で,図形を描画する準備ができました.
さて、いよいよ画面に表示させます。
OpenGLの図形描画では,図形が描画されるバッファとよばれる領域が2つ用意されています.このうちどちらか一方はPC上に表示されており,もう一方は表示されていません.表示されている方をフロントバッファ,表示されていない方をバックバッファと呼びます.さらにこのふたつのバッファは瞬時に入れ替える事ができます.すなわち今までバックバッファだったものをフロントバッファに,フロントバッファだったものをバックバッファにできます.この仕組みを利用してアニメーションができます.
glClearColor(r, g, b, a);
glClear(GL_COLOR_BUFFER_BIT);
バッファの初期化設定をします.r, g, bの値をそれぞれ0-1の間で定義して色をつくります.aはα値ですが,これは色の混合を行うときに用いますが,今回は使用しませんので0を指定します.この後,実際にglClear
でバッファを初期化しています.
この後は先に述べたような方法で図形を描いていくわけですが,これはすべてバックバッファに描かれます.すなわち描き終わってもそのままでは表示されません.これを表示させる,すなわちフロントバッファとバックバッファを入れ替えるために,以下の関数を実行します.
glfwSwapBuffers();
これで,図形が表示されました.あとはこの動作の繰り返しです.