D3D学习笔记之七---光照效果

来源:互联网 发布:qt网络编程账号登录 编辑:程序博客网 时间:2024/06/11 04:53

这次我们来讨论一下,光照的效果,有了光照可以把我们的虚拟世界渲染的更加的逼真,那么我们怎么去控制关照呢,这次我们就好好的研究它一番

先把代码上来吧,

 

//=============================================================================

// Desc: 简单灯光范例程序

//=============================================================================

 

#include <d3dx9.h>

 

 

//-----------------------------------------------------------------------------

// Desc: 全局变量

//-----------------------------------------------------------------------------

LPDIRECT3D9               g_pD3D         = NULL;   //Direct3D对象

LPDIRECT3DDEVICE9         g_pd3dDevice   = NULL;   //Direct3D设备对象

LPDIRECT3DVERTEXBUFFER9   g_pVB          = NULL;   //顶点缓冲区对象

 

//-----------------------------------------------------------------------------

// Desc: 顶点结构

//-----------------------------------------------------------------------------

struct CUSTOMVERTEX

{

    D3DXVECTOR3 position;   //顶点位置

    D3DXVECTOR3 normal;     //顶点法线

};

#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ|D3DFVF_NORMAL)

 

 

//-----------------------------------------------------------------------------

// Desc: 设置变换矩阵

//-----------------------------------------------------------------------------

VOID SetMatrices()

{

       //建立并设置世界矩阵

    D3DXMATRIX matWorld;

       D3DXMatrixIdentity( &matWorld );

    g_pd3dDevice->SetTransform( D3DTS_WORLD, &matWorld );

 

       //建立并设置观察矩阵

    D3DXVECTOR3 vEyePt( 0.0f, 3.0f,-5.0f );

    D3DXVECTOR3 vLookatPt( 0.0f, 0.0f, 0.0f );

    D3DXVECTOR3 vUpVec( 0.0f, 1.0f, 0.0f );

    D3DXMATRIX matView;

    D3DXMatrixLookAtLH( &matView, &vEyePt, &vLookatPt, &vUpVec );

    g_pd3dDevice->SetTransform( D3DTS_VIEW, &matView );

 

    //建立并设置投影矩阵

    D3DXMATRIX matProj;

    D3DXMatrixPerspectiveFovLH( &matProj, D3DX_PI/4, 1.0f, 1.0f, 100.0f );

    g_pd3dDevice->SetTransform( D3DTS_PROJECTION, &matProj );

}

 

 

//-----------------------------------------------------------------------------

// Desc: 初始化Direct3D

//-----------------------------------------------------------------------------

HRESULT InitD3D( HWND hWnd )

{

       //创建Direct3D对象, 该对象用于创建Direct3D设备对象

    if( NULL == ( g_pD3D = Direct3DCreate9( D3D_SDK_VERSION ) ) )

        return E_FAIL;

 

    //设置D3DPRESENT_PARAMETERS结构, 准备创建Direct3D设备对象

    D3DPRESENT_PARAMETERS d3dpp;

    ZeroMemory( &d3dpp, sizeof(d3dpp) );

    d3dpp.Windowed = TRUE;

    d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;

    d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;

    d3dpp.EnableAutoDepthStencil = TRUE;

    d3dpp.AutoDepthStencilFormat = D3DFMT_D16;

      

 

    //创建Direct3D设备对象

    if( FAILED( g_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd,

                                      D3DCREATE_SOFTWARE_VERTEXPROCESSING,

                                      &d3dpp, &g_pd3dDevice ) ) )

    {

        return E_FAIL;

    }

 

    //设置剔出模式为不剔出任何面(正面和方面)

    g_pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE );

 

    //启用深度测试

    g_pd3dDevice->SetRenderState( D3DRS_ZENABLE, TRUE );   

      

       //设置变换矩阵

       SetMatrices();

 

    return S_OK;

}

 

 

//-----------------------------------------------------------------------------

// Desc: 创建场景图形

//-----------------------------------------------------------------------------

HRESULT InitGeometry()

