今天學習了移動光源,奉上源代碼:
#pragma comment(lib, "glaux.lib")
#include "gl\glaux.h"
#include <gl\glut.h>

float yRot = 0;
unsigned int nPre = 0;

GLfloat light_position[4] =
{0,0,0,1}; //光位置

GLfloat light_diffuse[4] =
{1,0,1,1}; //光的漫反色

GLfloat light_direction[4] =
{-1, -2, -1, 1}; //光源聚光燈方向

GLfloat light_change[3] =
{3,3,-1}; //光源移動位置。

void display(void)


{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // 清楚顏色數據和深度數據(清屏)
glColor3f(1.0,1.0,1.0);
glLoadIdentity(); //初始變換矩陣為單位矩陣

glTranslated(0,-1,-5); //平移0,0,-5向Z負方向平移5個單位

glPushMatrix(); //壓縮矩陣,設定光源的位置
glDisable(GL_LIGHTING);
glRotatef(yRot, 0, 1, 0); //光源的旋轉
glTranslatef(light_change[0],light_change[1],light_change[2]); //光源的位置
glTranslatef(light_position[0], light_position[1],light_position[2]); //光源位置
glutSolidSphere(0.1, 4,4);//利用庫函數繪制一個半徑為1的球體。表示光源在這里
glEnable(GL_LIGHTING);
glLightfv(GL_LIGHT0, GL_POSITION, light_position);
glPopMatrix();
light_direction[0] = -light_change[0];
light_direction[1] = -light_change[1];
light_direction[2] = -light_change[2];
glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, light_direction);
glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse);
glPopMatrix(); //光源設置完畢

glPushMatrix(); //要入矩陣,繪制地面
glBegin(GL_QUADS);
glVertex3f(-3,0,3);
glVertex3f(3,0,3);
glVertex3f(3,0,-3);
glVertex3f(-3,0,-3);
glEnd();
glPopMatrix(); //地面繪制完畢

glPushMatrix(); //壓入變換矩陣那
glutSolidSphere(1, 30,30);//利用庫函數繪制一個半徑為1的球體。
glPopMatrix(); //彈出矩陣。

glutSwapBuffers(); //交換緩沖區。顯示圖形
}

//初始化
void init (void)


{
//srand(0); 隨機種子
glClearColor (0.5, 0.5, 0.5, 0.0); //清理顏色,為黑色,(也可認為是背景顏色)

GLfloat light_param[] =
{ 1, 1, 1, 1.0 }; //初始化光參數。
//glLightfv(GL_LIGHT0, GL_AMBIENT, light_param); //設置光為環境光。
//glLightf(GL_LIGHT0, GL_SPOT_CUTOFF, 45.0); //設置聚光的范圍為45度。
glLightf(GL_LIGHT0,GL_SPOT_EXPONENT,2.0); //設置聚光燈的聚光強度。
glMaterialfv(GL_FRONT, GL_SPECULAR, light_param); //設置材質的漫反射屬性
//glMaterialfv(GL_FRONT, GL_AMBIENT, light_param); //設置材質的環境屬性
glMaterialf(GL_FRONT, GL_SHININESS, 64); //設置材質的高光屬性

glEnable(GL_LIGHTING); //啟動光照
glEnable(GL_LIGHT0); //啟動GL_LIGHTO光
glCullFace(GL_BACK); //剔除背面
glEnable(GL_CULL_FACE); //啟動剔除
glDepthFunc(GL_LEQUAL); //深度檢測為小于等于
glEnable(GL_DEPTH_TEST); //啟動深度檢測
glFrontFace(GL_CCW); //定義逆時針為正面

}

//當窗口大小改變時,會調用這個函數
void reshape(GLsizei w,GLsizei h)


{
//這里小說明一下:矩陣模式是不同的,他們各自有一個矩陣。投影相關
//只能用投影矩陣。(只是目前情況下哦,等我學多了可能就知道為什么了。)

glViewport(0,0,w,h); //設置視口
glMatrixMode(GL_PROJECTION); //設置矩陣模式為投影變換矩陣,
glLoadIdentity(); //變為單位矩陣
gluPerspective(60, (GLfloat)w / h, 0, 1000); //設置投影矩陣
//glOrtho(-6.0, 6.0, -6.0 * h / w, 6.0* h / w, -10, 10); //為了不變形,則要長和寬成比例
glMatrixMode(GL_MODELVIEW); //設置矩陣模式為視圖矩陣(模型)
glLoadIdentity(); //變為單位矩陣
}

