光照的组成:
在D3D光照模型中,光源发出的光由以下3种类型的光组成:
- 环境光(Ambient Light)可用于物体没有直接被光照射,而是而是由于其他物体对光的反射。
- 漫射光(Diffuse Light)当光达到物体表面时它将向各个方向反射,观察者处于任何角度观察都一样。从一个光源发出的光一般都是这种类型。
- 镜面光(Specular Light)光沿着特定方向传播,当达到一个表面时,严格的沿着另一个方向反射。
材质:
struct D3DMATERIAL9{
D3DCOLORVALUE Diffuse; //对漫射光的反射率
D3DCOLORVALUE Ambient; //对环境光的反射率
D3DCOLORVALUE Specular; //对镜面光的反射率
D3DCOLORVALUE Emissive; //用于增强物体的亮度,使之看起来好像自己在发光
float Power; //镜面高光点的锐度,该值越大,高光点的锐度越大
}
顶点法线:
为了描述顶点法线,我们必须修改顶点的结构:
struct Vertex
{
Vertex(){}
Vertex(float x, float y, float z, float nx, float ny, float nz)
{
_x = x; _y = y; _z = z;
_nx = nx; _ny = ny; _nz = nz;
}
float _x, _y, _z;
float _nx, _ny, _nz;
static const DWORD FVF;
};
const DWORD Vertex::FVF = D3DFVF_XYZ | D3DFVF_NORMAL;
FVF由DIFFUSE改为NORMAL,也就是去掉了颜色的成员变量,这是因为我们将用光照来计算顶点的颜色。NORMAL表示向量的意思
假设有三个三角形共享顶点v,其面的法向量为n0,n1,n2.则顶点v的法向量vn可以取1/3(n0+n1+n2).
ComputeNormal函数用于计算三个顶点构成三角形的法向量。
Device->SetRenderState(D3DRS_NORMALIZENORMALS, true);使所有的法向量重新规范化。
光源:
Direct3D支持三种类型的光源:
- 电光源(Point lights)
- 方向光(Direction lights)
- 聚光灯(Spot lights)
光源用结构D3DLIGHT9来表示。
例程:
这里只复制Setup()和Render()
VOID Setup()
{
g_d3dDevice->SetRenderState(D3DRS_LIGHTING, true);
g_d3dDevice->SetRenderState(D3DRS_NORMALIZENORMALS, true);
g_d3dDevice->SetRenderState(D3DRS_SPECULARENABLE, true);
//设置顶点缓存
g_d3dDevice->CreateVertexBuffer(12 * sizeof(Vertex),
D3DUSAGE_WRITEONLY,
Vertex::FVF,
D3DPOOL_MANAGED,
&Pyramid,
0);
Vertex* v;
Pyramid->Lock(0, 0, (void**)&v, 0);
v[0] = Vertex(-1.0f, 0.0f, -1.0f, 0.0f, 0.707f, -0.707f);
v[1] = Vertex( 0.0f, 1.0f, 0.0f, 0.0f, 0.707f, -0.707f);
v[2] = Vertex( 1.0f, 0.0f, -1.0f, 0.0f, 0.707f, -0.707f);
// left face
v[3] = Vertex(-1.0f, 0.0f, 1.0f, -0.707f, 0.707f, 0.0f);
v[4] = Vertex( 0.0f, 1.0f, 0.0f, -0.707f, 0.707f, 0.0f);
v[5] = Vertex(-1.0f, 0.0f, -1.0f, -0.707f, 0.707f, 0.0f);
// right face
v[6] = Vertex( 1.0f, 0.0f, -1.0f, 0.707f, 0.707f, 0.0f);
v[7] = Vertex( 0.0f, 1.0f, 0.0f, 0.707f, 0.707f, 0.0f);
v[8] = Vertex( 1.0f, 0.0f, 1.0f, 0.707f, 0.707f, 0.0f);
// back face
v[9] = Vertex( 1.0f, 0.0f, 1.0f, 0.0f, 0.707f, 0.707f);
v[10] = Vertex( 0.0f, 1.0f, 0.0f, 0.0f, 0.707f, 0.707f);
v[11] = Vertex(-1.0f, 0.0f, 1.0f, 0.0f, 0.707f, 0.707f);
Pyramid->Unlock();
//create material
D3DMATERIAL9 mtrl;
mtrl.Ambient = WHITE;
mtrl.Diffuse = WHITE;
mtrl.Specular = WHITE;
mtrl.Emissive = BLACK;
mtrl.Power = 5.0f;
g_d3dDevice->SetMaterial(&mtrl);
//set light
D3DLIGHT9 light;
ZeroMemory(&light, sizeof(light));
light.Type = D3DLIGHT_DIRECTIONAL;
light.Ambient = WHITE*0.3f;
light.Specular = WHITE*0.6f;
light.Diffuse = WHITE;
light.Direction = D3DXVECTOR3(1.0f, 0.0f, 0.0f);
g_d3dDevice->SetLight(0, &light);
g_d3dDevice->LightEnable(0, true);
//设置观察坐标系
D3DXVECTOR3 position(0.0f,1.0f,-3.0f);
D3DXVECTOR3 target(0,0,0);
D3DXVECTOR3 up(0,1,0);
D3DXMATRIX myView;
D3DXMatrixLookAtLH(&myView, &position, &target, &up);
g_d3dDevice->SetTransform(D3DTS_VIEW, &myView);
//设置投影
D3DXMATRIX proj;
D3DXMatrixPerspectiveFovLH(&proj, D3DX_PI*0.5, (float)Width/(float)Height, 1.0f, 1000.0f);
g_d3dDevice->SetTransform(D3DTS_PROJECTION, &proj);
}
VOID Render(float timeDelta)
{
//旋转
D3DXMATRIX yRot;
static float y = 0.0f;
D3DXMatrixRotationY(&yRot, y);
y += timeDelta;
if(y>=6.28)
y = 0.0f;
g_d3dDevice->SetTransform(D3DTS_WORLD, &yRot);
g_d3dDevice->Clear(0, 0, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0, 0, 255), 1.0f, 0);
g_d3dDevice->BeginScene();
g_d3dDevice->SetStreamSource(0, Pyramid, 0, sizeof(Vertex));
g_d3dDevice->SetFVF(Vertex::FVF);
g_d3dDevice->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 4);
g_d3dDevice->EndScene();
g_d3dDevice->Present(NULL, NULL, NULL, NULL);
}
浙公网安备 33010602011771号