設(shè)置燈光
在Direct3D的一個(gè)場(chǎng)景中,最多可設(shè)置8個(gè)光源,設(shè)置光源由IDirect3DDevice9::SetLight()函數(shù)完成。該函數(shù)的聲明如下:
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.
函數(shù)IDirect3DDevice9::SetLight()只是設(shè)置光源,在默認(rèn)情況下,設(shè)置的任何光源都還不起作用,具體使用哪些光源,由函數(shù)IDirect3DDevice9::LightEnable()確定,該函數(shù)聲明如下:
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 |
因?yàn)殓R面反射的計(jì)算量很大,所以Direct3D在默認(rèn)狀態(tài)下不進(jìn)行鏡面反射運(yùn)算。如果想得到鏡面反射效果,可以先設(shè)置好結(jié)構(gòu)體D3DLIGHT9的Specular成員和物體表面材質(zhì)結(jié)構(gòu)體D3DMATERIAL9的Specular和Power成員,然后通過(guò)下面的代碼激活鏡面反射運(yùn)算。
g_device->SetRenderState(D3DRS_SPECULARENABLE, TRUE);
如果需要進(jìn)行漫反射或鏡面反射運(yùn)算,那么在頂點(diǎn)緩沖區(qū)中必須包含頂點(diǎn)的法向量信息,這是因?yàn)镈irect3D在進(jìn)行光照運(yùn)算時(shí),要用到頂點(diǎn)法向量。
材質(zhì)
對(duì)于光照計(jì)算,光源和材質(zhì)兩者缺一不可,物體表面材質(zhì)屬性決定了它能反射什么顏色的光線以及能反射多少,在Direct3D中,物體表面材質(zhì)屬性由結(jié)構(gòu)體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).
浮點(diǎn)成員Power為鏡面反射指數(shù),即鏡面反射光照計(jì)算模型計(jì)算公式中的n,Power值越大,高光強(qiáng)度和周?chē)炼认嗖钤酱蟆?/p>
Emissive表示物體自身的發(fā)光度,以R、G、B表示。
物體頂點(diǎn)的顏色亮度總和為:
Itotal = Iambient + Idiffuse
+ Ispecular + Iemissive
I表示物體的顏色值,上式表示物體的顏色總和 = 物體反射環(huán)境光 + 物體反射漫反射光 + 物體反射鏡面光 +
物體自發(fā)光。
設(shè)置材質(zhì)
函數(shù)IDirect3DDevice9::SetMaterial()用來(lái)設(shè)置Direct3D當(dāng)前材質(zhì)屬性,該函數(shù)聲明如下:
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.
下面的示例代碼設(shè)置當(dāng)前材質(zhì)為能漫反射50%紅光、80%綠光和60%藍(lán)光的表面。
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圖形系統(tǒng)在進(jìn)行光照計(jì)算時(shí),會(huì)根據(jù)3種光照計(jì)算模型分別進(jìn)行計(jì)算,然后將計(jì)算結(jié)果疊加在一起,作為頂點(diǎn)的光照顏色值,如果物體表面只能進(jìn)行漫反射,則鏡面反射系數(shù)應(yīng)當(dāng)為0,這時(shí)鏡面反射計(jì)算得到的顏色值顯然為0,從而使物體不具有鏡面反射效果,但是實(shí)際上鏡面反射計(jì)算也在進(jìn)行。因?yàn)殓R面反射計(jì)算量大,會(huì)對(duì)性能造成沖擊,所以如果物體表面不具有鏡面反射效果,就不要啟用鏡面反射計(jì)算。
如果應(yīng)用程序沒(méi)有指定材質(zhì)屬性,系統(tǒng)將使用默認(rèn)材質(zhì)。默認(rèn)材質(zhì)反射所有漫反射光,沒(méi)有環(huán)境反射和鏡面反射,也沒(méi)有自發(fā)光顏色。
默認(rèn)材質(zhì)的光照屬性
|
成員
|
默認(rèn)值
|
| 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) |
獲取材質(zhì)屬性
通過(guò)調(diào)用接口函數(shù)IDirect3DDevice9::GetMaterial()可獲取渲染設(shè)備當(dāng)前正在使用的材質(zhì)屬性。
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.