{

    //创顶点缓冲区

    if( FAILED( g_pd3dDevice->CreateVertexBuffer( 50*2*sizeof(CUSTOMVERTEX),

                                                  0, D3DFVF_CUSTOMVERTEX,

                                                  D3DPOOL_DEFAULT, &g_pVB, NULL ) ) )

    {

        return E_FAIL;

    }

 

    //填充顶点缓冲区

    CUSTOMVERTEX* pVertices;

    if( FAILED( g_pVB->Lock( 0, 0, (void**)&pVertices, 0 ) ) )

        return E_FAIL;

    for( DWORD i=0; i<50; i++ )

    {

        FLOAT theta = (2*D3DX_PI*i)/(50-1);

        pVertices[2*i+0].position = D3DXVECTOR3( sinf(theta),-1.0f, cosf(theta) );

        pVertices[2*i+0].normal   = D3DXVECTOR3( sinf(theta), 0.0f, cosf(theta) );

        pVertices[2*i+1].position = D3DXVECTOR3( sinf(theta), 1.0f, cosf(theta) );

        pVertices[2*i+1].normal   = D3DXVECTOR3( sinf(theta), 0.0f, cosf(theta) );

    }

    g_pVB->Unlock();

 

    return S_OK;

}

 

 

//-----------------------------------------------------------------------------

// Desc: 设置材质和灯光

//-----------------------------------------------------------------------------

VOID SetLight()

{

    //设置材质

    D3DMATERIAL9 mtrl;

    ZeroMemory( &mtrl, sizeof(D3DMATERIAL9) );

    mtrl.Diffuse.r = mtrl.Ambient.r = 1.0f;

    mtrl.Diffuse.g = mtrl.Ambient.g = 1.0f;

    mtrl.Diffuse.b = mtrl.Ambient.b = 0.0f;

    mtrl.Diffuse.a = mtrl.Ambient.a = 1.0f;

    g_pd3dDevice->SetMaterial( &mtrl );

 

    //设置灯光

    D3DXVECTOR3 vecDir;

    D3DLIGHT9 light;

    ZeroMemory( &light, sizeof(D3DLIGHT9) );

    light.Type       = D3DLIGHT_DIRECTIONAL;

    light.Diffuse.r  = 1.0f;

    light.Diffuse.g  = 1.0f;

    light.Diffuse.b  = 1.0f;

    vecDir = D3DXVECTOR3(cosf(timeGetTime()/350.0f),

                         1.0f,

                         sinf(timeGetTime()/350.0f) );

       vecDir = D3DXVECTOR3(1.0f, 1.0f, 0.0f);

    D3DXVec3Normalize( (D3DXVECTOR3*)&light.Direction, &vecDir );

    light.Range       = 1000.0f;

    g_pd3dDevice->SetLight( 0, &light );

    g_pd3dDevice->LightEnable( 0, TRUE );

    g_pd3dDevice->SetRenderState( D3DRS_LIGHTING, TRUE );

 

    //设置环境光

    g_pd3dDevice->SetRenderState( D3DRS_AMBIENT, 0x00505050);

}

 

 

//-----------------------------------------------------------------------------

// Desc: 释放创建的对象

//-----------------------------------------------------------------------------

VOID Cleanup()

{

       //释放顶点缓冲区对象

    if( g_pVB != NULL )

        g_pVB->Release();

 

       //释放Direct3D设备对象

    if( g_pd3dDevice != NULL )

        g_pd3dDevice->Release();

 

       //释放Direct3D对象

    if( g_pD3D != NULL )

        g_pD3D->Release();

}

 

 

//-----------------------------------------------------------------------------

// Desc: 渲染图形

//-----------------------------------------------------------------------------

VOID Render()

{

    //清空后台缓冲区

    g_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER,

                         D3DCOLOR_XRGB(45, 50, 170), 1.0f, 0 );

 

    //开始在后台缓冲区绘制图形

    if( SUCCEEDED( g_pd3dDevice->BeginScene() ) )

    {

        //设置灯光和材质

        SetLight();

 

        //在后台缓冲区绘制图形

        g_pd3dDevice->SetStreamSource( 0, g_pVB, 0, sizeof(CUSTOMVERTEX) );

        g_pd3dDevice->SetFVF( D3DFVF_CUSTOMVERTEX );

        g_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLESTRIP, 0, 2*50-2 );

 

        //结束在后台缓冲区渲染图形

        g_pd3dDevice->EndScene();

    }

 

    //将在后台缓冲区绘制的图形提交到前台缓冲区显示

    g_pd3dDevice->Present( NULL, NULL, NULL, NULL );

}

 

 

