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;

那么其结果就是对漫反射光,这个材质将一半的红色光反射, 全部的蓝色光反射, 全部的绿色光吸收.





还有一点非常重要, 在渲染一个模型时你可以打开光源, 而渲染另外一个时你可以关闭光源. 以前我的理解是在场景中选择了一个光源后那么所有在这个场景中的模型都是一直受影响的. 原来可以随时打开光源, 关闭光源. 可以随时设置另外一种光源.

 

 

 

posted @ 2013-05-16 14:30  SoarNo1  阅读(462)  评论(0编辑  收藏  举报