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

            永遠(yuǎn)也不完美的程序

            不斷學(xué)習(xí),不斷實踐,不斷的重構(gòu)……

            常用鏈接

            統(tǒng)計

            積分與排名

            好友鏈接

            最新評論

            HLSL初級教程(1)

            作者:trcj

            目錄

            前言

            1.HLSL入門

                   1.1什么是著色器

                   1.2什么是HLSL

                   1.3怎么寫HLSL著色器

                   1.4怎么用HLSL著色器

            2.頂點著色器

                   2.1可編程數(shù)據(jù)流模型

                   2.2頂點聲明

                   2.3用頂點著色器實現(xiàn)漸變動畫

            3.像素著色器

                   3.1多紋理化

                   3.2多紋理效果的像素著色器

                   3.3應(yīng)用程序

            4.HLSL Effect(效果框架)

                   4.1Effect代碼結(jié)構(gòu)

                   4.2Effect實現(xiàn)多紋理化效果

            結(jié)語

            參考資料

            前言

                   本教程針對HLSLHigh Level Shading Language初學(xué)者,從應(yīng)用的角度對HLSL、頂點著色器、像素著色器和Effect效果框架進行了介紹,教程中去掉了對HLSL語法等一些細(xì)節(jié)內(nèi)容的討論,力求幫助讀者盡可能快地理解HLSL編程的概念,掌握HLSL編程的方法。

                   教程中部分闡述直接引用了其他文檔,這是因為這些文檔表述之精要,已經(jīng)達到了不能更改的地步,這里表示感謝。

                   本文檔版權(quán)為作者所有,非商業(yè)用途可免費使用,轉(zhuǎn)載請注明出處。

                  

                作者也是HLSL的初學(xué)者,教程中難免紕漏之處,望大家指正。有任何意見請發(fā)信到taoboxiang2006@yahoo.com.cn或者留言到 http://blog.csdn.net/trcj1/進行討論。


            1.HLSL入門

            1.1什么是著色器

            DirectX使用管道技術(shù)(pipeline)進行圖形渲染,其構(gòu)架如下:

            1.1 Direct3D Graphics Pipeline

            之前我們使用管道的步驟如下:

            1.       設(shè)定頂點、圖元、紋理等數(shù)據(jù)信息;

            2.       設(shè)定管道狀態(tài)信息;

            ²        渲染狀態(tài)

            通過SetRenderState方法設(shè)定渲染狀態(tài);

            另外,使用以下方法設(shè)置變換、材質(zhì)和光照:

                          SetTransform

                          SetMaterial

            SetLight

                          LightEnable

            ²        取樣器狀態(tài)

            通過SetSamplerState方法設(shè)定取樣器狀態(tài);

            ²        紋理層狀態(tài)

            通過SetTextureStageState設(shè)定紋理層狀態(tài);

            3.       渲染;

            這部分交由D3D管道按照之前的設(shè)定自行完成,這部分操作是D3D預(yù)先固定的,所以這種管道技術(shù)被稱為固定功能管道(fixed function pipeline)

             

            固定功能管道給我們編程提供了一定的靈活性,但是仍有很多效果難以通過這種方式實現(xiàn),比如:

            1.       在渲染過程中,我們要求y坐標(biāo)值大于10的頂點要被繪制到坐標(biāo)值(000)的地方,在之前的固定功能管道中,頂點被繪制的位置是在第1步即被設(shè)定好的,不可能在渲染過程中進行改變,所以是不可行的;

            2.       謀頂點在紋理貼圖1上映射為點A,在紋理貼圖2上映射為點B,我們要求該頂點顏色由AB共同決定,即:

            定點顏色 = A點色彩值*0.7 + B點色彩值*0.3

               這在固定管道編程中也是不可行的。

            以上兩個問題都可以由可編程管道(pragrammable pipeline)來解決。

                   可編程管線允許用戶自定義一段可以在GPU上執(zhí)行的程序,代替固定管道技術(shù)中的Vertex ProcessingPixel Processing階段(參照圖1.1),從而在使我們在編程中達到更大的靈活性。其中替換Vertex Processing的部分叫做Vertex Shader(頂點著色器),替換Pixel Proccessing的部分叫做Pixel Shader(像素著色器),這就是我們所說的著色器Shader


            1.2什么是HLSL

            Direct8.x中,著色器是通過低級著色匯編語言來編寫的,這樣的程序更像是匯編式的指令集合,由于其效率低、可讀性差、版本限制等缺點,迫切要求出現(xiàn)一門更高級的著色語言。到了Direct3D9HLSLHigh Level Shading Language,高級渲染語言)應(yīng)運而生了。

            HLSL的語法非常類似于CC++,學(xué)習(xí)起來是很方便的。


            1.3怎么寫HLSL著色器

            我們可以直接把HLSL著色器代碼作為一長串字符串編寫進我們的應(yīng)用程序源文件中,但是,更加方便和模塊化的方法是把著色器的代碼從應(yīng)用程序代碼中分離出來。因此,我們將著色器代碼單獨保存為文本格式,然后在應(yīng)用程序中使用特定函數(shù)將其加載進來。

            下面是一個完整的HLSL著色器程序代碼,我們把它保存在BasicHLSL.txt中。該著色器完成頂點的世界變換、觀察變換和投影變幻,并將頂點顏色設(shè)定為指定的顏色。

            //

            // BasicHLSL.txt

            //

             

            //

            // Global variable

            //

             

            matrix WVPMatrix;

            vector color;

             

            //

            // Structures

            //

             

            struct VS_INPUT

            {

                   vector position : POSITION;

            };

             

            struct VS_OUTPUT

            {

                   vector position : POSITION;

                   vector color : COLOR;

            };

             

            //

            // Functions

            //

             

            VS_OUTPUT SetColor(VS_INPUT input)

            {

                   VS_OUTPUT output = (VS_OUTPUT)0;

                  

                   output.position = mul(input.position, WVPMatrix);     

                   output.color = color;

                  

                   return output;

            }

             

            下面就針對上述代碼講解一下HLSL著色器程序的編寫:

            1.3.1全局變量

                   代碼中聲明了兩個全局變量:

            matrix WVPMatrix;

            vector color;

                   變量WVPMatrix是一個矩陣類型,它包含了世界、觀察、投影的合矩陣,用于對頂點進行坐標(biāo)變換;

                   變量color是一個向量類型,它用于設(shè)定頂點顏色;

                   代碼中并沒有對全局變量進行初始化,這是因為我們對全局變量的初始化過程將在應(yīng)用程序中進行,全局變量在應(yīng)用程序中賦值而在著色器程序中使用,這是應(yīng)用程序和著色器通信的關(guān)鍵所在。具體賦值過程將在后續(xù)部分講述。

            1.3.2輸入輸出

            ²        輸入輸出結(jié)構(gòu)

            程序中定義了兩個輸入輸出結(jié)構(gòu)VS_INPUTVS_OUTPUT

            struct VS_INPUT

            {

                   vector position : POSITION;

            };

             

            struct VS_OUTPUT

            {

                   vector position : POSITION;

                   vector color : COLOR;

            };

            自定義的結(jié)構(gòu)可以采用任意名稱,結(jié)構(gòu)不過是一種組織數(shù)據(jù)的方式,并不是強制的,你也可以不使用,而將本程序的輸入改為:

                   vector position : POSITION;

            ²        標(biāo)志符

            用于輸入輸出的變量采用用一種特殊的聲明方式:

            Type VariableName : Semantic

                   這個特殊的冒號語法表示一個語義,冒號后面的標(biāo)志符用來指定變量的用途,如

            vector position : POSITION;

                   其中,POSITION標(biāo)志符表明該變量表示頂點位置,另外還有諸如COLORNORMAL等很多表示其他意義的標(biāo)志符。

            本節(jié)所說的輸入輸出其實是指著色器代碼和編譯器、GPU之間的通信,和應(yīng)用程序是無關(guān)的,所以這些變量不需要在應(yīng)用程序中進行賦值,標(biāo)志符告訴編譯器各個輸入輸出變量的用途(頂點位置、法線、顏色等),這是著色器代碼和編譯器、GPU之間通信的關(guān)鍵。

            1.3.3入口函數(shù)

                   程序中還定義了一個函數(shù)SetColor

            OUTPUT SetColor(INPUT input)

            {

                   VS_OUTPUT output = (VS_OUTPUT)0;

                  

                   output.position = mul(input.position, WVPMatrix);     

                   output.color = color;

                  

                   return output;

            }

            1.       該函數(shù)以inputoutput類型作為輸入輸出;

            2.       使全局變量WVPMatrixinput.position相乘,以完成頂點的世界、觀察、投影變換,并把結(jié)果賦值到output.position

            output.position = mul(input.position, WVPMatrix);

            3.       將全局變量color的值賦給output.color

            output.color = color;

            4.       在同一個著色器代碼文件中,可以有多個用戶自定義函數(shù),因此在應(yīng)用程序中需要指定一個入口函數(shù),相當(dāng)于windows程序的WinMain函數(shù),本程序只包含SetColor一個函數(shù)而且它將被做為入口函數(shù)使用。

             

            1.3.4總結(jié)

                   至此,一個HLSL著色器編寫完畢,渲染過程中,當(dāng)一個頂點被送到著色器時:

            1.       全局變量WVPMatrixcolor將在應(yīng)用程序中被賦值;

            2.       入口函數(shù)SetColor被調(diào)用編譯器根據(jù)標(biāo)志符將頂點信息填充到VS_INPUT中的各個字段;

            3.       SetColor函數(shù)中,首先定義一個VS_OUTPUT信息,之后根據(jù)WVPMatrixcolor變量完成頂點的坐標(biāo)變換和顏色設(shè)定操作,最后函數(shù)返回VS_OUTPUT結(jié)構(gòu);

            4.       編譯器將會再次根據(jù)標(biāo)志符把返回的VS_OUTPUT結(jié)構(gòu)中的各字段映射為頂點相應(yīng)的信息。

            5.       頂點被送往下一個流程接受進一步處理。

            上述過程中,全局變量在應(yīng)用程序中賦值而在著色器程序中使用,這是應(yīng)用程序和著色器通信的關(guān)鍵所在;標(biāo)志符告訴編譯器各個輸入輸出變量的用途(頂點位置、法線、顏色等),這是著色器代碼和編譯器、GPU之間通信的關(guān)鍵。個人認(rèn)為這是著色器中最為精義的地方:)


            1.4怎么用HLSL著色器

            應(yīng)用程序中對HLSL著色器的使用分為以下步驟:

            1.       加載(稱為編譯更為妥當(dāng))著色器代碼;

            2.       創(chuàng)建(頂點/像素)著色器;

            3.       對著色器中的變量進行賦值,完成應(yīng)用程序和著色器之間的通信。

            4.       把著色器設(shè)定到渲染管道中;

            本例使用的著色器是一個頂點著色器,因此我們將通過頂點著色器的使用來講解著色器的使用過程,像素著色器的使用過程與此大同小異,二者之間僅有些微差別。

             

            1.4.1聲明全局變量

            IDirect3DVertexShader9* BasicShader = 0; //頂點著色器指針

             

            ID3DXConstantTable* BasicConstTable = 0; //常量表指針

            D3DXHANDLE WVPMatrixHandle          = 0;

            D3DXHANDLE ColorHandle              = 0;

             

            ID3DXMesh* Teapot                   = 0; //指向程序中D3D茶壺模型的指針

             

            1.4.2編譯著色器

            通過D3DXCompileShaderFromFile函數(shù)從應(yīng)用程序外部的文本文件BasicHLSL.txt中編譯一個著色器:

            //編譯后的著色器代碼將被放在一個buffer中,可以通過ID3DXBuffer接口對其進行訪問,之后的著色器將從這里創(chuàng)建

                   ID3DXBuffer* shaderBuffer      = 0;

                   //用于接受錯誤信息

                   ID3DXBuffer* errorBuffer       = 0;

             

                   //編譯著色器代碼

                   D3DXCompileShaderFromFile("BasicHLSL.txt", //著色器代碼文件名

                                                              0,

                                                              0,

                                                              "SetColor", //入口函數(shù)名稱

                                                              "vs_1_1", //頂點著色器版本號

                                                              D3DXSHADER_DEBUG,// Debug模式編譯      

                                                              &shaderBuffer, //指向編譯后的著色器代碼的指針

                                                              &errorBuffer,

                                                              &BasicConstTable); //常量表指針

            1.4.3創(chuàng)建著色器

                   應(yīng)用程序通過CreateVertexShader創(chuàng)建一個頂點著色器,注意使用了上一步得到的shaderBuffer

                   g_pd3dDevice->CreateVertexShader((DWORD*)shaderBuffer->GetBufferPointer(), &BasicShader);

            1.4.3對著色器中的變量進行賦值

            1.3.4節(jié)說到著色器的全局變量在應(yīng)用程序中賦值而在著色器程序中使用,這是應(yīng)用程序和著色器通信的關(guān)鍵所在,這里就具體說明賦值過程。

            著色器中的全局變量在編譯后都被放在一個叫常量表的結(jié)構(gòu)中,我們可以使用ID3DXConstantTable接口對其進行訪問,參照1.4.1中編譯著色器函數(shù)D3DXCompileShaderFromFile的最后一個參數(shù),該參數(shù)即返回了指向常量表的指針。

            對一個著色器中變量進行賦值的步驟如下:

            1.       通過變量名稱得到指向著色器變量的句柄;

            還記得在BasicHLSL.x著色器文件中我們聲明的兩個全局變量嗎:

                    matrix WVPMatrix;

            vector color;

                          我們在應(yīng)用程序中相應(yīng)的聲明兩個句柄:

            D3DXHANDLE WVPMatrixHandle          = 0;

            D3DXHANDLE ColorHandle              = 0;

                          然后通過變量名得到分別得到對應(yīng)的兩個句柄:

                                 WVPMatrixHandle = BasicConstTable->GetConstantByName(0, "WVPMatrix");

                                 ColorHandle = BasicConstTable->GetConstantByName(0, "color");

            2.       通過句柄對著色器變量進行賦值;

            我們可以先設(shè)置各變量為默認(rèn)值:

                    BasicConstTable->SetDefaults(g_pd3dDevice);

            之后,可以使用ID3DXConstantTable::SetXXX函數(shù)對各個變量進行賦值:

            HRESULT SetXXX(

             LPDIRECT3DDEVICE9 pDevice,

             D3DXHANDLE hConstant,

             XXX value

            );

            其中XXX代表變量類型,例如Matrix類型的變量就要使用SetMatrix函數(shù)賦值,而Vector類型的則要使用SetVector來賦值。

            1.4.4把著色器設(shè)定到渲染管道中

                   這里我們使用SetVertexShader方法把頂點著色器設(shè)定到渲染管道中:

                          g_pd3dDevice->SetVertexShader(BasicShader);

            1.4.5整個渲染過程如下

            在渲染過程中,我們設(shè)定頂點的變換坐標(biāo)和顏色值,渲染代碼如下:

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

            D3DCOLOR_XRGB(153,153,153), 1.0f, 0 );

                //開始渲染

                g_pd3dDevice->BeginScene();

             

                //得到世界矩陣、觀察矩陣和投影矩陣

                D3DXMATRIX matWorld, matView, matProj;

                g_pd3dDevice->GetTransform(D3DTS_WORLD, &matWorld);

                g_pd3dDevice->GetTransform(D3DTS_VIEW, &matView);

                g_pd3dDevice->GetTransform(D3DTS_PROJECTION, &matProj);

             

                D3DXMATRIX matWVP = matWorld * matView * matProj;

                //通過句柄對著色器中的WVPMatrix變量進行賦值

                BasicConstTable->SetMatrix(g_pd3dDevice, WVPMatrixHandle, &matWVP);

               

                D3DXVECTOR4 color(1.0f, 1.0f, 0.0f, 1.0f);

                //通過句柄對著色器中的color變量進行賦值,這里我們賦值為黃色

                BasicConstTable->SetVector(g_pd3dDevice, ColorHandle, &color);

             

                //把頂點著色器設(shè)定到渲染管道中

                g_pd3dDevice->SetVertexShader(BasicShader);

             

                //繪制模型子集

                Teapot->DrawSubset(0);

             

                //渲染完畢

                g_pd3dDevice->EndScene();

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

             

                   編譯運行程序,運行效果如圖1.2所示,這里我們將頂點顏色設(shè)置為黃色,如果讀者在渲染過程中不斷變換對著色器變量color的賦值,你將會得到一個色彩不斷變幻的D3D茶壺。

            D3DXVECTOR4 color(1.0f, 1.0f, 0.0f, 1.0f); //讀者可以嘗試改變顏色值

            BasicConstTable->SetVector(g_pd3dDevice, ColorHandle, &color);

            1.2 著色器效果


            posted on 2008-08-04 12:28 狂爛球 閱讀(8406) 評論(1)  編輯 收藏 引用

            評論

            # re: HLSL初級教程(1) 2010-07-14 10:05 楊漱玉青

            Thanks~教程很棒~  回復(fù)  更多評論   


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


            久久性生大片免费观看性| 国产成人无码久久久精品一 | 亚洲国产精品人久久| 免费观看久久精彩视频| 看全色黄大色大片免费久久久| 亚洲国产美女精品久久久久∴| .精品久久久麻豆国产精品| 久久久久国产一级毛片高清板| 精品国产乱码久久久久久人妻| 9191精品国产免费久久| 一本色道久久99一综合| 久久影院午夜理论片无码 | 无码伊人66久久大杳蕉网站谷歌| .精品久久久麻豆国产精品| 欧美成人免费观看久久| 亚洲成人精品久久| 久久亚洲精品人成综合网| 人妻无码精品久久亚瑟影视| 国产91色综合久久免费| 伊色综合久久之综合久久| 麻豆精品久久精品色综合| 久久久无码人妻精品无码| 四虎国产精品成人免费久久| 久久精品亚洲男人的天堂| 久久婷婷国产麻豆91天堂| 精品免费久久久久久久| 99久久精品免费看国产一区二区三区| 91亚洲国产成人久久精品| 国产亚洲综合久久系列| 久久久老熟女一区二区三区| 亚洲精品无码久久千人斩| 亚洲精品蜜桃久久久久久| 2021国内久久精品| 久久人人爽人人人人片av| 久久综合色老色| 区久久AAA片69亚洲| 久久99精品久久久大学生| 久久久久久国产精品美女| 97久久国产综合精品女不卡| 久久午夜福利无码1000合集| 色天使久久综合网天天|