//-----------------------------------------------------------------------------

// Desc: 消息处理

//-----------------------------------------------------------------------------

LRESULT WINAPI MsgProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )

{

    switch( msg )

    {

        case WM_DESTROY:

            Cleanup();

            PostQuitMessage( 0 );

            return 0;

    }

 

    return DefWindowProc( hWnd, msg, wParam, lParam );

}

 

 

//-----------------------------------------------------------------------------

// Desc: 入口函数

//-----------------------------------------------------------------------------

INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR, INT )

{

    //注册窗口类

    WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, MsgProc, 0L, 0L,

                      GetModuleHandle(NULL), NULL, NULL, NULL, NULL,

                      L"ClassName", NULL };

    RegisterClassEx( &wc );

 

    //创建窗口

    HWND hWnd = CreateWindow( L"ClassName", L"灯光",

                              WS_OVERLAPPEDWINDOW, 200, 100, 500, 500,

                              NULL, NULL, wc.hInstance, NULL );

 

    //初始化Direct3D

    if( SUCCEEDED( InitD3D( hWnd ) ) )

    {

        //创建场景图形

        if( SUCCEEDED( InitGeometry() ) )

        {

            //显示窗口

            ShowWindow( hWnd, SW_SHOWDEFAULT );

            UpdateWindow( hWnd );

 

            //进入消息循环

            MSG msg;

            ZeroMemory( &msg, sizeof(msg) );

            while( msg.message!=WM_QUIT )

            {

                if( PeekMessage( &msg, NULL, 0U, 0U, PM_REMOVE ) )

                {

                    TranslateMessage( &msg );

                    DispatchMessage( &msg );

                }

                else

                            {

                    Render();  //渲染图形

                            }

            }

        }

    }

 

    UnregisterClass( L"ClassName", wc.hInstance );

    return 0;

}

 

 

上面的程序是一个简单的光照的示例程序,里面就有一个光源。

我们把它编译运行一下,可以看到一个圆柱物体上的光照效果。是不是比以前有了很多的质感,怎么实现的呢?

 

 

我这里先对光照做下解释吧:

D3D中的光照计算模型有四种:环境光,漫反射光,镜面反射光和自发光。

环境光:

就是物体表面的一个基本亮度,D3D为了节省运算,没有采取光线跟踪算法,为了能够可视,世界种的所有物体都有一个基本的亮度,这个就是环境光,环境光可以通过设置D3D的渲染状态来设置:

 

g_pd3dDevice->SetRenderState( D3DRS_AMBIENT, 0x00505050);

第一个参数是一个标志,第二个参数就是环境光的颜色设置。

 

漫反射:

就是根据入射点的法线方向进行计算反射光的方向,D3D中这个计算模型默认的是打开的。

镜面反射:

观察金属物品火玻璃制品的表面时,在不同的地方观察所产生的光照效果是不一样的,这种效果就是镜面反射,D3D中镜面反射的计算默认是关闭的,如果要打开需要设置渲染状态。

g_pd3dDevice->SetRenderState( D3DRS_SPECULARENABLE, TRUE );//打开镜面反射

 

自发光:

自发光其实就是通过对象的自发光材质实现的。用结构D3DMATERIAL9的成员Emissive描述自发光的颜色和透明度。

介绍完了这四种光线计算模式,下面我们讨论一下D3D的光源类型,D3D支持3种光源类型:方向光,点光源,聚光灯。这三种光源,从名字上看就能知道大致的意思,我们分别了解下他们:

点光:

点光源有颜色和位置,但是没有方向。它所有方向发射的光都一样,比如说电灯泡。

 

方向光:

具有颜色和方向,没有位置。就像太阳光,是平行的光线。

聚光灯:

有颜色、位置和方向,类似于我们的手电筒。

 

这些事D3D中的光源类型,下面我们看下光源的属性都有什么,估计也能才出来几个了吧,呵呵

