1. 程式人生 > >顏色、光照、材料屬性(openGL)

顏色、光照、材料屬性(openGL)

0.顏色

a.顏色座標系


b.顏色設定與著色

void colortriangle()
{
	glClear(GL_COLOR_BUFFER_BIT);
	glShadeModel(GL_SMOOTH);
	glBegin(GL_TRIANGLES);
		/************************************顏色設定及著色**************************************************
			1、void glColorXt(red, green, blue, alpha);
				其中x代表引數個數,可以是3個值代表rgb顏色,或者使4個值分別代表rgba。alpha成分用來代表透明度。
				t代表引數的型別,可以是b,d,f,i,s,ub,ui,us對應的型別是byte,double,float,integer,short,unsigned byte, unsigned integer,unsigned short。
				glColor3f指定各個顏色成分的強度值的範圍為0.0到1.0之間。
				glColor3ub則可以指定各個顏色成分的強度值的範圍在0-255之間。
			2、著色分為兩種
				GL_FLAT:圖元是點(畫的是線什麼的情況下),使用最後一個點的顏色作為線(其他圖)顏色
				GL_SMOOTH:圖元是點(畫的是線什麼的情況下),均衡,顏色漸變(兩頂點間) 
		****************************************************************************************************/ 
		glColor3ub((GLubyte)255,(GLubyte)0,(GLubyte)0);							//ub:unsign byte
		glVertex3f(0.0f,100.0f,0.0f);
		glColor3ub((GLubyte)0,(GLubyte)255,(GLubyte)0);
		glVertex3f(100.0f,-35.0f,0.0f);
		glColor3ub((GLubyte)0,(GLubyte)0,(GLubyte)255);
		glVertex3f(-100.0f,-35.0f,0.0f);
	glEnd();
	glFlush();
} 


c.看到的顏色是光照顏色和材料屬性綜合的結果

若光源顏色為( LR , LG , LB ),材質顏色為( MR , MG , MB ),最終顏色為( LR*MR , LG*MG , LB*MB )。(B1+B2)*MB )。因此,材料的顏色成分決定了入射光被反射的百分比。

栗子:光源顏色為(0.5, 0.5, 0.5),材料的顏色為(0.5, 1.0, 0.5)那麼最終的顏色是(0.5*0.5, 0.5*1.0, 0.5*0.5) = (0.25, 0.5, 0.25) 。

1.光照

我們觀察到的實物的顏色除了,實物本身的顏色外,還包括實物的材質和光照對觀察的影響。

a.光照型別

環境光、散射光、鏡面光的強度都會衰減(這也是為什麼在設定光照的同事還要設定光照位置的一個原因),只有發射光和全域性環境光的強度沒有衰減。

環境光:

環境光沒有特定的方向。環境光的光線充滿著整個場景。場景中的物體都被環境光從各個方向照射著。環境光的特點是:照射在物體上的光來自周圍各個方向,又均勻地向各個方向反射。

全域性環境光栗子

//明亮的白光
GLfloat ambientLight[] = {1.0f, 1.0f, 1.0f, 1.0f};
//開啟光照
glEnable(GL_LIGHTING);
//設定全域性環境光為白光
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambientLight);
漫反射光:

漫放射光是一組來自特定方向,具有方向性的光。根據入射光線的角度在表面上均勻地向各個方向反射。漫反射的特點是:光源來自一個方向,反射光均勻地射向各個方向。漫反射光采用點光源照射物體。點光源是位於空間某個位置的一個點,向周圍所有的方向上輻射等光強的光。在點光源的照射下,物體表面的不同部分亮度不同,亮度的大小依賴於它的朝向以及它與點光源之間的距離。

鏡面光:

