1. 程式人生 > >OpenGL材質和光照(轉)

OpenGL材質和光照(轉)

      真實感圖形繪製是計算機圖形學的一個重要組成部分,它綜合利用數學、物理學、電腦科學和其它科學知識在計算機圖形裝置上生成象彩色照片那樣的具有真實感的圖形。一般說來,用計算機在圖形裝置上生成真實感圖形必須完成以下四個步驟:一是用建模,即用一定的數學方法建立所需三維場景的幾何描述,場景的幾何描述直接影響圖形的複雜性和圖形繪製的計算耗費;二是將三維幾何模型經過一定變換轉為二維平面透視投影圖;三是確定場景中所有可見面,運用隱藏面消隱演算法將視域外或被遮擋住的不可見面消去;四是計算場景中可見面的顏色,即根據基於光學物理的光照模型計算可見面投射到觀察者眼中的光亮度大小和顏色分量,並將它轉換成適合圖形裝置的顏色值,從而確定投影畫面上每一象素的顏色,最終生成圖形。

  由於真實感圖形是通過景物表面的顏色和明暗色調來表現景物的幾何形狀、空間位置以及表面材料的,而一個物體表面所呈現的顏色是由表面向視線方向輻射的光能決定的。在計算機圖形學中,常採用一個既能表示光能大小又能表示其顏色組成的物理量即光亮度(luminance)或光強(intensity of light)來描述物體表面朝某方向輻射光能的顏色。採用這個物理量可以正確描述光在物體表面的反射、透射和吸收現象,因而可以正確計算處物體表面在空間給定方向上的光能顏色。  物體表面向空間給定方向輻射的光強可應用光照模型進行計算。簡單的光照模型通常假定物體表面是光滑的且由理想材料構成,因此只考慮光源照射在物體表面產生的反射光,所生成的圖形可以模擬處不透明物體表面的明暗過渡,具有一定的真實感效果。複雜的光照模型除了考慮上述因素外,還要考慮周圍環境的光對物體表面的影響。如光亮平滑的物體表面會將環境中其它物體映像在表面上,而通過透明物體也可看到其後的環境景象。這類光照模型稱為整體光照模型,它能模擬出鏡面映像、透明等較精緻的光照效果。為了更真實的繪製圖形,還要考慮物體表面的細節紋理,這通常使用一種稱為
