Lighting and Keyboard Control in OpenGL (L3)

本篇要介紹如何在屏幕裡面增加光源以及鍵盤控制。

● Lighting

想要在屏幕裡打光的話就需要定義光源的位置、顏色、強度,以及物體反光係數。OpenGL 裡主要可以設定兩種光,分別是環境光( Ambient Light ) 和 散射光( Diffuse Light ),環境光就是一般的光源,是無方向性的;散射光則是指物體本身的反光,散射的強度與物體的材質有關。除了光源的特性外,還有光的位置( Light Position )要被定義,才能決定光呈現的效果。

在 initializeGL() function 裡面,先定義好光的特性:


 GLfloat LightAmbient[] = {1.0f, 1.0f, 1.0f, 1.0f};
 GLfloat LightDiffuse[] = {1.0f, 1.0f, 1.0f, 1.0f};
 GLfloat LightPosition[] = {0.0f, 0.0f, 2.0f, 1.0f};
 //@ key control
 Light = false;
 //@ glLight 
 glLightfv(GL_LIGHT1, GL_AMBIENT, LightAmbient);
 glLightfv(GL_LIGHT1, GL_DIFFUSE, LightDiffuse);
 glLightfv(GL_LIGHT1, GL_POSITION, LightPosition);
 glEnable(GL_LIGHT1);

LightAmbient[] 是定義光源的顏色強度,分別代表{ R, G, B, Alpah}。

LightDiffuse[] 則是物體表面反光強度,一樣 index 代表著 { R, G, B, Alpah}。

可以改變光源顏色與反光顏色,會有不同的效果。我上面的設定是強度最強的白光而反光係數也是最強。

LightPosition[] 前三個 index 表示光源所在的位置(x, y, z),第四個參數則是代表著定義在已訂的座標空間。

glLightfv(GL_LIGHT1, GL_AMBIENT, LightAmbient)

glLightfv(GL_LIGHT1,GL_DIFFUSE, LightDiffuse)

glLightfv(GL_LIGHT1, GL_POSITION, LightPosition) 表示把剛的光源設定建議在 GL_LIGHT1 裡面。

glEnable(GL_LIGHT1) 則是啟動 GL_LIGHT1 這個光。

接下來就是如何 rendering 在屏幕上了,


 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 
 glLoadIdentity();

