歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> Linux編程 >> OpenGL光源位置

OpenGL光源位置

日期:2017/3/1 9:16:58   编辑:Linux編程

一、OpenGL光源簡介

OpenGL提供了多種形式的光源,如點光源平行光源聚光燈光源等。所有光源都使用 glLight*接口來設置光源屬性,其中包括 glLight{if}glLight{if}v 兩類。

1、示例光源

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);

2、注意事項

  • 最大光源數:不同的硬件支持的光源數量不一樣,但至少會支持8個光源。表示光源的常量有GL_LIGHT0、GL_LIGHT1、GL_LIGHT2、...、GL_LIGHT7、...等。在片段著色中可通過gl_LightSource[0]、gl_LightSource[1]、gl_LightSource[2]、...、gl_LightSource[7]、...等內建變量訪問各個光源的參數;
  • 啟用和關閉光源 :可通過glEnable(GL_LIGHTING)啟用光照機制,然後使用glEnable(GL_LIGHTx)glDisable(GL_LIGHTx)打開或關閉相應光源(其中x代表光源序號);
  • 模型頂點必須指定法向:OpenGL光照機制是通過計算物體表面法向與入射光線的夾角來確定表面的亮度。故若傳入的模型沒有指定法向,則最終結果會變得一片漆黑;若法向有問題,最終結果也會莫名其妙。

二、控制光源的位置和方向

控制光源的矩陣變換和控制圖元的矩陣變換相同,故最終光源表現出來的性質(如點光源位置是固定在世界坐標系某點還是跟隨鏡頭移動,平行光源的方向在世界坐標系下是不變的還是跟隨相機移動等)與提交光源位置或朝向(glLight*())和視點變換(gluLookAt())的先後順序是息息相關的。據此我們可以定義出各式各樣的常見光源,如太陽光、白熾燈、汽車前照燈等。

1、定義在世界坐標系下的光源

如果在視點變換後提交光源位置或朝向,那麼光源就可以看作一個普通的幾何對象,提交的坐標是在世界坐標系中度量的,對普通幾何對象的各種變換同樣適用於光源。可通俗的理解為視圖變換矩陣作用於光源的位置或朝向參數上,此過程就如同世界坐標系下的普通物體轉換至觀察坐標系下。如果程序裡沒有視點變換,說明世界坐標系和攝像機坐標系重合,光源也可以看作一個普通的幾何對象。表現出這種性質的常見光源有太陽光,家裡的白熾燈等。示例代碼如下:

 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之後。

2、定義在相機坐標系下的光源

如果在視點變換前提交光源位置,視點和光源將捆綁在一起,即二者相對位置不變,一起運動。此時,可以理解為提交的光源位置是在相機坐標系中度量的(位置參數的默認值是(0.0, 0.0, 1.0, 0.0), 就是在攝像機坐標系中度量的)。亦可通俗的理解為視圖變換矩陣未作用於光源的位置或朝向參數上。光源的位置朝向參數在觀察坐標系的值會保持不變。表現出這種性質的常見光源有汽車前照燈(以駕駛員的視角觀察視角)或礦工頭上的礦燈。示例代碼如下:

 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();
    ...
 }

OpenGL 渲染篇 http://www.linuxidc.com/Linux/2011-10/45756.htm

Ubuntu 13.04 安裝 OpenGL http://www.linuxidc.com/Linux/2013-05/84815.htm

OpenGL三維球體數據生成與繪制【附源碼】 http://www.linuxidc.com/Linux/2013-04/83235.htm

Ubuntu下OpenGL編程基礎解析 http://www.linuxidc.com/Linux/2013-03/81675.htm

如何在Ubuntu使用eclipse for c++配置OpenGL http://www.linuxidc.com/Linux/2012-11/74191.htm

《OpenGL超級寶典》學習筆記 http://www.linuxidc.com/Linux/2013-10/91414.htm

Copyright © Linux教程網 All Rights Reserved