下面就是光源的结构体:

typedef struct D3DLIGHT9 {

    D3DLIGHTTYPE Type;

    D3DCOLORVALUE Diffuse;

    D3DCOLORVALUE Specular;

    D3DCOLORVALUE Ambient;

    D3DVECTOR Position;

    D3DVECTOR Direction;

    float Range;

    float Falloff;

    float Attenuation0;

    float Attenuation1;

    float Attenuation2;

    float Theta;

    float Phi;

} D3DLIGHT9, *LPD3DLIGHT;

Members

Type

指明具体是那种光源,(点,方向,聚光)

Diffuse

漫反射的颜色值

Specular

镜面反射的颜色值

Ambient

环境光的颜色值

Position

位置信息

Direction

光照方向

Range

光照范围,方向光没有该属性

Falloff

聚光灯特有的属性,是从中心位置到边缘位置的衰减系数。

Attenuation0

光向远处传播的衰减系数一

Attenuation1

光向远处传播的衰减系数二

Attenuation2

光向远处传播的衰减系数三

这三个衰减系数不可以为负值。一般第一个设置为1,其他为0

 

Theta

内椎体角度的弧度值,只在聚光灯中有效

Phi

外椎体角度的弧度制,只在聚光中有效

这些属性,每种光源并不是拥有所有的属性。

有了光源我们还要设置物体的材质,材质规定了物体对光源的反射情况。

在程序中:

D3DMATERIAL9 mtrl;

     ZeroMemory( &mtrl, sizeof(D3DMATERIAL9) );//初始化材质

     mtrl.Diffuse.r = mtrl.Ambient.r = 1.0f;

     mtrl.Diffuse.g = mtrl.Ambient.g = 1.0f;

     mtrl.Diffuse.b = mtrl.Ambient.b = 0.0f;

     mtrl.Diffuse.a = mtrl.Ambient.a = 1.0f;

g_pd3dDevice->SetMaterial( &mtrl );

就设置了材质的漫反射光的反射情况,具体的就是规定了漫反射对哪种颜色的光进行反射。

然后用g_pd3dDevice->SetMaterial( &mtrl );

将材质提交到引擎里面。

下面我们就用这几种光源在程序中设置几个光源。

// Desc: 设置材质和灯光

//-----------------------------------------------------------------------------

VOID SetLight()

{

    //设置材质

    D3DMATERIAL9 mtrl;

     ZeroMemory( &mtrl, sizeof(D3DMATERIAL9) );//初始化材质

     mtrl.Diffuse.r = mtrl.Ambient.r = 1.0f;

     mtrl.Diffuse.g = mtrl.Ambient.g = 1.0f;

     mtrl.Diffuse.b = mtrl.Ambient.b = 0.0f;

     mtrl.Diffuse.a = mtrl.Ambient.a = 1.0f;

     /*mtrl.Emissive.r = 0.0f;

     mtrl.Emissive.g = 0.75f;

     mtrl.Emissive.b = 0.5f;

     mtrl.Emissive.a = 0.3f;

     */

 

    g_pd3dDevice->SetMaterial( &mtrl );

 

    //设置灯光

    D3DXVECTOR3 vecDir;//方向光

    D3DLIGHT9 light;

    ZeroMemory( &light, sizeof(D3DLIGHT9) );//初始化光源

    light.Type       = D3DLIGHT_DIRECTIONAL;

    light.Diffuse.r  = 1.0f;

    light.Diffuse.g  = 1.0f;

    light.Diffuse.b  = 1.0f;

    vecDir = D3DXVECTOR3(cosf(timeGetTime()/350.0f),

                         1.0f,

                         sinf(timeGetTime()/350.0f) );

     vecDir = D3DXVECTOR3(1.0f, 1.0f, 0.0f);

    D3DXVec3Normalize( (D3DXVECTOR3*)&light.Direction, &vecDir );

    light.Range       = 1000.0f;

    g_pd3dDevice->SetLight( 0, &light );//将光源信息提交到引擎

    g_pd3dDevice->LightEnable( 0, TRUE );//打开光源

    g_pd3dDevice->SetRenderState( D3DRS_LIGHTING, TRUE );//启动引擎的光照计算。

 

    //设置环境光

    g_pd3dDevice->SetRenderState( D3DRS_AMBIENT, 0x00505050);

}

