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

永遠也不完美的程序

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

常用鏈接

統計

積分與排名

好友鏈接

最新評論

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>
            久久一区视频| 影音先锋国产精品| 亚洲电影一级黄| 国产日韩欧美在线观看| 国产伦精品一区二区三区| 欧美区亚洲区| 亚洲国产日韩美| 久久美女性网| 在线视频中文亚洲| 欧美日韩一区二区视频在线| 国产日韩欧美在线一区| 嫩草影视亚洲| 亚洲黄色性网站| 欧美日韩精品欧美日韩精品 | 午夜精品一区二区三区在线视 | 午夜精品福利在线| 免费成人在线视频网站| 久久久久久精| 国产亚洲女人久久久久毛片| 欧美中文在线免费| 国产精品日韩久久久| 亚洲欧美成人一区二区三区| 亚洲视频在线一区| 国产欧美日韩激情| 欧美成人小视频| 欧美激情一区二区在线 | 午夜在线精品偷拍| 激情亚洲网站| 欧美精品一区二区蜜臀亚洲| 影音先锋中文字幕一区| 亚洲一二区在线| 日韩视频一区二区三区在线播放免费观看| 美女黄网久久| 日韩一区二区高清| 亚洲专区一二三| 国产亚洲精品aa| 欧美成人a视频| 免费观看国产成人| 一区二区三区高清在线| 欧美午夜久久久| 亚洲欧洲在线视频| 欧美日韩亚洲高清一区二区| 一区二区激情| 亚洲一区二区三区精品在线| 国内精品久久久久久久97牛牛| 免费日韩成人| 欧美日一区二区三区在线观看国产免| 亚洲专区国产精品| 久久久91精品国产| 国产精品99久久久久久人| 亚洲一区二区黄色| 亚洲国产精品悠悠久久琪琪| 一二美女精品欧洲| 亚洲电影免费观看高清完整版在线 | 亚洲国产一区二区三区在线播| 欧美涩涩网站| 亚洲四色影视在线观看| 欧美尤物一区| 久久久久久黄| 狠狠色噜噜狠狠狠狠色吗综合| 一本色道久久| 久久九九久精品国产免费直播| 国产精品乱码妇女bbbb| 亚洲午夜精品| 亚洲一区精品电影| 亚洲一级在线观看| 欧美在线首页| 欧美成人免费va影院高清| 亚洲最新视频在线播放| 欧美在线国产| 宅男噜噜噜66国产日韩在线观看| 欧美一区2区三区4区公司二百| 亚洲欧洲日本mm| 欧美一级二级三级蜜桃| 中国亚洲黄色| 美女黄毛**国产精品啪啪| 久久国产精品99精品国产| 欧美人与性动交α欧美精品济南到| 久久精品视频免费播放| 国产精品ⅴa在线观看h| 亚洲日本欧美日韩高观看| 国外成人在线| 午夜影院日韩| 午夜伦理片一区| 欧美视频观看一区| 亚洲区欧美区| 亚洲精品资源| 欧美激情在线狂野欧美精品| 免费试看一区| 在线观看欧美黄色| 久久久久久综合网天天| 久久影院亚洲| 经典三级久久| 久久人人爽人人爽爽久久| 久久久久九九九| 国模精品一区二区三区色天香| 亚洲欧美资源在线| 欧美一级播放| 国产丝袜一区二区| 久久er99精品| 麻豆精品国产91久久久久久| 国内综合精品午夜久久资源| 久久狠狠婷婷| 美女黄毛**国产精品啪啪| 亚洲高清在线视频| 欧美成人精品三级在线观看| 亚洲国产另类精品专区| 亚洲精品午夜| 欧美日韩一区二区三区免费| 99re热精品| 亚洲欧美日韩一区二区在线| 国产乱码精品一区二区三区忘忧草 | 亚洲综合大片69999| 欧美激情在线| 在线国产日韩| 亚洲精品免费一区二区三区| 久久精品综合一区| 这里只有视频精品| 日韩一区二区久久| 亚洲欧美日韩电影| 久久爱www| 欧美日韩在线精品| 欧美日韩极品在线观看一区| 欧美激情一区二区三区在线视频| 欧美极品aⅴ影院| 久久婷婷亚洲| 欧美精品系列| 亚洲电影在线免费观看| 蜜乳av另类精品一区二区| 国产精品色午夜在线观看| 免费影视亚洲| 亚洲国产99| 久久久久9999亚洲精品| 好看的亚洲午夜视频在线| 久久免费视频网站| 亚洲全黄一级网站| 久久国产免费| 亚洲久久一区二区| 国产日韩欧美一区二区| 免费中文字幕日韩欧美| 亚洲欧美日韩国产一区二区三区| 麻豆久久精品| 亚洲欧美国产va在线影院| 影音先锋久久久| 国产精品大全| 美国十次成人| 欧美专区第一页| 99国产精品久久久| 噜噜噜久久亚洲精品国产品小说| 亚洲天堂免费在线观看视频| 黄色精品一区二区| 亚洲国产一区二区视频| 亚洲女优在线| 女女同性女同一区二区三区91| 欧美日韩免费区域视频在线观看| 免费观看一区| 99热免费精品| 国产精品女主播在线观看| 久久精品成人一区二区三区| 午夜久久电影网| 欧美午夜精品理论片a级按摩 | 久久久91精品国产一区二区精品| 国内自拍一区| 欧美日韩精品久久| 欧美va天堂| 久久在线视频在线| 午夜精品短视频| 亚洲一区二区在线视频| 日韩一本二本av| 亚洲毛片网站| 亚洲人成人一区二区在线观看| 老司机精品福利视频| 久久久国产精品亚洲一区 | 欧美亚洲综合网| 亚洲视频在线播放| 一二三区精品福利视频| 最近中文字幕mv在线一区二区三区四区| 国产一区清纯| 国内一区二区三区在线视频| 国产亚洲成av人片在线观看桃| 国产精品v欧美精品v日本精品动漫 | 午夜精品一区二区三区四区 | 国产精品爽爽ⅴa在线观看| 国产精品高潮呻吟视频| 国产精品播放| 国产麻豆综合| 激情另类综合| 蜜桃久久av| 亚洲视频中文字幕| 亚洲午夜av| 午夜久久一区| 久久久久高清| 蜜桃av一区二区在线观看| 亚洲美女啪啪| 韩日视频一区| 国产美女精品免费电影| 91久久精品日日躁夜夜躁国产| 91久久精品久久国产性色也91| 亚洲日本久久| 亚洲视频在线一区|