コンピューターグラフィックスC

コンピューターグラフィックスS
第13回 OpenGL演習(3)
システム創成情報工学科 尾下真樹
今日の内容
• 試験とレポート
• OpenGL演習
– 文字の描画
– テクスチャマッピング
• より高度な演習
• 昔の演習問題の解答(確認)
試験とレポート
スケジュール
• 7/30(月) 5限目 試験
• 8/22(水) レポート提出締め切り
– 8/14 → 8/22に延長 (8/13~8/17は情報科学セン
タが休みのため)
• 成績は、レポート締め切り終了後、なるべく
早く公開予定
• レポートの大まかな点数とコメントを個別に
公開する予定
– レポート提出と同じシステム上で個別に提示
レポートに関する連絡
• 提出締め切り
– 8/22(水) 17:00
• 講義のページから提出
– ファイル形式を守ること
– 提出後は、自分でダウ
ンロードして表示できる
ことを確認すること
• 読めないファイルを提出
しても評価しない
– 締め切りまで修正可能
レポートに関する注意
• ファイル形式
– c のソースファイル(拡張子 c または cpp)
– 必ずコンパイルできるファイルを提出すること
• 提出後のファイルをダウンロードして、コンパイルでき
ることを確認すること
• レポート
– 必ず、レポートの説明とプログラムが一致してい
ること (変換行列の計算)
– 他人のレポートやプログラムを、たとえ一部でも
丸写ししているものは不可(0点)
– 個別に試問等を行う場合がある
試験
• 教科書・ノートなどの持込は不可
• 出題範囲
– 講義で取り扱った内容全て
– 重要な概念を理解しているかどうか、アルゴリズ
ムや考え方を理解しているかどうかを問う問題
を出す
– 演習問題・過去問や講義資料を眺めておくだけ
では不十分だと思われるので注意
• 講義資料は、あくまで講義の補助資料なので、講義
の説明をきちんと聞いて理解していなければ、後から
資料だけ見ても理解できない
成績判定と再試験
• 成績判定(シラバス通り)
– 演習レポート 50点+試験 50点
+毎回の演習問題・課題(20点)
• 再試験は基本的に行わない(シラバス通り)
– もし、再試験を行う場合は、
• 全員受験可能とする
• 本試験と同じ難易度の問題を出す
• 試験点は、再試験の点数に80%をかけたものとする
– 再試験・レポート再提出等を場合は、夏休み~
再試期間中に連絡する
• いちいち個別に質問に来ないこと
文字の描画
文字の描画
• プログラムでは、何らかの情報を表示するた
め、画面に文字を表示したいことがある
• Windowsでは、Win32 API の GDI を使用
することで、本来は簡単に文字を描画できる
• OpenGLのダブルバッファリングを使用して
いると、この機能は使えない
• 何らかの描画方法を使う必要がある
文字の描画方法
• 基本的なやり方
– あらかじめ必要な文字
を並べた画像を用意
– その画像から画面上に
1文字ずつコピーするこ
とで画面上に文字を描画
– (昔のゲーム専用機などで
よく用いられた手法)
ABCDE…
HIJKL…
1234…
• 実現方法
– GLUTには内部でこのような機能を実現してくれる関数
があるので、それを利用する
– ただし、基本的に数字やアルファベットのみしか使えな
い(日本語は不可)
文字の描画の手順
• 描画の初期化
– 射影行列
• 座標を指定しやすいように並行投影行列を設定
– ウィンドウサイズの情報を使用して設定
– モデルビュー行列
• 同じく単位行列に設定
– その他、ライティングやZバッファなどの不要な
機能はオフにする
• 描画の設定
– 描画の位置や色を指定
文字の描画の手順
• 1文字描画の関数を使用
– glutBitmapCharacter( フォント, 文字コード)
– 描画の後は、自動的に描画位置が1文字分横
に移動するので、続けて次の文字を描画できる
– フォントの種類は、いくつかのものが定義されて
いる(関数説明の資料参照)
• 描画に必要なピクセル幅の計算
– glutBitmapWidth( フォント, 文字コード)
– 指定した文字を描画するのに何ピクセル必要か
が求まるので、レイアウトに使用できる
プログラムの修正
• ウィンドウサイズの記録
– グローバル変数を定義
– ウィンドウサイズ変更時(reshape()関数)に更新
• 描画処理(drawMessage()関数)
–
–
–
–
–
–
平行射影行列の設定
モデルビュー行列の初期化
Zバッファやライティングの機能をオフにする
描画色・位置の設定
描画
設定を元に復元(各行列、描画設定)
ウィンドウサイズの記録
• グローバル変数を定義
// ウィンドウのサイズを記録するための変数
static int win_width;
static int win_height
• ウィンドウサイズ変更時のコールバック関数
void reshape( int w, int h )
{
・・・・
// ウィンドウのサイズを記録(テキスト描画処理のため)
win_width = w;
win_height = h;
}
文字の描画設定・描画処理(1)
void drawMessage( int x, int y, const char * message )
{
// 射影行列を初期化(初期化の前に現在の行列を退避)
glMatrixMode( GL_PROJECTION );
glPushMatrix();
glLoadIdentity();
gluOrtho2D( 0.0, win_width, win_height, 0.0 );
// モデルビュー行列を初期化(初期化の前に現在の行列を退避)
glMatrixMode( GL_MODELVIEW );
glPushMatrix();
glLoadIdentity();
// Zバッファ・ライティングをオフにする
glDisable( GL_DEPTH_TEST );
glDisable( GL_LIGHTING );
文字の描画設定・描画処理(2)
・・・・
// メッセージの描画
glRasterPos2i( x, y );
for ( i=0; message[i]!='\0'; i++ )
glutBitmapCharacter( GLUT_BITMAP_HELVETICA_18,
message[i] );
// 設定を全て復元
glEnable( GL_DEPTH_TEST );
glEnable( GL_LIGHTING );
glMatrixMode( GL_PROJECTION );
glPopMatrix();
glMatrixMode( GL_MODELVIEW );
glPopMatrix();
}
テクスチャマッピング
テクスチャマッピング(復習)
• マッピング
– 面を描画する時に、面の表面に画像を貼り付け
る技術
– 複雑なモデリングをすることなく、細かい模様な
どを表現できる
基礎知識 図3-19
基礎と応用
図5.2
マッピングの方法(復習)
• 物体への画像の貼り付け方
– マッピングの方向や繰り返し
の方法
• uv座標系
基礎と応用 図5.3
– テクスチャ画像の座標は(u,v)
で表せる
– モデルデータの各頂点(x,y,z)ごとに、対応する
テクスチャ画像の(u,v)座標を与えておく
マッピングの例(復習)
• 人体モデルへのマッピングの例
v
u
各頂点にテクスチャの(u,v)座標を設定
テクスチャマッピング
• 地面にテクスチャマッピングを適用して描画
– 各頂点に、テクスチャ座標(u,v)を指定
v
(0.0, 1.0)
u
(0.0, 0.0)
(1.0, 1.0)
(1.0, 0.0)
プログラムの修正
• コンパイル方法(bitmap.cを一緒にコンパイル)
– gcc opengl.c bitmap.c ・・・(後は同じ)
• プログラムの修正箇所
– テクスチャ画像を格納する変数を追加
– テクスチャ画像の読み込み処理、テクスチャマッ
ピングの設定処理、を追加
• 画像の読み込みには bitmap.cpp の関数を使用
– 地面にテクスチャマッピングを行う処理を追加
• テクスチャマッピングの有効化
• 各頂点にテクスチャ座標を設定
ウィンドウサイズの記録
• グローバル変数を定義
// テクスチャ画像データ
int tex_width;
int tex_height;
unsigned char * tex_image = NULL;
• ヘッダファイルのインクルードの追加
– bitmap.h は、こちらで用意している BMP画像読
み込み関数の定義されたヘッダファイル
// Bitmap読み込み関数のためのヘッダファイルのインクルード
#include "bitmap.h"
テクスチャ画像読み込み
テクスチャマッピングの設定
void initEnvironment( void )
{
・・・・・・
// テクスチャ画像の読み込み
loadBitmap( "kyushu.bmp", &tex_image, &tex_width, &tex_height );
if ( tex_image == NULL )
return;
// テクスチャオブジェクトの設定
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, tex_width, tex_height, 0,
GL_RGB, GL_UNSIGNED_BYTE, tex_image );
// テクスチャマッピングの方法を設定
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
}
テクスチャマッピングを使った描画
// 地面を描画(テクスチャマッピング)
glEnable( GL_TEXTURE_2D );
glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL );
glBegin( GL_POLYGON );
glNormal3f( 0.0, 1.0, 0.0 );
glTexCoord2f( 1.0, 0.0 );
glVertex3f( 5.0, 0.0, 5.0 );
glTexCoord2f( 1.0, 1.0 );
glVertex3f( 5.0, 0.0,-5.0 );
glTexCoord2f( 0.0, 1.0 );
glVertex3f(-5.0, 0.0,-5.0 );
glTexCoord2f( 0.0, 0.0 );
glVertex3f(-5.0, 0.0, 5.0 );
glEnd();
glDisable( GL_TEXTURE_2D );
テクスチャマッピングの手順
• テクスチャ画像の読み込み
• テクスチャ画像を登録
• テクスチャマッピングのパラメタや、テクス
チャ画像の適用方法を設定
• 各頂点ごとにテクスチャ座標(u,v)を指定す
ることで、テクスチャ画像の一部がポリゴン
に貼り付けられる
テクスチャ画像の読み込み
• 画像をファイルから配列に読み込む
– OpenGLは、画像の読み込みはサポートしてい
ないので、別のライブラリや、自作関数を使用す
る必要がある
– サンプルプログラムでは、24ビットBMP画像を配
列に読み込む関数を作成している
各1バイト(8ビット)
配列データ
R G B R G B R G B R G B ・・・・・
ピクセル1
ピクセル2
ピクセル3
ピクセル4
テクスチャ画像の登録
• テクスチャマッピングを行うために、配列に
格納された画像データを登録する
• glTextureImage2D()関数
– 画像データの形式、サイズなどを指定
• GL_RGB・・・RGB 形式
• GL_RGBA・・・RGB+不透明度(A) 形式
• GL_UNSIGNED_BYTE・・・各色ごとに1バイト
– 画像データを設定
テクスチャマッピングのパラメタ設定
• glTexParameter()関数
– GL_TEXTURE_MAG_FILTER,
GL_TEXTURE_MIN_FILTER
• テクスチャの拡大縮小方法の設定
• GL_NEAREST・・・一番近くのピクセルのみ使用
• GL_LINEAR・・・近くのピクセルの色を補間して使用
– GL_TEXTURE_WRAP_S,
GL_TEXTURE_WRAP_T
• テクスチャの繰り返しを行うかどうかの設定
• GL_REPEATE or GL_CLAMP
テクスチャマッピングの適用方法
• glTexEnv()関数
– GL_REPLACE
• 単純にテクスチャ画像を貼り付ける
• 光源処理は行われないので、常に色は一定
– GL_DECAL
• テクスチャ画像のアルファ値に応じて、ポリゴンと
テクスチャの色を混合
• ポリゴンを白にしておけば、光源による明るさの変化を
再現できる
• テクスチャ画像にアルファ値がなければGL_REPLACE
と同じになることに注意
テクスチャマッピングの適用方法
• glTexEnv()関数 (続き)
– GL_MODULATE
• ポリゴンの色にテクスチャ画像の値をかける
• テクスチャ画像には、画像データの代わりに、明るさの
情報を入れておく
– GL_BLEND
• 別に設定した固定色とポリゴン画像を、テクスチャ画像
の値に応じて混合
• テクスチャ画像には、画像データの代わりに、混合比の
情報を格納しておく
テクスチャマッピング
• 各頂点ごとに、頂点座標・色・法線に加えて、
テクスチャ座標(u,v)を指定する
v
(0.0, 1.0)
u
(0.0, 0.0)
(1.0, 1.0)
(1.0, 0.0)
複数テクスチャの使用
• 複数テクスチャを使用する場合は、テクス
チャごとに、テクスチャを切り替える
• 毎回、glTextureImage2D()を行うと時間が
かかる
• glTextureBind()関数で、登録したテクス
チャ情報を記録しておき、切り替えられる
• テクスチャの切り替えはなるべく少なくする
– 同じテクスチャ画像を使用するポリゴンはまとめ
て描画する
より高度な演習
より高度な演習
• 本講義の演習で扱ったのは、グラフィックス
プログラミングの基本的な(最も重要な)内容
– コンピュータゲームなども、本講義の演習でやっ
た内容を発展させることで、作ることができる
• より高度な内容をやりたい人は、各自で勉強
してみることをすすめます
– 本やインターネットで、自分で勉強
– 大学院講義「コンピュータグラフィックス特論Ⅱ」
• 後期開講、学部生も履修可能(大学院に入学後に自
動的に単位として認定される)
より高度な演習の例(大学院の講義)
• 幾何形状データの読み込み
• 影の表現
• キーフレームアニメーション
• 物理シミュレーションと衝突判定
• 動作データの読み込みと表示
• 逆運動学
• 詳しくは大学院の講義のページを参照
– http://www.cg.ces.kyutech.ac.jp/lecture/cg2/
昔の演習問題の解答(確認)
変換行列の計算
演習問題(第7回)
• 下記のようなシーンがある時、モデル座標系
からカメラ座標系への変換行列を求めよ
– 物体の位置が(-5,0,3)にあり、Y軸周りに-30
度回転した向きにある
– カメラの位置が(7,4,2)にあり、Y軸周りに90度回
転した向きにある
x
y
y
(-5,0,3)
z
z
x
x z
y
(7,4,2)
解答
 cos  90 