这些代码就设置了一个方向光源,代码比较简单,相信大家能够读懂。

上面就是对光源和材质的设定,我们再看看其他的代码。

你会发现这次的用户自定义的顶点格式有了变化。

struct CUSTOMVERTEX

{

    D3DXVECTOR3 position;   //顶点位置

    D3DXVECTOR3 normal;     //顶点法线

};

 

没错,这次我们有了光线的漫反射计算,所以我们的顶点信息中有了法线的属性。

// Desc: 创建场景图形

//-----------------------------------------------------------------------------

HRESULT InitGeometry()

{

    //创顶点缓冲区

    if( FAILED( g_pd3dDevice->CreateVertexBuffer( 50*2*sizeof(CUSTOMVERTEX),

                                                  0, D3DFVF_CUSTOMVERTEX,

                                                  D3DPOOL_DEFAULT, &g_pVB, NULL ) ) )

    {

        return E_FAIL;

    }

 

    //填充顶点缓冲区

    CUSTOMVERTEX* pVertices;

    if( FAILED( g_pVB->Lock( 0, 0, (void**)&pVertices, 0 ) ) )

        return E_FAIL;

    for( DWORD i=0; i<50; i++ )

    {

        FLOAT theta = (2*D3DX_PI*i)/(50-1);

        pVertices[2*i+0].position = D3DXVECTOR3( sinf(theta),-1.0f, cosf(theta) );

        pVertices[2*i+0].normal   = D3DXVECTOR3( sinf(theta), 0.0f, cosf(theta) );

        pVertices[2*i+1].position = D3DXVECTOR3( sinf(theta), 1.0f, cosf(theta) );

        pVertices[2*i+1].normal   = D3DXVECTOR3( sinf(theta), 0.0f, cosf(theta) );

    }

    g_pVB->Unlock();

 

    return S_OK;

}

这些代码就创建了一个物体,是一个圆柱,和以前不同的是我们这次加入了顶点的法线情况。

其他的代码与以前的没有多少的差别,相信大家很容易能读懂。

 

生成一下就可以看到有了光线的效果。这个程序的光线比较简单,下面是一个比较复杂的光线程序:

大家自己看一下,相信有前面的基础,很容易能够读懂的。

 

//=============================================================================

// Desc: 多光源示例程序

//=============================================================================

 

#include <d3dx9.h>

 

 

//-----------------------------------------------------------------------------

// Desc: 全局变量

//-----------------------------------------------------------------------------

LPDIRECT3D9               g_pD3D         = NULL;   //Direct3D对象

LPDIRECT3DDEVICE9         g_pd3dDevice   = NULL;   //Direct3D设备对象

LPDIRECT3DVERTEXBUFFER9   g_pVB          = NULL;   //顶点缓冲区对象

 

 

//-----------------------------------------------------------------------------

// Desc: 顶点结构

//-----------------------------------------------------------------------------

struct CUSTOMVERTEX

{

    D3DXVECTOR3 position;   //顶点位置

    D3DXVECTOR3 normal;     //顶点法线

};

#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ|D3DFVF_NORMAL)

 

 

//-----------------------------------------------------------------------------

// Desc: 设置变换矩阵

//-----------------------------------------------------------------------------

VOID SetMatrices()

{

     //建立并设置世界矩阵

    D3DXMATRIX matWorld;

     D3DXMatrixIdentity( &matWorld );

    g_pd3dDevice->SetTransform( D3DTS_WORLD, &matWorld );

 

     //建立并设置观察矩阵

    D3DXVECTOR3 vEyePt( 0.0f, 3.0f,-5.0f );

    D3DXVECTOR3 vLookatPt( 0.0f, 0.0f, 0.0f );

    D3DXVECTOR3 vUpVec( 0.0f, 1.0f, 0.0f );

    D3DXMATRIX matView;

    D3DXMatrixLookAtLH( &matView, &vEyePt, &vLookatPt, &vUpVec );

    g_pd3dDevice->SetTransform( D3DTS_VIEW, &matView );

 

    //建立并设置投影矩阵

    D3DXMATRIX matProj;

    D3DXMatrixPerspectiveFovLH( &matProj, D3DX_PI/4, 1.0f, 1.0f, 100.0f );

    g_pd3dDevice->SetTransform( D3DTS_PROJECTION, &matProj );

}

 

 

