進階著色語言HLSL入門(1)

來源:互聯網
上載者:User
進階著色語言HLSL入門(1)

在我們寫的程式裡頂點和像素是很小的對象,它們由GPU來執行,是固定功能管線的一部分。用我們自己寫的著色器程式替換一部分固定功能管線,在繪製效果上我們獲得很大的靈活性。我們不再局限於預定義的"固定"操作。

為了編寫著色器程式,我們需要一種進階著色器語言(High-Level Shading Language ,簡稱HLSL)。 在DirectX 8中,著色器是用低級著色器組合語言編寫的。幸運的是,我們不必再用組合語言來寫著色器了,DirectX 9支援一種進階著色器語言來寫。用HLSL寫著色器程式與使用進階語言有同樣的優勢,像C++,它超越了組合語言,即:

增加生產力—用進階語言比用低級語言寫程式更快、更容易。 我們可以花費更多的時間關注於演算法而不是代碼。

增加可讀性—用進階語言寫的程式更易讀,這意味著用進階語言編程更易於調試和維護。

大多數情況下,編譯器產生的彙編代碼比手寫有效率。

使用HLSL 編譯器,我們可以編譯我們的代碼到任何可用shader版本,使用組合語言我們將不得不為每個需要的版本移植代碼。

HLSL 同C和C++文法很類似,所以縮短了學習曲線。

最後,如果你的顯卡不支援頂點和像素著色器的話,為了執行著色器的例子程式你將需要轉換REF裝置。使用REF裝置意味著著色器例子啟動並執行會很慢,但它至少能顯示結果,讓我們去檢查是否代碼可以被執行。

提示:頂點shaders可以用軟體來類比 ―― D3DCREATE_SOFTWARE_VERTEX-PROCESSING。


16.1編寫HLSL 著色器

我們可以在程式源檔案中用長字串直接編寫HLSL著色器代碼,然而更方便、更模組化的方法是把它與程式碼分離出來。因此,我們在記事本中編寫著色器並儲存成一般的ASCII文字檔,然後可以用D3DXCompileShaderFromFile函數(section 16.2.2)來編譯它們。

作為介紹,下面是用HLSL編寫的一個簡單的頂點著色器,用記事本產生並儲存成文字檔“VertexShader.cxx”。頂點著色器用複合檢視和投影矩陣轉換頂點,並設定頂點漫射光為紅色。

注意:這是一個頂點著色器的例子,不必關心頂點著色器做了什麼,現在的目標是熟悉HLSL編程的文法和格式。

      /************************************************************************************
      Vertex shader that transforms a vertex by the view and projection transformation, 
      and sets the vertex color to red.
     ************************************************************************************/
   
        // Global variable to store a combined view and projection transformation matrix,
    // we initialize this variable from the application.
    matrix g_view_proj_matrix;
   
        // initialize a global blue color vector
    const vector RED = {1.0f, 0.0f, 0.0f, 1.0f};
   
        // Input structure describes the vertex that is input into the shader.
    // Here the input vertex contains a position component only.
    struct sVertexInput
    {
        vector position : POSITION;
    };
   
        // Output structure describes the vertex that is output from the shader.
    // Here the output vertex contains a position and color component.
    struct sVertexOutput
    {
        vector position : POSITION;
        vector diffuse  : COLOR;
    };
   
        // Main Entry point, observe the main function receives a copy of the input vertex through
    // its parameter and returns a copy of the output vertex it computes.
    sVertexOutput main(sVertexInput input)
    {
        // zero out members of output
            sVertexOutput output = (sVertexOutput)0;
   
        // transform to view space and project
            output.position = mul(input.position, g_view_proj_matrix);
   
        // set vertex diffuse color to blue
        output.diffuse = RED;
   
        return output;
    }16.1.1 全域變數

首先是2個全域變數:
// Global variable to store a combined view and projection transformation matrix.
// We initialize this variable from the application.
matrix g_view_proj_matrix;

// Initialize a global blue color vector.
const vector BLUE = {0.0f, 0.0f, 1.0f, 1.0f};

