青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

永遠也不完美的程序

不斷學習,不斷實踐,不斷的重構……

常用鏈接

統計

積分與排名

好友鏈接

最新評論

HLSL初級教程(1)

作者:trcj

目錄

前言

1.HLSL入門

       1.1什么是著色器

       1.2什么是HLSL

       1.3怎么寫HLSL著色器

       1.4怎么用HLSL著色器

2.頂點著色器

       2.1可編程數據流模型

       2.2頂點聲明

       2.3用頂點著色器實現漸變動畫

3.像素著色器

       3.1多紋理化

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

       3.3應用程序

4.HLSL Effect(效果框架)

       4.1Effect代碼結構

       4.2Effect實現多紋理化效果

結語

參考資料

前言

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

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

       本文檔版權為作者所有,非商業用途可免費使用,轉載請注明出處。

      

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


1.HLSL入門

1.1什么是著色器

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

1.1 Direct3D Graphics Pipeline

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

1.       設定頂點、圖元、紋理等數據信息;

2.       設定管道狀態信息;

²        渲染狀態

通過SetRenderState方法設定渲染狀態;

另外,使用以下方法設置變換、材質和光照:

              SetTransform

              SetMaterial

SetLight

              LightEnable

²        取樣器狀態

通過SetSamplerState方法設定取樣器狀態;

²        紋理層狀態

通過SetTextureStageState設定紋理層狀態;

3.       渲染;

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

 

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

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

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

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

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

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

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


1.2什么是HLSL

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

HLSL的語法非常類似于CC++,學習起來是很方便的。


1.3怎么寫HLSL著色器

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

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

//

// 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是一個矩陣類型,它包含了世界、觀察、投影的合矩陣,用于對頂點進行坐標變換;

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

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

1.3.2輸入輸出

²        輸入輸出結構

程序中定義了兩個輸入輸出結構VS_INPUTVS_OUTPUT

struct VS_INPUT

{

       vector position : POSITION;

};

 

struct VS_OUTPUT

{

       vector position : POSITION;

       vector color : COLOR;

};

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

       vector position : POSITION;

²        標志符

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

Type VariableName : Semantic

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

vector position : POSITION;

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

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

1.3.3入口函數

       程序中還定義了一個函數SetColor

OUTPUT SetColor(INPUT input)

{

       VS_OUTPUT output = (VS_OUTPUT)0;

      

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

       output.color = color;

      

       return output;

}

1.       該函數以inputoutput類型作為輸入輸出;

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

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

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

output.color = color;

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

 

1.3.4總結

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

1.       全局變量WVPMatrixcolor將在應用程序中被賦值;

2.       入口函數SetColor被調用編譯器根據標志符將頂點信息填充到VS_INPUT中的各個字段;

3.       SetColor函數中,首先定義一個VS_OUTPUT信息,之后根據WVPMatrixcolor變量完成頂點的坐標變換和顏色設定操作,最后函數返回VS_OUTPUT結構;

4.       編譯器將會再次根據標志符把返回的VS_OUTPUT結構中的各字段映射為頂點相應的信息。

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

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


1.4怎么用HLSL著色器

應用程序中對HLSL著色器的使用分為以下步驟:

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

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

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

4.       把著色器設定到渲染管道中;

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

 

1.4.1聲明全局變量

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

 

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

D3DXHANDLE WVPMatrixHandle          = 0;

D3DXHANDLE ColorHandle              = 0;

 

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

 

1.4.2編譯著色器

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

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

       ID3DXBuffer* shaderBuffer      = 0;

       //用于接受錯誤信息

       ID3DXBuffer* errorBuffer       = 0;

 

       //編譯著色器代碼

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

                                                  0,

                                                  0,

                                                  "SetColor", //入口函數名稱

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

                                                  D3DXSHADER_DEBUG,// Debug模式編譯      

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

                                                  &errorBuffer,

                                                  &BasicConstTable); //常量表指針

1.4.3創建著色器

       應用程序通過CreateVertexShader創建一個頂點著色器,注意使用了上一步得到的shaderBuffer

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

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

