OpenGL提供了多種形式的光源,如點光源
、平行光源
和聚光燈光源
等。全部光源都使用 glLight*接口來設置光源屬性,其中包括 glLight{if} 和 glLight{if}v 兩類。code
GLfloat ambient[] = {0.3f, 0.3f, 0.3f, 1.0f}; // 環境強度 GLfloat diffuse[] = {1.0f, 1.0f, 1.0f, 1.0f}; // 散射強度 GLfloat specular[] = {1.0f, 1.0f, 1.0f, 1.0f}; // 鏡面強度 // 點光源, GL_POSITION屬性的最後一個參數爲1 GLfloat position[] = {-3.0f, -3.4f, -8.8f, 1.0f}; glLightfv(GL_LIGHT0, GL_POSITION, position); glLightfv(GL_LIGHT0, GL_AMBIENT, ambient); glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse); glLightfv(GL_LIGHT0, GL_SPECULAR, specular); // 平行光源, GL_POSITION屬性的最後一個參數爲0 GLfloat direction[] = {-3.0f, -3.4f, -8.8f, 0.0f}; glLightfv(GL_LIGHT1, GL_POSITION, direction); glLightfv(GL_LIGHT1, GL_AMBIENT, ambient); glLightfv(GL_LIGHT1, GL_DIFFUSE, diffuse); glLightfv(GL_LIGHT1, GL_SPECULAR, specular); // 聚光燈光源, 須要指定位置、方向、光錐半角 GLfloat spot_direction[] = {-3.0f, -3.4f, -8.8f}; glLightfv(GL_LIGHT2, GL_POSITION, position); glLightfv(GL_LIGHT2, GL_SPOT_DIRECTION, spot_direction); glLightfv(GL_LIGHT2, GL_SPOT_CUTOFF, 45.0); glLightfv(GL_LIGHT2, GL_AMBIENT, ambient); glLightfv(GL_LIGHT2, GL_DIFFUSE, diffuse); glLightfv(GL_LIGHT2, GL_SPECULAR, specular);
GL_LIGHT0、GL_LIGHT一、GL_LIGHT二、...、GL_LIGHT七、...
等。在片斷着色中可經過gl_LightSource[0]、gl_LightSource[1]、gl_LightSource[2]、...、gl_LightSource[7]、...
等內建變量訪問各個光源的參數;glEnable(GL_LIGHTING)
啓用光照機制,而後使用glEnable(GL_LIGHTx)
與glDisable(GL_LIGHTx)
打開或關閉相應光源(其中x表明光源序號);控制光源的矩陣變換和控制圖元的矩陣變換相同,故最終光源表現出來的性質(如點光源位置是固定在世界座標系某點仍是跟隨鏡頭移動,平行光源的方向在世界座標系下是不變的仍是跟隨相機移動等)與提交光源位置或朝向(glLight*())和視點變換(gluLookAt())的前後順序是息息相關的。據此咱們能夠定義出各式各樣的常見光源,如太陽光、白熾燈、汽車前照燈等。對象
若是在視點變換後提交光源位置或朝向,那麼光源就能夠看做一個普通的幾何對象,提交的座標是在世界座標系中度量的,對普通幾何對象的各類變換一樣適用於光源。可通俗的理解爲視圖變換矩陣做用於光源的位置或朝向參數上,此過程就如同世界座標系下的普通物體轉換至觀察座標系下。
若是程序裏沒有視點變換,說明世界座標系和攝像機座標系重合,光源也能夠看做一個普通的幾何對象。表現出這種性質的常見光源有太陽光,家裏的白熾燈等。示例代碼以下:接口
void myDisplay() { glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); gluLookAt(0, 0, 0, 0, 0, -1, 0, 1, 0); GLfloat sun_light_position[] = {-139.5f, -153.4f, -68.8f, 0.0f}; glLightfv(GL_LIGHT0, GL_POSITION, sun_light_position); // 光源的其餘參數可在程序初始化時設置 glPushMatrix(); glTranslated(-2.5, 6.9, -184.8); glRotated(87.4, 0, 0, 1); drawOBJ(); glPopMatrix(); ... }
注意:
光源位置或朝向的指定不能處於某個模型的模型變換代碼之間(如上例中的glPushMatrix()與glPopMatrix()之間),不然光源參數會受到影響。因此最好將光源位置或朝向設置代碼放在緊跟gluLookAt以後。it
若是在視點變換前提交光源位置,視點和光源將捆綁在一塊兒,即兩者相對位置不變,一塊兒運動。此時,能夠理解爲提交的光源位置是在相機座標系中度量的(位置參數的默認值是(0.0, 0.0, 1.0, 0.0), 就是在攝像機座標系中度量的)。亦可通俗的理解爲視圖變換矩陣未做用於光源的位置或朝向參數上。光源的位置朝向參數在觀察座標系的值會保持不變。
表現出這種性質的常見光源有汽車前照燈(以駕駛員的視角觀察視角)或礦工頭上的礦燈。示例代碼以下:io
void myDisplay() { glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); GLfloat sun_light_position[] = {-139.5f, -153.4f, -68.8f, 0.0f}; glLightfv(GL_LIGHT0, GL_POSITION, sun_light_position); // 光源的其餘參數可在程序初始化時設置 gluLookAt(0, 0, 0, 0, 0, -1, 0, 1, 0); glPushMatrix(); glTranslated(-2.5, 6.9, -184.8); glRotated(87.4, 0, 0, 1); drawOBJ(); glPopMatrix(); ... }