第1個變數g_view_proj_matrix是矩陣類型,它是一個在HLSL內建立的4×4的矩陣類型。這個變數儲存視圖與投影的組合矩陣,它描述兩者的變換。使用這種方法我們只要做一個向量和矩陣的乘法(而不是二個)。注意,在著色器原始碼的任何地方都沒有初始化這個變數,因為它是我們在應用程式的原始碼裡設定的,而不是在著色器中。從應用程式向著色器程式通訊是常用的操作。

第二個變數BLUE是built-in(內建)類型的4D向量,我們簡單的將它初始化成藍色,它是個RGBA的顏色向量。

 

16.1.2 輸入和輸出結構

在全域變數定義之後,定義2個特殊的結構,我們調用輸入和輸出結構。對於頂點著色器而言,這些結構定義了頂點的資料,分別是:
// Input structure describes the vertex that is input into the shader.
// Here the input vertex contains a position component only.
struct sVertexInput
{
  vector position : POSITION;
};

// Output structure describes the vertex that is output from the shader.
// Here the output vertex contains a position and color component.
struct sVertexOutput
{
  vector position : POSITION;
  vector diffuse : COLOR;
};

 

注意:給像素著色器的結構定義輸入和輸出像素資料。

在例子中,INPUT 頂點著色器只包含位置成員(POSITION),OUTPUT頂點著色器包含位置和顏色成員(POSITION and COLOR)。

特殊的冒號是一種語義,用於是聲明變數。這與vertex結構中的自由頂點格式(FVF)相似。例如,在sVertexInput中有成員:vector position : POSITION;

": COLOR"是說頂點的漫射光是用sVertexOutput結構的COLOR成員來說明的。
注意:從底層來說,著色器變數的語義和文法同硬體寄存器是相關聯的。即,input變數與input寄存器關聯,output變數與output寄存器關聯。例如,sVertexInput中的position成員與頂點input的position寄存器相關聯。同樣,diffuse與頂點的output的color寄存器關聯。

 

16.1.3 函數的進入點

在C++程式中,每個HLSL程式有一個進入點。在我們的著色器例子中,我們調用進入點函數main。然而名字不是強制的。進入點函數名可以是任何有效函數名,進入點函數必須有一個input結構參數,它通過input頂點進入著色器。進入點函數必須返回一個output結構執行個體,在著色器中使用output操作頂點。

sVertexOutput main(sVertexInput input)
{

 注意:實際上,使用input、output結構不是強制的。例如,有時你將會看到使用類似下面的文法,特別是在像素著色器中:

 

float4 Main(in float2 base : TEXCOORD0,

            in float2 spot : TEXCOORD1,

            in float2 text : TEXCOORD2) : COLOR

{

...

}

 

例子中,輸入到著色器中的參數是3個紋理座標。著色器輸出(返回)一個顏色,COLOR語句在函數的聲明以後。這種定義是類似於:

 

struct INPUT

 

{

     float2 base : TEXCOORD0;

     float2 spot : TEXCOORD1;

     float2 text : TEXCOORD2;

};

 

struct OUTPUT

{

     float4 c : COLOR;

};

 

OUTPUT Main(INPUT input)

{

...

}

 

輸入焦點函數負責根據給定的input頂點計算output頂點。例子中的著色器簡單的變換input頂點到視圖空間和投影空間,設定頂點顏色為紅色,並返回結果頂點。首先我們定義sVertexOutput的執行個體並初始化所有成員為0。

// zero out members of output
sVertexOutput output = (sVertexOutput)0;
 

然後著色器變換input頂點位置用g_view_proj_matrix變數,使用mul函數。它是一個built-in(內建)函數,實現向量與矩陣相乘,或矩陣與矩陣相乘。我們儲存結果變換的向量(在output執行個體的position成員中)。

// transform to view space and project
output.position = mul(input.position, g_view_proj_matrix);


然後設定output的成員diffuse的顏色為紅色:

// set vertex diffuse color to red
output.diffuse = RED;

 

最後返回結果向量:

return output;
}

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.