//@ key control
 if(Light)
 glEnable(GL_LIGHTING);
 else
 glDisable(GL_LIGHTING);

 double D = 10; // size 
 glTranslatef(0.0f, 0.0f, -50.f);
 glRotatef(rota_x, 1.0f, 0.0f, 0.0f);
 glRotatef(rota_y, 0.0f, 1.0f, 0.0f);
 glRotatef(rota_z, 0.0f, 0.0f, 1.0f); 
 glBindTexture( GL_TEXTURE_2D, texture[2]); 
 
 // Front Face
 glBegin( GL_QUADS );
 glNormal3f( 0.0f, 0.0f, 1.0f); 
 glTexCoord2f(0.0f, 0.0f); glVertex3f(-D, -D, D); // Bottom Left Of The Texture and Quad
 glTexCoord2f(1.0f, 0.0f); glVertex3f( D, -D, D); // Bottom Right Of The Texture and Quad
 glTexCoord2f(1.0f, 1.0f); glVertex3f( D, D, D); // Top Right Of The Texture and Quad
 glTexCoord2f(0.0f, 1.0f); glVertex3f(-D, D, D); // Top Left Of The Texture and Quad
 glEnd();
 //Back Face
 glBegin( GL_QUADS ); 
 glNormal3f( 0.0f, 0.0f, -1.0f); 
 glTexCoord2f(1.0f, 0.0f); glVertex3f(-D, -D, -D); // Bottom Right Of The Texture and Quad
 glTexCoord2f(1.0f, 1.0f); glVertex3f(-D, D, -D); // Top Right Of The Texture and Quad
 glTexCoord2f(0.0f, 1.0f); glVertex3f( D, D, -D); // Top Left Of The Texture and Quad
 glTexCoord2f(0.0f, 0.0f); glVertex3f( D, -D, -D); // Bottom Left Of The Texture and Quad
 glEnd();
 // Top Face
 glBegin( GL_QUADS ); 
 glNormal3f( 0.0f, 1.0f, 0.0f); 
 glTexCoord2f(0.0f, 1.0f); glVertex3f(-D, D, -D); // Top Left Of The Texture and Quad
 glTexCoord2f(0.0f, 0.0f); glVertex3f(-D, D, D); // Bottom Left Of The Texture and Quad
 glTexCoord2f(1.0f, 0.0f); glVertex3f( D, D, D); // Bottom Right Of The Texture and Quad
 glTexCoord2f(1.0f, 1.0f); glVertex3f( D, D, -D); // Top Right Of The Texture and Quad
 glEnd();
 // Bottom Face
 glBegin( GL_QUADS ); 
 glNormal3f( 0.0f,-1.0f, 0.0f); 
 glTexCoord2f(1.0f, 1.0f); glVertex3f( D, -D, D); // Top Right Of The Texture and Quad
 glTexCoord2f(0.0f, 1.0f); glVertex3f(-D, -D, D); // Top Left Of The Texture and Quad
 glTexCoord2f(0.0f, 0.0f); glVertex3f(-D, -D, -D); // Bottom Left Of The Texture and Quad
 glTexCoord2f(1.0f, 0.0f); glVertex3f( D, -D, -D); // Bottom Right Of The Texture and Quad
 glEnd();
 // Right face
 glBegin( GL_QUADS ); 
 glNormal3f( 1.0f, 0.0f, 0.0f); 
 glTexCoord2f(1.0f, 0.0f); glVertex3f( D, -D, -D); // Bottom Right Of The Texture and Quad
 glTexCoord2f(1.0f, 1.0f); glVertex3f( D, D, -D); // Top Right Of The Texture and Quad
 glTexCoord2f(0.0f, 1.0f); glVertex3f( D, D, D); // Top Left Of The Texture and Quad
 glTexCoord2f(0.0f, 0.0f); glVertex3f( D, -D, D); // Bottom Left Of The Texture and Quad
 glEnd();
 // Left Face
 glBegin( GL_QUADS );
 glNormal3f(-1.0f, 0.0f, 0.0f); 
 glTexCoord2f(0.0f, 0.0f); glVertex3f(-D, -D, -D); // Bottom Left Of The Texture and Quad
 glTexCoord2f(1.0f, 0.0f); glVertex3f(-D, -D, D); // Bottom Right Of The Texture and Quad
 glTexCoord2f(1.0f, 1.0f); glVertex3f(-D, D, D); // Top Right Of The Texture and Quad
 glTexCoord2f(0.0f, 1.0f); glVertex3f(-D, D, -D); 
 glEnd();

glNormal3f 是定義每個面的法向量,代表每個面朝外的方位,這樣光才能正確地打在每個平面上。若不加上 glNormal3f 的話,光不會出現在正確的地方,光源會隨著你的物體旋轉而跟著旋轉。這裡要注意到,glLightfv(GL_LIGHT1, GL_POSITION, LightPosition) 一定要定義在物體做旋轉或平移之前,不然光源也會跟著物體旋轉。

 


● Keyboard Control

在 keyboard control 的部分我是套用 Qt 裡的 <QKeyEvent> widget 來實作,那這裡主要的作用就是 Lighting 的開關, L 按鍵來做開關的動作。


void QtGL::keyPressEvent(QKeyEvent * event)
{
	if(event->key() == Qt::Key_Escape)
	{
		qApp->quit();
	}
	if(event->key() == Qt::Key_L)
	{
		myqgl->Light = !myqgl->Light;
	}
    myqgl->GLupdate();
}

 

執行結果:

  1. Light 開關

picasion.com_349410d8f8b7faf61be3ab125811092d

  1. 物體旋轉下打光的變化

picasion.com_d323d25c632f98b7fde39052abac8e9a

 

 


 

reference : http://nehe.gamedev.net/tutorial/texture_filters,_lighting_&_keyboard_control/

iron image : http://www.dreamstime.com/

 

Leave a Reply

Your email address will not be published. Required fields are marked *