鏡面光與漫反射光一樣是具有方向性的。高強度的鏡面光會在被照射的物體的表面上形成亮點。對於理想的高光澤度反射面,反射角等於入射角時,光線才會被反射,即只有在等於入射角的反射角方向上,觀察者才能看到反射光。對於這種理想的反射面,鏡面反射的光強要比環境光和漫反射的光強高出很多倍,這時,如果觀察者正好處在P點的鏡面反射方向上,就會看到一個比周圍亮得多的高光點。

b.光照與法線

作用於定義:

物體的法線向量決定了它相對於光源的方向(區別於材料顏色屬性定義時使用的多邊形正面和反面;這個法線定義方向,是光照用的)。對於物體的每個頂點,opengl使用法線判斷這個頂點從每個光源接受的光線數量。

為每個頂點定義法線向量:

OpenGL中,既可以為每個多邊形只指定一條法線(多邊形各頂點的法線方向相同),也可以為每個多邊形指定多條法線(多邊形頂點的法線方向有不同)。在OpenGL中,除了頂點之外,不能為多邊形其他地方分配法線。

法線向量:

物體的法線向量定義了它的表面在空間中的朝向,即,定義了表面相對於光源的方向。因為OpenGL是使用法線向量來確定一個物體表面的某個頂點所接受的光照的。如果不想使用OpenGL的光照功能,就可以免去為頂點指定法線向量這個步驟。GLUT工具庫中某些模型的法線向量已經內部給定好啦,如glutWireCube()等,所繪製的模型各個頂點的法線向量已經系統給出了,又如繪製一個球Sphere等。

指定法線向量:

glNormal*()函式是把當前法線向量這個狀態量設定為這個函式的引數所指示的向量值。後續頂點glVertex*()的法線向量將預設為此時法線向量狀態量所儲存的向量值。通常,頂點常具有不同的法線向量,因此常需要交替呼叫這兩個函式。

在一個表面的頂點上,將會有兩條向量垂直於這個表面,這兩條向量指向相反的方向,而指向外側的向量才為當前表面的法線向量。法線向量只表示方向,不表示大小(即與長度無關)。理論上可以為頂點指定任意大小的法線向量,但在OpenGL執行光照操作時,會將頂點的法線向量規範化(單位化),而這樣必然會降低程式的效能,所以一般應由我們自己提供各個頂點的規範化法線向量。
如果只是對模型進行移動、旋轉操作,法線向量的長度將不會發生變化,而如果對模型進行縮放操作,長度則將變化。如果需要OpenGL對法線向量進行規範化,就需要啟用這個功能,glEnable(GL_NORMALIZE),預設這個功能是關閉的。
如果所進行的縮放是均勻縮放,則可以使用glEnable(GL_RESCALE_NORMAL),這樣效能相比較GL_NORMALIZE更優。預設情況下,GL_RESCALE_NORMAL也是被禁用的。

2.材料

a.材料屬性

當我們使用光照時,我們通過材料的反射屬性來描述它的顏色,我們為三種光源指定材料相應的反射屬性。一個材料可能會很好的反射鏡面光,卻吸收了大多數的漫反射和環境光。

b.材料的屬性設定

1)在指定的多邊形前呼叫glMaterial函式。

void glMaterial{if}(GLenum face, GLenum pname, TYPE param);

引數:face:正面還是反面應用材料屬性設定;pname:材料屬性;param,引數


//灰色的材料屬性
GLfloat gray[] = {0.75f, 0.75f, 0.75f, 1.0f};

glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, gray);
glBegin(GL_TRIANGLES);
    glVertex3f(-15.0f, 0.0f, 30.0f);
    glVertex3f(0.0f, 15.0f, 30.0f);
    glVertex3f(0.0f, 0.0f, -56.0f);
glEnd();
2)材料的顏色追蹤

開啟GL_COLOR_MATERIAL;設定追蹤面和追蹤的材料屬性glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);;之後就可以通過glColor來設定顏色了

//開啟顏色追蹤
glEnable(GL_COLOR_MATERIAL);
//設定顏色追蹤的材料屬性以及多邊形的面
glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);

