1 章ではウィンドウを生成するプログラムを作りました。
今度は、ウィンドウに図形を描画するプログラムを作ってみます。
手始めに三角形を書いてみましょうか。
gl2_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.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
|
#include <GL/glut.h>
/* ディスプレイへの描画処理について記述 */
void display(void)
{
glClear(GL_COLOR_BUFFER_BIT);
glClearColor (1.0, 1.0, 1.0, 1.0); // ウィンドウの背景色(画面消去色)の設定
/* 図形の描画(三角形) */
glColor3f(0.1, 0.1, 0.8); // 図形を書く際の色を設定
glBegin(GL_TRIANGLES); // 図形の描画開始
glVertex2f(-0.9, -0.9);
glVertex2f(0.9, -0.9);
glVertex2f(0.9, 0.9);
glEnd(); // 図形の描画終了
glutSwapBuffers();
}
/* 個々のプログラム独自に行なうべき初期化 */
void myInit(void)
{
/* ウィンドウ生成前に行なうべき設定 */
glutInitWindowSize(800, 600); // ウィンドウサイズの設定
glutInitWindowPosition(200, 200); // 表示位置の設定
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE); // ディスプレイモードの設定
glutCreateWindow("OpenGL"); // ウィンドウを生成
/* イベント発生時に呼び出される関数の登録 */
glutDisplayFunc(display);
}
int main(int argc, char* argv[])
{
/* 初期化 */
glutInit(&argc, argv); // GLUT 関数を使用するための初期化
myInit(); // プログラマ定義の初期化
/* イベント待機状態に入る */
glutMainLoop(); // イベント待ち状態に入る
return 0;
}
|
実行結果はこちら。
それでは太字で示した関数の解説をしていきましょう。
- void glColor3[b, d, f, i, s, ub, ui, us] (TYPE red, TYPE green, TYPE blue)
- void glColor4[b, d, f, i, s, ub, ui, us] (TYPE red, TYPE green, TYPE blue, TYPE alpha)
図形を描画する際の色を、red(赤の割合), green(緑の割合). blue(青の割合)の3つの引数で指定する。
glColor4~ の場合は、アルファ値も指定する。
なお、glColor系列の関数のうち、どれを使用するべきかは、ここのページに関数名と引数の型名のかかれたものが箇条書きされているので、そちらを見たほうが早いと思います。
注意としては、GLbyte, GLubyte, GLshort, GLushort, GLint, GLuintで指定する場合、(型で定められた最小値)~(型で定められた最大値)の間の値で指定すること。
(例えば GLbyte なら 0 ~ 255)
また、GLfloat, GLdoubleで指定する場合は 0.0~1.0 の範囲の値で指定する必要があります。
- void glBegin(GLenum mode)
図形描画モードを開始する。
引数には、描画する図形の種類を表す定数を指定する。
引数の設定の仕方によって、描かれる図形がどう変化するかは、こちらのページを御覧ください。
glBegin の引数に用いる定数
GL_POINTS | 指定した位置に点を打つ |
GL_LINES | 指定した 2 点を結ぶ直線を引く |
GL_LINE_STRIP | 指定した順番通りに各点を通る直線を引いていく |
GL_LINE_LOOP | 指定した順番通りに各点を通る直線を引き、最後に始点と終点を結ぶ |
GL_TRIANGLES | 三角形を書く |
GL_TRIANGLE_STRIP | 三角形の 1 辺を共有しつつ、折り返しながらくっつけていく図形を書く。 |
GL_TRIANGLE_FAN | 三角形の 1 辺を共有しつつ、扇状にくっつけていく図形を書く。 |
GL_QUADS | 四角形を書く |
GL_QUAD_STRIP | 四角形の 1 辺を共有しつつ、折り返しながらくっつけていく図形を書く。 |
GL_POLYGON | 多角形を書く |
- void glEnd(void)
図形の描画を終了する。
- void glVertex2[d, f, i, s] (TYPE x, TYPE y)
- void glVertex3[d, f, i, s] (TYPE x, TYPE y, TYPE z)
- void glVertex4[d, f, i, s] (TYPE x, TYPE y, TYPE z, TYPE w)
頂点の座標を、引数で指定する。
glVertex2~の場合は(x, y)の 2 つ, glVertex3~の場合は(x, y, z)の 3 つ, glVertex2~の場合は(x, y, z, w)の 4 つ。
座標の値域は、初期設定では-1.0~1.0。
glVertex4~は「同次座標」というものを用いたい時に使うもので、w < 0 の時の動作は未定義。
まとめると、図形の描画の手順は以下のようになります。
- glBeginで図形描画モードを開始
- glVertexで、頂点を順々に指定(glBeginに渡した引数によって、描画される図形が変化)
- glEndで図形描画モードを終了
実際には、1.の前にglColorで図形の色を設定したり, 線の太さを変える事などもあるでしょう。
さて、次はもう少し発展させて、ハンマーっぽいものでも作ってみますか。
図形を組み合わせたり, 回転させたりと、前回のプログラムよりは高度なものになります。
gl2_2.c (ハンマーを表示, display関数内のみ変更)
[表示・非表示]
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.
28.
29.
30.
31.
32.
33.
34.
35.
36.
|
~インクルードファイル 変更なし~
* ディスプレイへの描画処理について記述 */
void display(void)
{
glClear(GL_COLOR_BUFFER_BIT);
glClearColor (1.0, 1.0, 1.0, 1.0); // ウィンドウの背景色(画面消去色)の設定
/* 図形の描画(ハンマー) */
glPushMatrix();
glColor3f(0.0, 0.0, 1.0);
glRotatef(45.0, 0.0, 0.0, 1.0); // ハンマー全体を回転
/* 先端の少し突き出た部分(おまけ) */
glPushMatrix();
glTranslatef(0.0, -0.75, 0.0); // 先端の突き出た部分のみを下に平行移動
glBegin(GL_TRIANGLES);
glVertex2f(0.0, 1.0);
glVertex2f(-0.1, 0.9);
glVertex2f(0.1, 0.9);
glEnd();
glPopMatrix();
/* 柄の部分 */
glRectf(-0.05, -1.0, 0.05, 0.2);
/* 打撃部分 */
glRectf(-0.3, -0.15, 0.3, 0.15);
glPopMatrix();
glutSwapBuffers();
}
~myInit 関数 変更なし~
~main 関数 変更なし~
|
実行結果はこちら。
ようやく、少しはまともなものが出来た気がします。
それでは、太字で紹介した関数の説明をしていきます。
- void glPushMatrix(void)
変換行列を「スタック」先頭へ「プッシュ」する(状態を保存)。
OpenGLでは、オブジェクト(図形)の座標データをまず定義した後、その座標データに対して、回転, 拡大・縮小, 平行移動などの操作を行なう行列(変換行列)をかけている。
glPushMatrix と glPopMatrix を使うと、座標データの状態を保存しておいたり, 取り出したりすることが出来るため、回転などの変換操作を行なう対象を制御できるようになる。
つまり、glPushMatrix と glPopMatrix の間で変換操作を行なっても、2つの関数の間の中で描画されたオブジェクトにしか、効果が適用されない。
- void glPopMatrix(void)
変換行列をスタック先頭から「ポップ」する(保存しておいた状態に戻す)。
- void glRotate[d, f] (TYPE angle, TYPE x, TYPE y, TYPE z)
回転を行なう。(実際には回転行列をかける)
TYPE は、glRotatef なら GLfloat, glRotated なら GLdouble となる。
引数は、x, y, z で原点から点(x, y, z)を通過する回転軸を設定し、angle で回転軸にしたがってどれだけ回転させるかを指定する。
- void glTranslate[d, f] (TYPE x, TYPE y, TYPE z)
平行移動を行なう。(実際には平行移動を行なう変換行列をかける)
TYPE は、glRotatef なら GLfloat, glRotated なら GLdouble となる。
なお、x, y, z の値域は、初期設定では -1.0 ~ 1.0。
- void glRect[d, f, i, s] (TYPE x1, TYPE y1, TYPE x2. TYPE y2)
長方形を描画する。
(x1, y1)は長方形左下の端点の座標, (x2, y2)は長方形右上の端点の座標を表す。
これで、回転角を10ミリ秒ごとに変化させるプログラムなんてものを書いてしまえば、もうそれだけでアニメーションが作れてしまいます。
このサイトでは、時間に関する関数は wxWidgets のものを使うため、アニメーションが行えるようになるのはまだまだ先の話です。
ですが、一足先に試してみたい方はこのページの「アニメーション」の項を参考にしてみるとよいでしょう。
ということで、このページで紹介した OpenGL 関数一覧でも。
3. 画像の表示へ