天行健 君子当自强而不息

光照与材质(3)

设置灯光

在Direct3D的一个场景中,最多可设置8个光源,设置光源由IDirect3DDevice9::SetLight()函数完成。该函数的声明如下:

Assigns a set of lighting properties for this device.

HRESULT SetLight(
DWORD Index,
CONST D3DLight9 * pLight
);

Parameters

Index
[in] Zero-based index of the set of lighting properties to set. If a set of lighting properties exists at this index, it is overwritten by the new properties specified in pLight.
pLight
[in] Pointer to a D3DLIGHT9 structure, containing the lighting parameters to set.

Return Values

If the method succeeds, the return value is D3D_OK. If the method fails, the return value can be D3DERR_INVALIDCALL.

Remarks

Set light properties by preparing a D3DLIGHT9 structure and then calling the IDirect3DDevice9::SetLight method. The IDirect3DDevice9::SetLight method accepts the index at which the device should place the set of light properties to its internal list of light properties, and the address of a prepared D3DLIGHT9 structure that defines those properties. You can call IDirect3DDevice9::SetLight with new information as needed to update the light's illumination properties.

The system allocates memory to accommodate a set of lighting properties each time you call the IDirect3DDevice9::SetLight method with an index that has never been assigned properties. Applications can set a number of lights, with only a subset of the assigned lights enabled at a time. Check the MaxActiveLights member of the D3DCAPS9 structure when you retrieve device capabilities to determine the maximum number of active lights supported by that device. If you no longer need a light, you can disable it or overwrite it with a new set of light properties.

The following example prepares and sets properties for a white point-light whose emitted light will not attenuate over distance.

// Assume d3dDevice is a valid pointer to an IDirect3DDevice9 interface.
D3DLight9 d3dLight;
HRESULT hr;

// Initialize the structure.
ZeroMemory(&D3dLight, sizeof(d3dLight));

// Set up a white point light.
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;

// Position it high in the scene and behind the user.
// Remember, these coordinates are in world space, so
// the user could be anywhere in world space, too.
// For the purposes of this example, assume the user
// is at the origin of world space.
d3dLight.Position.x = 0.0f;
d3dLight.Position.y = 1000.0f;
d3dLight.Position.z = -100.0f;

// Don't attenuate.
d3dLight.Attenuation0 = 1.0f;
d3dLight.Range = 1000.0f;

// Set the property information for the first light.
hr = d3dDevice->SetLight(0, &d3dLight);
if (SUCCEEDED(hr))
// Handle Success
else
// Handle failure

Enable a light source by calling the IDirect3DDevice9::LightEnable method for the device.

函数IDirect3DDevice9::SetLight()只是设置光源,在默认情况下,设置的任何光源都还不起作用,具体使用哪些光源,由函数IDirect3DDevice9::LightEnable()确定,该函数声明如下:

Enables or disables a set of lighting parameters within a device.

HRESULT LightEnable(
DWORD LightIndex,
BOOL bEnable
);

Parameters

LightIndex
[in] Zero-based index of the set of lighting parameters that are the target of this method.
bEnable
[in] Value that indicates if the set of lighting parameters are being enabled or disabled. Set this parameter to TRUE to enable lighting with the parameters at the specified index, or FALSE to disable it.

Return Values

If the method succeeds, the return value is D3D_OK. If the method fails, the return value can be D3DERR_INVALIDCALL.

Remarks

If a value for LightIndex is outside the range of the light property sets assigned within the device, the IDirect3DDevice9::LightEnable method creates a light source represented by a D3DLIGHT9 structure with the following properties and sets its enabled state to the value specified in bEnable.

Member Default
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

因为镜面反射的计算量很大,所以Direct3D在默认状态下不进行镜面反射运算。如果想得到镜面反射效果,可以先设置好结构体D3DLIGHT9的Specular成员和物体表面材质结构体D3DMATERIAL9的Specular和Power成员,然后通过下面的代码激活镜面反射运算。

g_device->SetRenderState(D3DRS_SPECULARENABLE, TRUE);

如果需要进行漫反射或镜面反射运算,那么在顶点缓冲区中必须包含顶点的法向量信息,这是因为Direct3D在进行光照运算时,要用到顶点法向量。

 