//設定顏色
glColor3f(0.75f, 0.75f, 0.75f);
glBegin(GL_TRIANGLES);
    glVertex3f(-15.0f, 0.0f, 30.0f);
    glVertex3f(0.0f, 15.0f, 30.0f);
    glVertex3f(0.0f, 0.0f, -56.0f);
glEnd();
3.綜合栗子

a.綜合栗子1-----材料顏色屬性:

#include "grapg.h"

static GLfloat xRot=0.0f;
static GLfloat yRot=0.0f;
void setuprc_000()
{
	GLfloat ambientLight[]={0.5f,0.5f,0.5f,1.0f};
	glEnable(GL_DEPTH_TEST);													//開啟深度測試 
	glEnable(GL_CULL_FACE);														//開啟隱藏面,因為後面設定了材料的顏色追蹤,只追蹤正面,所以要先剔除反面,在把反面用正面的方式畫上去 
	glFrontFace(GL_CCW);														//設定逆時針為正面
	
	glEnable(GL_COLOR_MATERIAL);												//開啟材料的顏色追蹤
	glEnable(GL_LIGHTING);														//開啟光照
	glLightModelfv(GL_LIGHT_MODEL_AMBIENT,ambientLight);						//設定全域性環境光
	glColorMaterial(GL_FRONT,GL_AMBIENT_AND_DIFFUSE);							//設定材料的顏色追蹤 
	
	glClearColor(0.0f,0.0f,0.0f,1.0f); 
}

void aircraft()
{	
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glPushMatrix();
		glRotatef(xRot, 1.0f, 0.0f, 0.0f);
    	glRotatef(yRot, 0.0f, 1.0f, 0.0f);

    	glBegin(GL_TRIANGLES);
    	//機頭
    		glColor3f(1.0f, 1.0f, 1.0f);
      		glVertex3f(-15.0f, 0.0f, 30.0f);
      		glVertex3f(15.0f, 0.0f, 30.0f);
      		glVertex3f(0.0f, 0.0f, 60.0f);

      		glColor3f(0.0f, 0.0f, 0.0f);
      		glVertex3f(-15.0f, 0.0f, 30.0f);
      		glVertex3f(0.0f, 0.0f, 60.0f);
      		glVertex3f(0.0f, 15.0f, 30.0f);

      		glColor3f(1.0f, 0.0f, 0.0f);
      		glVertex3f(0.0f, 0.0f, 60.0f);
      		glVertex3f(15.0f, 0.0f, 30.0f);
      		glVertex3f(0.0f, 15.0f, 30.0f);
      //機身
      		glColor3f(0.0f, 1.0f, 0.0f);
      		glVertex3f(-15.0f, 0.0f, 30.0f);
      		glVertex3f(0.0f, 15.0f, 30.0f);
      		glVertex3f(0.0f, 0.0f, -53.0f);

      		glColor3f(1.0f, 1.0f, 0.0f);
      		glVertex3f(0.0f, 15.0f, 30.0f);
      		glVertex3f(15.0f, 0.0f, 30.0f);
      		glVertex3f(0.0f, 0.0f, -53.0f);

      		glColor3f(0.5f, 0.5f, 0.3f);
      		glVertex3f(15.0f, 0.0f, 30.0f);
      		glVertex3f(-15.0f, 0.0f, 30.0f);
      		glVertex3f(0.0f, 0.0f, -53.0f);

      //機尾巴
      		glColor3f(0.3f, 1.0f, 0.2f);
      		glVertex3f(0.0f, 0.0f, -53.0f);
      		glVertex3f(0.0f, 0.0f, -70.0f);
      		glVertex3f(0.0f, 15.0f, -70.0f);

      		glColor3f(0.7f, 0.5f, 0.3f);
      		glVertex3f(-15.0f, 0.0f, -70.0f);
      		glVertex3f(0.0f, 0.0f, -53.0f);
      		glVertex3f(0.0f, 0.0f, -70.0f);

      		glColor3f(0.2f, 0.2f, 0.8f);
      		glVertex3f(15.0f, 0.0f, -70.0f);
      		glVertex3f(0.0f, 0.0f, -70.0f);
      		glVertex3f(0.0f, 0.0f, -53.0f);

      //由於背面被消除,背面再畫一次
      		glColor3f(0.3f, 1.0f, 0.2f);
      		glVertex3f(0.0f, 0.0f, -70.0f);
      		glVertex3f(0.0f, 0.0f, -53.0f);
      		glVertex3f(0.0f, 15.0f, -70.0f);
      
      		glColor3f(0.7f, 0.5f, 0.3f);
      		glVertex3f(0.0f, 0.0f, -53.0f);
      		glVertex3f(-15.0f, 0.0f, -70.0f);
      		glVertex3f(0.0f, 0.0f, -70.0f);

      		glColor3f(0.2f, 0.2f, 0.8f);
      		glVertex3f(0.0f, 0.0f, -70.0f);
      		glVertex3f(15.0f, 0.0f, -70.0f);
      		glVertex3f(0.0f, 0.0f, -53.0f);

      // 左翼 
      		glColor3ub(128,128,128);
      		glVertex3f(0.0f,2.0f,27.0f);
      		glVertex3f(-60.0f, 2.0f, -8.0f);
      		glVertex3f(60.0f, 2.0f, -8.0f);

      		glColor3ub(64,64,64);
      		glVertex3f(60.0f, 2.0f, -8.0f);
      		glVertex3f(0.0f, 7.0f, -8.0f);
      		glVertex3f(0.0f,2.0f,27.0f);

      		glColor3ub(192,192,192);
      		glVertex3f(60.0f, 2.0f, -8.0f);
      		glVertex3f(-60.0f, 2.0f, -8.0f);
      		glVertex3f(0.0f,7.0f,-8.0f);

      //右翼 
      		glColor3ub(64,64,64);
      		glVertex3f(0.0f,2.0f,27.0f);
      		glVertex3f(0.0f, 7.0f, -8.0f);
      		glVertex3f(-60.0f, 2.0f, -8.0f);
    	glEnd();
  	glPopMatrix();
  	glutSwapBuffers();	
}