//-----------------------------------------------------------------------------

// Desc: 初始化Direct3D

//-----------------------------------------------------------------------------

HRESULT InitD3D( HWND hWnd )

{

     //创建Direct3D对象, 该对象用于创建Direct3D设备对象

    if( NULL == ( g_pD3D = Direct3DCreate9( D3D_SDK_VERSION ) ) )

        return E_FAIL;

 

    //设置D3DPRESENT_PARAMETERS结构, 准备创建Direct3D设备对象

    D3DPRESENT_PARAMETERS d3dpp;

    ZeroMemory( &d3dpp, sizeof(d3dpp) );

    d3dpp.Windowed = TRUE;

    d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;

    d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;

    d3dpp.EnableAutoDepthStencil = TRUE;

    d3dpp.AutoDepthStencilFormat = D3DFMT_D16;

    

 

    //创建Direct3D设备对象

    if( FAILED( g_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd,

                                      D3DCREATE_SOFTWARE_VERTEXPROCESSING,

                                      &d3dpp, &g_pd3dDevice ) ) )

    {

        return E_FAIL;

    }

 

    //设置剔出模式为不剔出任何面(正面和方面)

    g_pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE );

 

    //启用深度测试

    g_pd3dDevice->SetRenderState( D3DRS_ZENABLE, TRUE );

 

     //启用镜面反射光照模型

     g_pd3dDevice->SetRenderState(D3DRS_SPECULARENABLE, TRUE);

    

     //设置变换矩阵

     SetMatrices();

 

    return S_OK;

}

 

 

//-----------------------------------------------------------------------------

// Desc: 创建场景图形

//-----------------------------------------------------------------------------

HRESULT InitGeometry()

{

    //创顶点缓冲区

    if( FAILED( g_pd3dDevice->CreateVertexBuffer( 50*2*sizeof(CUSTOMVERTEX),

                                                  0, D3DFVF_CUSTOMVERTEX,

                                                  D3DPOOL_DEFAULT, &g_pVB, NULL ) ) )

    {

        return E_FAIL;

    }

 

    //填充顶点缓冲区

    CUSTOMVERTEX* pVertices;

    if( FAILED( g_pVB->Lock( 0, 0, (void**)&pVertices, 0 ) ) )

        return E_FAIL;

    for( DWORD i=0; i<50; i++ )

    {

        FLOAT theta = (2*D3DX_PI*i)/(50-1);

        pVertices[2*i+0].position = D3DXVECTOR3( sinf(theta),-1.0f, cosf(theta) );

        pVertices[2*i+0].normal   = D3DXVECTOR3( sinf(theta), 0.0f, cosf(theta) );

        pVertices[2*i+1].position = D3DXVECTOR3( sinf(theta), 1.0f, cosf(theta) );

        pVertices[2*i+1].normal   = D3DXVECTOR3( sinf(theta), 0.0f, cosf(theta) );

    }

    g_pVB->Unlock();

 

    return S_OK;

}

 

 

//-----------------------------------------------------------------------------

// Desc: 设置材质和灯光

//-----------------------------------------------------------------------------

VOID SetupLights()

