VisualC++ を使った OpenGL 入門
【4日目】 光源
4日目。光源の登場。
物体に光と影が描画されます。
OpenGL と C++ によるソース
#include <GL/glut.h>
int WindowPositionX = 100; //生成するウィンドウ位置のX座標
int WindowPositionY = 100; //生成するウィンドウ位置のY座標
int WindowWidth = 512; //生成するウィンドウの幅
int WindowHeight = 512; //生成するウィンドウの高さ
char WindowTitle[] = "世界の始まり"; //ウィンドウのタイトル
//----------------------------------------------------
// 直方体の定義
//----------------------------------------------------
GLdouble vertex[][3] = {
{ 0.0, 0.0, 0.0 },
{ 2.0, 0.0, 0.0 },
{ 2.0, 2.0, 0.0 },
{ 0.0, 2.0, 0.0 },
{ 0.0, 0.0, 30.0 },
{ 2.0, 0.0, 30.0 },
{ 2.0, 2.0, 30.0 },
{ 0.0, 2.0, 30.0 }
};
int face[][4] = {//面の定義
{ 0, 1, 2, 3 },
{ 1, 5, 6, 2 },
{ 5, 4, 7, 6 },
{ 4, 0, 3, 7 },
{ 4, 5, 1, 0 },
{ 3, 2, 6, 7 }
};
GLdouble normal[][3] = {//面の法線ベクトル
{ 0.0, 0.0,-1.0 },
{ 1.0, 0.0, 0.0 },
{ 0.0, 0.0, 1.0 },
{-1.0, 0.0, 0.0 },
{ 0.0,-1.0, 0.0 },
{ 0.0, 1.0, 0.0 }
};
//----------------------------------------------------
// 物質質感の定義
//----------------------------------------------------
struct MaterialStruct {
GLfloat ambient[4];
GLfloat diffuse[4];
GLfloat specular[4];
GLfloat shininess;
};
//jade(翡翠)
MaterialStruct ms_jade = {
{0.135, 0.2225, 0.1575, 1.0},
{0.54, 0.89, 0.63, 1.0},
{0.316228, 0.316228, 0.316228, 1.0},
12.8};
//ruby(ルビー)
MaterialStruct ms_ruby = {
{0.1745, 0.01175, 0.01175, 1.0},
{0.61424, 0.04136, 0.04136, 1.0},
{0.727811, 0.626959, 0.626959, 1.0},
76.8};
//----------------------------------------------------
// 色の定義の定義
//----------------------------------------------------
GLfloat red[] = { 0.8, 0.2, 0.2, 1.0 }; //赤色
GLfloat green[] = { 0.2, 0.8, 0.2, 1.0 };//緑色
GLfloat blue[] = { 0.2, 0.2, 0.8, 1.0 };//青色
GLfloat yellow[] = { 0.8, 0.8, 0.2, 1.0 };//黄色
GLfloat white[] = { 1.0, 1.0, 1.0, 1.0 };//白色
GLfloat shininess = 30.0;//光沢の強さ
//-----------------------------------------
//----------------------------------------------------
// 関数プロトタイプ(後に呼び出す関数名と引数の宣言)
//----------------------------------------------------
void Initialize(void);
void Display(void);
void Ground(void); //大地の描画
//----------------------------------------------------
// メイン関数
//----------------------------------------------------
int main(int argc, char *argv[]){
glutInit(&argc, argv);//環境の初期化
glutInitWindowPosition(WindowPositionX, WindowPositionY);//ウィンドウの位置の指定
glutInitWindowSize(WindowWidth, WindowHeight); //ウィンドウサイズの指定
glutInitDisplayMode(GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE);//ディスプレイモードの指定
glutCreateWindow(WindowTitle); //ウィンドウの作成
glutDisplayFunc(Display); //描画時に呼び出される関数を指定する(関数名:Display)
Initialize(); //初期設定の関数を呼び出す
glutMainLoop();
return 0;
}
//----------------------------------------------------
// 初期設定の関数
//----------------------------------------------------
void Initialize(void){
glClearColor(1.0, 1.0, 1.0, 1.0); //背景色
glEnable(GL_DEPTH_TEST);//デプスバッファを使用:glutInitDisplayMode() で GLUT_DEPTH を指定する
//光源の設定--------------------------------------
GLfloat light_position0[] = { -50.0, -50.0, 20.0, 1.0 }; //光源0の座標
glLightfv(GL_LIGHT0, GL_POSITION, light_position0); //光源0を
//透視変換行列の設定------------------------------
glMatrixMode(GL_PROJECTION);//行列モードの設定(GL_PROJECTION : 透視変換行列の設定、GL_MODELVIEW:モデルビュー変換行列)
glLoadIdentity();//行列の初期化
gluPerspective(30.0, (double)WindowWidth/(double)WindowHeight, 0.1, 1000.0); //透視投影法の視体積gluPerspactive(th, w/h, near, far);
//視点の設定------------------------------
gluLookAt(
0.0, -100.0, 50.0, // 視点の位置x,y,z;
0.0, 100.0, 0.0, // 視界の中心位置の参照点座標x,y,z
0.0, 0.0, 1.0); //視界の上方向のベクトルx,y,z
//----------------------------------------
}
//----------------------------------------------------
// 描画の関数
//----------------------------------------------------
void Display(void) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //バッファの消去
//モデルビュー変換行列の設定--------------------------
glMatrixMode(GL_MODELVIEW);//行列モードの設定(GL_PROJECTION : 透視変換行列の設定、GL_MODELVIEW:モデルビュー変換行列)
glLoadIdentity();//行列の初期化
glViewport(0, 0, WindowWidth, WindowHeight);
//----------------------------------------------
//陰影ON-----------------------------
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);//光源0を利用
//-----------------------------------
//球
glPushMatrix();
glMaterialfv(GL_FRONT, GL_AMBIENT, ms_ruby.ambient);
glMaterialfv(GL_FRONT, GL_DIFFUSE, ms_ruby.diffuse);
glMaterialfv(GL_FRONT, GL_SPECULAR, ms_ruby.specular);
glMaterialfv(GL_FRONT, GL_SHININESS, &ms_ruby.shininess);
glTranslated(0.0, 10.0, 20.0);//平行移動値の設定
glutSolidSphere(4.0, 20, 20);//引数:(半径, Z軸まわりの分割数, Z軸に沿った分割数)
glPopMatrix();
//立方体
glPushMatrix();
glMaterialfv(GL_FRONT, GL_DIFFUSE, green);
glTranslated(-20.0, 0.0, 20.0);//平行移動値の設定
glutSolidCube(10.0);//引数:(一辺の長さ)
glPopMatrix();
//円錐
glPushMatrix();
glMaterialfv(GL_FRONT, GL_DIFFUSE, blue);
glTranslated(20.0, 100.0, 0.0);//平行移動値の設定
glutSolidCone(5.0,10.0,20,20);//引数:(半径, 高さ, Z軸まわりの分割数, Z軸に沿った分割数)
glPopMatrix();
//直方体
glPushMatrix();
glMaterialfv(GL_FRONT, GL_AMBIENT, ms_jade.ambient);
glMaterialfv(GL_FRONT, GL_DIFFUSE, ms_jade.diffuse);
glMaterialfv(GL_FRONT, GL_SPECULAR, ms_jade.specular);
glMaterialfv(GL_FRONT, GL_SHININESS, &ms_jade.shininess);
glTranslated(30.0, 50.0, 0.0);//平行移動値の設定
glBegin(GL_QUADS);
for (int j = 0; j < 6; ++j) {
glNormal3dv(normal[j]); //法線ベクトルの指定
for (int i = 0; i < 4; ++i) {
glVertex3dv(vertex[face[j][i]]);
}
}
glEnd();
glPopMatrix();
//陰影OFF-----------------------------
glDisable(GL_LIGHTING);
//-----------------------------------
Ground();
glutSwapBuffers(); //glutInitDisplayMode(GLUT_DOUBLE)でダブルバッファリングを利用可
}
//----------------------------------------------------
// 大地の描画
//----------------------------------------------------
void Ground(void) {
double ground_max_x = 300.0;
double ground_max_y = 300.0;
glColor3d(0.8, 0.8, 0.8); // 大地の色
glBegin(GL_LINES);
for(double ly = -ground_max_y ;ly <= ground_max_y; ly+=10.0){
glVertex3d(-ground_max_x, ly,0);
glVertex3d(ground_max_x, ly,0);
}
for(double lx = -ground_max_x ;lx <= ground_max_x; lx+=10.0){
glVertex3d(lx, ground_max_y,0);
glVertex3d(lx, -ground_max_y,0);
}
glEnd();
}
ソースの解説
光源番号0の光源の座標を決めます。
光源は0番目から順番に指定することができます。
GLfloat light_position0[] = { -50.0, -50.0, 20.0, 1.0 }; //光源0の座標
glLightfv(GL_LIGHT0, GL_POSITION, light_position0); //光源0を
光を当てたい物体の前で、光源の全体のスイッチと光源番号1のスイッチを入れます。
glEnable(GL_LIGHTING); glEnable(GL_LIGHT0);//光源0を利用
光源を作用させると、「glColor3d」関数で指定していた色が無効となります。
「glMaterialfv」を利用して、物体に光源に対する質感を与えます。
glMaterialfv(GL_FRONT, GL_AMBIENT, ms_ruby.ambient); glMaterialfv(GL_FRONT, GL_DIFFUSE, ms_ruby.diffuse); glMaterialfv(GL_FRONT, GL_SPECULAR, ms_ruby.specular); glMaterialfv(GL_FRONT, GL_SHININESS, &ms_ruby.shininess);
「GLUT」に関数が与えられている球(glutSolidSphere)や立方体(glutSolidCube)の場合には、 物体の「表」「裏」の情報に与えたれているが、任意の物体を自前で定義した場合には、各面に対して法線ベクトルを定義する必要があります。
GLdouble normal[][3] = {//面の法線ベクトル
{ 0.0, 0.0,-1.0 },
{ 1.0, 0.0, 0.0 },
{ 0.0, 0.0, 1.0 },
{-1.0, 0.0, 0.0 },
{ 0.0,-1.0, 0.0 },
{ 0.0, 1.0, 0.0 }
};
glBegin(GL_QUADS);
for (int j = 0; j < 6; ++j) {
glNormal3dv(normal[j]); //法線ベクトルの指定
for (int i = 0; i < 4; ++i) {
glVertex3dv(vertex[face[j][i]]);
}
}
glEnd();
参考ページ
物体の質感を出すために必要な構造体として、 「OpenGL(Akita National College of Technology Yamamoto's Laboratory )」 のページ内にあるソースを利用させていただきました。
【目次】 (VisualC++ を使った OpenGL 入門)
- 【参考文献リスト】
- ■ 【0日目】はじめに ・ (0.1日目)OpenGL と Visual C++ 2008 Express Edition の準備
- ■ 【1日目】 世界の始まり ・(1.1日目)OpenGL の基本形
- ■ 【2日目】 地平線 ・ (2.1日目)視点の設定
- ■ 【3日目】 創造物
- ■ 【4日目】 光源
- ■ 【5日目】 視点
- ■ 【6日目】 記憶
- ■ 【7日目】 キーボード入力
- ■ 【8日目】 影
- ■ 【9日目】 文字
- ■ 【10日目】 回転
未分類
- ・ Windows7 OpenGL freeglut のインストール
- ・ OpenGLで霧を表現
- ・ 光源のパラメータ設定1
- ・ 光源のパラメータ設定2
- ・ 光源のパラメータ設定3
- ・ 平面に光をあてるときの注意点
- ・ 波動方程式のテスト
- ・ OpenGLで霧を表現
- ・ OpenGLのカラーサンプル(teapots.c)
- ・ 直方体を回転させよう!