void specialkeys(int key,int x,int y)
{
	if(key == GLUT_KEY_UP)
    	xRot-= 5.0f;
	if(key == GLUT_KEY_DOWN)
    	xRot += 5.0f;
	if(key == GLUT_KEY_LEFT)
    	yRot -= 5.0f;
	if(key == GLUT_KEY_RIGHT)
    	yRot += 5.0f;
  	if(key > 356.0f)
    	xRot = 0.0f;
  	if(key < -1.0f)
    	xRot = 355.0f;
  	if(key > 356.0f)
    	yRot = 0.0f;
	if(key < -1.0f)
    	yRot = 355.0f;
	glutPostRedisplay();//標記重繪 
} 

void reshape(int w,int h)						
{								
	GLfloat nRange = 100.0f; 
 	if (h == 0)   
 	{ 
	 	h = 1; 
 	}
 	glViewport(0, 0, w, h);
 	glMatrixMode(GL_PROJECTION);												//設定當前矩陣為投影矩陣  
	glLoadIdentity();															//將當前使用者座標系重置   
	GLfloat aspect = (GLfloat)w/(GLfloat)h; 
	if (w<=h)																	//設定投影    
	{ 
		glOrtho(-nRange, nRange, -nRange/aspect, nRange/aspect, -nRange, nRange);//引數為:x軸左、右;y軸下、上;z軸裡、外 
	} 
	else 
	{
		glOrtho(-nRange*aspect, nRange*aspect, -nRange, nRange, -nRange, nRange);//重新定義了裁剪區域,但保持縱橫比不變 
	}
	glMatrixMode(GL_MODELVIEW);													 //將當前矩陣設定為模型檢視矩陣 
	glLoadIdentity(); 
}