0


  sin  90 

0

0 sin  90
1
0
0 cos  90
0

0

01

00

00

0
1
0 0 7  1

1 0 4  0
0 1 2  0

0 0 1  0
0 0 5   cos  30 

1 0 0 
0

0 1 3    sin  30 

0 0 1 
0

0 sin  30
1
• 検算
– 変換行列を計算すると、以下のようになる
 1/ 2

 0

 3/2
 0

0  3/2
1
0
0
0
1/ 2
0
1 

4 

12 
1 
0
0 cos  30
0

0

0

0

0

1
変換行列の検算
 cos  90 

0


  sin  90 

0

0 sin  90
1
0
0 cos  90
0
0
0

0

1

0
0 1 0  1

1 0 0  0
0 0 0  0

0 0 1  0
0

0

1

0
0 1 0   3 / 2

1 0 0 0
0 0 0   1/ 2

0 0 1   0
 1/ 2

 0

 3/2
 0

0  3/2
1
0
0
0
1/ 2
0


01

00

00

0
1
0 0 7  1

1 0 4  0
0 1 2  0

0 0 1  0
0
1
0
0
1 

4 

12 
1 
0 0 7  1

1 0 4  0
0 1 2  0

0 0 1  0
0 0 5   3 / 2

1 0 0  0
0 1 3   1/ 2