1.3.4節說到著色器的全局變量在應用程序中賦值而在著色器程序中使用,這是應用程序和著色器通信的關鍵所在,這里就具體說明賦值過程。

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

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

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

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

        matrix WVPMatrix;

vector color;

              我們在應用程序中相應的聲明兩個句柄:

D3DXHANDLE WVPMatrixHandle          = 0;

D3DXHANDLE ColorHandle              = 0;

              然后通過變量名得到分別得到對應的兩個句柄:

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

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

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

我們可以先設置各變量為默認值:

        BasicConstTable->SetDefaults(g_pd3dDevice);

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

HRESULT SetXXX(

 LPDIRECT3DDEVICE9 pDevice,

 D3DXHANDLE hConstant,

 XXX value

);

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

1.4.4把著色器設定到渲染管道中

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

              g_pd3dDevice->SetVertexShader(BasicShader);

1.4.5整個渲染過程如下

在渲染過程中,我們設定頂點的變換坐標和顏色值,渲染代碼如下:

    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);

 

    //把頂點著色器設定到渲染管道中

    g_pd3dDevice->SetVertexShader(BasicShader);

 

    //繪制模型子集

    Teapot->DrawSubset(0);

 

    //渲染完畢

    g_pd3dDevice->EndScene();

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

 

       編譯運行程序,運行效果如圖1.2所示,這里我們將頂點顏色設置為黃色,如果讀者在渲染過程中不斷變換對著色器變量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 狂爛球 閱讀(8552) 評論(1)  編輯 收藏 引用

評論

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

Thanks~教程很棒~  回復  更多評論   


只有注冊用戶登錄后才能發表評論。
網站導航: 博客園   IT新聞   BlogJava   博問   Chat2DB   管理


