• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            OpenGL特殊光處理

             目 錄
              14.1 光照模型
              14.2 光源位置與衰減
              14.3 聚光和多光源
              14.4 光源位置與方向的控制
              14.5 輻射光

             

              本章內(nèi)容是基礎(chǔ)篇第七章的補(bǔ)充和提高。這一章主要講述一些特殊光效果處理,如全局環(huán)境光、雙面光照、光的衰減、聚光、多光源、光源位置的改變等等。讀者若有興趣,可以按照本章例程的方法作出許多變換,則會(huì)出現(xiàn)意想不到的效果,充分發(fā)揮你的藝術(shù)才能。

            14.1、光照模型
              OpenGL光照模型的概念由一下三部分組成:1)全局泛光強(qiáng)度、2)視點(diǎn)位置在景物附近還是在無(wú)窮遠(yuǎn)處、3)物體的正面和背面是否分別進(jìn)行光照計(jì)算。

              14.1.1 全局環(huán)境光
              正如前面基礎(chǔ)篇中所提到的一樣,每個(gè)光源都能對(duì)一個(gè)場(chǎng)景提供環(huán)境光。此外,還有一個(gè)環(huán)境光,它不來(lái)自任何特定的光源,即稱為全局環(huán)境光。下面用參數(shù)GL_LIGHT_MODEL_AMBIENT來(lái)說(shuō)明全局環(huán)境光的RGBA強(qiáng)度:
            GLfloat lmodel_ambient[]={0.2,0.2,0.2,1.0};
            glLightModelfv(GLLIGHT_MODEL_AMBIENT,lmodel_ambient);

              在這個(gè)例子中,lmodel_ambient所用的值為GL_LIGHT_MODEL_AMBIENT的缺省值。這些數(shù)值產(chǎn)生小量的白色環(huán)境光。

              14.1.2 近視點(diǎn)與無(wú)窮遠(yuǎn)視點(diǎn)
              視點(diǎn)位置能影響鏡面高光的計(jì)算,也就是說(shuō),頂點(diǎn)的高光強(qiáng)度依賴于頂點(diǎn)法向量,從頂點(diǎn)到光源的方向和從頂點(diǎn)到視點(diǎn)的方向。實(shí)際上,調(diào)用光照函數(shù)并不能移動(dòng)視點(diǎn)。但是可以對(duì)光照計(jì)算作出不同的假定,這樣視點(diǎn)似乎移動(dòng)了。對(duì)于一個(gè)無(wú)窮遠(yuǎn)視點(diǎn),視點(diǎn)到任何頂點(diǎn)的方向保持固定,缺省時(shí)為無(wú)窮遠(yuǎn)視點(diǎn)。對(duì)于一個(gè)近視點(diǎn),物體每個(gè)頂點(diǎn)到視點(diǎn)的方向是不同的,需要逐個(gè)計(jì)算,從而整體性能降低,但效果更真實(shí)。下面一句函數(shù)代碼是假定為近視 點(diǎn):
             

            glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER,GL_TRUE);

              這個(gè)調(diào)用把視點(diǎn)放在視點(diǎn)坐標(biāo)系的原點(diǎn)處。若要切換到無(wú)窮遠(yuǎn)視點(diǎn),只需將參數(shù)GL_TRUE 改為GL_FALSE即可。

              14.1.3 雙面光照
              光照計(jì)算通常是對(duì)所有多邊形進(jìn)行的,無(wú)論其是正面或反面。一般情況下,設(shè)置光照條件時(shí)總是正面多邊形,因此不能對(duì)背面多邊形進(jìn)行正確地光照。在基礎(chǔ)篇的第七章中的例子里,物體是一個(gè)球,只有正面多邊形能看到,即球的外部可見(jiàn),這種情況下不必考慮背面光照。若球被砍開(kāi),其內(nèi)部的曲面是可見(jiàn)的,那么對(duì)內(nèi)部多邊形需進(jìn)行光照計(jì)算,這時(shí)應(yīng)該調(diào)用如下函數(shù):

            glLightModeli(LIGHT_MODEL_TWO_SIDE,GL_TRUE);

              啟動(dòng)雙面光照。實(shí)際上,這就是OpenGL給背面多邊形定義一個(gè)相反的法向量(相對(duì)于正面多邊形而言)。一般來(lái)說(shuō),這意味著可見(jiàn)正面多邊形和可見(jiàn)反面多邊形的法向量都面朝觀察者,而不是向里,這樣所有多邊形都能進(jìn)行正確的光照。關(guān)閉雙面光照,只需將參數(shù)GL_TRUE改為GL_FALSE即可。

            14.2、光源位置與衰減
              在基礎(chǔ)篇中已經(jīng)提到過(guò),光源有無(wú)窮遠(yuǎn)光源和近光源兩種形式。無(wú)窮遠(yuǎn)光源又稱作定向光源,即這種光到達(dá)物體時(shí)是平行光,例如現(xiàn)實(shí)生活中的太陽(yáng)光。近光源又稱作定位光源,光源在場(chǎng)景中的位置影響場(chǎng)景的光照效果,尤其影響光到達(dá)物體的方向。臺(tái)燈是定位光源的范例。在以前所有與光照有關(guān)的例子里都采用的是定向光源,如:
             

            GLfloat light_position[]={1.0,1.0,1.0,0.0};
            glLightfv(GL_LIGHT0,GL_POSITION,light_position);

              光源位置坐標(biāo)采用的齊次坐標(biāo)(x, y, z, w),這里的w為0,所以相應(yīng)的光源是定向光,(x, y, z)描述光源的方向,這個(gè)方向也要進(jìn)行模型變換。GL_POSITION的缺省值是(0.0, 0.0, 1.0, 0.0),它定義了一個(gè)方向指向Z負(fù)軸的平行光源。若w非零,光源為定位光源。(x, y, z, w)指定光源在齊次坐標(biāo)系下的具體位置,這個(gè)位置經(jīng)過(guò)模型變換等在視點(diǎn)坐標(biāo)系下保存下來(lái)。
              真實(shí)的光,離光源越遠(yuǎn)則光強(qiáng)越小。因?yàn)槎ㄏ蚬庠词菬o(wú)窮遠(yuǎn)光源,因此距離的變換對(duì)光強(qiáng)的影響幾乎沒(méi)有,所以定向光沒(méi)有衰減,而定位光有衰減。OpenGL的光衰減是通過(guò)光源的發(fā)光量乘以衰減因子計(jì)算出來(lái)的。其中衰減因子在第十章表10-2中說(shuō)明過(guò)。缺省狀態(tài)下,常數(shù)衰減因子是1.0,其余兩個(gè)因子都是0.0。用戶也可以自己定義這些值,如:
             

            glLightf(GL_LIGHT0,GL_CONSTANT_ATTENUATION,2.0);
            glLightf(GL_LIGHT0,GL_LINEAR_ATTENUATION,1.0);
            glLightf(GL_LIGHT0,GL_QUADRATIC_ATTENUATION,0.5);

              注意:環(huán)境光、漫反射光和鏡面光的強(qiáng)度都衰減,只有輻射光和全局環(huán)境光的強(qiáng)度不衰減。

            14.3、聚光和多光源

              14.3.1 聚光
              定位光源可以定義成聚光燈形式,即將光的形狀限制在一個(gè)圓錐內(nèi)。OpenGL中聚光的定義有以下幾步:
              1)定義聚光源位置。因?yàn)榫酃庠匆彩嵌ㄏ蚬庠矗运奈恢猛话愣ㄏ蚬庖粯?。如?BR>
             

            GLfloat light_position[]={1.0,1.0,1.0,1.0};
            glLightfv(GL_LIGHT0,LIGHT_POSITION,light_position);

              2)定義聚光截止角。參數(shù)GL_SPOT_CUTOFF給定光錐的軸與中心線的夾角,也可說(shuō)成是光錐頂角的一半,如圖14-1所示。缺省時(shí),這個(gè)參數(shù)為180.0,即頂角為360度,光向所有的方向發(fā)射,因此聚光關(guān)閉。一般在聚光啟動(dòng)情況下,聚光截止角限制在[0.0, 90.0] 之間,如下面一行代碼設(shè)置截止角為45度:
             

            glLightf(GL_LIGHT0,GL_SPOT_CUTOFF,45.0);

              3)定義聚光方向。聚光方向決定光錐的軸,它齊次坐標(biāo)定義,其缺省值為(0.0, 0.0, -1.0),即指向Z負(fù)軸。聚光方向也要進(jìn)行幾何變換,其結(jié)果保存在視點(diǎn)坐標(biāo)系中。它的定義如下:
             

            GLfloat spot_direction[]={-1.0,-1.0,0.0};
            glLightfv(GL_LIGHT0,GL_SPOT_DIRECTION,spot_direction);

              4)定義聚光指數(shù)。參數(shù)GL_SPOT_EXPONENT控制光的集中程度,光錐中心的光強(qiáng)最大,越靠邊的光強(qiáng)越小,缺省時(shí)為0。如:
             

            glLightf(GL_LIGHT0,GL_SPOT_EXPONENT,2.0);

             此外,除了定義聚光指數(shù)控制光錐內(nèi)光強(qiáng)的分布,還可利用上一節(jié)所講的衰減因子的設(shè)置來(lái)實(shí)現(xiàn),因?yàn)樗p因子與光強(qiáng)相乘得最終光強(qiáng)值。

              14.3.2 多光源及例程
              在前面已提到過(guò)場(chǎng)景中最多可以設(shè)置八個(gè)光源(根據(jù)OpenGL的具體實(shí)現(xiàn)也許會(huì)更多一些)。在多光源情況下,OpenGL需計(jì)算每個(gè)頂點(diǎn)從每個(gè)光源接受的光強(qiáng),這樣會(huì)增加計(jì)算量,降低性能,因此在實(shí)時(shí)仿真中最好盡可能地減少光源數(shù)目。在前面都已討論過(guò)八個(gè)光源的常數(shù):GL_LIGHT0、GL_LIGHT1、…、LIGHT7,注意:GL_LIGHT0的參數(shù)缺省值與其它光源的參數(shù)缺省值不同。下面這段代碼定義了紅色的聚光:

             

            GLfloat light1_ambient[]= { 0.2, 0.2, 0.2, 1.0 };
            GLfloat light1_diffuse[]= { 1.0, 0.0, 0.0, 1.0 };
            GLfloat light1_specular[] = { 1.0, 0.6, 0.6, 1.0 };
            GLfloat light1_position[] = { -3.0, -3.0, 3.0, 1.0 };
             
            GLfloat spot_direction[]={ 1.0,1.0,-1.0}; 
             
            glLightfv(GL_LIGHT1, GL_AMBIENT, light1_ambient);
            glLightfv(GL_LIGHT1, GL_DIFFUSE, light1_diffuse);
            glLightfv(GL_LIGHT1, GL_SPECULAR,light1_specular);
            glLightfv(GL_LIGHT1, GL_POSITION,light1_position);
             
            glLightf (GL_LIGHT1, GL_SPOT_CUTOFF, 30.0);
            glLightfv(GL_LIGHT1, GL_SPOT_DIRECTION,spot_direction);
             
            glEnable(GL_LIGHT1);
             
            // 這段代碼描述的是一個(gè)紅色的立方體,用它來(lái)代表所定義的聚光光源 //
            // 可加到程序的函數(shù)display()中去。 //
             
            glPushMatrix();
            glTranslated (-3.0, -3.0, 3.0);
            glDisable (GL_LIGHTING);
            glColor3f (1.0, 0.0, 0.0);
            auxWireCube (0.1);
            glEnable (GL_LIGHTING);
            glPopMatrix ();
             
            //////////////////////////////////////////////////////////////////

              將這些代碼加到基礎(chǔ)篇第十章光照的例程(light2.c)中去:

              例14-1 聚光和多光源運(yùn)用例程spmulght.c
             

            #include "glos.h"
            #include <GL/gl.h>
            #include <GL/glu.h>
            #include <GL/glaux.h>
             
            void myinit(void);
            void CALLBACK myReshape(GLsizei w, GLsizei h);
            void CALLBACK display(void);
             
            /* 初始化光源、材質(zhì)等 */
            void myinit(void)
            {
              GLfloat mat_ambient[]= { 0.2, 0.2, 0.2, 1.0 };
              GLfloat mat_diffuse[]= { 0.8, 0.8, 0.8, 1.0 };
              GLfloat mat_specular[] = { 1.0, 1.0, 1.0, 1.0 };
              GLfloat mat_shininess[] = { 50.0 };
             
              GLfloat light0_diffuse[]= { 0.0, 0.0, 1.0, 1.0};
              GLfloat light0_position[] = { 1.0, 1.0, 1.0, 0.0 };
             
              GLfloat light1_ambient[]= { 0.2, 0.2, 0.2, 1.0 };
              GLfloat light1_diffuse[]= { 1.0, 0.0, 0.0, 1.0 };
              GLfloat light1_specular[] = { 1.0, 0.6, 0.6, 1.0 };
              GLfloat light1_position[] = { -3.0, -3.0, 3.0, 1.0 };
             
              GLfloat spot_direction[]={ 1.0,1.0,-1.0};
             
              glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient);
              glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);
              glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
              glMaterialfv(GL_FRONT, GL_SHININESS,mat_shininess);
             
              glLightfv(GL_LIGHT0, GL_DIFFUSE, light0_diffuse);
              glLightfv(GL_LIGHT0, GL_POSITION,light0_position);
             
              glLightfv(GL_LIGHT1, GL_AMBIENT, light1_ambient);
              glLightfv(GL_LIGHT1, GL_DIFFUSE, light1_diffuse);
              glLightfv(GL_LIGHT1, GL_SPECULAR,light1_specular);
              glLightfv(GL_LIGHT1, GL_POSITION,light1_position);
             
              glLightf (GL_LIGHT1, GL_SPOT_CUTOFF, 30.0);
              glLightfv(GL_LIGHT1, GL_SPOT_DIRECTION,spot_direction);
             
              glEnable(GL_LIGHTING);
              glEnable(GL_LIGHT0);
              glEnable(GL_LIGHT1);
              glDepthFunc(GL_LESS);
              glEnable(GL_DEPTH_TEST);
            }
             
            void CALLBACK display(void)
            {
              glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
             
              glPushMatrix();
              glTranslated (-3.0, -3.0, 3.0);
              glDisable (GL_LIGHTING);
              glColor3f (1.0, 0.0, 0.0);
              auxWireCube (0.1); 
              glEnable (GL_LIGHTING);
              glPopMatrix ();
             
              auxSolidSphere(2.0);
              glFlush();
            }
             
            void CALLBACK myReshape(GLsizei w, GLsizei h)
            {
              glViewport(0, 0, w, h);
              glMatrixMode(GL_PROJECTION);
              glLoadIdentity();
              if (w <= h)
                glOrtho (-5.5, 5.5, -5.5*(GLfloat)h/(GLfloat)w, 5.5*(GLfloat)h/(GLfloat)w,
                -10.0, 10.0);
              else
                glOrtho (-5.5*(GLfloat)w/(GLfloat)h, 5.5*(GLfloat)w/(GLfloat)h,
                -5.5, 5.5, -10.0, 10.0);
              glMatrixMode(GL_MODELVIEW);
              glLoadIdentity();
            }
             
            void main(void)
            {
              auxInitDisplayMode (AUX_SINGLE | AUX_RGBA);
              auxInitPosition (0, 0, 500, 500);
              auxInitWindow ("Spotlight and Multi_lights ");
              myinit();
              auxReshapeFunc (myReshape);
              auxMainLoop(display);
            }
              以上程序運(yùn)行結(jié)果是球被兩個(gè)光源照射,一個(gè)是藍(lán)色的定向光,另一個(gè)紅色的是聚光。

             
            圖14-1 聚光與多光源

            14.4、光源位置與方向的控制
              OpenGL光源的位置和方向與其它幾何圖元的位置和方向一樣都必須經(jīng)過(guò)變換矩陣的作用。尤其是當(dāng)用glLight*()說(shuō)明光源的位置和方向時(shí),位置和方向都要經(jīng)過(guò)當(dāng)前變換矩陣的作用并保存在視點(diǎn)坐標(biāo)系中,注意投影矩陣變換對(duì)它們不起作用。OpenGL可通過(guò)調(diào)整光源函數(shù)和視點(diǎn)變換函數(shù)在程序中的相對(duì)位置來(lái)獲得三種不同的效果:1)光源位置保持固定、2)光源繞靜止物體移動(dòng)、3)光源隨視點(diǎn)移動(dòng)。
              在第一種情況下,為獲得光源位置固定的效果,必須在所有視點(diǎn)和模型變換之后設(shè)置光源位置。第二種情況下,有兩種方法可以達(dá)到這種效果,一種是在模型變換后設(shè)置光源位置,變換的改變將修改光源位置;另一種是使物體和視點(diǎn)繞光源移動(dòng),相對(duì)地光源就能繞物體移動(dòng)了。第三種情況下,要建立一個(gè)沿視線移動(dòng)的光源,必須在視點(diǎn)變換之前設(shè)置光源位置,則視點(diǎn)變換按同樣的方式影響光源和視點(diǎn)。下面有一個(gè)光源移動(dòng)的例子:

              例14-1 光源移動(dòng)例程mvlight.c
             
             
            #include "glos.h"
            #include <GL/gl.h>
            #include <GL/glu.h>
            #include <GL/glaux.h>
             
            void myinit(void);
            void CALLBACK movelight (AUX_EVENTREC *event);
            void CALLBACK display(void);
            void CALLBACK myReshape(GLsizei w, GLsizei h);
             
            static int step = 0;
             
            void CALLBACK movelight (AUX_EVENTREC *event)
            {
              step = (step + 15) % 360;
            }
             
            void myinit (void)
            {
              GLfloat mat_diffuse[]={0.0,0.5,1.0,1.0};
              GLfloat mat_ambient[]={0.0,0.2,1.0,1.0};
              GLfloat light_diffuse[]={1.0,1.0,1.0,1.0};
              GLfloat light_ambient[]={0.0,0.5,0.5,1.0};
             
              glMaterialfv(GL_FRONT_AND_BACK,GL_DIFFUSE,mat_diffuse);
              glLightfv(GL_LIGHT0,GL_DIFFUSE,light_diffuse);
              glLightfv(GL_LIGHT0,GL_AMBIENT,light_ambient);
              glEnable(GL_LIGHTING);
              glEnable(GL_LIGHT0);
             
              glDepthFunc(GL_LESS);
              glEnable(GL_DEPTH_TEST);
            }
             
            void CALLBACK display(void)
            {
              GLfloat position[] = { 0.0, 0.0, 1.5, 1.0 };
             
              glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
              glPushMatrix ();
              glTranslatef (0.0, 0.0, -5.0);
             
              glPushMatrix ();
              glRotated ((GLdouble) step, -1.0, 1.0, 1.0);
              glRotated (0.0, 1.0, 0.0, 0.0);
              glLightfv (GL_LIGHT0, GL_POSITION, position);
             
              glTranslated (0.0, 0.0, 1.5);
              glDisable (GL_LIGHTING);
              glColor3f (1.0, 1.0, 0.0);
              auxWireSphere (0.1);
              glEnable (GL_LIGHTING);
              glPopMatrix ();
             
              auxSolidTorus (0.275, 0.85);
              glPopMatrix ();
              glFlush ();
            }
             
            void CALLBACK myReshape(GLsizei w, GLsizei h)
            {
              glViewport(0, 0, w, h);
              glMatrixMode(GL_PROJECTION);
              glLoadIdentity();
              gluPerspective(40.0, (GLfloat) w/(GLfloat) h, 1.0, 20.0);
              glMatrixMode(GL_MODELVIEW);
            }
             
            void main(void)
            {
              auxInitDisplayMode (AUX_SINGLE | AUX_RGBA);
              auxInitPosition (0, 0, 500, 500);
              auxInitWindow ("Moving Light");
              myinit();
              auxMouseFunc (AUX_LEFTBUTTON, AUX_MOUSEDOWN, movelight);
              auxReshapeFunc (myReshape);
              auxMainLoop(display);
            }
              以上程序運(yùn)行結(jié)果是在屏幕中央顯示一個(gè)藍(lán)色的環(huán)形圈,按下鼠標(biāo)左鍵則可移動(dòng)光源,其中一個(gè)黃色的小球代表光源。

             
            圖14-2 光源移動(dòng)

            14.5、輻射光
              在前面的章節(jié)中已經(jīng)應(yīng)用了輻射光,可以參見(jiàn)10.4.4材質(zhì)改變的例程(chgmat1.c)的運(yùn)行效果。這里再一次強(qiáng)調(diào)提出,通過(guò)給GL_EMISSION定義一個(gè)RGBA值,可以使物體看起來(lái)象發(fā)出這種 顏色的光一樣,以達(dá)到某種特殊效果。實(shí)際上,現(xiàn)實(shí)生活中的物體除光源外都不發(fā)光,但我們可以利用這一特性來(lái)模擬燈和其他光源。代碼舉例如下:
             
            GLfloat mat_emission[]={0.3,0.3,0.5,0.0};
            glMaterialfv(GL_FRONT,GL_EMISSION,mat_emission);

              這樣,物體看起來(lái)稍微有點(diǎn)發(fā)光。比如繪制一個(gè)打開(kāi)的臺(tái)燈,就可以將一個(gè)小球的材質(zhì)定義成上述形式,并且在小球內(nèi)部建立一個(gè)聚光源,這樣臺(tái)燈的燈泡效果就出來(lái)了。

            posted on 2006-01-17 01:09 zmj 閱讀(4290) 評(píng)論(1)  編輯 收藏 引用

            評(píng)論

            # re: OpenGL特殊光處理 2008-12-29 21:08 sosoyoyo

            你好,我在做圖形學(xué)最后的大作業(yè)可否麻煩你把這個(gè)源代碼發(fā)給我,謝謝,sosoyoyo918@sina.com  回復(fù)  更多評(píng)論   

            久久久精品国产免大香伊| 国产精品欧美久久久久无广告| 女人高潮久久久叫人喷水| 要久久爱在线免费观看| 99久久婷婷国产综合亚洲| 草草久久久无码国产专区| 久久精品国产亚洲av麻豆图片 | 怡红院日本一道日本久久 | 大蕉久久伊人中文字幕| 天堂无码久久综合东京热| 久久久婷婷五月亚洲97号色 | 无码任你躁久久久久久久| 久久99国产综合精品女同| 久久涩综合| AV无码久久久久不卡网站下载| 久久丝袜精品中文字幕| 久久A级毛片免费观看| 亚洲乱码日产精品a级毛片久久 | 99国内精品久久久久久久| 久久精品国产亚洲αv忘忧草 | 中文字幕无码免费久久| 九九久久精品无码专区| 国产婷婷成人久久Av免费高清| 午夜视频久久久久一区| 94久久国产乱子伦精品免费| 久久久久久久久久久| 久久国产香蕉一区精品| 久久综合狠狠综合久久激情 | 久久香蕉超碰97国产精品| 欧美激情一区二区久久久| 久久久久亚洲AV无码专区网站| 青青草原1769久久免费播放| 日本久久久久亚洲中字幕| 久久久久亚洲av成人网人人软件| 久久午夜综合久久| 久久性生大片免费观看性| 国产精久久一区二区三区| 久久美女网站免费| 久久久久中文字幕| 亚洲国产精久久久久久久| 69久久精品无码一区二区|