int main_light_material()
{
  glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
  glutInitWindowSize(800,600);
  glutCreateWindow("test");
  glutReshapeFunc(reshape);
  glutSpecialFunc(specialkeys);
  glutDisplayFunc(aircraft);
  setuprc_000();
  glutMainLoop();
  return 0;
} 
b.綜合栗子2------光照與法線設定:
<pre name="code" class="cpp">#include "grapg.h"
static GLfloat xRot=0.0f;
static GLfloat yRot=0.0f;
void countnormal(GLfloat normal[],GLfloat p1[],GLfloat p2[],GLfloat p3[])		//叉乘計算平面法線向量 
{
	GLfloat v1[]={0.0f,0.0f,0.0f};
	GLfloat v2[]={0.0f,0.0f,0.0f};	
	v1[0]=p2[0]-p1[0];
	v1[1]=p2[1]-p1[1];
	v1[2]=p2[2]-p1[2];
	v2[0]=p3[0]-p1[0];
	v2[1]=p3[1]-p1[1];
	v2[2]=p3[2]-p1[2];
	normal[0]=v1[1]*v2[2]-v1[2]*v2[1];
	normal[1]=v1[2]*v2[0]-v1[0]*v2[2];
	normal[2]=v1[0]*v2[1]-v1[1]*v2[0];
}
void aircraft_001()
{
	GLfloat normal[]={0.0f,0.0f,0.0f};
	GLfloat p1[]={0.0f,0.0f,0.0f};
	GLfloat p2[]={0.0f,0.0f,0.0f};
	GLfloat p3[]={0.0f,0.0f,0.0f};

	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glPushMatrix();
		glRotatef(xRot, 1.0f, 0.0f, 0.0f);
    	glRotatef(yRot, 0.0f, 1.0f, 0.0f);
		glColor3ub(128,128,128);
    	glBegin(GL_TRIANGLES);
    	//機頭
    		p1[0]=-15.0f;p1[1]=0.0f;p1[2]=30.0f;
    		p2[0]=15.0f;p2[1]=0.0f;p2[2]=30.0f;
    		p3[0]=0.0f;p3[1]=0.0f;p3[2]=60.0f;
    		countnormal(normal,p1,p2,p3);
    		glNormal3f(normal[0],normal[1],normal[2]);							//因為此處均是三角形,為平面,所以指定一個法線向量就行 
      		glVertex3f(p1[0],p1[1],p1[2]);
      		glVertex3f(p2[0],p2[1],p2[2]);
      		glVertex3f(p3[0],p3[1],p3[2]);

      		p1[0]=-15.0f;p1[1]=0.0f;p1[2]=30.0f;
    		p2[0]=0.0f;p2[1]=0.0f;p2[2]=60.0f;
    		p3[0]=0.0f;p3[1]=15.0f;p3[2]=30.0f;
    		countnormal(normal,p1,p2,p3);
    		glNormal3f(normal[0],normal[1],normal[2]);
      		glVertex3f(p1[0],p1[1],p1[2]);
      		glVertex3f(p2[0],p2[1],p2[2]);
      		glVertex3f(p3[0],p3[1],p3[2]);

      		p1[0]=0.0f;p1[1]=0.0f;p1[2]=60.0f;
    		p2[0]=15.0f;p2[1]=0.0f;p2[2]=30.0f;
    		p3[0]=0.0f;p3[1]=15.0f;p3[2]=30.0f;
    		countnormal(normal,p1,p2,p3);
    		glNormal3f(normal[0],normal[1],normal[2]);
      		glVertex3f(p1[0],p1[1],p1[2]);
      		glVertex3f(p2[0],p2[1],p2[2]);
      		glVertex3f(p3[0],p3[1],p3[2]);
      //機身
      		p1[0]=-15.0f;p1[1]=0.0f;p1[2]=30.0f;
    		p2[0]=0.0f;p2[1]=15.0f;p2[2]=30.0f;
    		p3[0]=0.0f;p3[1]=0.0f;p3[2]=-53.0f;
    		countnormal(normal,p1,p2,p3);
    		glNormal3f(normal[0],normal[1],normal[2]);
      		glVertex3f(p1[0],p1[1],p1[2]);
      		glVertex3f(p2[0],p2[1],p2[2]);
      		glVertex3f(p3[0],p3[1],p3[2]);

      		p1[0]=0.0f;p1[1]=15.0f;p1[2]=30.0f;
    		p2[0]=15.0f;p2[1]=0.0f;p2[2]=30.0f;
    		p3[0]=0.0f;p3[1]=0.0f;p3[2]=-53.0f;
    		countnormal(normal,p1,p2,p3);
    		glNormal3f(normal[0],normal[1],normal[2]);
      		glVertex3f(p1[0],p1[1],p1[2]);
      		glVertex3f(p2[0],p2[1],p2[2]);
      		glVertex3f(p3[0],p3[1],p3[2]);

      		p1[0]=15.0f;p1[1]=0.0f;p1[2]=30.0f;
    		p2[0]=-15.0f;p2[1]=0.0f;p2[2]=30.0f;
    		p3[0]=0.0f;p3[1]=0.0f;p3[2]=-53.0f;
    		countnormal(normal,p1,p2,p3);
    		glNormal3f(normal[0],normal[1],normal[2]);
      		glVertex3f(p1[0],p1[1],p1[2]);
      		glVertex3f(p2[0],p2[1],p2[2]);
      		glVertex3f(p3[0],p3[1],p3[2]);

      //機尾巴
      		p1[0]=0.0f;p1[1]=0.0f;p1[2]=-53.0f;
    		p2[0]=0.0f;p2[1]=0.0f;p2[2]=-70.0f;
    		p3[0]=0.0f;p3[1]=15.0f;p3[2]=-70.0f;
    		countnormal(normal,p1,p2,p3);
    		glNormal3f(normal[0],normal[1],normal[2]);
      		glVertex3f(p1[0],p1[1],p1[2]);
      		glVertex3f(p2[0],p2[1],p2[2]);
      		glVertex3f(p3[0],p3[1],p3[2]);

      		p1[0]=-15.0f;p1[1]=0.0f;p1[2]=-70.0f;
    		p2[0]=0.0f;p2[1]=0.0f;p2[2]=-53.0f;
    		p3[0]=0.0f;p3[1]=0.0f;p3[2]=-70.0f;
    		countnormal(normal,p1,p2,p3);
    		glNormal3f(normal[0],normal[1],normal[2]);
      		glVertex3f(p1[0],p1[1],p1[2]);
      		glVertex3f(p2[0],p2[1],p2[2]);
      		glVertex3f(p3[0],p3[1],p3[2]);

      		p1[0]=15.0f;p1[1]=0.0f;p1[2]=-70.0f;
    		p2[0]=0.0f;p2[1]=0.0f;p2[2]=-70.0f;
    		p3[0]=0.0f;p3[1]=0.0f;p3[2]=-53.0f;
    		countnormal(normal,p1,p2,p3);
    		glNormal3f(normal[0],normal[1],normal[2]);
      		glVertex3f(p1[0],p1[1],p1[2]);
      		glVertex3f(p2[0],p2[1],p2[2]);
      		glVertex3f(p3[0],p3[1],p3[2]);

      //由於背面被消除,背面再畫一次
      		p1[0]=0.0f;p1[1]=0.0f;p1[2]=-70.0f;
    		p2[0]=0.0f;p2[1]=0.0f;p2[2]=-53.0f;
    		p3[0]=0.0f;p3[1]=15.0f;p3[2]=-70.0f;
    		countnormal(normal,p1,p2,p3);
    		glNormal3f(normal[0],normal[1],normal[2]);
      		glVertex3f(p1[0],p1[1],p1[2]);
      		glVertex3f(p2[0],p2[1],p2[2]);
      		glVertex3f(p3[0],p3[1],p3[2]);
      
      		p1[0]=0.0f;p1[1]=0.0f;p1[2]=-53.0f;
    		p2[0]=-15.0f;p2[1]=0.0f;p2[2]=-70.0f;
    		p3[0]=0.0f;p3[1]=0.0f;p3[2]=-70.0f;
    		countnormal(normal,p1,p2,p3);
    		glNormal3f(normal[0],normal[1],normal[2]);
      		glVertex3f(p1[0],p1[1],p1[2]);
      		glVertex3f(p2[0],p2[1],p2[2]);
      		glVertex3f(p3[0],p3[1],p3[2]);

      		p1[0]=0.0f;p1[1]=0.0f;p1[2]=-70.0f;
    		p2[0]=15.0f;p2[1]=0.0f;p2[2]=-70.0f;
    		p3[0]=0.0f;p3[1]=0.0f;p3[2]=-53.0f;
    		countnormal(normal,p1,p2,p3);
    		glNormal3f(normal[0],normal[1],normal[2]);
      		glVertex3f(p1[0],p1[1],p1[2]);
      		glVertex3f(p2[0],p2[1],p2[2]);
      		glVertex3f(p3[0],p3[1],p3[2]);

      // 左翼 
      		p1[0]=0.0f;p1[1]=2.0f;p1[2]=27.0f;
    		p2[0]=-60.0f;p2[1]=2.0f;p2[2]=-8.0f;
    		p3[0]=60.0f;p3[1]=2.0f;p3[2]=-8.0f;
    		countnormal(normal,p1,p2,p3);
    		glNormal3f(normal[0],normal[1],normal[2]);
      		glVertex3f(p1[0],p1[1],p1[2]);
      		glVertex3f(p2[0],p2[1],p2[2]);
      		glVertex3f(p3[0],p3[1],p3[2]);

      		p1[0]=60.0f;p1[1]=2.0f;p1[2]=-8.0f;
    		p2[0]=0.0f;p2[1]=7.0f;p2[2]=-8.0f;
    		p3[0]=0.0f;p3[1]=2.0f;p3[2]=27.0f;
    		countnormal(normal,p1,p2,p3);
    		glNormal3f(normal[0],normal[1],normal[2]);
      		glVertex3f(p1[0],p1[1],p1[2]);
      		glVertex3f(p2[0],p2[1],p2[2]);
      		glVertex3f(p3[0],p3[1],p3[2]);

      		p1[0]=60.0f;p1[1]=2.0f;p1[2]=-8.0f;
    		p2[0]=-60.0f;p2[1]=2.0f;p2[2]=-8.0f;
    		p3[0]=0.0f;p3[1]=7.0f;p3[2]=-8.0f;
    		countnormal(normal,p1,p2,p3);
    		glNormal3f(normal[0],normal[1],normal[2]);
      		glVertex3f(p1[0],p1[1],p1[2]);
      		glVertex3f(p2[0],p2[1],p2[2]);
      		glVertex3f(p3[0],p3[1],p3[2]);
      //右翼 
      		p1[0]=0.0f;p1[1]=2.0f;p1[2]=27.0f;
    		p2[0]=0.0f;p2[1]=7.0f;p2[2]=-8.0f;
    		p3[0]=-60.0f;p3[1]=2.0f;p3[2]=-8.0f;
    		countnormal(normal,p1,p2,p3);
    		glNormal3f(normal[0],normal[1],normal[2]);
      		glVertex3f(p1[0],p1[1],p1[2]);
      		glVertex3f(p2[0],p2[1],p2[2]);
      		glVertex3f(p3[0],p3[1],p3[2]);
      		glVertex3f(0.0f,2.0f,27.0f);
      		glVertex3f(0.0f, 7.0f, -8.0f);
      		glVertex3f(-60.0f, 2.0f, -8.0f);
    	glEnd();
  	glPopMatrix();
  	glutSwapBuffers();	
}