{

     //设置材料属性, 只反射红光分量和绿光分量, 整体上看该物体材料反射黄色光

    D3DMATERIAL9 mtrl;

    ZeroMemory( &mtrl, sizeof(D3DMATERIAL9) );

 

     mtrl.Ambient.r = 1.0f;

     mtrl.Ambient.g = 1.0f;

     mtrl.Ambient.b = 0.0f;

     mtrl.Ambient.a = 1.0f;

 

    mtrl.Diffuse.r = 1.0f;

    mtrl.Diffuse.g = 1.0f;

    mtrl.Diffuse.b = 0.0f;

    mtrl.Diffuse.a = 0.5f;

 

     mtrl.Specular.r = 1.0f;

     mtrl.Specular.g = 1.0f;

     mtrl.Specular.b = 0.0f;

     mtrl.Specular.a = 1.0f;

 

    g_pd3dDevice->SetMaterial( &mtrl );

 

     //设置一号光源为方向光,颜色为绿色

    D3DXVECTOR3 vecDir;

    D3DLIGHT9 light1;

    ZeroMemory( &light1, sizeof(D3DLIGHT9) );

    light1.Type       = D3DLIGHT_DIRECTIONAL;

    light1.Diffuse.r  = 0.0f;

    light1.Diffuse.g  = 1.0f;

    light1.Diffuse.b  = 0.0f;

    vecDir = D3DXVECTOR3(-10, 0 ,10); //方向光方向

   

     D3DXVec3Normalize( (D3DXVECTOR3*)&light1.Direction, &vecDir );

    g_pd3dDevice->SetLight( 0, &light1 );

 

     //二号光源为点光源,颜色为红色

    D3DXVECTOR3  vecPos2;

    D3DLIGHT9 light2;

    ZeroMemory( &light2, sizeof(D3DLIGHT9) );

    light2.Type       = D3DLIGHT_POINT; 

    light2.Diffuse.r  = 1.0f;

    light2.Diffuse.g  = 0.0f;

    light2.Diffuse.b  = 0.0f;

 

    light2.Position= D3DXVECTOR3(10*sinf(timeGetTime()/350.0f) ,

                         0,

                             10*cosf(timeGetTime()/350.0f) );

 

    light2.Range        = 100.0f;

     light2.Attenuation0 = 1.0f;

    g_pd3dDevice->SetLight( 1, &light2 );

 

     //三号光源为方向光,颜色为绿色, *镜面反射*

     D3DXVECTOR3 vecDir3;

    D3DLIGHT9 light3;

    ZeroMemory( &light3, sizeof(D3DLIGHT9) );

    light3.Type       = D3DLIGHT_DIRECTIONAL;

     light3.Specular.r  = 0.0f;

     light3.Specular.g  = 1.0f;

     light3.Specular.b  = 0.0f;

     light3.Specular.a  = 1.0f;

    vecDir3 = D3DXVECTOR3(-10,0,10);

   

     D3DXVec3Normalize( (D3DXVECTOR3*)&light3.Direction, &vecDir3 );

    g_pd3dDevice->SetLight( 2, &light3 );

 

     //设置一定的环境光

     g_pd3dDevice->SetRenderState( D3DRS_AMBIENT, 0x00505050);

}

 

 

//--------------------------------------------------------------

// Name: 释放创建的对象

//--------------------------------------------------------------

VOID Cleanup()

{

     //释放顶点缓冲区对象

    if( g_pVB != NULL )

        g_pVB->Release();

 

     //释放Direct3D设备对象

    if( g_pd3dDevice != NULL )

        g_pd3dDevice->Release();

 

     //释放Direct3D对象

    if( g_pD3D != NULL )

        g_pD3D->Release();

}

 

 

//-----------------------------------------------------------------------------

// Desc: 渲染图形

//-----------------------------------------------------------------------------

VOID Render()

{

    //清空后台缓冲区和深度缓冲区

    g_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER,

                         D3DCOLOR_XRGB(45, 50, 170), 1.0f, 0 );

 

    //开始在后台缓冲区绘制图形

    if( SUCCEEDED( g_pd3dDevice->BeginScene() ) )

    {

          //设置材料和灯光, 因为灯光属性不断变化,所以在此设置

         SetupLights();

 

         //在后台缓冲区绘制图形

        g_pd3dDevice->SetStreamSource( 0, g_pVB, 0, sizeof(CUSTOMVERTEX) );

        g_pd3dDevice->SetFVF( D3DFVF_CUSTOMVERTEX );

        g_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLESTRIP, 0, 2*50-2 );

 

       //结束在后台缓冲区绘制图形

        g_pd3dDevice->EndScene();

    }

 

     //将在后台缓冲区绘制的图形提交到前台缓冲区显示

    g_pd3dDevice->Present( NULL, NULL, NULL, NULL );

}

 

 

//-----------------------------------------------------------------------------