void Keyboard(unsigned char key, int x, int y)


{
}

//閑置函數,當主循環空閑時就會調用這個函數
void MyIdle(void)


{
unsigned int nNow = ::GetTickCount();
float delt = nNow - nPre;
if (delt > 100)

{
nPre = nNow;
yRot += 0.1 * delt; //旋轉角度

/**//*light_diffuse[0] = (rand() % 255) / 255.0;//太花不用了。
light_diffuse[1] = (rand() % 255) / 255.0;
light_diffuse[2] = (rand() % 255) / 255.0;*/
glutPostRedisplay();
}
}

int main(int argc, char** argv)


{
glutInit(&argc, argv); //Opnegl初始化
glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGBA); //設置顯示模式為雙緩沖,RGEBA

glutInitWindowSize (800, 600); //窗口大小
glutInitWindowPosition (100, 100); //窗口位置
glutCreateWindow ("hello"); //創建一個標題為hello的窗口
init (); //初始化資源,這里一定要在創建窗口以后,不然會無效。
glutDisplayFunc(display); //窗口大小改變時的回調
glutReshapeFunc(reshape); //繪制圖形時的回調
glutKeyboardFunc(Keyboard);
glutIdleFunc(MyIdle);
glutMainLoop(); //主循環。
return 0;
}
學習光源已經好幾天,始終入不了門。不過這次學習移動光源之后,有一點點感覺。函數的功能就不能介紹了。書上有,再次分享一下這本書,下載鏈接為:
http://download.csdn.net/source/1247246主要心得:
1.每個光源GL_LIGHT0--7都有相應的環境光,點光源,聚光燈,漫射光等所有光的屬性,我們設置的屬性也只屬于這個光源。當光源照射到物體上時,OpenGL的函數會用這些所有的屬性與該物體做光照射的計算,實現光的效果。而沒有照射到得物體就不會計算。例如設置了環境光為[0.5,0.5,0.5,1.0],漫反射光為[1,0,1,1];如果照射到物體上,他會分別計算環境光的效果和漫射光的效果,然后再疊加他們的效果。疊加方式為取分量的最大值。若物體沒有被照射,則所有效果都不會被計算。也就是說會呈現黑色。我開始就沒有理解這些屬性關系,以為只要設置的環境光之后就能所有物體都能用了。其實不然,只有照射到得物體才會計算。如果想所有物體都有環境光,設置全局環境光才能達到這個效果。
2.什么時候計算光照,在物體繪制的時候光照效果會計算。他會把光照設置光源的屬性通過矩陣變換到該物體坐標系中,然后在進行光照計算。也就是他會跟著物體變化。例如:設置了一個點光源在這個物體的前方。如果是通過矩陣變換來改變物體的位置。那么光源會一直在該物體的前方,因為他是以物體坐標系參照的。所以這里要注意,并不是說物體glTranslate(),glRotate()之后光照會發生變化。光的位置也會跟著變,使光照不變化。如果你想光源不隨著變化的話,在設置光源位置的時候,就要反著變一下。在設置光源的時候,也可以用平移旋轉的能矩陣運算。
3.兩個物體之間光照是否有影響:兩個物體光照不會有影響,也就是說不會出現一個物體遮住另一個物體的情況。因為他是在一個物體的物體坐標系中計算效果的,而且只對該物體計算效果。所以不會對其他物體產生影響,如果要真實,就得自己算出陰影在繪制。我還沒有學會。呵呵。如果不想物體產生光照,就用glDisable(GL_LIGHTIING);就可以了。在繪制其他物體再啟動他。
4.聚光燈:聚光燈我是沒有弄懂的,特別是他的方向,很暈很暈。感覺是向量,有感覺不像向量。到底怎么回事還得努力學習,希望能碰到高手指點一下。
5.其他方面:
glFrontFace(GL_CW); 確定順時針為front面,默認是GL_CCW既逆時針為正面。所以在繪制茶壺和球的時候會出問題,在繪制一個矩形的時候也要注意這個問題。