void setuprc_001()
{
	GLfloat ambientLight[]={0.3f,0.3f,0.3f,1.0f};								//環境光rgba
	GLfloat diffuseLight[]={0.7f,0.7f,0.7f,1.0f};								//漫射光 
	GLfloat specular[]={1.0f,1.0f,1.0f,1.0f};
	glEnable(GL_DEPTH_TEST);													//開啟深度測試 
	glEnable(GL_CULL_FACE);														//開啟隱藏面,因為後面設定了材料的顏色追蹤,只追蹤正面,所以要先剔除反面,在把反面用正面的方式畫上去 
	glFrontFace(GL_CCW);														//設定逆時針為正面
	
	glEnable(GL_LIGHTING);														//開啟光照
	glLightfv(GL_LIGHT0,GL_AMBIENT,ambientLight);								//設定光照 
	glLightfv(GL_LIGHT0,GL_DIFFUSE,diffuseLight);
	glLightfv(GL_LIGHT0,GL_SPECULAR,specular);
	glEnable(GL_LIGHT0);
	
	GLfloat specref[]={1.0f,1.0f,1.0f,1.0f};
	glEnable(GL_COLOR_MATERIAL);
	glColorMaterial(GL_FRONT,GL_AMBIENT_AND_DIFFUSE);							//設定材料的顏色追蹤 
	glMaterialfv(GL_FRONT,GL_SPECULAR,specref);
	//GL_SHININESS屬性。該屬性只有一個值,稱為“鏡面指數”,取值範圍是0到128。
	//該值越小,表示材質越粗糙,點光源發射的光線照射到上面,也可以產生較大的亮點。
	//該值越大,表示材質越類似於鏡面,光源照射到上面後,產生較小的亮點。
	glMateriali(GL_FRONT,GL_SHININESS,128);
	
	glClearColor(0.0f,0.0f,1.0f,1.0f); 
	glEnable(GL_NORMALIZE);														//開啟自動標準化法線向量 
}

