• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            天行健 君子當(dāng)自強(qiáng)而不息

            D3D中的光照(2)

            5.4光源

            Direct3D支持三種類(lèi)型的光源。

            點(diǎn)光源——這種光源在世界坐標(biāo)中有一個(gè)位置且向所有方向上都照射光線。

            方向光源——這種光源沒(méi)有位置但是向指定方向發(fā)出平行光線。

            聚光燈——這種類(lèi)型的光源和手電筒的光類(lèi)似;它有位置并且發(fā)出的光在指定方向上按照?qǐng)A錐形照射。這個(gè)圓錐形有兩個(gè)角度,θ和φ。角度θ描述內(nèi)圓錐,φ描述外圓錐。

             

            在代碼中一個(gè)燈光資源是通過(guò)D3DLIGHT9結(jié)構(gòu)來(lái)表現(xiàn)的。

             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;

             

            Type——定義燈光類(lèi)型,我們能夠使用下面三種類(lèi)型之一:D3DLIGHT_POINT, D3DLIGHT_SPOT, D3DLIGHT_DIRECTIONAL

            Diffuse——此光源發(fā)出的漫射光顏色。

            Specular——此光源發(fā)出的鏡面光顏色。

            Ambient——此光源發(fā)出的環(huán)境光顏色。

            Position——用一個(gè)向量來(lái)描述的光源世界坐標(biāo)位置。這個(gè)值對(duì)于燈光的方向是無(wú)意義的。

            Direction——用一個(gè)向量來(lái)描述的光源世界坐標(biāo)照射方向。這個(gè)值不能用在點(diǎn)光源上。

            Range——燈光能夠傳播的最大范圍。這個(gè)值不能比大。且不能用于方向光源。

            Attenuation0, Attenuation1, Attenuation2——這些衰減變量被用來(lái)定義燈光強(qiáng)度的傳播距離衰減。它們只被用于點(diǎn)光源和聚光燈上。Attenuation0定義恒定衰減,Attenuation1定義線性衰減,Attenuation2定義二次衰減。適當(dāng)?shù)氖褂眠@個(gè)公式,D是代表到光源的距離,A0,A1,A2與Attenuation0,1,2相匹配。

                                                     attenuation = 1/(A0 + A1D + A2D2)

            Theta——只用于聚光燈;指定內(nèi)圓錐的角度,單位是弧度。

            Phi——只用于聚光燈;指定外圓錐的角度,單位是弧度。

            現(xiàn)在只是演示怎樣使用InitDirectionalLight。其他的也很類(lèi)似:

            創(chuàng)建一個(gè)方向光源,它沿著x軸正方向照射白色燈光。我們按照下面的方法來(lái)做:

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

            D3DXCOLOR c = d3d::WHITE;

            D3DLIGHT9 dirLight = d3d::InitDirectionalLight(&dir, &c);

            在把D3DLIGHT9初始化好以后,我們需要用Direct3D內(nèi)在支持的燈光來(lái)注冊(cè)。就象這樣做:

            Device->SetLight(

                   0, // element in the light list to set, range is 0-maxlights

                   &light);// address of the D3DLIGHT9 structure to set

            一旦燈光注冊(cè)了,我們就能使用下面的列舉的例子來(lái)開(kāi)或關(guān)燈光了:

            Device->LightEnable(

                   0, // the element in the light list to enable/disable

                   true); // true = enable, false = disable

             

            5.5實(shí)例程序:燈光

                   這一章的例子是創(chuàng)建如圖5.7所顯示的場(chǎng)景。它示范了怎樣指定頂點(diǎn)法線,怎樣創(chuàng)建材質(zhì),以及怎樣創(chuàng)建和使用一個(gè)方向燈光。注意在這個(gè)示例程序中我們不會(huì)使用在文件d3dUtility.h/cpp中的材質(zhì)和燈光函數(shù)。因?yàn)槲覀兿胝故驹鯓邮謩?dòng)來(lái)做這些設(shè)置。

             

            圖5.7

             

            給場(chǎng)景增加燈光的步驟是:

            1、 允許使用燈光。

            2、 為每個(gè)物體創(chuàng)建材質(zhì)并且在渲染相應(yīng)物體前應(yīng)將材質(zhì)附予物體。

            3、 創(chuàng)建一個(gè)或多個(gè)光源,設(shè)置它們,把它們?cè)O(shè)為可用。

            4、 將其他附加光源設(shè)為可用,比如鏡面高光。

            /**************************************************************************************
              Renders a light pyramid.  Demonstrates how to specify the vertex normals, how to create 
              and set a material, and how to create and set a directional light.
             *************************************************************************************
            */

            #include 
            "d3dUtility.h"

            #pragma warning(disable : 
            4100)

            class cLightVertex
            {
            public:
                
            float m_x, m_y, m_z;
                
            float m_nx, m_ny, m_nz; 

                cLightVertex() {}

                cLightVertex(
            float x, float y, float z, float nx, float ny, float nz)
                {
                    m_x  
            = x;    m_y  = y;    m_z  = z;
                    m_nx 
            = nx;    m_ny = ny;    m_nz = nz;
                }
            };

            const DWORD LIGHT_VERTEX_FVF = D3DFVF_XYZ | D3DFVF_NORMAL;

            ////////////////////////////////////////////////////////////////////////////////////////////////////

            const int WIDTH  = 640;
            const int HEIGHT = 480;

            IDirect3DDevice9
            *        g_d3d_device  = NULL;
            IDirect3DVertexBuffer9
            *    g_pyramid_vb = NULL;

            ////////////////////////////////////////////////////////////////////////////////////////////////////

            bool setup()
            {    
                
            // turn on lighting
                g_d3d_device->SetRenderState(D3DRS_LIGHTING, TRUE);

                g_d3d_device
            ->CreateVertexBuffer(12 * sizeof(cLightVertex), D3DUSAGE_WRITEONLY, LIGHT_VERTEX_FVF, 
                                                 D3DPOOL_MANAGED, 
            &g_pyramid_vb, NULL);

                
            // fill the buffers with the triangle data

                cLightVertex
            * vertices;

                g_pyramid_vb
            ->Lock(00, (void**)&vertices, 0);
                
                
            // front face
                vertices[0= cLightVertex(-1.0f0.0f-1.0f0.0f0.707f-0.707f);
                vertices[
            1= cLightVertex( 0.0f1.0f,  0.0f0.0f0.707f-0.707f);
                vertices[
            2= cLightVertex( 1.0f0.0f-1.0f0.0f0.707f-0.707f);

                
            // left face
                vertices[3= cLightVertex(-1.0f0.0f,  1.0f-0.707f0.707f0.0f);
                vertices[
            4= cLightVertex( 0.0f1.0f,  0.0f-0.707f0.707f0.0f);
                vertices[
            5= cLightVertex(-1.0f0.0f-1.0f-0.707f0.707f0.0f);

                
            // right face
                vertices[6= cLightVertex( 1.0f0.0f-1.0f0.707f0.707f0.0f);
                vertices[
            7= cLightVertex( 0.0f1.0f,  0.0f0.707f0.707f0.0f);
                vertices[
            8= cLightVertex( 1.0f0.0f,  1.0f0.707f0.707f0.0f);

                
            // back face
                vertices[9]  = cLightVertex( 1.0f0.0f,  1.0f0.0f0.707f0.707f);
                vertices[
            10= cLightVertex( 0.0f1.0f,  0.0f0.0f0.707f0.707f);
                vertices[
            11= cLightVertex(-1.0f0.0f,  1.0f0.0f0.707f0.707f);

                g_pyramid_vb
            ->Unlock();

                
            // create and set the material

                D3DMATERIAL9 material;

                material.Ambient  
            = WHITE;
                material.Diffuse  
            = WHITE;
                material.Specular 
            = WHITE;
                material.Emissive 
            = BLACK;
                material.Power      
            = 5.0f;

                g_d3d_device
            ->SetMaterial(&material);

                
            // setup a directional light

                D3DLIGHT9 dir_light;
                ZeroMemory(
            &dir_light, sizeof(dir_light));

                dir_light.Type        
            = D3DLIGHT_DIRECTIONAL;
                dir_light.Diffuse    
            = WHITE;
                dir_light.Specular  
            = WHITE * 0.3f;
                dir_light.Ambient   
            = WHITE * 0.3f;
                dir_light.Direction 
            = D3DXVECTOR3(1.0f0.0f0.0f);

                
            // set and enable the light
                g_d3d_device->SetLight(0&dir_light);
                g_d3d_device
            ->LightEnable(0, TRUE);

                
            // turn on specular lighting and instruct Direct3D to renormalize normals
                g_d3d_device->SetRenderState(D3DRS_NORMALIZENORMALS, TRUE);
                g_d3d_device
            ->SetRenderState(D3DRS_SPECULARENABLE, TRUE);

                
            // position and aim the camera

                D3DXMATRIX view_matrix;

                D3DXVECTOR3 pos(
            0.0f1.0f-3.0f);
                D3DXVECTOR3 target(
            0.0f0.0f0.0f);
                D3DXVECTOR3 up(
            0.0f1.0f0.0f);

                D3DXMatrixLookAtLH(
            &view_matrix, &pos, &target, &up);
                g_d3d_device
            ->SetTransform(D3DTS_VIEW, &view_matrix);

                
            // set the projection matrix

                D3DXMATRIX proj;
                D3DXMatrixPerspectiveFovLH(
            &proj, D3DX_PI * 0.5f, (float)WIDTH/HEIGHT, 1.0f1000.0f);

                g_d3d_device
            ->SetTransform(D3DTS_PROJECTION, &proj);
                
                
            return true;
            }

            void cleanup()
            {
                safe_release
            <IDirect3DVertexBuffer9*>(g_pyramid_vb);
            }

            bool display(float time_delta)
            {
                
            // update the scene: rotate the pyramid

                D3DXMATRIX y_rot;
                
            static float y = 0.0f;

                D3DXMatrixRotationY(
            &y_rot, y);
                y 
            += time_delta;

                
            if(y >= 6.28f)
                    y 
            = 0.0f;

                g_d3d_device
            ->SetTransform(D3DTS_WORLD, &y_rot);

                
            // draw the scene

                g_d3d_device
            ->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0x000000001.0f0);

                g_d3d_device
            ->BeginScene();

                g_d3d_device
            ->SetStreamSource(0, g_pyramid_vb, 0sizeof(cLightVertex));
                g_d3d_device
            ->SetFVF(LIGHT_VERTEX_FVF);
                g_d3d_device
            ->DrawPrimitive(D3DPT_TRIANGLELIST, 04);
                
                g_d3d_device
            ->EndScene();

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

                
            return true;
            }

            LRESULT CALLBACK wnd_proc(HWND hwnd, UINT msg, WPARAM word_param, LPARAM long_param)
            {
                
            switch(msg)
                {
                
            case WM_DESTROY:
                    PostQuitMessage(
            0);
                    
            break;

                
            case WM_KEYDOWN:
                    
            if(word_param == VK_ESCAPE)
                        DestroyWindow(hwnd);
                    
            break;
                }

                
            return DefWindowProc(hwnd, msg, word_param, long_param);
            }

            int WINAPI WinMain(HINSTANCE inst, HINSTANCE, PSTR cmd_line, int cmd_show)
            {
                
            if(! init_d3d(inst, WIDTH, HEIGHT, true, D3DDEVTYPE_HAL, &g_d3d_device))
                {
                    MessageBox(NULL, 
            "init_d3d() - failed."0, MB_OK);
                    
            return 0;
                }

                
            if(! setup())
                {
                    MessageBox(NULL, 
            "Steup() - failed."0, MB_OK);
                    
            return 0;
                }

                enter_msg_loop(display);

                cleanup();
                g_d3d_device
            ->Release();

                
            return 0;
            }

             


            Setup函數(shù)給場(chǎng)景加入燈光。首先允許使用燈光,當(dāng)然這不是必須的因?yàn)槟J(rèn)設(shè)置就是允許使用燈光的。

            下一步,我們創(chuàng)建頂點(diǎn)緩存,鎖定,并且把“金字塔”的三角形頂點(diǎn)放入其中。頂點(diǎn)法線是利用5.3節(jié)中的運(yùn)算法則預(yù)先計(jì)算好的。注意三角形共享頂點(diǎn),但它們的法線不能共享;因此對(duì)這個(gè)物體使用索引列表并不是最有利的。例如,所有三角形都共享頂點(diǎn)(0,1,0);然而,對(duì)每個(gè)三角形,它們的頂點(diǎn)法線是不相同的。

            為物體產(chǎn)生了頂點(diǎn)數(shù)據(jù)以后,我們描述利用燈光表現(xiàn)各自材質(zhì)的物體間是怎樣相互影響的。在這個(gè)例子中,“金字塔”反射出白光,自身不發(fā)光,且會(huì)產(chǎn)生一些高光。

            接著,我們創(chuàng)建一個(gè)方向光并將其設(shè)為可用。方向光是沿著x軸的正方向照射的。燈光照射最強(qiáng)的白色漫射光(dir.Diffuse = WHITE),較弱的白色鏡面光(dir.Specular = WHITE * 0.3f)以及一個(gè)中等強(qiáng)度的白色環(huán)境光(dir.Ambient = WHITE *0.6f)。

            最后,我們?cè)O(shè)置狀態(tài)使法線重新單位化且把鏡面高光設(shè)置為可用。


            下載源程序


            posted on 2008-03-16 13:58 lovedday 閱讀(1018) 評(píng)論(0)  編輯 收藏 引用


            只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。
            網(wǎng)站導(dǎo)航: 博客園   IT新聞   BlogJava   博問(wèn)   Chat2DB   管理


            公告

            導(dǎo)航

            統(tǒng)計(jì)

            常用鏈接

            隨筆分類(lèi)(178)

            3D游戲編程相關(guān)鏈接

            搜索

            最新評(píng)論

            影音先锋女人AV鲁色资源网久久| 区亚洲欧美一级久久精品亚洲精品成人网久久久久 | 久久99精品国产自在现线小黄鸭| 中文字幕亚洲综合久久| 久久精品无码一区二区WWW| 久久亚洲高清观看| 久久综合九色综合网站| 精品国产乱码久久久久久呢| A狠狠久久蜜臀婷色中文网| 午夜精品久久久久久久无码| 99久久国产免费福利| 久久精品一区二区三区AV| 嫩草影院久久国产精品| 色综合久久综合中文综合网| 亚洲人成伊人成综合网久久久| 久久这里只精品国产99热| 国内精品久久久久久久久电影网 | 久久久午夜精品| 伊人精品久久久久7777| 99久久国产亚洲高清观看2024| 一本色道久久综合亚洲精品| 久久婷婷五月综合97色直播| 亚洲精品乱码久久久久久蜜桃| 狠狠色丁香婷婷综合久久来| 久久综合丁香激情久久| 国产成人久久精品一区二区三区 | 国产亚洲色婷婷久久99精品| 伊人久久大香线蕉av不卡| 久久久久亚洲AV无码观看| 要久久爱在线免费观看| 久久人妻少妇嫩草AV无码蜜桃 | 日韩AV毛片精品久久久| 国内精品久久久久国产盗摄| 欧美麻豆久久久久久中文| 国内精品久久久久久久影视麻豆| 久久青青草原综合伊人| 国产2021久久精品| AV无码久久久久不卡蜜桃| 久久人人爽人人爽人人片av麻烦| 久久久高清免费视频| 97精品依人久久久大香线蕉97 |