D3D 光和材質

材質在3D場景中決定了三角面片如果產生及反射光。材質屬性包含如下幾部分:diffuse reflection, ambient reflection, light emission 和 specular highlight。D3D用D3DMATERIAL9結構體包含材質屬性信息。除了specular property這一例外,其它屬性都是由RGBA值來表示的,決定了它們是如何反射一個光源。

Diffuse 和 Ambient反射
這兩個屬性決定了材質是如何反射場景中的diffuse跟ambient光源的。由於在大部分場景中,diffuse光比ambient光更多一些,所以diffuse反射在決定材質顏色方面扮演的角色更重一些。此外,diffuse光是方向性的,所以diffuse光的入射角度決定了整體反射的強度。當入射光線跟頂點法向量平行時,diffuse反射是最強的。
ambient反射,跟ambient光一樣是非方向性的。ambient反射對材質所屬物體的顏色影響很小,但,它的確影響了物體的整體顏色,尤其當diffuse光很小或者沒有的時候,ambient反射很容易察覺到。材質的ambient反射是受場景的ambient光影響的,該光是通過調用IDirect3DDevice9::SetRenderState方法,並使用D3DRS_AMBIENT標誌設置的。
Diffuse跟ambient反射一起工作決定了我們所察覺到的物體的顏色,通常,它們的值是一樣的。例如,要render一個藍色的水晶物體,我們創建一個只反射diffuse跟ambient光藍色部分的材質。當該物體放到一個有白光的房子裏,水晶顯示爲藍色。然後,如果放到一個只有紅光的房間裏,水晶將是黑色的,因爲它的材質只不反射紅光。

Emission
材質可以用來使被render的物體自我發光。D3DMATERIAL9結構體中的emissive成員用來描述放射光的顏色跟透明情況。emission影響物體的顏色,可以使黑暗的物體更明亮一些,呈現emmitted顏色的部分。
可以使用材質的emissive屬性添加物體發光的幻覺,這樣可以避免增加一個光源到場景中的overhead。在藍色水晶這個案例中,emissive屬性很有用,如果你想讓這水晶看起來被點亮了,卻不想在場景中cast一個光源。記住,具有emissive屬性的材質所“發散”的光並不會被場景中的其他物體反射。要想有反射光,必須在場景中增加一個額外的光源。

Specular Reflection
specular reflection創造物體的高亮效果,使其看起來很閃亮。D3DMATERIAL9結構體中有兩個成員描述高亮顏色及材質的整體閃亮度。通過設置specular成員到期待的RGBA顏色值,來建立鏡面高亮顏色。最常見的顏色是白色跟淺灰色。設置power成員來決定鏡面反射的尖銳度。

鏡面高亮可以創造引人注目的效果。高power值可以是鏡面高亮更閃耀,小的power值會增加該效果的區域,使其感覺比較冷淡。要想使一個物體感覺不光滑的,設置power值爲0,specular值爲黑色。

設置材質屬性
D3D渲染設備一次只能r渲染一組材質屬性。
下面是一段C++示例代碼:
D3DMATERIAL9 mat;

// Set the RGBA for diffuse reflection.
mat.Diffuse.r = 0.5f;
mat.Diffuse.g = 0.0f;
mat.Diffuse.b = 0.5f;
mat.Diffuse.a = 1.0f;

// Set the RGBA for ambient reflection.
mat.Ambient.r = 0.5f;
mat.Ambient.g = 0.0f;
mat.Ambient.b = 0.5f;
mat.Ambient.a = 1.0f;

// Set the color and sharpness of specular highlights.
mat.Specular.r = 1.0f;
mat.Specular.g = 1.0f;
mat.Specular.b = 1.0f;
mat.Specular.a = 1.0f;
mat.Power = 50.0f;

// Set the RGBA for emissive color.
mat.Emissive.r = 0.0f;
mat.Emissive.g = 0.0f;
mat.Emissive.b = 0.0f;
mat.Emissive.a = 0.0f;

// This code example uses the material properties defined for
// the mat variable earlier in this topic. The pd3dDev is assumed
// to be a valid pointer to an IDirect3DDevice9 interface.
HRESULT hr;
hr = pd3dDev->SetMaterial(&mat);
if(FAILED(hr))
{
// Code to handle the error goes here.
}

當我們創建一個D3D設備時,當前材質會被自動設置爲如下值:
Member Value
Diffuse (R:1, G:1, B:1, A:0) //我認爲1代表255的意思。
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)

獲取材質屬性
示例代碼如下所示:
// For this example, the pd3dDev variable is assumed to
// be a valid pointer to an IDirect3DDevice9 interface.
HRESULT hr;
D3DMATERIAL9 mat;

hr = pd3dDev->GetMaterial(&mat);
if(FAILED(hr))
{
// Code to handle the error goes here.
}

 

————————————————————————————————————————————————————————————

我們在生活中看到的光有環境光, 漫反射光以及璄面反射光還有物體本身發射的光. 因此我們在定義材質時就要描述對這些光反應.

看看材質結構體的定義:



typedef struct _D3DMATERIAL9 {
D3DCOLORVALUE Diffuse; /* Diffuse color RGBA */
D3DCOLORVALUE Ambient; /* Ambient color RGB */
D3DCOLORVALUE Specular; /* Specular 'shininess' */
D3DCOLORVALUE Emissive; /* Emissive color RGB */
float Power; /* Sharpness if specular highlight */
} D3DMATERIAL9;



typedef struct _D3DCOLORVALUE { float r; float g; float b; float a; } D3DCOLORVALUE;



Diffuse: 指定表面反射的漫射光數量.

Ambient: 指定表面反射的環境光數量.

Specular: 指定表面發射的境面光數量.

Emissive: 這個用來給表面添加顏色, 用來指定物體本身發出光的顏色.



材質中每個值都是D3DCOLORVALUE 結構, 這個結構其實反映了, 這個材質對某種光的那些顏色反射多少.

D3DMATERIAL9 matrl;

matrl.Diffuse.r = 0.5f;

matrl.Diffuse.b = 1.0f;

matrl.Diffuse.g = 0.0f;

那麼其結果就是對漫反射光,這個材質將一半的紅色光反射, 全部的藍色光反射, 全部的綠色光吸收.





還有一點非常重要, 在渲染一個模型時你可以打開光源, 而渲染另外一個時你可以關閉光源. 以前我的理解是在場景中選擇了一個光源後那麼所有在這個場景中的模型都是一直受影響的. 原來可以隨時打開光源, 關閉光源. 可以隨時設置另外一種光源.

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章