void specialkeys_001(int key,int x,int y)
{
	if(key == GLUT_KEY_UP)
    	xRot-= 5.0f;
	if(key == GLUT_KEY_DOWN)
    	xRot += 5.0f;
	if(key == GLUT_KEY_LEFT)
    	yRot -= 5.0f;
	if(key == GLUT_KEY_RIGHT)
    	yRot += 5.0f;
  	if(key > 356.0f)
    	xRot = 0.0f;
  	if(key < -1.0f)
    	xRot = 355.0f;
  	if(key > 356.0f)
    	yRot = 0.0f;
	if(key < -1.0f)
    	yRot = 355.0f;
	glutPostRedisplay();														//標記重繪 
} 

void reshape_001(int w,int h)						
{								
	GLfloat faspect;
	GLfloat lightPos[] = { -50.f, 50.0f, 100.0f, 1.0f };
	if(h == 0)
    	h = 1;
  	glViewport(0, 0, w, h);														//視口大小設定 
  	glMatrixMode(GL_PROJECTION);												//設定投影 
  	glLoadIdentity();
 	faspect = (GLfloat) w / (GLfloat) h;
  	gluPerspective(45.0f, faspect, 1.0f, 225.0f);

  	glMatrixMode(GL_MODELVIEW);
  	glLoadIdentity();

  	glLightfv(GL_LIGHT0,GL_POSITION,lightPos);									//設定光源位置 
  	glTranslatef(0.0f, 0.0f, -150.0f);
}

int main_light_material()
{
  glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
  glutInitWindowSize(800,600);
  glutCreateWindow("test");
  glutReshapeFunc(reshape_001);
  glutSpecialFunc(specialkeys_001);
  glutDisplayFunc(aircraft_001);
  setuprc_001();
  glutMainLoop();
  return 0;
}