0 0 1   0
12 

0
4 

3/2 1 
0
1 
1/ 2
0 0 5   cos  30 

1 0 0 
0

0 1 3    sin  30 

0 0 1 
0

0
1
0
0
0

0
0

3 / 2 0
0
1 
1/ 2
0 sin  30
1
0
0 cos  30
0

0

0

0

0

1
検算
• モデル座標系の (0,0,0) に変換行列を適用し、変換後の座
標を計算すると、変換後の座標は (-1,-4,-12) となる。シー
ンを見ると、モデル座標系の原点は、カメラから見て、カメラ
の奥方向の、やや左下の位置にある。変換後の座標もそ
のような値になっているので、この変換行列は妥当であると
考えられる。
• また、モデル座標系の (0,0,1) に変換行列を適用し、変換
後の座標を計算すると、変換後の座標は ( -1.87,-4,-12.5 )
となる。シーンを見ると、モデル座標系の (0,0,1) の位置は、
カメラから見て、モデル座標系の原点よりも、やや左方向の、
さらにやや奥の位置にある。変換後の座標もそのような値
になっているので、この変換行列は妥当であると考えられ
る。
検算
 1/ 2

 0

 3/2
 0

 1/ 2

 0

 3/2
 0

0  3/2
1
0
0
0
1/ 2
0
0  3/2
1
0
0
0
1/ 2
0
1   0   1 
  

