• <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>

            永遠也不完美的程序

            不斷學習,不斷實踐,不斷的重構……

            常用鏈接

            統計

            積分與排名

            好友鏈接

            最新評論

            光與材質(轉)

            轉載自:http://www.gesoftfactory.com/developer/LnM.htm

            光用于照亮場景中的物體。當光照被啟用時,Microsoft® Direct3D®根據下列組合計算每個頂點的顏色。

            • 當前材質的顏色及相關紋理貼圖中的紋理像素(texels)。
            • 若已給出頂點的漫反射色和鏡面反射色,則使用。
            • 場景中光源產生的光的顏色和強度,或場景中環境光的級別。

            當使用Direct3D光照和材質時,應用程序允許Direct3D代為處理照明的各種細節。如果需要的話,高級用戶可以執行自己的光照計算。

            應用程序如何使用光照和材質使渲染得到的場景有很大區別。材質定義了光在表面上如何反射。直射光和環境光級別定義了反射的光。如果啟用了光照,應用程序渲染場景時必須使用材質。對于渲染場景而言,光不是必須的,但是如果渲染的場景沒有光,那么會有許多細節不可見。渲染一個未經光照的場景至多也只能得到場景中物體的輪廓,而這對大多數用途而言是不夠的。

            以下主題包含了更多信息。


            Direct3D光照模型與自然光的比較


            在自然界,當光從光源發出后,在到達用戶的眼睛之前,已經經過了成千上萬個物體的反射。每經過一次反射,一部分光被表面吸收,一部分被散射到各個方向,而剩余的則被反射到其它表面或用戶的眼睛里。這個過程一直持續,直到光衰減為零或到達用戶眼中。

            顯然,要完美地模擬自然光所需的計算量太大以致于無法用在實時三維圖形中。因此,考慮到速度,Microsoft® Direct3D®光照模型對自然光的工作方式進行模擬。Direct3D用紅、綠、藍三原色描述光,并將它們合成產生最終的顏色。

            Direct3D中,當光從表面反射時,光的顏色與表面本身以某種數學方式相互作用,并產生最終顯示在屏幕上的顏色。有關Direct3D使用的具體算法,請參閱與光照相關的數學

            Direct3D光照模型將光歸納為兩類:環境光和直射光。每種光具有不同的屬性,并以不同的方式與表面材質相互作用。環境光是經過多次散射的光以至于它的方向和來源都無法確定:它給各處提供一個較低級別的光強。攝像師使用的非直射光是環境光的一個很好的例子。Direct3D中的環境光,和自然界中的一樣,沒有實際的方向和光源,只有顏色和光強。事實上,環境光的級別完全獨立于場景中的任何發光物體。環境光不參與鏡面反射。

            直射光是場景中的光源產生的光,它總是具有顏色和強度,并沿特定的方向傳播。直射光與表面材質相互作用產生鏡面反射高光(highlight),它的方向用作各種著色算法(包括高洛德著色算法)中的一個因子。當直射光反射時,它不影響場景中的環境光級別。場景中產生直射光的光源具有不同的特征,這些特征影響到光如何照亮場景。更多信息,請參閱光照與材質

            另外,多邊形的材質具有一些屬性,這些屬性影響多邊形如何反射它接收的光線。應用程序可以設置一個專門的反射系數,用于描述材質如何反射環境光,應用程序還可以設置另一個反射系數以決定材質的鏡面反射和漫反射。更多信息請參閱材質


            光與材質的顏色值


            Microsoft® Direct3D®用四個成員——紅、綠、藍和阿爾法——描述顏色,并將它們合成,產生最終顏色。Direct3D為C++程序定義了D3DCOLORVALUE結構,該結構包含了所有成員,每個成員是一個浮點數,一般在0.0到1.0范圍內,閉區間。雖然光照和材質使用相同的結構描述顏色,但對結構中的值的使用略有不同。

            光源的顏色值表示它發出的某種光成分的數量。因為光不包含阿爾法成員,所以只有顏色的紅、綠和藍成員是有用的。可以把三種成員想象成投影電視的紅、綠、藍鏡頭。每個鏡頭可能被關掉(相應成員的值為0.0),或是位于范圍內的某個值。鏡頭中照射出的顏色組合成光的最終顏色。如R: 1.0, G: 1.0, B: 1.0組合成白光,而R: 0.0, G: 0.0, B: 0.0則完全不發光。也可以產生只發出某個成員顏色的光,這樣可以得到純紅、純綠或純藍光,或者也可以將它們組合,得到黃色或紫色。甚至可以將顏色的成員設為負值,這樣就產生了實際上將光從場景中移除的“暗光(dark light)”,得到場景變暗的效果。或者,也可以將成員設為大于1.0的值,產生特別亮的光。

            另一方面,材質的顏色值表示用該材質渲染的表面對某種光成分的反射度。顏色成員為R: 1.0, G: 1.0, B: 1.0, A: 1.0的材質會反射所有的入射光。同樣,成員為R: 0.0, G: 1.0, B: 0.0, A: 1.0的材質會反射所有入射的綠光。具有多重反射系數值(譯注:漫反射、鏡面反射、等等)的材質可以創建不同類型的效果,更多信息,請參閱材質屬性

            環境光的顏色值和用于直射光的光源及材質的顏色值是不一樣的。更多信息,請參閱直射光與環境光的比較


            直射光與環境光的比較


            雖然直射光與環境光都用于照亮場景中的物體,但它們互不相關,且具有非常不同的效果,并要按照完全不同的方法使用。

            直射光就是直接照射的光。直射光總有方向和顏色,并且用作著色算法的一個因子,如高洛德著色算法。不同類型的光以不同的方式發出直射光,產生特殊的衰減效果。通過調用IDirect3DDevice9::SetLight方法,可以設置一組直射光參數。

            環境光存在于場景中的任何地方。可以認為它是充滿整個場景的光的強度,與物體及它們在場景中的位置無關。環境光沒有位置和方向,只有顏色和強度。每個光源會增加場景中總的環境光級別。可以調用IDirect3DDevice9::SetRenderState方法設置環境光的級別,將State參數指定為D3DRS_AMBIENT,將Value參數設置為希望的RGBA顏色值。

            環境反射色采用RGBA值的形式表示,其中每個成分為從0到255之間的整數值。這與Microsoft® Direct3D®中大多數的顏色值有所不同。更多信息,請參閱光源和材質的顏色值

            可以用D3DCOLOR_RGBA宏生成RGBA值。紅、綠、藍成分組合成最終的環境反射色值。阿爾法成分控制顏色的透明度。當使用硬件加速或RGB模擬設備時,阿爾法成分被忽略。


            光的屬性


            光的屬性描述了光源的類型和顏色。取決于正在使用的光源的類型,光源可以擁有表示衰減和范圍的屬性,或表示聚光燈效果的屬性。但是,并不是所有類型的光源都使用所有的屬性。Microsoft® Direct3D®用D3DLIGHT9結構存放所有類型光源的屬性。本節包含關于所有光的屬性的信息。信息被劃分為以下部分。

            • 光的類型
            • 光的顏色
            • 有顏色的頂點(Color Vertices)
            • 光源的位置、范圍和衰減
            • 光的方向

            光的類型


            光的類型屬性定義了正在使用的光源是什么類型。光的屬性由D3DLIGHT9結構的Type成員的值設置,在C++程序中該成員是一個D3DLIGHTTYPE枚舉類型。Microsoft® Direct3D®中有三種類型的光——點光源、聚光燈和平行光。每種類型以不同的方式照亮場景中的物體,所需的計算量也不同。

            點光源

            場景中的點光源具有顏色和位置,但沒有確定的方向。點光源向各個方向發出的光相等,如下圖所示。

             

            燈泡是點光源的一個很好的例子。點光源受衰減和范圍的影響,并基于每個頂點對網格進行照明。在計算光照的過程中,Direct3D使用點光源在世界坐標中的位置和當前頂點的坐標得到光的方向向量,以及光傳播的距離。兩者連同頂點法向一起,用于計算光在表面照明中所起的作用。

            平行光

            平行光只有顏色和方向,沒有位置。平行光發出平行的光,這意味著所有平行光產生的光在場景中以相同的方向傳播。可以認為平行光是位于無限遠處的光源,如太陽。平行光不受衰減和范圍的影響,因此應用程序指定的方向和顏色是Direct3D計算頂點顏色時要考慮的唯二因子。因為照明因子的數量少,所以平行光是可用的計算量最小的光。

            聚光燈

            聚光燈具有顏色、位置和發出光的方向。聚光燈發出的光由一個比較亮的內圓錐和一個較大的外圓錐組成,光強由內而外逐漸減小,如下圖所示。

             

            聚光燈受輻射(falloff)、衰減和范圍的影響。這些因子同光到每個頂點的距離一起,參與計算場景中物體的光照效果。由于需要對每個頂點計算這些效果,因此這使得聚光燈成為Direct3D所有類型的光源中最為耗時的。

            C++程序中,D3DLIGHT9結構包含了三個僅用于聚光燈的成員。這些成員——FalloffTheta、和Phi——控制聚光燈內外錐的大小,以及光如何在兩者之間減弱。

            Theta值為聚光燈內錐的角度,以弧度為單位,Phi值為聚光燈外錐的角度。Falloff值控制光強如何從內錐的外側向外錐的內側減弱。大多數應用程序將Falloff設為1.0,使光在兩個圓錐間平滑地減弱,但也可以根據需要設成其它值。

            下圖顯示了這些成員的值之間的關系,以及它們如何決定聚光燈的內外錐。

             

            • 聚光燈模型

            這里包含了有關聚光燈如何工作的更多信息。


            聚光燈模型


            聚光燈發出圓錐形的光,圓錐分為兩部分:較亮的內錐和外錐。內錐中的光最亮,而外錐以外則沒有光,在內外錐之間光強逐漸衰減。這種衰減一般被稱為輻射。

            一個頂點接收到的光的數量(譯注:此后簡稱為光量)取決于頂點在內錐或外錐中的位置。Microsoft® Direct3D®計算聚光燈的方向向量(L)和從頂點到聚光燈的向量(D)的點積。這個值等于兩個向量夾角的余弦值,并作為頂點位置的一個指標,可與聚光燈的圓錐角度進行比較以確定頂點位于內錐或外錐的何處。下面提供了這兩個向量之間關系的表示圖。

             

            系統將這個值與聚光燈的內錐和外錐角度的余弦值進行比較。在聚光燈的D3DLIGHT9結構中,ThetaPhi成員表示內錐和外錐的整個圓錐的角度。因為衰減和頂點與照明中心(亦即圓錐的中線)的夾角有關,所以在計算余弦值時Direct3D會將這兩個圓錐的角度除以二。

            如果向量LD的點積小于等于外錐角度的余弦值,那么頂點位于外錐以外,不接收任何光。如果LD的點積大于內錐角度的余弦值,那么頂點位于內錐里面,接收最多的光量,此時仍需考慮光隨距離的衰減。如果頂點位于這兩個區域之間的某處,那么Direct3D使用以下公式計算頂點的輻射值。

             

            在這個公式中,If為輻射后的光強,對正在計算光照的頂點來說,α為向量LD之間的夾角,F為二分之一外錐角度的余弦值,φ為二分之一內錐角度,為聚光燈在D3DLIGHT9結構中的輻射屬性Falloff。這個公式產生一個從0.0到1.0之間的值,用這個值對光強進行縮放就產生了輻射的效果。作為從頂點到聚光燈的距離的因子,衰減同時也被使用。p值對應D3DLIGHT9結構的Falloff成員,控制輻射曲線的形狀。下圖顯示了不同的Falloff值如何作用于輻射曲線。

             

            在實際光照中,不同的Falloff值產生的效果是很敏感的,并且如果使用除了1.0之外的值作為Falloff值描述輻射曲線,那么還會導致些許性能下降。為此,這個值一般被設為1.0。


            光的顏色


            Microsoft® Direct3D®中光源發出三種顏色,這三種顏色單獨用于系統的光照計算:漫反射色、環境反射色、和鏡面反射色。每種顏色在Direct3D光照模型的協助下,與當前材質中的對應部分相互作用,產生用于渲染的最終顏色。漫反射色與當前材質的漫反射系數屬性相互作用,鏡面反射色與材質的鏡面反射反射系數屬性相互作用,依次類推。有關Direct3D如何應用這些顏色的細節,請參閱與光照相關的數學

            C++應用程序中,D3DLIGHT9結構包含了三個與這些顏色——漫反射色環境反射色和鏡面反射色——相對應的成員,每個成員都是一個D3DCOLORVALUE結構,定義了發出的顏色。

            對系統計算量影響最大的顏色類型是漫反射色。最常用的漫反射色是白色(R:1.0 G:1.0 B:1.0),但是應用程序可以根據需要創建其它顏色以達到想要的效果。例如,應用程序可以為火爐使用紅光,或者為處于“通行”狀態的紅綠燈使用綠光。

            一般來說,應用程序將光的顏色成員設為從0.0到1.0之間的值,閉區間,但這不是必需的。例如,應用程序可以將所有成員設為2.0,創建出一個“比白色更亮”的光源。當應用程序使用的衰減值不為常數時,這種設定尤其有用。

            注意,雖然Direct3D使用RGBA值表示光的顏色,但是并沒有使用顏色的阿爾法成員。更多信息,請參閱光和材質和顏色值


            有顏色的頂點(Color Vertices)


            通常用材質顏色進行光照計算。但是,應用程序可以指定用頂點的漫反射色或鏡面反射色覆蓋材質顏色——放射色(emissive),環境反射色、漫反射色、和鏡面反射色。這可以通過調用IDirect3DDevice9::SetRenderState方法并用下表所列的值設置設備的狀態變量來完成。

            設備狀態變量

            含義

            類型

            默認值

            D3DRS_AMBIENTMATERIALSOURCE

            定義從何處得到環境光的材質色。

            D3DMATERIALCOLORSOURCE

            D3DMCS_MATERIAL

            D3DRS_DIFFUSEMATERIALSOURCE

            定義從何處得到漫反射材質色。

            D3DMATERIALCOLORSOURCE

            D3DMCS_COLOR1

            D3DRS_SPECULARMATERIALSOURCE

            定義從何處得到鏡面反射材質色。

            D3DMATERIALCOLORSOURCE

            D3DMCS_COLOR2

            D3DRS_EMISSIVEMATERIALSOURCE

            定義從何處得到emissive材質色。

            D3DMATERIALCOLORSOURCE

            D3DMCS_MATERIAL

            D3DRS_COLORVERTEX

            禁用或啟用頂點色。

            BOOL

            TRUE

            阿爾法/透明度值總是從漫反射色的阿爾法通道中得到。

            霧因子的值總是從鏡面反射色的阿爾法通道中得到。

            D3DMATERIALCOLORSOURCE可以為以下值:

            • D3DMCS_MATERIAL - 用材質顏色作為材質顏色的來源。
            • D3DMCS_COLOR1 - 用頂點的漫反射色作為材質顏色的來源。
            • D3DMCS_COLOR2 - 用頂點的鏡面反射色作為材質顏色的來源。

            光的位置、范圍和衰減


            位置、范圍和衰減屬性定義了光源在世界空間中的位置和光源發出的光如何隨距離而變化。同C++應用程序中使用的所有其它光的屬性一樣,這些屬性被包含在光源的D3DLIGHT9結構中。

            位置

            光源的位置用D3DVECTOR結構表示,它對應于D3DLIGHT9結構中的Position成員。約定x,y和z坐標在世界空間中。平行光是唯一不使用位置屬性的光源類型。

            范圍

            光源的范圍屬性決定在世界空間中的距離,場景中與光源相距超出這個距離的網格不再接收該光源發出的光。Range成員是一個浮點數,表示光源在世界空間中的最大范圍。平行光不使用范圍屬性。

            衰減

            衰減控制光強如何朝范圍屬性指定的最大范圍逐漸減弱。D3DLIGHT9結構中有三個成員用于表示衰減:Attenuation0Attenuation1、和Attenuation2。這些成員為從0.0到無窮大的浮點數,用于控制光強的衰減。一些應用程序將Attenuation1成員設為1.0,而其余的設為0.0,得到光強的變化為1/D,這里D為從光源到頂點之間的距離。光強在光源處最大,在光的最大范圍處減弱到1/(Light Range)。一般來說,應用程序將Attenuation0設為0.0,將Attenuation1設為一個常數,將Attenuation2設為0.0。(譯注:請參閱與光照相關的數學

            為得到更復雜的衰減效果,應用程序可以將衰減值結合起來使用。或者,為創建更奇怪的衰減效果,應用程序也可以將它們設為正常范圍外的值。但是,負的衰減值是不允許的。


            光的方向


            光的方向屬性決定光源發出的光在世界空間中傳播的方向。只有平行光和聚光燈使用方向,方向用一個向量表示。

            C++應用程序在D3DLIGHT結構的Direction成員中設置光的方向。Direction成員為D3DVECTOR類型。方向向量用始于邏輯原點的一段距離描述,與光源在場景中的位置無關。因此,一個筆直指向場景內——沿正z軸——的聚光燈,無論它的位置在哪里,它的方向向量都是<0,0,1>。類似地,通過使用方向為<0,-1,0>的平行光,應用程序可以模擬直射到場景中的陽光。顯然,應用程序不一定要創建沿坐標軸照射的光,可以混合搭配這些值,創建出沿某個更有意義的角度照射的光。

            注意 雖然應用程序無需歸一化光的方向向量,但是要保證該向量長度不為零。換句話說,不要將<0,0,0>用作方向向量。


            光的使用


            設置和取得光的屬性

            C++應用程序中,可以通過先準備一個D3DLIGHT9結構,然后調用IDirect3DDevice9::SetLight方法設置光的屬性。IDirect3DDevice9::SetLight方法接收一個索引值,告訴設備將這組光屬性存放在它的內部屬性列表的何處,及定義這些屬性的D3DLIGHT9結構的地址。要更新光的照明屬性,應用程序可以根據需要用新的屬性信息調用IDirect3DDevice9::SetLight

            每次應用程序用一個索引值調用IDirect3DDevice9::SetLight,但該索引值從未設置過屬性時,系統會分配內存以容納新的一組光屬性。應用程序可以設置許多光源,但是任一時刻只能啟用其中的一個子集(譯注:子集的大小由硬件能力決定)。要確定設備支持的可激活的光源,應用程序可以在取得設備能力后檢查D3DCAPS9結構的MaxActiveLights成員。如果應用不再需要使用某個光源,可以將它禁用或用新的一組光屬性將它覆蓋。

            以下C++示例代碼準備并設置了一個白色點光源的屬性,它發出的光不會隨距離而衰減。

            // 假設d3dDevice為一個指向IDirect3DDevice9接口的有效指針。
            D3DLIGHT9 d3dLight;
            HRESULT   hr;
             
            // 初始化結構。
            ZeroMemory(&d3dLight, sizeof(d3dLight));
             
            // 設置一個白色的點光源。
            d3dLight.Type = D3DLIGHT_POINT;
            d3dLight.Diffuse.r = 1.0f;
            d3dLight.Diffuse.g = 1.0f;
            d3dLight.Diffuse.b = 1.0f;
            d3dLight.Ambient.r = 1.0f;
            d3dLight.Ambient.g = 1.0f;
            d3dLight.Ambient.b = 1.0f;
            d3dLight.Specular.r = 1.0f;
            d3dLight.Specular.g = 1.0f;
            d3dLight.Specular.b = 1.0f;
             
            // 將它放在場景中的高處,位于用戶的后面。
            // 記住,這些坐標是在世界空間中的,因此用戶也可以在世界空間中的任何位置。
            // 根據本示例代碼的目的,假設用戶位于世界空間的原點。
            d3dLight.Position.x = 0.0f;
            d3dLight.Position.y = 1000.0f;
            d3dLight.Position.z = -100.0f;
             
            // 不隨距離衰減。
            d3dLight.Attenuation0 = 1.0f; 
            d3dLight.Range        = 1000.0f;
             
            // 設置第一個光源的屬性。
            hr = d3dDevice->SetLight(0, &d3dLight);
            if (SUCCEEDED(hr))
                     // 成功后的處理
            else
                     // 失敗后的處理

            應用程序可以在任何時候再次調用IDirect3DDevice9::SetLight方法以更新一組光屬性。只需指定要更新的那組光屬性的索引值和包含新屬性的D3DLIGHT9結構的地址。

            注意    給設備分配一組光屬性并不意味著啟用對應的光源。要對設備調用IDirect3DDevice9::LightEnable方法才能啟用光源。

            C++程序中,通過對設備調用IDirect3DDevice9::GetLight方法,應用程序可以取得一個現存光源的所有屬性。

            以下示例代碼描述了這個過程。

            // 假設d3dDevice為一個指向IDirect3DDevice9接口的有效指針。
            HRESULT hr;
            D3DLIGHT9 light;
             
            // 取得第一個光源的屬性信息。
            hr = pd3dDevice->GetLight(0, &light);
            if (SUCCEEDED(hr))
                     // 成功后的處理
            else
                     // 失敗后的處理

            如果應用程序提供的索引值超出了分配給設備的光源的范圍,那么IDirect3DDevice9::GetLight方法將會失敗,返回D3DERR_INVALIDCALL錯誤碼。

            啟用和禁用光源

            當應用程序給場景中的光源指定了光屬性時,就可以對該設備調用IDirect3DDevice9::LightEnable方法激活這個光源。默認情況下新的光源是禁用的。IDirect3DDevice9::LightEnable方法接收兩個參數。將第一個參數設為要用改變的光源的索引值,從零開始計數,將第二個參數設為TRUE啟用該光源或FALSE禁用該光源。

            以下示例代碼描述了用這種方法啟用設備的光源屬性列表中的第一個光源。

            // 假設d3dDevice為一個指向IDirect3DDevice9接口的有效指針。
            HRESULT hr;
             
            hr = pd3dDevice->LightEnable(0, TRUE);
            if (SUCCEEDED(hr))
                     // 成功后的處理
            else
                     // Handle failure

            要確定設備支持的最多可激活的光源的數量,應用程序可以在取得設備能力時,檢查D3DCAPS9結構的MaxActiveLights成員。

            如果應用程序啟用或禁用一個光源,但沒有調用IDirect3DDevice9::SetLight設置過該光源的屬性,那么IDirect3DDevice9::LightEnable方法會先用下表所列的屬性創建一個光源,然后再啟用或禁用該光源。

            成員

            默認值

            Type

            D3DLIGHT_DIRECTIONAL

            Diffuse

            (R:1, G:1, B:1, A:0)

            Specular

            (R:0, G:0, B:0, A:0)

            Ambient

            (R:0, G:0, B:0, A:0)

            Position

            (0, 0, 0)

            Direction

            (0, 0, 1)

            Range

            0

            Falloff

            0

            Attenuation0

            0

            Attenuation1

            0

            Attenuation2

            0

            Theta

            0

            Phi

            0


            與光照相關的數學


            Microsoft® Direct3D®光照模型涵蓋了環境光、漫反射光、鏡面反射光和放射光,這足以解決絕大部分的光照情況。我們將場景中光的總和稱為全局照明(global illumination,并使用以下公式計算:

            全局照明 = 環境光 + 漫反射光 + 鏡面反射光 + 放射光

            環境光是恒定的光照。它在所有方向上不發生變化,對物體中所有像素產生的作用也完全相同。它計算起來很快,但得到的物體看起來是平面的,沒有真實感。要了解Direct3D如何計算環境光,請參閱環境光

            漫反射光取決于光的方向和表面的法向。由于光的方向和表面法向量的變化,因此漫反射光會隨物體的表面而變化。因為漫反射光隨著每個頂點而變化,所以需要更長的時間進行計算,但是使用漫反射光帶來的好處是它使物體呈現出明暗變化和三維深度。要了解Direct3D如何計算漫反射光,請參閱漫反射光

            鏡面反射光代表了當光線照射到物體表面時反射回攝像機形成的明亮的鏡面反射高光。它比漫反射光更強,但在物體表面也衰減得更快。計算鏡面反射光需要比計算漫反射光更長的時間,但是使用鏡面反射光帶來的好處是它給表面增添了重要的細節。要了解Direct3D如何計算鏡面反射光,請參閱鏡面反射光

            放射光是物體發出的光,例如光暈(glow)。要了解Direct3D如何計算放射光,請參閱放射光

            通過在三維場景中使用這些類型的光,可以得到真實的光照效果。要得到更為真實的光照效果,應用程序可以添加更多的光源,但是,這增加了渲染場景的時間。要達到(游戲)設計師想要的所有效果,一些游戲使用了超出一般的CPU計算能力。在這種情況下,一般通過在使用紋理貼圖的同時,使用光照貼圖和環境貼圖給場景加入光照的效果,這樣就可以把光照所需的計算量減到最少。

            光照計算在攝像機空間進行。要了解如何計算光照變換,請參閱攝像機空間的變換。經過優化的光照計算可以在建模空間進行,但需滿足以下特殊條件:法向量已經歸一化(D3DRS_NORMALIZENORMALS為TRUE),不需要進行頂點混合,變換矩陣為正交的,等等。

            環境光、漫反射光和鏡面反射光會受到給定光源的衰減和聚光燈因子的影響。為環境光、放射光和漫反射光成分計算的顏色值被保存在輸出頂點的漫反射色中。漫反射和鏡面反射公式都包含了衰減和聚光燈因子屬性。更多信息,請參閱衰減和聚光燈因子


            環境光


            環境光為場景提供了一種恒定不變的光。環境光對所有物體的頂點的照明效果相同,因為它與其余光照因子無關,如頂點法向、光的方向、光的位置、范圍或衰減等。環境光是最快的一種類型,但它提供的真實感最少。Microsoft® Direct3D®包含了一個全局的環境光屬性,應用程序可以直接使用而無需創建任何光源。另外,應用程序也可以指定某個光源提供環境光。場景中環境光的計算由以下公式描述。

            Ambient Lighting = Ca*[Ga + sum(Lai*Attenuationi*SpotFactori)]

            環境光的公式不完全正確。應該是Ambient Lighting = Ca*[Ga + sum(Lai)*Atti*Spoti],這里AttSpot為第i個光源的衰減和聚光燈因子。

            參數在下表中定義。

            參數

            默認值

            類型

            描述

            Ca

            (0,0,0,0)

            D3DCOLORVALUE

            材質的環境反射色。

            Ga

            (0,0,0,0)

            D3DCOLORVALUE

            全局的環境反射色。

            sum

            N/A

            N/A

            所有光源產生的環境光的總和。

            Lai

            (0,0,0,0)

            D3DVECTOR

            i個光源產生的環境反射色。

            Atteni

            (0,0,0,0)

            D3DCOLORVALUE

            i個光源的衰減因子。請參閱衰減和聚光燈因子

            Spoti

            (0,0,0,0)

            D3DVECTOR

            i個光源的聚光燈因子。請參閱衰減和聚光燈因子

            Ca的值可以是:

            • 頂點顏色1,如果AMBIENTMATERIALSOURCE = D3DMCS_COLOR1,并且頂點聲明中給出了第一個頂點的顏色。
            • 頂點顏色2,如果AMBIENTMATERIALSOURCE = D3DMCS_COLOR2,并且頂點聲明中給出了第二個頂點的顏色。
            • 材質的環境反射色。

            注意 如果使用了任何一種AMBIENTMATERIALSOURCE,但是沒有提供頂點顏色,那么系統會使用材質的環境反射色。

            要使用材質的環境反射色,按以下示例代碼使用SetMaterial方法。

            Ga為全局的環境反射色,通過SetRenderState(D3DRENDERSTATE_AMBIENT)設置。Direct3D場景中只有一個全局環境反射色,它與其余Direct3D光源無關。

            Lai為場景中第i個光源的環境反射色。每個Direct3D光源都有一組屬性,其中一個就是環境反射色。符號sum(Lai)表示場景中所有環境反射色的總和。

            示例

            在本例中,通過計算場景的環境光的顏色和材質的環境反射色得到物體的顏色。代碼如下所示。

            #define GRAY_COLOR                          0x00bfbfbf
             
            // 創建材質
            D3DMATERIAL9 mtrl;
            ZeroMemory( &mtrl, sizeof(mtrl) );
            mtrl.Ambient.r = 0.75f;
            mtrl.Ambient.g = 0.0f;
            mtrl.Ambient.b = 0.0f;
            mtrl.Ambient.a = 0.0f;
            m_pd3dDevice->SetMaterial( &mtrl );
            m_pd3dDevice->SetRenderState( D3DRS_AMBIENT, GRAY_COLOR);

            根據公式,得到的物體頂點的顏色是材質顏色和光的顏色的合成。

            下面兩張圖片顯示了材質顏色,為灰色,和光的顏色,為紅色。

             

            渲染得到的場景如下所示。場景中唯一的物體是一個球體。環境光用相同的顏色對物體的所有頂點進行光照計算,它不依賴于頂點法向和光的方向。因此,球體看起來像是二維的圓,因為物體的表面沒有明暗變化。

             

            要使物體看起來更真實,除了環境光之外,需要再添加漫反射光或鏡面反射光。


            漫反射光


            在根據任何衰減效果調整完光的強度之后,光照引擎用給定的頂點法向與入射光方向之間的夾角,計算剩余的光中有多少會從頂點反射。對于平行光,光照引擎略過這一步,因為平行光不隨距離而衰減。系統會考慮兩種反射類型,漫反射和鏡面反射,并使用不同的公式計算每種類型各反射多少光。在計算完反射光的數量后,Microsoft® Direct3D®把得到的新值應用于當前材質的漫反射和鏡面反射反射系數屬性。最終的顏色值是漫反射色和鏡面反射色成員,會被光柵化器用于計算高洛德著色和鏡面反射高光。

            漫反射光由以下公式描述。

            Diffuse Lighting = sum[Cd*Ld*(N.Ldir)*Atten*Spot]

             

            參數

            默認值

            類型

            描述

            sum

            N/A

            N/A

            每個光源的漫反射色成分的總和。

            Cd

            (0,0,0,0)

            D3DCOLORVALUE

            漫反射色。

            Ld

            (0,0,0,0)

            D3DCOLORVALUE

            光源的漫反射色。

            N

            N/A

            D3DVECTOR

            頂點法向。

            Ldir

            N/A

            D3DVECTOR

            從頂點到光源的方向向量。

            Atten

            N/A

            FLOAT

            光的衰減因子。請參閱衰減和聚光燈因子

            Spot

            N/A

            FLOAT

            聚光燈因子。請參閱衰減和聚光燈因子

            Cd的值可以是:

            • 頂點顏色1,如果DIFFUSEMATERIALSOURCE = D3DMCS_COLOR1,并且頂點聲明中給出了第一個頂點的顏色。
            • 頂點顏色2,如果DIFFUSEMATERIALSOURCE = D3DMCS_COLOR2,并且頂點聲明中給出了第二個頂點的顏色。
            • 材質的環境反射色。

            注意 如果使用了任何一種DIFFUSEMATERIALSOURCE,但是沒有提供頂點顏色,那么系統會使用材質的漫反射色。

            要計算衰減(Atten)或聚光燈(Spot)屬性,請參閱衰減和聚光燈因子

            在所有光源都經過單獨處理和插值后,漫反射成員被截取到從0到255之間。最終的漫反射光的顏色值是環境光、漫反射光和放射光的顏色值的組合。

            示例

            在本例中,通過計算光源的漫反射色和材質的漫反射色得到物體的顏色。代碼如下所示。

            D3DMATERIAL9 mtrl;
            ZeroMemory( &mtrl, sizeof(mtrl) );
             
            D3DLIGHT9 light;
            ZeroMemory( &light, sizeof(light) );
            light.Type = D3DLIGHT_DIRECTIONAL;
             
            D3DXVECTOR3 vecDir;
            vecDir = D3DXVECTOR3(0.5f, 0.0f, -0.5f);
            D3DXVec3Normalize( (D3DXVECTOR3*)&light.Direction, &vecDir );
             
            // 設置平行光的漫反射色
            light.Diffuse.r = 1.0f;
            light.Diffuse.g = 1.0f;
            light.Diffuse.b = 1.0f;
            light.Diffuse.a = 1.0f;
            m_pd3dDevice->SetLight( 0, &light );
            m_pd3dDevice->LightEnable( 0, TRUE );
             
            // 如果使用了材質,那么必須使用SetRenderState。
            // 頂點顏色 = 光的漫反射色 * 材質的漫反射色
            mtrl.Diffuse.r = 0.75f;
            mtrl.Diffuse.g = 0.0f;
            mtrl.Diffuse.b = 0.0f;
            mtrl.Diffuse.a = 0.0f;
            m_pd3dDevice->SetMaterial( &mtrl );
            m_pd3dDevice->SetRenderState(D3DRS_DIFFUSEMATERIALSOURCE, D3DMCS_MATERIAL);

            根據公式,得到的物體頂點的顏色是材質顏色和光的顏色的組合。

            下面兩張圖片顯示了材質顏色,為灰色,和光的顏色,為紅色。

             

            渲染得到的場景如下所示。場景中唯一的物體是一個球體。漫反射光照計算取得材質和光的漫反射色,用光的方向和頂點法向的點積作為它們之間的夾角修正得到的顏色。因此,球體的后面變得較黑,因為那部分球面背向光源。

             

            將漫反射光和前例產生的環境光結合起來,會使物體的整個表面呈現出明暗效果。環境光使整個表面變亮,而漫反射光則有助于展現出物體的三維形狀。

             

            漫反射光比環境光需要更多的計算,因為它依賴于頂點的法向和光的方向。我們可以看一下在三維場景中的幾何體,漫反射光產生了比環境光更為真實的光照效果。我們還可以使用鏡面反射高光來達到更為真實的效果。


            鏡面反射光


            建立一個鏡面反射模型需要系統不僅知道光傳播的方向,還要知道從頂點到視點的方向。Direct3D光照系統使用了一個經過簡化的Phong(譯注:馮)鏡面反射模型,該簡化模型使用一個中間向量(原文:halfway vector,譯注:某些圖形學書籍譯為半角矢量)計算鏡面反射光強的近似值。

            默認的光照狀態不計算鏡面反射高光。要啟用鏡面反射高光,需要將D3DRS_SPECULARENABLE設置為TRUE。

            鏡面反射光公式

            鏡面反射光由以下公式描述。

            Specular Lighting = Cs*sum[Ls*(N.H)P*Atten*Spot]

            下表描述了所有變量,其類型及范圍。

            參數

            默認值

            類型

            描述

            Cs

            (0,0,0,0)

            D3DCOLORVALUE

            鏡面反射色。

            sum

            N/A

            N/A

            每個光源的鏡面反射成員的總和。

            N

            N/A

            D3DVECTOR

            頂點法向。

            H

            N/A

            D3DVECTOR

            中間向量。請參閱中間向量相關的部分。

            P

            0.0

            FLOAT

            鏡面反射反射指數。范圍從0到正無窮大。

            Ls

            (0,0,0,0)

            D3DCOLORVALUE

            光的鏡面反射色。

            Atten

            N/A

            FLOAT

            光的衰減值。請參閱衰減和聚光燈因子

            Spot

            N/A

            FLOAT

            聚光燈因子。請參閱衰減和聚光燈因子

            Cs的值可以是:

            • 頂點顏色1,如果SPECULARMATERIALSOURCE = D3DMCS_COLOR1,并且頂點聲明中給出了第一個頂點的顏色。
            • 頂點顏色2,如果SPECULARMATERIALSOURCE = D3DMCS_COLOR2,并且頂點聲明中給出了第二個頂點的顏色。
            • 材質的環境反射色。

            注意 如果使用了任何一種SPECULARMATERIALSOURCE,但是沒有提供頂點顏色,那么系統會使用材質的鏡面反射色。

            在所有光源都經過單獨處理和插值后,鏡面反射成員被截取到從0到255之間。

            中間向量

            中間向量(H)位于兩個向量之間:從頂點到光源的向量,和從頂點到攝像機位置的向量。Microsoft® Direct3D®提供了兩種方法來計算中間向量。當D3DRS_LOCALVIEWER被設為TRUE時,系統使用攝像機的位置和頂點的位置,與光源的方向向量來計算中間向量。以下公式描述了這種方法。

            H = norm(norm(Cp - Vp) + Ldir)

             

            參數

            默認值

            類型

            描述

            Cp

            N/A

            D3DVECTOR

            攝像機的位置。

            Vp

            N/A

            D3DVECTOR

            頂點的位置。

            Ldir

            N/A

            D3DVECTOR

            從頂點位置到光源位置的向量。

            用這種方法計算中間向量的計算量會非常大。另一種可選的方法是將D3DRS_LOCALVIEWER設置為FALSE,告訴系統將視點當作在z軸無限遠處進行計算。下面的公式反映了這種方法。

            H = norm((0,0,1) + Ldir)

            這種設定計算量不很大,但很不精確,因此它最適合用在使用正交投影的應用程序中。

            示例

            在本例中,通過計算光源的鏡面反射色和材質的鏡面反射色得到物體的顏色。代碼如下所示。

            D3DMATERIAL9 mtrl;
            ZeroMemory( &mtrl, sizeof(mtrl) );
             
            D3DLIGHT9 light;
            ZeroMemory( &light, sizeof(light) );
            light.Type = D3DLIGHT_DIRECTIONAL;
             
            D3DXVECTOR3 vecDir;
            vecDir = D3DXVECTOR3(0.5f, 0.0f, -0.5f);
            D3DXVec3Normalize( (D3DXVECTOR3*)&light.Direction, &vecDir );
             
            light.Specular.r = 1.0f;
            light.Specular.g = 1.0f;
            light.Specular.b = 1.0f;
            light.Specular.a = 1.0f;
             
            light.Range = 1000;
            light.Falloff = 0;
            light.Attenuation0 = 1;
            light.Attenuation1 = 0;
            light.Attenuation2 = 0;
            m_pd3dDevice->SetLight( 0, &light );
            m_pd3dDevice->LightEnable( 0, TRUE );
            m_pd3dDevice->SetRenderState( D3DRS_SPECULARENABLE, TRUE );
             
            mtrl.Specular.r = 1.0f;
            mtrl.Specular.g = 1.0f;
            mtrl.Specular.b = 1.0f;
            mtrl.Specular.a = 1.0f;
            mtrl.Power = 20;
            m_pd3dDevice->SetMaterial( &mtrl );
            m_pd3dDevice->SetRenderState(D3DRS_SPECULARMATERIALSOURCE, D3DMCS_MATERIAL);

            根據公式,得到的物體頂點的顏色是材質顏色和光的顏色的組合。

            以下兩張圖片顯示了材質顏色,為灰色,和光的顏色,為白色。

             

            得到的鏡面反射高光如下所示。

             

            將鏡面反射高光與前例產生的環境光和漫反射光結合起來,會得到以下圖像。當所有三種類型的光一起使用時,渲染得到的球體明顯看起來更像是真實物體。

             

            鏡面反射光需要比漫反射光更多的計算量。鏡面反射光一般用于以可見的方式提供有關表面材質的信息。鏡面反射高光會隨著表面材質的不同在大小和顏色上有所不同。


            放射光


            放射光由一個單獨的參數表示。

            Emissive Lighting = Ce

            這里:

            參數

            默認值

            類型

            描述

            Ce

            (0,0,0,0)

            D3DCOLORVALUE

            Emissive color.

            Ce的值可以是:

            • 頂點顏色1,如果EMISSIVEMATERIALSOURCE = D3DMCS_COLOR1,并且頂點聲明中給出了第一個頂點的顏色。
            • 頂點顏色2,如果EMISSIVEMATERIALSOURCE = D3DMCS_COLOR2,并且頂點聲明中給出了第二個頂點的顏色。
            • 材質的放射色。

            注意 如果使用了任何一種EMSSIVEMATERIALSOURCE,但是沒有提供頂點顏色,那么系統會使用材質的放射色。

            示例

            在本例中,通過計算場景的環境光的顏色和材質的環境反射色得到物體的顏色。代碼如下所示。

            // 創建材質
            D3DMATERIAL9 mtrl;
            ZeroMemory( &mtrl, sizeof(mtrl) );
            mtrl.Emissive.r = 0.0f;
            mtrl.Emissive.g = 0.75f;
            mtrl.Emissive.b = 0.0f;
            mtrl.Emissive.a = 0.0f;
            m_pd3dDevice->SetMaterial( &mtrl );
            m_pd3dDevice->SetRenderState(D3DRS_EMISSIVEMATERIALSOURCE, D3DMCS_MATERIAL);

            根據公式,得到的物體頂點的顏色為材質的顏色。

            下圖顯示了材質顏色,為綠色。放射光用相同的顏色對物體的所有頂點進行光照計算,它不依賴于頂點法向或光的方向。因此,球體看起來像是二維的圓,因為物體表面沒有明暗變化。

             

            下圖顯示了放射光與前例中其余三種類型的光混合后得到的結果。球體的右邊是綠色的放射光和紅色的環境光的混合。球體的左邊,綠色的放射光與紅色的環境光和漫反射光混合產生了紅色的顏色梯度。中間是白色的鏡面反射高光,隨著鏡面反射高光向周圍迅速衰減,產生了一個黃色的圓環,其余區域只有環境光、漫反射光和放射光混合成黃色。

             


            攝像機空間的變換


            攝像機空間中的頂點通過用世界視矩陣(world view matrix)對頂點進行變換得到。

            V = V * wvMatrix

            攝像機空間中的頂點法向通過用世界視矩陣的轉置逆矩陣對物體的法向進行變換得到。世界視矩陣可能是也可能不是正交的。

            N = N * (wvMatrix-1)T

            求逆矩陣和轉置矩陣的操作在一個4x4矩陣上進行。乘法操作將法向和得到的4x4矩陣中的3x3那部分相乘。

            如果渲染狀態D3DRENDERSTATE_NORMALIZENORMALS被設置為TURE,那么在變換到攝像機空間后,頂點法向量被歸一化,如下所示。

            N = norm(N)

            攝像機空間中光源的位置通過用視矩陣對光源位置進行變換得到。

            Lp = Lp * vMatrix

            攝像機空間中平行光的方向通過將光源的方向與視矩陣相乘、歸一化、并對結果取反得到。

            Ldir = -norm(Ldir * wvMatrix)

            D3DLIGHT_POINT和D3DLIGHT_SPOT類型的光源,光的方向用以下公式計算:

            Ldir = norm(V * Lp), 這里的參數由下表定義。

            參數

            默認值

            類型

            描述

            Ldir

            N/A

            D3DVECTOR

            從頂點到光源的方向向量

            V

            N/A

            D3DVECTOR

            攝像機空間中頂點的位置

            wvMatrix

            Identity

            D3DMATRIX

            包含世界和視變換和合成矩陣

            N

            N/A

            D3DVECTOR

            頂點法向

            Lp

            N/A

            D3DVECTOR

            攝像機空間中光源的位置

            vMatrix

            Identity

            D3DMATRIX

            包含視變換的矩陣


            衰減和聚光燈因子


            漫反射光和鏡面反射光成員的全局照明公式中包含了描述光的衰減和聚光燈因子的屬性。這些屬性在下面描述。

            衰減因子

            光的衰減因子取決于光的類型和從光到頂點所在位置的距離。要計算衰減因子,可以使用以下三個公式之一。

            Atten = 1/( att0i + att1i * d + att2i * d2)

            這里:

            參數

            默認值

            類型

            描述

            att0i

            0.0

            FLOAT

            線性衰減因子。范圍從0到正無窮大

            att1i

            0.0

            FLOAT

            平方衰減因子。范圍從0到正無窮大

            att2i

            0.0

            FLOAT

            指數衰減因子。范圍從0到正無窮大。

            d

            N/A

            FLOAT

            從頂點位置到光源位置的距離

            • Atten = 1, 如果光源為平行光。
            • Atten = 0, 如果從光源到頂點的距離超出了光的范圍。

            att0、att1、和att2值由D3DLIGHT9結構的Attenuation0Attenuation1、和Attenuation2成員給出。

            從光源到頂點位置的距離總是正的。

            d = | Ldir |

            這里:

            參數

            默認值

            類型

            描述

            Ldir

            N/A

            D3DVECTOR

            從頂點位置到光源位置的方向向量

            如果d大于光的范圍,也就是D3DLIGHT9結構的Range成員,Microsoft® Direct3D®不再進行更進一步的衰減計算,也不應用任何光照效果于該頂點。

            衰減常數作為公式中的一個系數——應用程序僅需調整它們的值就可以產生不同的衰減曲線。應用程序可以將Attenuation1設為1.0,創建一個不隨距離衰減但仍受距離限制的光源,或者應用程序也可以試驗不同的值以達到不同的衰減效果。

            位于最大范圍處,光的衰減因子不是0.0。為防止光在最大范圍處突然出現,應用程序可以增加光的范圍。或者,應用程序也可以設置衰減常數使衰減因子在光的最大范圍處接近0.0。作為光到達一個頂點所經過的距離的因子,衰減值與光的顏色的紅、綠和藍成分相乘以縮放光強。

            聚光燈因子

             

             

            參數

            默認值

            類型

            描述

            rhoi

            N/A

            FLOAT

            聚光燈i的余弦值(角度)

            phii

            0.0

            FLOAT

            聚光燈i的外錐角度,以弧度為單位。范圍為:[theta, pi)

            thetai

            0.0

            FLOAT

            聚光燈i的內錐角度,以弧度為單位。范圍為:[0, pi)

            falloff

            0.0

            FLOAT

            輻射因子。范圍為:(負無窮,正無窮)

            這里:

            rho = norm(Ldcs).norm(Ldir)

            并且:

            參數

            默認值

            類型

            描述

            Ldcs

            N/A

            D3DVECTOR

            光在攝像機空間中的方向取反

            Ldir

            N/A

            D3DVECTOR

            從頂點位置到光源位置的方向向量

            在計算光的衰減后,Direct3D還會考慮:聚光燈效果,如果適用的話,光從表面反射的角度,用于計算頂點的漫反射和鏡面反射成員的當前材質的反射系數。更多信息,請參閱聚光燈模型


            材質


            材質描述在三維場景中的多邊形如何反射光或如何發光。本質上,材質是一組屬性集合,告訴Microsoft® Direct3D®有關正在渲染的多邊形的下列信息。

            • 材質如何反射環境光和漫反射光
            • 材質和鏡面反射高光看起來是什么樣
            • 多邊形發光時看起來是什么樣

            C++寫的Direct3D應用程序用D3DMATERIAL9結構描述材質屬性。更多信息,請參閱材質屬性

            設置材質屬性

            Direct3D渲染設備在同一時刻可以使用一組材質屬性進行渲染。

            C++應用程序通過先準備一個D3DMATERIAL9結構,然后調用IDirect3DDevice9::SetMaterial方法設置給系統使用的材質屬性。

            要準備使用一個D3DMATERIAL9結構,需根據想要創建的渲染效果設置該結構的屬性信息。以下示例代碼為一個具有高強度白色鏡面反射高光的紫色材質設立了相應的D3DMATERIAL9結構。

            D3DMATERIAL9 mat;
             
            // 設置漫反射反射系數的RGBA值。
            mat.Diffuse.r = 0.5f;
            mat.Diffuse.g = 0.0f;
            mat.Diffuse.b = 0.5f;
            mat.Diffuse.a = 1.0f;
             
            // 設置環境光反射系數的RGBA值
            mat.Ambient.r = 0.5f;
            mat.Ambient.g = 0.0f;
            mat.Ambient.b = 0.5f;
            mat.Ambient.a = 1.0f;
             
            // 設置鏡面反射高光的顏色和強度。
            mat.Specular.r = 1.0f;
            mat.Specular.g = 1.0f;
            mat.Specular.b = 1.0f;
            mat.Specular.a = 1.0f;
            mat.Power = 50.0f;
             
            // 設置放射光的RGBA顏色值。
            mat.Emissive.r = 0.0f;
            mat.Emissive.g = 0.0f;
            mat.Emissive.b = 0.0f;
            mat.Emissive.a = 0.0f;

            在準備D3DMATERIAL9結構之后,應用程序通過調用IDirect3DDevice9::SetMaterial方法將材質屬性應用于渲染設備。這個方法接收一個準備好的D3DMATERIAL9結構的地址作為它唯一的參數。要更新設備的材質屬性,應用程序可以根據需要用新的屬性調用IDirect3DDevice9::SetMaterial。以下示例代碼顯示了這個過程。

            // 本示例代碼使用本節前面定義的mat變量保存的材質屬性。 
            // 假設pd3dDev為一個指向IDirect3DDevice9接口的有效指針。
            HRESULT hr;
            hr = pd3dDev->SetMaterial(&mat);
            if(FAILED(hr))
            {
                // 錯誤處理的代碼放在這里。
            }

            當應用程序創建Direct3D設備時,當前材質被自動設為如下表所示的默認值。

            成員

            Diffuse

            (R:1, G:1, B:1, A:0)

            Specular

            (R:0, G:0, B:0, A:0)

            Ambient

            (R:0, G:0, B:0, A:0)

            Emissive

            (R:0, G:0, B:0, A:0)

            Power

            (0.0)

            取得材質屬性

            通過對設備調用IDirect3DDevice9::GetMaterial方法,應用程序可以取得當前設備正在使用的材質屬性。與IDirect3DDevice9::SetMaterial方法不同的是,IDirect3DDevice9::GetMaterial無需準備工作。IDirect3DDevice9::GetMaterial方法接收一個D3DMATERIAL9結構的地址,將描述當前材質屬性的信息填入該結構,然后返回。

            // 在這個例子中,假設pd3dDev變量為一個指向IDirect3DDevice9接口的有效指針。
            HRESULT hr;
            D3DMATERIAL9 mat;
             
            hr = pd3dDev->GetMaterial(&mat);
            if(FAILED(hr))
            {
                // 錯誤處理的代碼放在這里。
            }

            更多關于材質屬性的信息,請參閱:

            • 材質屬性

            注意    如果應用程序不指定渲染使用的材質屬性,系統會使用默認的材質。默認的材質反射所有漫反射光——也就是白色——但沒有環境反射和鏡面反射,也沒有放射色。


            材質屬性


            材質屬性詳細描述了材質的漫反射系數、環境反射系數、發光度和鏡面反射高光的特性。Microsoft® Direct3D®使用D3DMATERIAL9結構保存所有材質屬性信息。材質屬性會影響Direct3D對使用該材質的多邊形做光柵化操作得到的顏色。除了鏡面反射屬性,其余每個屬性都用一個RGBA顏色描述,表示該材質對某一給定類型的光的紅、綠和藍成分的反射度,以及一個阿爾法混合因子——RGBA顏色的阿爾法成員。材質的鏡面反射屬性用兩部分描述:顏色和冪指數。更多信息,請參閱光和材質的顏色值

            漫反射和環境反射

            D3DMATERIAL9結構的DiffuseAmbient成員描述了材質如何反射場景中的環境光和漫反射光。因為大多數場景包含的漫反射光比環境光要多,所以在決定最終顏色的過程中漫反射所起的作用最大。另外,因為漫反射具有方向性,漫反射光的入射角會影響到整個反射光的強度。當光的入射方向與頂點法向平行時,漫反射最強。隨著入射方向與頂點法向之間夾角的增大,漫反射效果逐漸減少。反射光的數量是入射光與頂點法向之間夾角的余弦值,如下所示。

             

            環境反射和環境光一樣,沒有方向性。環境反射對被渲染物體最終的顏色影響較小,但它確實會影響最終的顏色,最為明顯的就是當材質很少甚至不反射漫反射光時。材質的環境反射受場景中的環境光的影響,場景的環境光通過調用IDirect3DDevice9::SetRenderState方法,并用D3DRS_AMBIENT作為參數設置。

            漫反射和環境反射一起用來決定物體反射的顏色,而且通常是相同的值。例如,要渲染一個藍色水晶物體,應用程序可以創建一個只反射漫反射光和環境光中藍色成分的材質。當水晶放在有白光的地方,它看起來會是藍色的。但是,在一個只有紅光的地方,同一個水晶看起來就會是黑色的,因為它的材質不反射紅光。

            放射

            材質可以用來使被渲染的物體看起來像是自身發光的。D3DMATERIAL9結構的Emissive成員就是用來描述物體發出的光的顏色和透明度的。放射會影響物體的顏色,也可以使暗的材質變亮并部分呈現出所發光的顏色。

            應用程序可以使用材質的發光屬性給一個物體增加發光的感覺,這不會導致因為給場景增加光源而帶來的計算開銷。在藍色水晶的例子中,如果希望水晶顯得亮,但又不照射到場景中的其它物體上,發光屬性就很有用。記住,具有發光屬性的材質不發射可以被場景中其它物體反射的光。要得到可以被其它物體反射的光,需要在場景中另外增加一個光源。

            鏡面反射

            鏡面反射在物體表面產生高光,這使它們看起來像是有光澤的。D3DMATERIAL9結構包含了兩個描述鏡面反射高光和整體亮度的成員。應用程序可以通過Specular成員將鏡面反射高光設為想要的RGBA顏色值——最常用的顏色是白色或淡灰色。應用程序可以設置Power成員的值控制鏡面反射效果的劇烈程度。

            鏡面反射高光可以產生生動的效果。還是以藍色水晶為例:較大的Power值會產生更為明亮的鏡面反射高光,使水晶看起來光芒四射。較小的值增大了產生效果的區域,造成不太明亮的反射,這使水晶看起來像灰色的。要使物體的表面真正是粗糙的,只需將Power成員設為零,并將Specular成員設為黑色。為了根據自己的需要產生真實的反射,可以試驗不同的反射系數。下圖描繪了兩個相同的建模。左邊使用了Power為10的鏡面反射,而右邊沒有鏡面反射。

             

            posted on 2009-08-22 17:44 狂爛球 閱讀(2312) 評論(0)  編輯 收藏 引用 所屬分類: 圖形編程

            国产国产成人久久精品| 久久久久亚洲精品天堂久久久久久| 亚洲精品无码专区久久同性男| 精品久久久无码人妻中文字幕| 久久国产精品-久久精品| 久久人妻无码中文字幕| 亚洲精品国产美女久久久| 久久综合九色综合欧美就去吻| 国产成人无码精品久久久性色| 久久青青国产| 无码专区久久综合久中文字幕| 久久免费高清视频| 久久精品国产只有精品2020| 欧美日韩精品久久久免费观看| 亚洲乱亚洲乱淫久久| 日本精品久久久久中文字幕| 伊人色综合久久天天网| 91精品久久久久久无码| 亚洲国产一成人久久精品| 久久久久久噜噜精品免费直播| 国产精品美女久久久久AV福利| 亚洲AV无一区二区三区久久| 日本亚洲色大成网站WWW久久 | 国产精品久久久福利| 99精品国产在热久久无毒不卡| 久久亚洲精品国产亚洲老地址 | 99久久99久久精品国产片| 亚洲精品美女久久久久99| 热久久国产欧美一区二区精品| 91精品免费久久久久久久久| 国产精品久久午夜夜伦鲁鲁| 99久久精品免费看国产| 国产成人久久激情91| 99久久精品影院老鸭窝| 国产∨亚洲V天堂无码久久久| 久久久久久精品无码人妻| 一本大道久久香蕉成人网| 日本精品久久久久久久久免费| 少妇被又大又粗又爽毛片久久黑人 | 伊人久久大香线蕉精品| 狠狠色丁香婷综合久久|