青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            国产精品久久久久久模特| 在线日本成人| 国产一区二区精品丝袜| 亚洲一区二三| 亚洲国产综合91精品麻豆| 久久本道综合色狠狠五月| 欧美午夜大胆人体| 亚洲影音先锋| 亚洲视频一区在线观看| 欧美午夜在线观看| 一区二区三区欧美在线| 最新国产成人在线观看| 欧美国产精品一区| 亚洲人成毛片在线播放| 亚洲黄色尤物视频| 欧美日韩一区在线观看视频| 亚洲一级黄色| 亚洲午夜精品视频| 国产精品视频xxx| 欧美一区二区三区视频免费| 亚洲欧美日韩网| 狠久久av成人天堂| 亚洲电影免费在线观看| 你懂的视频欧美| 一区二区三区国产精品| 在线综合+亚洲+欧美中文字幕| 欧美日韩性视频在线| 亚洲一区二区三区免费在线观看| 亚洲天堂av在线免费观看| 国产欧美日韩亚洲精品| 久久免费视频在线观看| 欧美大片一区二区三区| 欧美夜福利tv在线| 91久久嫩草影院一区二区| 欧美肥婆在线| 亚洲一区二区免费| 欧美在线观看一区二区| 亚洲黄一区二区三区| 亚洲裸体俱乐部裸体舞表演av| 欧美日韩国产一区二区三区| 欧美一区二区久久久| 久久综合九色欧美综合狠狠| 9色porny自拍视频一区二区| 亚洲视频精品| 亚洲高清色综合| 亚洲精品一区二区三区福利| 国内精品伊人久久久久av一坑| 亚洲欧洲偷拍精品| 国产一区二区视频在线观看| 亚洲国产一区二区三区青草影视 | 亚洲国产91精品在线观看| 欧美另类videos死尸| 久久国内精品视频| 欧美激情精品久久久久| 亚洲欧美中文在线视频| 欧美gay视频| 久久精品午夜| 欧美新色视频| 欧美激情区在线播放| 国产欧美在线播放| 日韩视频在线观看| 亚洲品质自拍| 久久亚洲欧洲| 久久九九免费视频| 欧美午夜一区二区| 亚洲激情不卡| 伊人婷婷久久| 欧美一级播放| 午夜国产精品视频免费体验区| 欧美国产另类| 欧美xx视频| 国产一区二区三区日韩| 在线视频精品一| 在线亚洲精品| 欧美日韩国产123| 欧美激情视频一区二区三区不卡| 国内精品久久久久影院 日本资源 国内精品久久久久伊人av | 国产精品美女久久| 亚洲激情女人| 亚洲欧洲另类| 男人的天堂亚洲在线| 久久伊人精品天天| 国产亚洲一级高清| 欧美综合国产| 久久国产精品第一页| 国产精品毛片va一区二区三区| 亚洲片在线资源| 亚洲欧洲一区二区在线播放| 久久精品99国产精品日本| 久久激情综合| 红桃视频一区| 亚洲国产福利在线| 欧美激情一区二区三区高清视频 | 欧美一区二区三区在线看| 亚洲尤物视频网| 国产精品成人免费| 亚洲一区二区在线看| 亚洲欧美第一页| 国产精品一区二区黑丝| 午夜精品久久久久久久| 久久精品国产一区二区三| 国产日韩精品视频一区二区三区 | 亚洲欧洲精品一区二区三区| 欧美国产视频日韩| 99精品国产一区二区青青牛奶| 亚洲在线中文字幕| 国产亚洲欧美一区二区三区| 欧美综合国产精品久久丁香| 久久精品成人欧美大片古装| 狠狠做深爱婷婷久久综合一区 | 一本久久精品一区二区| 国产精品成人播放| 午夜精品一区二区三区电影天堂| 欧美专区在线观看| 亚洲国产成人精品久久久国产成人一区 | 亚洲日本在线观看| 亚洲男女自偷自拍| 黄色成人av网| 欧美日韩精品在线播放| 中国成人黄色视屏| 久久人人超碰| 9色porny自拍视频一区二区| 国产精品久久久久久久久搜平片 | 久久看片网站| 亚洲欧洲一区二区在线播放| 欧美性感一类影片在线播放 | 在线观看精品| 国产精品videosex极品| 久久久久久穴| 亚洲视频在线观看| 欧美福利电影网| 亚洲欧美日韩在线不卡| 1000部国产精品成人观看| 欧美日韩免费一区二区三区视频| 久久高清国产| 日韩视频国产视频| 免费成人在线观看视频| 亚洲一区在线观看免费观看电影高清| 国产日韩精品入口| 欧美日韩国产电影| 久久夜色精品国产亚洲aⅴ| 亚洲香蕉网站| 亚洲高清色综合| 久久精品系列| 亚洲字幕一区二区| 亚洲精品国精品久久99热| 国内久久视频| 国产精品美女主播| 欧美另类一区二区三区| 久久另类ts人妖一区二区| 亚洲欧美日韩国产综合| 加勒比av一区二区| 另类天堂av| 午夜精品三级视频福利| 日韩视频中文字幕| 亚洲国产精品专区久久| 久久人人九九| 久久久久久久久蜜桃| 欧美一区二区免费视频| 亚洲婷婷综合久久一本伊一区| 亚洲大片精品永久免费| 国内成+人亚洲| 国产伦精品一区| 国产精品久久久久久久久久尿| 农夫在线精品视频免费观看| 久久久久久久一区二区| 久久av一区二区| 久久激情五月丁香伊人| 欧美一区二视频在线免费观看| 亚洲一区二区成人在线观看| 亚洲视频一区二区免费在线观看| 91久久精品网| 亚洲美女av黄| 99精品视频免费全部在线| 亚洲精品在线观看免费| 亚洲乱码国产乱码精品精98午夜| 亚洲大黄网站| 亚洲精品三级| 一本一本a久久| 亚洲私人影吧| 亚洲免费伊人电影在线观看av| 夜夜狂射影院欧美极品| 宅男精品视频| 午夜免费日韩视频| 久久精品国产清高在天天线| 欧美淫片网站| 老司机成人网| 欧美精品123区| 欧美日韩免费观看一区| 欧美三级中文字幕在线观看| 国产精品国产三级国产专播精品人| 国产精品高潮视频| 国产欧美一区二区三区另类精品| 国产麻豆日韩欧美久久| 国产一区在线免费观看| 亚洲激情另类| 亚洲欧美国产日韩天堂区| 久久久精品国产免费观看同学| 美女精品网站| 亚洲免费电影在线|