4   0   4 
  0    12 
12 
  


1
1
1   

1   0    3 / 2  1  1.87 
  
 

4   0  

4
4



  1    1/ 2  12    12.5 
12 
 
  


1
1
1
1   

 
演習問題(第8回)
• 下記のようなシーンがある時、モデル座標系
からカメラ座標系への変換行列を求めよ
– オブジェクト(車)の位置が(-1, 0, 5)にあり、Y
軸を中心として-30度回転した向きにある。
– カメラの位置が( 5, 12, 2)にあり、ワールド座標
系から見て水平方向に90度回転(ワールド座標
系のY軸を中心として90度回転)、水平面に対し
て上下方向に-60 度回転(カメラ座標系のX軸
を中心として-60度回転)した状態にある。
演習問題(第8回)
y
z
x
(5,12,2)
y
y
(-1,0,5)
z
x
x z
解答
0
0
1

 0 cos  60   sin  60 
 0 sin  60  cos  60 

0
0
0
0   cos  90 

0
0
0    sin  90 

1  
0
0 sin  90 
1
0
0 cos  90 
0
0
01

00
00

1   0
5  1

1 0 12  0
0 1 2  0

0 0 1 
 0
0 0
0 0 1  cos  30 

1 0 0 
0
0 1 5    sin  30 

