• <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>

            天行健 君子當自強而不息

            頂點著色器入門(2)

            新建網頁 1

            17.3使用頂點著色器的步驟

            下面的列表概括了創建和使用頂點著色器的必須步驟:

            1.      編寫并編譯頂點著色器

            2.      創建一個IDirect3DVertexShader9接口以引用已編譯的著色器代碼上的頂點著色器。

            3.      IDirect3DDevice9:: SetVertexShader方法使用這個頂點著色器。

            當然,在我們做完這些之后,我們還得銷毀這個頂點著色器。

            17.3.1 編寫并編譯頂點著色器

            首先,我們必須編寫一個頂點著色器程序。一旦著色器代碼寫好之后,我們就使用D3DXCompileShaderFromFile函數編譯這個著色器。回憶一下,這個函數返回一個ID3DXBuffer指針,它包含已編譯的著色器代碼。

            17.3.2 創建頂點著色器

            一旦我們擁有了編譯好的著色器代碼,我們就能夠獲得一個IDirect3DVertexShader9接口的指針,它代表一個頂點著色器——通過使用下面的方法:

                           
                   

                    HRESULT IDirect3DDevice9::CreateVertexShader(

                   

                         const DWORD *pFunction,

                   

                         IDirect3DVertexShader9** ppShader

                   

            );

            pFunction——已編譯著色器代碼的指針

            ppShader——返回一個IDirect3DVertexShader9接口的指針

            例如,假設變量shader是一個包含已編譯的,著色器代碼的ID3DXBuffer指針。然后要獲得一個IDirect3DVertexShader9接口,我們可以寫:

                           
                   

                    IDirect3DVertexShader9* ToonShader = 0;

                   

            hr =         Device->CreateVertexShader(

                   

                               (DWORD*)shader->GetBufferPointer(),

                   

                               &ToonShader);

            注意:重申一遍,D3DXCompileShaderFromFile是一個函數,它將返回已編譯著色器的代碼(shader)。

            17.3.3 建立頂點著色器

            在我們獲得了一個代表我們的頂點著色器的IDirect3DVertexShader9接口的指針之后,我們就能夠使用下面的方法使用它:

                           
                   

                    HRESULT IDirect3DDevice9::SetVertexShader(

                   

                         IDirect3DVertexShader9* pShader

                   

            );

            這個方法僅接受一個參數,我們在其中傳遞一個想要使用的頂點著色器的指針。要使用這個著色器,我們可以寫:Device->SetVertexShader(ToonShader);

             

            17.3.4 銷毀頂點著色器

            和所有的Direc3D接口一樣,要清除他們,我們就必須在用完它們之后調用其的Release方法。

            17.4應用程序:散射光照

            作為創建并使用頂點著色器的熱身,我們寫一個頂點著色器,它用一個方向(平行)光對每個頂點進行標準的散射光照。簡而言之,散射光照根據頂點法線和光線向量(它朝向光源方向)的角度計算頂點接收到的光線的數量。角度越小,則頂點接收到的光線就越多;而角度越大,則頂點接收到的光線就越少。如果角度大于等于90度,頂點就接收不到光線了。

            我們以檢閱著色器代碼作為開始:

                 /**********************************************************************************
                  Vertex shader that does diffuse lighting.         
                 **********************************************************************************/

               
                matrix g_view_matrix;
                matrix g_view_proj_matrix;
               
                vector g_ambient_material;
                vector g_diffuse_material;
               
                vector g_dir_to_light;    
            // the direction to the light source
               
                // Global variables used to hold the ambient light intensity (ambient light the light 
                // source emits) and the diffuse light intensity (diffuse light the light source emits).  
                // These variables are initialized here in the shader.
               

               
            const vector DIFFUSE_LIGHT_INTENSITY = {0.5f, 0.5f, 0.5f, 1.0f};
               
            const vector AMBIENT_LIGHT_INTENSITY = {2.0f, 2.0f, 1.0f, 1.0f};
               
               
               
            struct sVertexInput
                {
                    vector position : POSITION;
                    vector normal    : NORMAL;
                };
               
               
            struct sVertexOutput
                {
                    vector position : POSITION;
                    vector diffuse  : COLOR;
                };
               
               
               
                ///////////////////////////////////////////////////////////////////////////////////////////////
               

                sVertexOutput main(sVertexInput vertex_input)
                {
                    sVertexOutput vertex_output = (sVertexOutput) 0;
               
                    
            // transform position to homogeneous clip space
               
                    vertex_output.position = mul(vertex_input.position, g_view_proj_matrix);
               
                    
            // Transform lights and normals to view space.
                    // Set w components to zero since we're transforming vectors here and not points.
               

                    g_dir_to_light.w      = 0.0f;
                    vertex_input.normal.w = 0.0f;
               
                    g_dir_to_light        = mul(g_dir_to_light,       g_view_matrix);
                    vertex_input.normal = mul(vertex_input.normal, g_view_matrix);
               
                    
            // compute cosine of the angle between light and normal
               
                float scalar = dot(g_dir_to_light, vertex_input.normal);
               
                    
            // Recall that if the angle between the surface and light is greater than 90 degrees 
                    // the surface recieves no light. Thus, if the angle is greater than 90 degrees we set
                    // scalar to zero so that the surface will not be lit.
               
                if(scalar < 0.0f)
                        scalar = 0.0f;
               
                    
            // Ambient light reflected is computed by performing a component wise multiplication with 
                    // the ambient material vector and the ambient light intensity vector.
                    //
                    // Diffuse light reflected is computed by performing a component wise multiplication with 
                    // the diffuse material vector and the diffuse light intensity vector.  
                    // Further we scale each component by the shading scalar s, which shades the color based on 
                    // how much light the vertex received from the light source.
                    //
                    // The sum of both the ambient and diffuse components gives us our final vertex color.
               
                    vertex_output.diffuse = (g_ambient_material * AMBIENT_LIGHT_INTENSITY) +
                                            (scalar * (g_diffuse_material * DIFFUSE_LIGHT_INTENSITY));
               
                    
            return vertex_output;
                }

            執行程序:
                 /**************************************************************************************************
                  Demonstrates diffuse lighting using a vertex shader.  You will have to switch to 
                  the REF device to run this sample if your hardware does not support shaders.  
                  Or you can use software vertex processing: D3DCREATE_SOFTWARE_VERTEXPROCESSING. 
                 **************************************************************************************************/

               
                #include "d3dUtility.h"
               
                #pragma warning(disable : 4100)
               
               
            const int WIDTH  = 640;
               
            const int HEIGHT = 480;
               
                IDirect3DDevice9*        g_device;
                ID3DXMesh*                g_teapot_mesh;
                IDirect3DVertexShader9* g_vertex_shader;
                ID3DXConstantTable*        g_constant_table;
               
                D3DXHANDLE                g_view_matrix_handle;
                D3DXHANDLE                g_view_proj_matrix_handle;
                D3DXHANDLE                g_ambient_material_handle;
                D3DXHANDLE                g_diffuse_material_handle;
                D3DXHANDLE                g_dir_to_light_handle;
               
                D3DXMATRIX                g_proj_matrix;
               
               
                ////////////////////////////////////////////////////////////////////////////////////////////////////
               

               
            bool setup()
                {    
                    D3DXCreateTeapot(g_device, &g_teapot_mesh, NULL);
               
                    
            // compile shader
               

                    ID3DXBuffer*    shader_buffer;
                    ID3DXBuffer*    error_buffer;
               
                    HRESULT hr = D3DXCompileShaderFromFile("DiffuseShader.cxx", NULL, NULL, "main", "vs_1_1",
                                                           D3DXSHADER_ENABLE_BACKWARDS_COMPATIBILITY,
                                                           &shader_buffer, &error_buffer, &g_constant_table);
               
                    
            // output any error messages
               
                if(error_buffer)
                    {
                        MessageBox(NULL, (
            char*)error_buffer->GetBufferPointer(), "ERROR", MB_OK);
                        safe_release<ID3DXBuffer*>(error_buffer);
                    }
               
                    
            if(FAILED(hr))
                    {
                        MessageBox(NULL, "D3DXCreateEffectFromFile() - FAILED", "ERROR", MB_OK);
                        
            return false;
                    }
               
                    hr = g_device->CreateVertexShader((DWORD*) shader_buffer->GetBufferPointer(), &g_vertex_shader);
               
                    
            if(FAILED(hr))
                    {
                        MessageBox(NULL, "CreateVertexShader - FAILED", "ERROR", MB_OK);
                        
            return false;
                    }
               
                    safe_release<ID3DXBuffer*>(shader_buffer);
               
                    
            // get handles
               
                    g_view_matrix_handle        = g_constant_table->GetConstantByName(NULL, "g_view_matrix");
                    g_view_proj_matrix_handle    = g_constant_table->GetConstantByName(NULL, "g_view_proj_matrix");
                    g_ambient_material_handle   = g_constant_table->GetConstantByName(NULL, "g_ambient_material");
                    g_diffuse_material_handle   = g_constant_table->GetConstantByName(NULL, "g_diffuse_material");
                    g_dir_to_light_handle        = g_constant_table->GetConstantByName(NULL, "g_light_direction");
               
                    
            //
                    // set shader constants
                    //
               
                    // light direction
               
                    D3DXVECTOR4 dir_to_light(-0.57f, 0.57f, -0.57f, 0.0f);
                    g_constant_table->SetVector(g_device, g_dir_to_light_handle, &dir_to_light);
               
                    
            // materials
               
                    D3DXVECTOR4 ambient_material(1.0f, 1.0f, 0.5f, 1.0f);
                    D3DXVECTOR4 diffuse_material(1.0f, 1.0f, 0.5f, 1.0f);
               
                    g_constant_table->SetVector(g_device, g_ambient_material_handle, &ambient_material);
                    g_constant_table->SetVector(g_device, g_diffuse_material_handle, &diffuse_material);
               
                    g_constant_table->SetDefaults(g_device);
               
                    
            // set the projection matrix
               
                    D3DXMatrixPerspectiveFovLH(&g_proj_matrix, D3DX_PI/4.0f, (float)WIDTH/HEIGHT, 1.0f, 1000.0f);
                    
                    
            //g_device->SetRenderState(D3DRS_FILLMODE, D3DFILL_WIREFRAME);
               
                
                    
            return true;
                }
               
               
                ///////////////////////////////////////////////////////////////////////////////////////////////////////
               

               
            void cleanup()
                {    
                    safe_release<ID3DXMesh*>(g_teapot_mesh);
                    safe_release<IDirect3DVertexShader9*>(g_vertex_shader);
                    safe_release<ID3DXConstantTable*>(g_constant_table);
                }
               
               
                ///////////////////////////////////////////////////////////////////////////////////////////////////////
               

               
            bool display(float time_delta)
                {    
                    
            static float angle  = (3.0f * D3DX_PI) / 2.0f;
                    
            static float height = 3.0f;
               
                    
            if(GetAsyncKeyState(VK_LEFT) & 0x8000f)
                        angle -= 0.5f * time_delta;
               
                    
            if(GetAsyncKeyState(VK_RIGHT) & 0x8000f)
                        angle += 0.5f * time_delta;
               
                    
            if(GetAsyncKeyState(VK_UP) & 0x8000f)
                        height += 5.0f * time_delta;
               
                    
            if(GetAsyncKeyState(VK_DOWN) & 0x8000f)
                        height -= 5.0f * time_delta;
               
                    D3DXVECTOR3 position(cosf(angle) * 7.0f, height, sinf(angle) * 7.0f);
                    D3DXVECTOR3 target(0.0f, 0.0f, 0.0f);
                    D3DXVECTOR3 up(0.0f, 1.0f, 0.0f);
               
                    D3DXMATRIX view_matrix;
                    D3DXMatrixLookAtLH(&view_matrix, &position, &target, &up);
                    
                    D3DXMATRIX view_proj_matrix = view_matrix * g_proj_matrix;
                    g_constant_table->SetMatrix(g_device, g_view_proj_matrix_handle, &view_proj_matrix);
                    
                    
            // render now
               

                    g_device->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0x00000000, 1.0f, 0);
               
                    g_device->BeginScene();
               
                    g_device->SetVertexShader(g_vertex_shader);
                    g_teapot_mesh->DrawSubset(0);
                    
                    g_device->EndScene();
               
                    g_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_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_device->Release();
               
                    
            return 0;
                }

            運行截圖:

            setup函數執行下列任務:

            創建茶壺網格

            編譯頂點著色器

            根據已編譯代碼創建頂點著色器

            通過常量表獲取著色器程序中的幾個變量的句柄

            通過常量表初始化著色器的這幾個變量

            注意:對于本應用程序,我們的頂點結構不需要任何自由頂點格式沒有的額外的分量。

            display函數非常簡單。它檢測用戶輸入(這里指的是用戶輸入的傳入著色器程序的變量),并相應的更新視圖矩陣。但是,因為我們在著色器中執行這個視圖矩陣變換,所以我們還必須更新著色器中的視圖矩陣變量。我們用常量表完成這件事情。


            下載源程序


            posted on 2008-04-06 14:23 lovedday 閱讀(1389) 評論(2)  編輯 收藏 引用

            評論

            # re: 頂點著色器入門(2) 2008-04-13 09:17 zjh

            發現樓主渲染的地方少了一行

            g_constant_table->SetMatrix(g_device, g_view_matrix_handle, &view_matrix);

            運行的截圖似乎不對啊  回復  更多評論   

            # re: 頂點著色器入門(2) 2008-04-13 10:51 lovedday

            確實是少了那么一行,不過我測試的時候有沒有那一行都沒什么影響。  回復  更多評論   

            公告

            導航

            統計

            常用鏈接

            隨筆分類(178)

            3D游戲編程相關鏈接

            搜索

            最新評論

            无码人妻久久一区二区三区蜜桃| 午夜人妻久久久久久久久| 久久93精品国产91久久综合| 久久一本综合| 久久福利青草精品资源站| 午夜精品久久影院蜜桃| 国产成人无码久久久精品一| 久久综合久久性久99毛片| 精品久久久久香蕉网| 久久福利片| 韩国无遮挡三级久久| 一个色综合久久| 国产三级精品久久| 国产国产成人精品久久| 77777亚洲午夜久久多人| 狠狠色丁香婷婷综合久久来来去| 久久精品国产久精国产果冻传媒| 精品国产一区二区三区久久蜜臀| 亚洲va久久久噜噜噜久久天堂| 国产福利电影一区二区三区,免费久久久久久久精 | 精品久久久久久久久午夜福利| 精品人妻伦一二三区久久| 狠狠色噜噜狠狠狠狠狠色综合久久| 久久久国产99久久国产一| 久久国产综合精品五月天| 久久精品国产免费| 99re久久精品国产首页2020| 久久国产劲爆AV内射—百度| 亚洲?V乱码久久精品蜜桃| 国产精品亚洲综合专区片高清久久久 | 久久久久国产成人精品亚洲午夜| 精品九九久久国内精品| 久久精品亚洲一区二区三区浴池| 亚洲人AV永久一区二区三区久久| 久久国产成人精品国产成人亚洲| 久久99热这里只有精品国产| 国产2021久久精品| 久久男人AV资源网站| 四虎久久影院| 久久精品国产亚洲AV久| 伊人久久精品无码二区麻豆|