材质

对于光照计算,光源和材质两者缺一不可,物体表面材质属性决定了它能反射什么颜色的光线以及能反射多少,在Direct3D中,物体表面材质属性由结构体D3DMATERIAL9定义:

Specifies material properties.

typedef struct D3DMATERIAL9 {
D3DCOLORVALUE Diffuse;
D3DCOLORVALUE Ambient;
D3DCOLORVALUE Specular;
D3DCOLORVALUE Emissive;
float Power;
} D3DMATERIAL9, *LPD3DMATERIAL9;

Members

Diffuse
Value specifying the diffuse color of the material. See D3DCOLORVALUE.
Ambient
Value specifying the ambient color of the material. See D3DCOLORVALUE.
Specular
Value specifying the specular color of the material. See D3DCOLORVALUE.
Emissive
Value specifying the emissive color of the material. See D3DCOLORVALUE.
Power
Floating-point value specifying the sharpness of specular highlights. The higher the value, the sharper the highlight.

Remarks

To turn off specular highlights, set D3DRS_SPECULARENABLE to FALSE, using D3DRENDERSTATETYPE. This is the fastest option because no specular highlights will be calculated.

For more information about using the lighting engine to calculate specular lighting, see Specular Lighting (Direct3D 9).

浮点成员Power为镜面反射指数,即镜面反射光照计算模型计算公式中的n,Power值越大,高光强度和周围亮度相差越大。

Emissive表示物体自身的发光度,以R、G、B表示。

物体顶点的颜色亮度总和为:

Itotal = Iambient + Idiffuse + Ispecular + Iemissive

I表示物体的颜色值,上式表示物体的颜色总和 = 物体反射环境光 + 物体反射漫反射光 + 物体反射镜面光 + 物体自发光。

 

设置材质

函数IDirect3DDevice9::SetMaterial()用来设置Direct3D当前材质属性,该函数声明如下:

Sets the material properties for the device.

HRESULT SetMaterial(
CONST D3DMATERIAL9 * pMaterial
);

Parameters

pMaterial
[in] Pointer to a D3DMATERIAL9 structure, describing the material properties to set.

Return Values

If the method succeeds, the return value is D3D_OK. D3DERR_INVALIDCALL if the pMaterial parameter is invalid.

下面的示例代码设置当前材质为能漫反射50%红光、80%绿光和60%蓝光的表面。

D3DMATERIAL9 material;
ZeroMemory(&material, sizeof(material));

material.Diffuse.r = 0.5f;
material.Diffuse.g = 0.8f;
material.Diffuse.b = 1.6f;
material.Diffuse.a = 0.0f;

g_device->SetMaterial(&material);

Direct3D图形系统在进行光照计算时,会根据3种光照计算模型分别进行计算,然后将计算结果叠加在一起,作为顶点的光照颜色值,如果物体表面只能进行漫反射,则镜面反射系数应当为0,这时镜面反射计算得到的颜色值显然为0,从而使物体不具有镜面反射效果,但是实际上镜面反射计算也在进行。因为镜面反射计算量大,会对性能造成冲击,所以如果物体表面不具有镜面反射效果,就不要启用镜面反射计算。

如果应用程序没有指定材质属性,系统将使用默认材质。默认材质反射所有漫反射光,没有环境反射和镜面反射,也没有自发光颜色。

默认材质的光照属性

成员

默认值

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()可获取渲染设备当前正在使用的材质属性。

Retrieves the current material properties for the device.

HRESULT GetMaterial(
D3DMATERIAL9 * pMaterial
);

Parameters

pMaterial
[out] Pointer to a D3DMATERIAL9 structure to fill with the currently set material properties.

Return Values

If the method succeeds, the return value is D3D_OK. D3DERR_INVALIDCALL if the pMaterial parameter is invalid.

Remarks

This method will not return device state for a device that is created using D3DCREATE_PUREDEVICE. If you want to use this method, you must create your device with any of the other values in D3DCREATE.


posted on 2008-05-04 14:48 lovedday 阅读(1328) 评论(0)  编辑 收藏 引用


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理


公告

导航

统计

常用链接

随笔分类(178)

3D游戏编程相关链接

搜索

最新评论