0 0 1  
0
0 sin  30  0 

1
0
0
0 cos  30  0 

0
0
1 
• 検算
– 変換行列をTと置いて計算すると、以下のように
なる
 1/ 2

 3/ 4
T
 3/4
 0

0
1/ 2
3/2
0
 3/2
3/4
1/ 4
0
  0.5
0
0.87
3 
 

6  3 3   0.75 0.5 0.43 0.81 
   0.43 0.87 0.25 13.38 
6 3  3 



0
0
0
1

1
 
3
変換行列の検算
0
0
1

 0 cos  60   sin  60 
 0 sin  60  cos  60 

0
0
0
0   cos  90 

0
0


0  sin  90 

1  
0
0 sin  90 
1
0
0 cos  90 
0
0
1

0

0
0

00

1/ 2  3 / 2 0   0

3/2
1/ 2
01

0
0
1   0
0 1 0  1

1 0 0  0
0 0 0  0

0 0 1 
 0
1

0

0
0

00

1/ 2  3 / 2 0   0

3/2
1/ 2
01

0
0
1   0
0 1 0   3 / 2

1 0 0 0
0 0 0   1/ 2

0 0 1   0
1

0

0
0

0  1/ 2

1/ 2  3 / 2 0  0

3/2
1/ 2
0  3 / 2
0
0
1 
 0
0
0
0
0
0
 1/ 2

 3 / 4

 3/4
 0

0
0
1/ 2
3/2
0
 3/2
3/4
1/ 4
0
0  3/2
1
0
0
0
1/ 2
0


6  3 3 

6 3  3 

1

3
01

00
00

1   0
5  1

1 0 12  0
0 1 2  0

0 0 1 
 0
0 0
0
1
0
0
3 

12 

6 
1 
5  1

1 0 12  0
0 1 2  0

0 0 1 
 0
0 0
0 0 1  3 / 2

1 0 0  0
0 1 5   1/ 2

0 0 1   0
6 

0
12 

3/2 3 
0
1 
1/ 2
0 0 1  cos  30 

1 0 0 
0


0 1 5  sin  30 

0 0 1  
0
0
1
0
0
0

0
0

3 / 2 0
0
1 
1/ 2
0 sin  30  0 

1
0
0
0 cos  30  0 

0
0
1 
検算
• モデル座標系の (0,0,0) に変換行列を適用し、変
換後の座標を計算すると、変換後の座標は (-3, 0.81, -13.38) となる。シーンを見ると、モデル座標
系の原点は、カメラから見て、カメラの奥方向の、
少し左、さらに少し下の位置にある。変換後の座標
もそのような値になっているので、この変換行列は
妥当であると考えられる。
• また、モデル座標系の (1,0,0.5) に変換行列を適
用し、変換後の座標を計算すると、変換後の座標
は (-3.93, -1.77, -13.02) となる。シーンを見ると、
モデル座標系の (1,0,0.5) の位置は、カメラから見
て、モデル座標系の原点よりも、やや手前、左下の
位置にある。変換後の座標もそのような値になって
いるので、この変換行列は妥当であると考えられる。
検算
 1/ 2

 3/ 4

 3/4
 0

 1/ 2

 3/ 4

 3/4
 0

0
1/ 2
3/2
0
0
1/ 2
3/2
0
 3/2
3/4
1/ 4
0
 3/2
3/4
1/ 4
0
  0   3   3 
  
 

6  3 3   0   6  3 3   0.81 
0  
   13.38 
6 3  3 
6 3  3 
  
  1 

1
1


1



3
  1   1/ 2  3 / 4  3  
0.5  0.43  3
  3.93 
  
 
 

6  3 3   0   3/ 4  3 / 8  6  3 3   0.75  0.22  6  5.2   1.77 
  0.5   
   0.43  0.13  10.32  3    13.02 
6 3  3 
3 / 4  1/ 8  6 3  3 
  

 




1
1
1






1
1



3