博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

光照

Posted on 2011-03-01 22:11  +石头+  阅读(251)  评论(0)    收藏  举报

光照的组成:

在D3D光照模型中,光源发出的光由以下3种类型的光组成:

  1. 环境光(Ambient Light)可用于物体没有直接被光照射,而是而是由于其他物体对光的反射。
  2. 漫射光(Diffuse Light)当光达到物体表面时它将向各个方向反射,观察者处于任何角度观察都一样。从一个光源发出的光一般都是这种类型。
  3. 镜面光(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支持三种类型的光源:

  1. 电光源(Point lights)
  2. 方向光(Direction lights)
  3. 聚光灯(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);

}