1. 程式人生 > >Shader學習之Cg語言二(Cg資料型別)

Shader學習之Cg語言二(Cg資料型別)

由於在用Cg語言寫程式碼的時候,沒有好用的編輯器,也不可以像Java,C++,C#這類語言的斷點除錯,所有邏輯需要寫得很小心,變數名字也需要自己全部記住,相當於在文字編輯器上寫程式碼,這樣一些資料型別名稱很容易寫錯,因此我記錄下來,當自己忘記後方便查詢。

Cg基本資料型別

Cg 支援 7 種基本的資料型別:
1. float : 32 位浮點資料,一個符號位。浮點資料型別被所有的 profile 支援(但是 DirectX8 pixel profiles 在一些操作中降低了浮點數的精度和範圍);
2. half : 16 為浮點資料;
3. int : 32 位整形資料,有些 profile 會將 int 型別作為 float 型別使用;
4. fixed

: 12 位定點數,被所有的 fragment profiles 所支援;
5. bool: 布林資料,通常用於 if 和條件操作符( ?: ),布林資料型別被所有的profiles 支援;
6. sampler* :紋理物件的控制代碼( the handle to a texture object ),分為 6 類:sampler, sampler1D, sampler2D, sampler3D, samplerCUBE, 和 samplerRECT 。DirectX profiles 不支援 samplerRECT 型別,除此之外這些型別被所有的 pixelprofiles和 NV40 vertex program profile 所支援。
7. string
:字元型別,該型別不被當前存在的 profile 所支援,實際上也沒有必要在 Cg 程式中用到字元型別,但是你可以通過 Cg runtime API 宣告該型別變數,並賦值;因此,該型別變數可以儲存 Cg 檔案的資訊。

除了上面的基本資料型別外, Cg還提供了內建的向量資料型別 (built-in vector data types) ,內建的向量資料型別基於基礎資料型別。例如:float4,表示 float 型別的 4 元向量;bool4,表示 bool型別 4 元向量。
注意:向量最長不能超過 4 元,即在 Cg 程式中可以宣告 float1 、 float2 、float3 、float4 型別的陣列變數,但是不能宣告超過 4 元的向量,例如:

float5 array;//編譯報錯

向量初始化方式一般為:

float4 array = float4(1.0, 2.0, 3.0, 4.0);

較長的向量還可以通過較短的向量進行構建:

float2 a = float2(1.0, 1.0);
float4 b = float4(a, 0.0, 0.0);

此外, Cg 還提供矩陣資料型別,不過最大的維數不能超過 4*4 階。例如:

float1x1 matrix1;//等價於 float matirx1; x 是字元,並不是乘號!
float2x3 matrix2;// 表示 2*3 階矩陣,包含 6 個 float 型別資料
float4x2 matrix3;// 表示 4*2 階矩陣,包含 8 個 float 型別資料
float4x4 matrix4;//表示 4*4 階矩陣,這是最大的維數
矩陣

的初始化方式為:

float2x3 matrix5 = {1.0, 2.0, 3.0, 4.0, 5.0, 6.0};

注意: Cg 中向量、矩陣與陣列是完全不同,向量和矩陣是內建的資料型別(矩陣基於向量),而陣列則是一種資料結構,不是內建資料型別!這一點和C\C++ 中不太一樣,在 C\C++ 中,這三者同屬於資料結構,陣列可以構建向量和矩陣。

Cg陣列型別

在著色程式中,陣列通常的使用目的是:作為從外部應用程式傳入大量引數到 Cg 的頂點程式中的形參介面,例如與面板形變相關的矩陣陣列,或者光照引數陣列等。簡而言之,陣列資料型別在 Cg 程式中的作用是:作為函式的形參,用於大量資料的轉遞。
Cg 中宣告陣列變數的方式和 C 語言類似:例如:

float a[10];//聲明瞭一個數組,包含 10 個 float 型別資料
float4 b[10];//聲明瞭一個數組,包含 10 個 float4 型別向量資料

對陣列進行初始化的方式為:

float a[4] = {1.0, 2.0, 3.0, 4.0}; //初始化一個數組

要獲取陣列長度,可以呼叫“ .length ”,例如:

float a[10]; //宣告一個數組
int length = a.length;//獲取陣列長度

宣告多維陣列以及初始化的方式如下所示:

float b[2][3] = {{0.0, 0.0, 0.0},{1.0, 1.0, 1.0}};

對多維陣列取長度的方式為:

int length1 = b.length; // length1 值為 2
int length2 = b[0].length; // length2 值為 3

陣列和矩陣有些類似,但是並不是相同。 例如 4*4 階陣列的的宣告方式為:float M[4][4];4 階矩陣的宣告方式為: float4x4 M 。前者是一個數據結構,包含 16個 float 型別資料,後者是一個 4 階矩陣資料。 float4x4 M[4] ,表示一個數組,包含 4 個 4 階矩陣資料。進行陣列變數宣告時,一定要指定陣列長度,除非是作為函式引數而宣告的形引數組。並且在當前的 profiles 中,陣列的長度和所引用的陣列元素的地址必須在編譯時就知道。

Cg結構型別

Cg 語言支援結構體( structure ),實際上 Cg 中的結構體的宣告、使用和 C++非常類似(只是類似,不是相同)。一個結構體相當於一種資料型別,可以定義該型別的變數。引入結構體機制,賦予了 Cg 語言一絲面向物件的色彩。不過目前的 Cg 語言中的結構體以展現 “ 封裝 ” 功能為主,並不支援繼承機制。

結構體的宣告以關鍵字 struct 開始,然後緊跟結構體的名字,接下來是一個大括號,並以分號結尾(不要忘了分號)。大括號中是結構體的定義,分為兩大類:成員變數和成員函式。例如,定義一個名為 myAdd 的結構體,包含一個成員變數,和一個執行相加功能的成員函式,然後宣告一個該結構體型別的變數,
程式碼為:

struct myAdd
{
    float val;
    float add(float x)
    {
        return val + x;
    }
};
myAdd s;

使用符號“ • ”引用結構體中的成員變數和成員函式。例如:

float a = s.value;
float b = s.add(a);

注意:在當前的所有的 profile 版本下,如果結構體的一個成員函式使用了成員變數,則該成員變數要宣告在前。此外,成員函式是否可以過載依賴於使用的 profile 版本一般來說 ,Cg 的原始碼都會在檔案首部定義二個結構體,分別用於定義輸人和輸出的型別,這二個結構體定義與普通的 C 結構定義不同,除了定義結構體成員的資料型別外,還定義了該成員的繫結語義型別 ( Binding Semantics) ,所謂繫結語義型別是為了與宿主環境進行資料交換的時候識別不同資料型別的。目前Cg 支援的繫結語義型別包括 POSTION(位置) , COLOR( 顏色 ) , NORMAL( 法向量 ) , Texcoord( 紋理座標 ) 等型別。當頂點著色程式向片段著色程式傳遞的資料型別較多的情況下,使用結構體可以大大的方便程式碼的編寫和維護。

Cg型別轉換

Cg 中的型別轉換和 C 語言中的型別轉換很類似。 C 語言中型別轉換可以是強制型別轉換,也可以是隱式轉換,如果是後者,則資料型別從低精度向高精度轉換。在 Cg 語言中也是如此。例如:

float a = 1.0;
half b = 2.0;
float c = a+b; //等價於 float c = a + (float)b;

當有型別變數和無型別常量資料進行運算時,該常量資料不做型別轉換,舉
例如下:

float a = 1.0;
float b = a + 2.0; //2.0 為無型別常量資料,編譯時作為 float 型別

Cg 語言中對於常量資料可以加上型別字尾,表示該資料的型別,例如:

float a = 1.0;
float b = a + 2.0h; //2.0h 為 half 型別常量資料,運算是需要做型別轉換

常量的型別字尾( type suffix )有 3 種:
f :表示 float;
h:表示 half;
x:表示 fixed