紋理對映texture mapping)的技術把已有的平面花紋圖案對映到物體表面上,並在應用光照模型時將這些花紋的顏色考慮進去,物體表面細節的模擬使繪製的圖形更接近自然景物。  以上內容中,真實感圖形繪製的四大步驟前兩步在前面的章節已經詳細介紹過,這裡不再重複,第三步OpenGL將自動完成所有消隱過程,第四步下面幾節詳述。另外,部分複雜光照模型應用將在後續章節裡介紹。10.2、光照模型10.2.1 簡單光照模型  當光照射到一個物體表面上時,會出現三種情形。首先,光可以通過物體表面向空間反射,產生反射光。其次,對於透明體,光可以穿透該物體並從另一端射出,產生透射光。最後,部分光將被物體表面吸收而轉換成熱。在上述三部分光中,僅僅是透射光和反射光能夠進入人眼產生視覺效果。這裡介紹的簡單光照模型只考慮被照明物體表面的反射光影響,假定物體表面光滑不透明且由理想材料構成,環境假設為由白光照明。
  一般來說,反射光可以分成三個分量,即環境反射、漫反射和鏡面反射。環境反射分量假定入射光均勻地從周圍環境入射至景物表面並等量地向各個方向反射出去,通常物體表面還會受到從周圍環境來的反射光(如來自地面、天空、牆壁等的反射光)的照射,這些光常統稱為環境光(Ambient Light);漫反射分量表示特定光源在景物表面的反射光中那些向空間各方向均勻反射出去的光,這些光常稱為漫射光(Diffuse Light);鏡面反射光為朝一定方向的反射光,如一個點光源照射一個金屬球時會在球面上形成一塊特別亮的區域,呈現所謂高光(Highlight,它是光源在金屬球面上產生的鏡面反射光(Specular Light)。對於較光滑物體,其鏡面反射光的高光區域小而亮;相反,粗糙表面的鏡面反射光呈發散狀態,其高光區域大而不亮。下面先看一個簡單的光照例程。  10-1 簡單光照例程light0.c#include "glos.h"#include <GL/gl.h>#include <GL/glu.h>#include <GL/glaux.h>void myinit(void);void CALLBACK myReshape(GLsizei w, GLsizeih);void CALLBACK display(void);void myinit(void){GLfloat light_position[] = { 1.0, 1.0, 1.0,0.0 };glLightfv(GL_LIGHT0, GL_POSITION,light_position);glEnable(GL_LIGHTING);glEnable(GL_LIGHT0);glDepthFunc(GL_LESS);glEnable(GL_DEPTH_TEST);}void CALLBACK display(void){glClear(GL_COLOR_BUFFER_BIT |GL_DEPTH_BUFFER_BIT);auxSolidSphere(1.0);glFlush();}void CALLBACK myReshape(GLsizei w, GLsizeih){glViewport(0, 0, w, h);glMatrixMode(GL_PROJECTION);glLoadIdentity();if (w <= h)glOrtho (-1.5, 1.5,-1.5*(GLfloat)h/(GLfloat)w, 1.5*(GLfloat)h/(GLfloat)w, -10.0, 10.0);elseglOrtho (-1.5*(GLfloat)w/(GLfloat)h,1.5*(GLfloat)w/(GLfloat)h, -1.5, 1.5, -10.0, 10.0);glMatrixMode(GL_MODELVIEW);glLoadIdentity();}void main(void){auxInitDisplayMode (AUX_SINGLE | AUX_RGBA);auxInitPosition (0, 0, 500, 500);auxInitWindow ("SimpleLighting");myinit();auxReshapeFunc (myReshape);auxMainLoop(display);}  以上程式執行結果是顯示一個具有灰色光影的球。其中函式myinit()中包含了關鍵的設定光源位置、啟動光照等幾句,而其它程式語言幾乎與以前的沒有多大區別,但效果卻完全不一樣。下面幾個小節將詳細介紹有關函式的用法。

<!--[if gte vml 1]> <![endif]-->

10-1 帶光影的灰色球體

10.2.2 OpenGL光組成  在OpenGL簡單光照模型中的幾種光分為:輻射光(Emitted Light)、環境光(Ambient Light)、漫射光(Diffuse Light)、鏡面光(Specular Light)。  輻射光是最簡單的一種光,它直接從物體發出並且不受任何光源影響。  環境光是由光源發出經環境多次散射而無法確定其方向的光,即似乎來自所有方向。一般說來,房間裡的環境光成分要多些,戶外的相反要少得多,因為大部分光按相同方向照射,而且在戶外很少有其他物體反射的光。當環境光照到曲面上時,它在各個方向上均等地發散(類似於無影燈光)。  漫射光來自一個方向,它垂直於物體時比傾斜時更明亮。一旦它照射到物體上,則在各個方向上均勻地發散出去。於是,無論視點在哪裡它都一樣亮。來自特定位置和特定方向的任何光,都可能有散射成分。  鏡面光來自特定方向並沿另一方向反射出去,一個平行鐳射束在高質量的鏡面上產生100%的鏡面反射。光亮的金屬和塑料具有很高非反射成分,而象粉筆和地毯等幾乎沒有反射成分。因此,三某種意義上講,物體的反射程度等同於其上的光強(或光亮度)。10.2.3 建立光源Light Source  光源有許多特性,如顏色、位置、方向等。選擇不同的特性值,則對應的光源作用在物體上的效果也不一樣,這在以後的章節中會逐步介紹的。下面詳細講述定義光源特性的函式glLight*()void glLight{if}[v](GLenum light , GLenumpname, TYPE param)  建立具有某種特性的光源。其中第一個引數light指定所建立的光源號,如GL_LIGHT0GL_LIGHT1...GL_LIGHT7。第二個引數pname指定光源特性,這個引數的輔助資訊見表10-1所示。最後一個引數設定相應的光源特性值。

pname 引數名

預設值

說明

GL_AMBIENT

(0.0, 0.0, 0.0, 1.0)

RGBA模式下環境光

GL_DIFFUSE

(1.0, 1.0, 1.0, 1.0)

RGBA模式下漫反射光

GL_SPECULAR

(1.0,1.0,1.0,1.0)

RGBA模式下鏡面光

GL_POSITION

(0.0,0.0,1.0,0.0)

光源位置齊次座標(x,y,z,w

GL_SPOT_DIRECTION

(0.0,0.0,-1.0)

點光源聚光方向向量(x,y,z

GL_SPOT_EXPONENT

0.0

點光源聚光指數

GL_SPOT_CUTOFF

180.0

點光源聚光截止角

GL_CONSTANT_ATTENUATION

1.0

常數衰減因子

GL_LINER_ATTENUATION

0.0

線性衰減因子

GL_QUADRATIC_ATTENUATION

0.0

平方衰減因子

10-1 函式glLight*()引數pname說明

?注意:以上列出的GL_DIFFUSEGL_SPECULAR的預設值只能用於GL_LIGHT0,其他幾個光源的GL_DIFFUSEGL_SPECULAR預設值為(0.0,0.0,0.0,1.0)。另外,表中後六個引數的應用放在下一篇中介紹。在上面例程中,光源的建立為:GLfloat light_position[] = { 1.0, 1.0, 1.0,0.0 };glLightfv(GL_LIGHT0, GL_POSITION,light_position);  其中light_position是一個指標,指向定義的光源位置齊次座標陣列。其它幾個光源特性都為預設值。同樣,我們也可用類似的方式定義光源的其他幾個特性值,例如:GLfloat light_ambient [] = { 0.0, 0.0, 0.0,1.0 };GLfloat light_diffuse [] = { 1.0, 1.0, 1.0,1.0 };GLfloat light_specular[] = { 1.0, 1.0, 1.0,1.0 };glLightfv(GL_LIGHT0, GL_AMBIENT ,light_ambient );glLightfv(GL_LIGHT0, GL_DIFFUSE ,light_diffuse );glLightfv(GL_LIGHT0, GL_SPECULAR,light_specular);10.2.4 啟動光照  在OpenGL中,必須明確指出光照是否有效或無效。如果光照無效,則只是簡單地將當前顏色對映到當前頂點上去,不進行法向、光源、材質等複雜計算,那麼顯示的圖形就沒有真實感,如前幾章例程執行結果顯示。要使光照有效,首先得啟動光照,即:glEnable(GL_LIGHTING);  若使光照無效,則呼叫gDisable(GL_LIGHTING)可關閉當前光照。然後,必須使所定義的每個光源有效,例light0.c中只用了一個光源,即:glEnable(GL_LIGHT0);  其它光源類似,只是光源號不同而已。10.3、明暗處理  在計算機圖形學中,光滑的曲面表面常用多邊形予以逼近和表示,而每個小多邊形輪廓(或內部)就用單一的顏色或許多不同的顏色來勾畫(或填充),這種處理方式就稱為明暗處理。在OpenGL中,用單一顏色處理的稱為平面明暗處理(Flat Shading),用許多不同顏色處理的稱為光滑明暗處理(Smooth Shading),也稱為Gourand明暗處理(Gourand Shading)。設定明暗處理模式的函式為:void glShadeModel(GLenum mode);  函式引數為GL_FLATGL_SMOOTH,分別表示平面明暗處理和光滑明暗處理。  應用平面明暗處理模式時,多邊形內每個點的法向一致,且顏色也一致;應用光滑明暗處理模式時,多邊形所有點的法向是由內插生成的,具有一定的連續性,因此每個點的顏色也相應內插,故呈現不同色。這種模式下,插值方法採用的是雙線性插值法,如圖10-2所示。

<!--[if gte vml 1]> <![endif]-->

10-2 Gouraud明暗處理

Gouraud明暗處理通常演算法為:先用多邊形頂點的光強線性插值出當前掃描線與多邊形邊交點處的光強,然後再用交點的光強線插值處掃描線位於多邊形內區段上每一象素處的光強值。圖中顯示出一條掃描線與多邊形相交,交線的端點是A點和B點,P點是掃描線上位於多邊形內的任一點,多邊形三個頂點的光強分別為I1I2I3.A點的光強IaI1I2的線性插值,B點的光強IbI1I3的線性插值,P點的光強Ip則為IaIb的線性插值。採用Gouraud明暗處理不但可以使用多邊形表示的曲面光強連續,而且計算量很小。這種演算法還可以以增量的形式改進,且能用硬體直接實現演算法,從而廣泛用於計算機實時圖形生成。請看下面光滑明暗處理的例程:  10-2 明暗處理例程Shading.c#include "glos.h"#include <GL/gl.h>#include <GL/glu.h>#include <GL/glaux.h>void myinit(void);void object(void);void CALLBACK display(void);void CALLBACK myReshape(GLsizei w, GLsizeih);/* GL_SMOOTH is actually the defaultshading model. */void myinit (void){glShadeModel (GL_SMOOTH);}void object(void){glBegin (GL_POLYGON);glColor3f (1.0, 0.0, 0.0);glVertex2f (4.0, 4.0);glColor3f(1.0,1.0,1.0);glVertex2f (12.0, 4.0);glColor3f(0.0,0.0,1.0);glVertex2f (12.0, 12.0);glColor3f(0.0,1.0,0.0);glVertex2f (4.0, 12.0);glEnd ();}void CALLBACK display(void){glClear (GL_COLOR_BUFFER_BIT);object ();glFlush ();}void CALLBACK myReshape(GLsizei w, GLsizeih){glViewport(0, 0, w, h);glMatrixMode(GL_PROJECTION);glLoadIdentity();if (w <= h)gluOrtho2D (0.0, 16.0, 0.0, 16.0 *(GLfloat) h/(GLfloat) w);elsegluOrtho2D (0.0, 16.0 * (GLfloat)w/(GLfloat) h, 0.0, 16.0);glMatrixMode(GL_MODELVIEW);}void main(void){auxInitDisplayMode (AUX_SINGLE | AUX_RGBA);auxInitPosition (0, 0, 500, 500);auxInitWindow ("Smooth Shading");myinit();auxReshapeFunc (myReshape);auxMainLoop(display);}  以上程式執行結果是在螢幕上顯示一個色彩連續變化的三角形。這個程式是用的RGBA顯示模式,若改用顏色表模式,則顏色內插實際上是顏色表的內插,因此呈現的顏色可能不連續。網友不妨自己試試。  另外,若在light0.c程式中加上一句定義GL_FLAT明暗處理模式,則又會出現怎樣的情形呢?讀者可以仔細比較一下。

<!--[if gte vml 1]> <![endif]-->

10-3 高氏明暗處理的正方形

10.4、材質10.4.1 材質顏色OpenGL用材料對光的紅、綠、藍三原色的反射率來近似定義材料的顏色。象光源一樣,材料顏色也分成環境、漫反射和鏡面反射成分,它們決定了材料對環境光、漫反射光和鏡面反射光的反射程度。在進行光照計算時,材料對環境光的反射率與每個進入光源的環境光結合,對漫反射光的反射率與每個進入光源的漫反射光結合,對鏡面光的反射率與每個進入光源的鏡面反射光結合。對環境光與漫反射光的反射程度決定了材料的顏色,並且它們很相似。對鏡面反射光的反射率通常是白色或灰色(即對鏡面反射光中紅、綠、藍的反射率相同)。鏡面反射高光最亮的地方將變成具有光源鏡面光強度的顏色。例如一個光亮的紅色塑料球,球的大部分表現為紅色,光亮的高光將是白色的。10.4.2 材質定義  材質的定義與光源的定義類似。其函式為:void glMaterial{if}[v](GLenum face,GLenumpname,TYPE param);  定義光照計算中用到的當前材質。face可以是GL_FRONTGL_BACKGL_FRONT_AND_BACK,它表明當前材質應該應用到物體的哪一個面上;pname說明一個特定的材質;param是材質的具體數值,若函式為向量形式,則param是一組值的指標,反之為引數值本身。非向量形式僅用於設定GL_SHINESSpname引數值具體內容見表10-1。另外,引數GL_AMBIENT_AND_DIFFUSE表示可以用相同的RGB值設定環境光顏色和漫反射光顏色。

引數名

預設值

說明

GL_AMBIENT

(0.2, 0.2, 0.2, 1.0)

材料的環境光顏色

GL_DIFFUSE

(0.8, 0.8, 0.8, 1.0)

材料的漫反射光顏色

GL_AMBIENT_AND_DIFFUSE

?

材料的環境光和漫反射光顏色

GL_SPECULAR

(0.0, 0.0, 0.0, 1.0)

材料的鏡面反射光顏色

GL_SHINESS

0.0

鏡面指數(光亮度)

GL_EMISSION

(0.0, 0.0, 0.0, 1.0)

材料的輻射光顏色

GL_COLOR_INDEXES

(0, 1, 1)

材料的環境光、漫反射光和鏡面光顏色

10-2 函式glMaterial*()引數pname的預設值

  10-3 材質定義例程light1.c#include "glos.h"#include <GL/gl.h>#include <GL/glaux.h>void myinit(void);void CALLBACK myReshape(GLsizei w, GLsizeih);void CALLBACK display(void); voidmyinit(void){/* 設定材質的各種光的顏色成分反射比率 */GLfloat mat_ambient[]={0.8,0.8,0.8,1.0};GLfloat mat_diffuse[]={0.8,0.0,0.8,1.0};/* 紫色 */GLfloat mat_specular[] = { 1.0, 0.0, 1.0,1.0 };/* 亮紫色 */GLfloat mat_shininess[] = { 50.0 };GLfloat light_position[] = { 1.0, 1.0, 1.0,0.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_POSITION,light_position);glEnable(GL_LIGHTING);glEnable(GL_LIGHT0);glDepthFunc(GL_LESS);glEnable(GL_DEPTH_TEST);}void CALLBACK display(void){glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);auxSolidSphere(1.0);glFlush();}void CALLBACK myReshape(GLsizei w, GLsizeih){glViewport(0, 0, w, h);glMatrixMode(GL_PROJECTION);glLoadIdentity();if (w <= h)glOrtho (-1.5, 1.5, -1.5*(GLfloat)h/(GLfloat)w,1.5*(GLfloat)h/(GLfloat)w, -10.0, 10.0);elseglOrtho (-1.5*(GLfloat)w/(GLfloat)h,1.5*(GLfloat)w/(GLfloat)h, -1.5, 1.5, -10.0, 10.0);glMatrixMode(GL_MODELVIEW);?glLoadIdentity();}void main(void){auxInitDisplayMode (AUX_SINGLE | AUX_RGBA |AUX_DEPTH16);auxInitPosition (0, 0, 500, 500);auxInitWindow ("Lighting_1 ");myinit();auxReshapeFunc (myReshape);auxMainLoop(display);}  以上程式執行結果是一個紫色的球。在函式myinit()中定義了球的材質顏色,光源的定義仍延用light0.c中的,而light.c物體的光源定義為預設形式。從例子中明顯地看出,物體的材質顏色定義與光源顏色定義幾乎一樣,物體反射到眼中的顏色與二者都有關係,具體關係請看下一小節。10.4.3 材質RGB值和光源RGB值的關係  材質的顏色與光源的顏色有些不同。對於光源,RGB值等於RGB對其最大強度的百分比。若光源顏色的RGB值都是1.0,則是最強的白光;若值變為0.5,顏色仍為白色,但強度為原來的一半,於是表現為灰色;若RG1.0B0.0,則光源為黃色。對於材質,RGB值為材質對光的RGB成分的反射率。比如,一種材質的R1.0G0.5B0.0,則材質反射全部的紅色成分,一半的綠色成分,不反射藍色成分。也就是說,若OpenGL的光源顏色為(LRLGLB),材質顏色為(MRMGMB),那麼,在忽略所有其他反射效果的情況下,最終到達眼睛的光的顏色為(LR*MRLG*MGLB*MB)。  同樣,如果有兩束光,相應的值分別為(R1G1B1)和(R2G2B2),則OpenGL將各個顏色成分相加,得到(R1+R2G1+G2B1+B2),若任一成分的和值大於1(超出了裝置所能顯示的亮度)則約簡到1.0。下面一例程就說明了二者之間的關係。  10-4 材質與光源的RGB關係例程light2.c#include "glos.h"#include <GL/gl.h>#include <GL/glaux.h>void myinit(void);void CALLBACK myReshape(GLsizei w, GLsizeih);void CALLBACK display(void);void myinit(void){GLfloat mat_ambient[]= { 0.8, 0.8, 0.8, 1.0};GLfloat mat_diffuse[]= { 0.8, 0.0, 0.8, 1.0};/* 紫色 */GLfloat mat_specular[] = { 1.0, 0.0, 1.0,1.0 };GLfloat mat_shininess[] = { 50.0 };GLfloat light_diffuse[]= { 0.0, 0.0, 1.0,1.0};/* 藍色 */GLfloat light_position[] = { 1.0, 1.0, 1.0,0.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,light_diffuse);glLightfv(GL_LIGHT0, GL_POSITION,light_position);glEnable(GL_LIGHTING);glEnable(GL_LIGHT0);glDepthFunc(GL_LESS);glEnable(GL_DEPTH_TEST);}void CALLBACK display(void){glClear(GL_COLOR_BUFFER_BIT |GL_DEPTH_BUFFER_BIT);auxSolidSphere(1.0);glFlush();}void CALLBACK myReshape(GLsizei w, GLsizeih){glViewport(0, 0, w, h);glMatrixMode(GL_PROJECTION);glLoadIdentity();if (w <= h)glOrtho (-1.5, 1.5,-1.5*(GLfloat)h/(GLfloat)w, 1.5*(GLfloat)h/(GLfloat)w, -10.0, 10.0);elseglOrtho (-1.5*(GLfloat)w/(GLfloat)h,1.5*(GLfloat)w/(GLfloat)h, -1.5, 1.5, -10.0, 10.0);glMatrixMode(GL_MODELVIEW);glLoadIdentity();}void main(void){auxInitDisplayMode (AUX_SINGLE | AUX_RGBA |AUX_DEPTH16);auxInitPosition (0, 0, 500, 500);auxInitWindow ("Lighting_2 ");myinit();auxReshapeFunc (myReshape);auxMainLoop(display);}  以上程式執行結果是一個藍色的球,其中高光部分仍為上一例的亮紫色。從上可看出,球漫反射光的結果是mat_diffuse[]light_diffuse[]中的三個顏色分量值相乘,即(0.0*1.0,0.0*1.0,0.8*1.0,1.0*1.0)=(0.0,0.0,0.8,1.0),所以球大部分呈現藍色。

<!--[if gte vml 1]> <![endif]-->

10-4 光照藍色球高光為紅色

10.4.4 材質改變  在實際應用的許多情況下,不同的物體或同一物體的不同部分都有可能設定不同的材質,OpenGL函式庫提供了兩種方式實現這種要求。下面一例程採用的是設定矩陣堆疊來儲存不同物體的材質資訊:  10-5 矩陣堆疊改變材質例程chgmat1.c#include "glos.h"#include <GL/gl.h>#include <GL/glu.h>#include <GL/glaux.h>void myinit(void);void CALLBACK display(void);void CALLBACK myReshape(GLsizei w, GLsizeih);/* 初始化z-buffer、光源和光照模型,在此不具體定義材質。*/void myinit(void){GLfloat ambient[] = { 0.0, 0.0, 0.0, 1.0 };GLfloat diffuse[] = { 1.0, 1.0, 1.0, 1.0 };GLfloat specular[] = { 1.0, 1.0, 1.0, 1.0};GLfloat position[] = { 0.0, 3.0, 2.0, 0.0};GLfloat lmodel_ambient[] = { 0.4, 0.4, 0.4,1.0 };glEnable(GL_DEPTH_TEST);glDepthFunc(GL_LESS);glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);glLightfv(GL_LIGHT0, GL_POSITION,position);glEnable(GL_LIGHTING);glEnable(GL_LIGHT0);glClearColor(0.0, 0.1, 0.1, 0.0);}void CALLBACK display(void){GLfloat no_mat[] = { 0.0, 0.0, 0.0, 1.0 };GLfloat mat_ambient[] = { 0.7, 0.7, 0.7,1.0 };GLfloat mat_ambient_color[] = { 0.8, 0.8,0.2, 1.0 };GLfloat mat_diffuse[] = { 0.1, 0.5, 0.8,1.0 };GLfloat mat_specular[] = { 1.0, 1.0, 1.0,1.0 };GLfloat no_shininess[] = { 0.0 };GLfloat low_shininess[] = { 5.0 };GLfloat high_shininess[] = { 100.0 };GLfloat mat_emission[] = {0.3, 0.2, 0.2,0.0};glClear(GL_COLOR_BUFFER_BIT |GL_DEPTH_BUFFER_BIT);/* 第一行第一列繪製的球僅有漫反射光而無環境光和鏡面光。*/glPushMatrix();glTranslatef (-3.75, 3.0, 0.0);glMaterialfv(GL_FRONT, GL_AMBIENT, no_mat);glMaterialfv(GL_FRONT, GL_DIFFUSE,mat_diffuse);glMaterialfv(GL_FRONT, GL_SPECULAR,no_mat);glMaterialfv(GL_FRONT, GL_SHININESS,no_shininess);glMaterialfv(GL_FRONT, GL_EMISSION,no_mat);auxSolidSphere(1.0);glPopMatrix();/* 第一行第二列繪製的球有漫反射光和鏡面光,並有低高光,而無環境光*/glPushMatrix();glTranslatef (-1.25, 3.0, 0.0);glMaterialfv(GL_FRONT, GL_AMBIENT, no_mat);glMaterialfv(GL_FRONT, GL_DIFFUSE,mat_diffuse);glMaterialfv(GL_FRONT, GL_SPECULAR,mat_specular);glMaterialfv(GL_FRONT, GL_SHININESS,low_shininess);glMaterialfv(GL_FRONT, GL_EMISSION,no_mat);auxSolidSphere(1.0);glPopMatrix();/* 第一行第三列繪製的球有漫反射光和鏡面光,並有很亮的高光,而無環境光*/glPushMatrix();glTranslatef (1.25, 3.0, 0.0);glMaterialfv(GL_FRONT, GL_AMBIENT, no_mat);glMaterialfv(GL_FRONT, GL_DIFFUSE,mat_diffuse);glMaterialfv(GL_FRONT, GL_SPECULAR,mat_specular);glMaterialfv(GL_FRONT, GL_SHININESS,high_shininess);glMaterialfv(GL_FRONT, GL_EMISSION,no_mat);auxSolidSphere(1.0);glPopMatrix();/* 第一行第四列繪製的球有漫反射光和輻射光,而無環境和鏡面反射光。*/glPushMatrix();glTranslatef (3.75, 3.0, 0.0);glMaterialfv(GL_FRONT, GL_AMBIENT, no_mat);glMaterialfv(GL_FRONT, GL_DIFFUSE,mat_diffuse);glMaterialfv(GL_FRONT, GL_SPECULAR,no_mat);glMaterialfv(GL_FRONT, GL_SHININESS,no_shininess);glMaterialfv(GL_FRONT, GL_EMISSION,mat_emission);auxSolidSphere(1.0);glPopMatrix();/* 第二行第一列繪製的球有漫反射光和環境光,而鏡面反射光。*/glPushMatrix();glTranslatef (-3.75, 0.0, 0.0);glMaterialfv(GL_FRONT, GL_AMBIENT,mat_ambient);glMaterialfv(GL_FRONT, GL_DIFFUSE,mat_diffuse);glMaterialfv(GL_FRONT, GL_SPECULAR,no_mat);glMaterialfv(GL_FRONT, GL_SHININESS,no_shininess);glMaterialfv(GL_FRONT, GL_EMISSION,no_mat);auxSolidSphere(1.0);glPopMatrix();/* 第二行第二列繪製的球有漫反射光、環境光和鏡面光,且有低高光。*/glPushMatrix();glTranslatef (-1.25, 0.0, 0.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,low_shininess);glMaterialfv(GL_FRONT, GL_EMISSION,no_mat);auxSolidSphere(1.0);glPopMatrix();/* 第二行第三列繪製的球有漫反射光、環境光和鏡面光,且有很亮的高光。*/glPushMatrix();glTranslatef (1.25, 0.0, 0.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,high_shininess);glMaterialfv(GL_FRONT, GL_EMISSION,no_mat);auxSolidSphere(1.0);glPopMatrix();/* 第二行第四列繪製的球有漫反射光、環境光和輻射光,而無鏡面光。*/glPushMatrix();glTranslatef (3.75, 0.0, 0.0);glMaterialfv(GL_FRONT, GL_AMBIENT,mat_ambient);glMaterialfv(GL_FRONT, GL_DIFFUSE,mat_diffuse);glMaterialfv(GL_FRONT, GL_SPECULAR,no_mat);glMaterialfv(GL_FRONT, GL_SHININESS,no_shininess);glMaterialfv(GL_FRONT, GL_EMISSION,mat_emission);auxSolidSphere(1.0); glPopMatrix();/* 第三行第一列繪製的球有漫反射光和有顏色的環境光,而無鏡面光。*/glPushMatrix();glTranslatef (-3.75, -3.0, 0.0);glMaterialfv(GL_FRONT, GL_AMBIENT,mat_ambient_color);glMaterialfv(GL_FRONT, GL_DIFFUSE,mat_diffuse);glMaterialfv(GL_FRONT, GL_SPECULAR,no_mat);glMaterialfv(GL_FRONT, GL_SHININESS,no_shininess);glMaterialfv(GL_FRONT, GL_EMISSION,no_mat);auxSolidSphere(1.0);glPopMatrix();/* 第三行第二列繪製的球有漫反射光和有顏色的環境光以及鏡面光,且有低高光。*/glPushMatrix();glTranslatef (-1.25, -3.0, 0.0);glMaterialfv(GL_FRONT, GL_AMBIENT,mat_ambient_color);glMaterialfv(GL_FRONT, GL_DIFFUSE,mat_diffuse);glMaterialfv(GL_FRONT, GL_SPECULAR,mat_specular);glMaterialfv(GL_FRONT, GL_SHININESS,low_shininess);glMaterialfv(GL_FRONT, GL_EMISSION,no_mat);auxSolidSphere(1.0);glPopMatrix();/* 第三行第三列繪製的球有漫反射光和有顏色的環境光以及鏡面光,且有很亮的高光。*/glPushMatrix();glTranslatef (1.25, -3.0, 0.0);glMaterialfv(GL_FRONT, GL_AMBIENT,mat_ambient_color);glMaterialfv(GL_FRONT, GL_DIFFUSE,mat_diffuse);glMaterialfv(GL_FRONT, GL_SPECULAR,mat_specular);glMaterialfv(GL_FRONT, GL_SHININESS,high_shininess);glMaterialfv(GL_FRONT, GL_EMISSION,no_mat);auxSolidSphere(1.0);glPopMatrix();/* 第三行第四列繪製的球有漫反射光和有顏色的環境光以及輻射光,而無鏡面光。*/glPushMatrix();glTranslatef (3.75, -3.0, 0.0);glMaterialfv(GL_FRONT, GL_AMBIENT,mat_ambient_color);glMaterialfv(GL_FRONT, GL_DIFFUSE,mat_diffuse);glMaterialfv(GL_FRONT, GL_SPECULAR,no_mat);glMaterialfv(GL_FRONT, GL_SHININESS, no_shininess);glMaterialfv(GL_FRONT, GL_EMISSION,mat_emission);auxSolidSphere(1.0);glPopMatrix();glFlush();}void CALLBACK myReshape(GLsizei w, GLsizeih){glViewport(0, 0, w, h);glMatrixMode(GL_PROJECTION);glLoadIdentity();if (w <= (h * 2))glOrtho (-6.0, 6.0,-3.0*((GLfloat)h*2)/(GLfloat)w,3.0*((GLfloat)h*2)/(GLfloat)w, -10.0,10.0);elseglOrtho (-6.0*(GLfloat)w/((GLfloat)h*2),6.0*(GLfloat)w/((GLfloat)h*2), -3.0, 3.0,-10.0, 10.0);glMatrixMode(GL_MODELVIEW);}void main(void){auxInitDisplayMode (AUX_SINGLE | AUX_RGBA);auxInitPosition (0, 0, 600, 450);auxInitWindow ("Material");myinit();auxReshapeFunc (myReshape);auxMainLoop(display);}