// Desc: 消息处理

//-----------------------------------------------------------------------------

LRESULT WINAPI MsgProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )

{

     switch( msg )

     {

     case WM_DESTROY:

         Cleanup();

         PostQuitMessage( 0 );

         return 0;

 

     case WM_KEYDOWN:

         switch(wParam)

         {

          case 48:  //"0"键, 禁用所有的光源,只使用环境光

              g_pd3dDevice->LightEnable( 0, false );

             g_pd3dDevice->LightEnable( 1, false );

             g_pd3dDevice->LightEnable( 2, false );

              break;

         case 49:  //"1"键, 启用号光源, 方向光

              g_pd3dDevice->LightEnable( 0, true );

             g_pd3dDevice->LightEnable( 1, false );

             g_pd3dDevice->LightEnable( 2, false );

              break;

         case 50:  //"2"键, 启用号光源, 点光源

              g_pd3dDevice->LightEnable( 0, false );

             g_pd3dDevice->LightEnable( 1, true );

             g_pd3dDevice->LightEnable( 2, false );

              break;

         case 51:  //"3"键, 启用号光源, 方向光

              g_pd3dDevice->LightEnable( 0, false );

             g_pd3dDevice->LightEnable( 1, false );

             g_pd3dDevice->LightEnable( 2, true );

              break;

         case 52:  //"4"键, 同时启用三个光源

              g_pd3dDevice->LightEnable( 0, true );

             g_pd3dDevice->LightEnable( 1, true );

             g_pd3dDevice->LightEnable( 2, true );

              break;

         case 53:  //"5"键,平面着色模式

              g_pd3dDevice->SetRenderState(D3DRS_SHADEMODE,D3DSHADE_FLAT);

              break;

        

         case 54:  //"6"键,戈劳德着色模式

            g_pd3dDevice->SetRenderState(D3DRS_SHADEMODE,D3DSHADE_GOURAUD);

              break;

         }

         return 0;

    }

 

    return DefWindowProc( hWnd, msg, wParam, lParam );

}

 

 

//-----------------------------------------------------------------------------

// Desc: 入口函数

//-----------------------------------------------------------------------------

INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR, INT )

{

    //注册窗口类

    WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, MsgProc, 0L, 0L,

                      GetModuleHandle(NULL), NULL, NULL, NULL, NULL,

                      L"ClassName", NULL };

    RegisterClassEx( &wc );

 

    //创建窗口

    HWND hWnd = CreateWindow( L"ClassName", L"多光源",

                              WS_OVERLAPPEDWINDOW, 200, 100, 500, 500,

                              GetDesktopWindow(), NULL, wc.hInstance, NULL );

 

    //初始化Direct3D

    if( SUCCEEDED( InitD3D( hWnd ) ) )

    {

       //创建场景图形

        if( SUCCEEDED( InitGeometry() ) )

        {

            //显示窗口

            ShowWindow( hWnd, SW_SHOWDEFAULT );

            UpdateWindow( hWnd );

 

             //进入消息循环

            MSG msg;

            ZeroMemory( &msg, sizeof(msg) );

            while( msg.message!=WM_QUIT )

            {

                if( PeekMessage( &msg, NULL, 0U, 0U, PM_REMOVE ) )

                {

                    TranslateMessage( &msg );

                    DispatchMessage( &msg );

                }

                else

                   {

                    Render();  //渲染场景

                   }

            }

        }

    }

 

    UnregisterClass( L"ClassName", wc.hInstance );

    return 0;

}

 

 

 

代码中的点光源的位置是随着时间的变化而改变的

 

    light2.Position= D3DXVECTOR3(10*sinf(timeGetTime()/350.0f) ,

                         0,

                             10*cosf(timeGetTime()/350.0f) );

 

所以当我们观察电光源的时候,光源在不断地变化,在每次的渲染的时候,光源都会重新的设置一下,所以点光源的位置变化会实时的反应到我们程序的显示中,大家都明白吧,呵呵。

恩,关于光源的讨论我们就先讨论到这里,以后光源用处多多,呵呵。

 

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/luoya263547560/archive/2009/04/03/4047193.aspx

原创粉丝点击