Unity Shader (二)Cg語言


一、Cg基本數據類型

float 32位浮點數
half 16位浮點數
int 32位整型
fixed 12位定點數
bool 布爾數據
simpler* 紋理對象的句柄( the handle to a texture object ) ,分為 6 類:
sampler, sampler1D, sampler2D, sampler3D, samplerCUBE, 和 samplerRECT 
string 字符類型(幾乎不使用)
例如float4,bool4等

向量數據類型,向量長度不能超過4元,可以有float1,float2,float3,float4,沒有float5及以上

例如float4x4,float2x3等

矩陣數據類型,最大維數不超過4*4階矩陣

計算機中的數除了整數之外,還有小數。如何確定小數點的位置呢?通常有兩種方法:

一種是規定小數點位置固定不變,稱為定點數。

另一種是小數點的位置不固定,可以浮動,稱為浮點數。

在計算機中,通常是用定點數來表示整數和純小數,分別稱為定點整數和定點小數。對於既有整數部分、又有小數部分的數,一般用浮點數表示。

類型轉換:
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 類型常量數據,運算是需要做類型轉換  
 
常量的類型后綴有3種:
f:表示float
h:表示half
x:表示fixed

二、數組

 數組數據類型在Cg中的作用:作為函數的形參,用於大量數據的傳遞,例如:頂點參數數組、光照參數數據等。
 
 一維數組:
float a[10];//聲明了一個數組,包含 10 個 float 類型數據  
float a[4] = {1.0, 2.0, 3.0, 4.0}; //初始化一個數組  
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  
 

三、結構體

結構體的聲明以關鍵字 struct 開始,然后緊跟結構體的名字,接下來是一個大括號,並以分號結尾(不要忘了分號) 。大括號中是結構體的定義,分為兩大類:成員變量和成員函數。例如:

struct myAdd  

{  

    float val;  

    float add(float x)  

    {  

        return val + x;  

    }  

};  

myAdd s;  

使用符號“.”引用結構體的成員變量和成員函數:

float a = s.value;  

float b = s.add(a);  

 一般來說 ,Cg 的源代碼都會在文件首部定義二個結構體,分別用於定義輸人和輸出的類型,這二個結構體定義與普通的 C 結構定義不同,除了定義結構體成員的數據類型外,還定義了該成員的綁定語義類型( Binding Semantics) ,所謂綁定語義類型是為了與宿主環境進行數據交換的時候識別不同數據類型的。 目前Cg 支持的綁定語義類型包括 POSTION 位置 ) , COLOR( 顏色 ) , NORMAL( 法向量 ) , Texcoord( 紋理坐標 ) 等類型。

 

四、Cg語言操作符

1、關系操作符

小於

<=

小於或等於

!=

不等於

==

等於

>=

大於或等於

>

大於

2、邏輯操作符

&&

邏輯與

||

邏輯或

!

邏輯非

3、數學操作符

 * 乘法; / 除法; - 取反; + 加法;- 減法; % 求余; ++ ;--; *= ; /= ; += ; -= ;

需要注意的是:求余操作符 % 。只能在 int 類型數據間進行

 4、移位操作符

Cg 語言中的移位操作符,功能和 C 語言中的一樣,也可以作用在向量上,但是向量類型必須是 int 類型。例如:

 int2 a = int2(0.0,0.0);

int2 b = a>>1;

5、Swizzle 操作符

可以使用 Cg 語言中的 swizzle 操作符( . )將一個向量的成員取出組成一個新的向量。 swizzle 操作符被 GPU 硬件高效支持。 swizzle 操作符后接 x 、 y 、 z 、 w ,分別表示原始向量的第一個、第二個、第三個、第四個元素; swizzle操作符后接 r 、 g 、 b 和 a 的含義與前者等同。不過為了程序的易讀性,建議對於表示顏色值的向量,使用 swizzle 操作符后接 r 、 g 、 b 和 a 的方式。

舉例如下:

float4(a, b, c, d).xyz    等價於   float3(a, b, c)

float4(a, b, c, d).xyy    等價於   float3(a, b, b)

float4(a, b, c, d).wzyx   等價於   float4(d, c, b, a)

float4(a, b, c, d).w      等價於   float d

值得注意的是, Cg 語言中 float a 和 float1 a 是基本等價的,兩者可以進行類型轉換; float 、 bool 、 half 等基本類型聲明的變量也可以使用 swizzle 操作符。例如:

 float a = 1.0;

float4 b = a.xxxx;

 注意: swizzle 操作符只能對結構體和向量使用,不能對數組使用,如果對數組使用 swizzle 操作符則會出現錯誤信息: error C1010: expression left of . ” x ” is not a struct or array (其實個人覺得,提示的錯誤信息中 array 換成vector 更加合適)。

要從數組中取值必須使用 [] 符號。例如:

 float a[3] = {1.0,1.0,0.0};

float b = a[0]; // 正確

float c = a.x; // 編譯會提示錯誤信息

6、條件操作符

條件操作符的語法格式為: expr1 ? expr2 : expr3;

expr1 的計算結果為 true 或者 flase ,如果是 true, 則 expr2 執行運算,否則 expr3 被計算。

五、控制流語句

條件語句有: if 、 if-else ;循環語句有: while 、 for 。 break 語句可以和在 for 語句中使用。

六、函數

1、入口函數

由於着色程序分為頂點程序和片段程序,兩者對應的圖形流水線上的不同階段,所以這兩個程序都各有一個入口函數。

struct C2E1v_Output {

  float4 position : POSITION;

  float3 color    : COLOR;

};

 C2E1v_Output C2E1v_green(float2 position : POSITION)

{    

  C2E1v_Output OUT;

  OUT.position = float4(position,0,1);

  OUT.color = float3(0,1,0);

 return OUT;    

}

2、Cg標准函數庫
數學函數
abs(x) 返回輸入參數的絕對值
acos(x) 反余切函數,輸入參數范圍為[-1,1], 返回[0,π]區間的角度值
all(x) 如果輸入參數均不為0,則返回ture; 否則返回flase。&&運算
any(x) 輸入參數只要有其中一個不為0,則返回true。
asin(x) 反正弦函數,輸入參數取值區間為[1,1],返回角度值范圍為, [π2,π2]
atan(x) 反正切函數,返回角度值范圍為[π2,π2]
atan2(y,x) 計算y/x的反正切值。實際上和atan(x)函數功能完全一樣,至少輸入參數不同。atan(x) = atan2(x, float(1))。
ceil(x) 對輸入參數向上取整。例如: ceil(float(1.3)) ,其返回值為2.0
clamp(x,a,b) 如果x值小於a,則返回a;
如果x值大於b,返回b;
否則,返回x。
cos(x) 返回弧度x的余弦值。返回值范圍為[1,1]
cosh(x) 雙曲余弦(hyperbolic cosine)函數,計算x的雙曲余弦值。
cross(A,B) 返回兩個三元向量的叉積(cross product)。注意,輸入參數必須是三元向量!
degrees(x) 輸入參數為弧度值(radians),函數將其轉換為角度值(degrees)
determinant(m) 計算矩陣的行列式因子。
dot(A,B) 返回A和B的點積(dot product)。參數A和B可以是標量,也可以是向量(輸入參數方面,點積和叉積函數有很大不同)。
exp(x) 計算ex的值,e=2.71828182845904523536
exp2(x) 計算2x的值
floor(x) 對輸入參數向下取整。例如floor(float(1.3))返回的值為1.0;但是floor(float(-1.3))返回的值為-2.0。該函數與ceil(x)函數相對應。
fmod(x,y) 返回x/y的余數。如果y為0,結果不可預料。
frac(x) 返回標量或矢量的小數
frexp(x, out i) 將浮點數x分解為尾數和指數,即x=m2i, 返回m,並將指數存入i中;如果x為0,則尾數和指數都返回0
isfinite(x) 判斷標量或者向量中的每個數據是否是有限數,如果是返回true;否則返回false;
isinf(x) 判斷標量或者向量中的每個數據是否是無限,如果是返回true;否則返回false;
isnan(x) 判斷標量或者向量中的每個數據是否是非數據(not-a-number NaN),如果是返回true;否則返回false;
ldexp(x, n) 計算x2n的值
lerp(a, b, f) 計算(1f)a+bf或者a+f(ba)的值。即在下限a和上限b之間進行插值,f表示權值。注意,如果a和b是向量,則權值f必須是標量或者等長的向量。
lit(NdotL, NdotH, m) N表示法向量;
L表示入射光向量;
H表示半角向量;
m表示高光系數。 
函數計算環境光、散射光、鏡面光的貢獻,返回的4元向量。 
X位表示環境光的貢獻,總是1.0; 
Y位代表散射光的貢獻,如果 NL<0,則為0;否則為N
Z位代表鏡面光的貢獻,如果NL<0 或者NH<0,則位0;否則為(NL)m;
W位始終位1.0
log(x) 計算ln(x)的值,x必須大於0
log2(x) 計算log(x)2的值,x必須大於0
log10(x) 計算log(x)10的值,x必須大於0
max(a, b) 比較兩個標量或等長向量元素,返回最大值。
min(a,b) 比較兩個標量或等長向量元素,返回最小值。
modf(x, out ip) 把x分解成整數和分數兩部分,每部分都和x有着相同的符號,整數部分被保存在ip中,分數部分由函數返回
mul(M, N) 矩陣M和矩陣N的積
mul(M, v) 矩陣M和列向量v的積
mul(v, M) 行向量v和矩陣M的積
noise(x) 根據它的參數類型,這個函數可以是一元、二元或三元噪音函數。返回的值在0和1之間,並且通常與給定的輸入值一樣
pow(x, y) xy
radians(x) 函數將角度值轉換為弧度值
round(x) 返回四舍五入值。
rsqrt(x) x的平方根的倒數,x必須大於0
saturate(x) 把x限制到[0,1]之間
sign(x) 如果x>0則返回1;否則返回0
sin(x) 輸入參數為弧度,計算正弦值,返回值范圍 為[-1,1]
sincos(float x, out s, out c) 該函數是同時計算x的sin值和cos值,其中s=sin(x),c=cos(x)。該函數用於“同時需要計算sin值和cos值的情況”,比分別運算要快很多!
sinh(x) 計算x的雙曲正弦
smoothstep(min, max, x) 值x位於min、max區間中。如果x=min,返回0;如果x=max,返回1;如果x在兩者之間,按照下列公式返回數據:
2(xminmaxmin)3+3(xminmaxmin)2
step(a, x) 如果x<a,返回0;否則,返回1
sqrt(x) 求x的平方根,x√,x必須大於0
tan(x) 計算x正切值
tanh(x) 計算x的雙曲線切線
transpose(M) 矩陣M的轉置矩陣
如果M是一個AxB矩陣,M的轉置是一個BxA矩陣,它的第一列是M的第一行,第二列是M的第二行,第三列是M的第三行,等等

幾何函數
distance(pt1, pt2) 兩點之間的歐幾里德距離(Euclidean distance)
faceforward(N,I,Ng) 如果NgI<0,返回N;否則返回-N。
length(v) 返回一個向量的模,即sqrt(dot(v,v))
normalize(v) 返回v向量的單位向量
reflect(I, N) 根據入射光纖方向I和表面法向量N計算反射向量,僅對三元向量有效
refract(I,N,eta) 根據入射光線方向I,表面法向量N和折射相對系數eta,計算折射向量。如果對給定的eta,I和N之間的角度太大,返回(0,0,0)。
只對三元向量有效

關於幾何函數需要注意以下兩點:

1、着色程序中的向量最好進行歸一化之后再使用,否則會出現難以預料的 錯誤;

2、reflect 函數和 refract 函數都存在以“入射光方向向量”作為輸入參數, 注意這兩個函數中使用的入射光方向向量,是從外指向幾何頂點的;平時我 們在着色程序中都是將入射光方向向量作為從頂點出發的。

紋理映射函數
tex1D(sampler1D tex, float s) 一維紋理查詢
tex1D(sampler1D tex, float s, float dsdx, float dsdy) 使用導數值(derivatives)查詢一維紋理
Tex1D(sampler1D tex, float2 sz) 一維紋理查詢,並進行深度值比較
Tex1D(sampler1D tex, float2 sz, float dsdx,float dsdy) 使用導數值(derivatives)查詢一維紋理, 並進行深度值比較
Tex1Dproj(sampler1D tex, float2 sq) 一維投影紋理查詢
Tex1Dproj(sampler1D tex, float3 szq) 一維投影紋理查詢,並比較深度值
Tex2D(sampler2D tex, float2 s) 二維紋理查詢
Tex2D(sampler2D tex, float2 s, float2 dsdx, float2 dsdy) 使用導數值(derivatives)查詢二維紋理
Tex2D(sampler2D tex, float3 sz) 二維紋理查詢,並進行深度值比較
Tex2D(sampler2D tex, float3 sz, float2 dsdx,float2 dsdy) 使用導數值(derivatives)查詢二維紋理,並進行深度值比較
Tex2Dproj(sampler2D tex, float3 sq) 二維投影紋理查詢
Tex2Dproj(sampler2D tex, float4 szq) 二維投影紋理查詢,並進行深度值比較
texRECT(samplerRECT tex, float2 s) 二維非投影矩形紋理查詢(OpenGL獨有)
texRECT (samplerRECT tex, float3 sz, float2 dsdx,float2 dsdy) 二維非投影使用導數的矩形紋理查詢(OpenGL獨有)
texRECT (samplerRECT tex, float3 sz) 二維非投影深度比較矩形紋理查詢(OpenGL獨有)
texRECT (samplerRECT tex, float3 sz, float2 dsdx,float2 dsdy) 二維非投影深度比較並使用導數的矩形紋理查詢(OpenGL獨有)
texRECT proj(samplerRECT tex, float3 sq) 二維投影矩形紋理查詢(OpenGL獨有)
texRECT proj(samplerRECT tex, float3 szq) 二維投影矩形紋理深度比較查詢(OpenGL獨有)
Tex3D(sampler3D tex, float s) 三維紋理查詢
Tex3D(sampler3D tex, float3 s, float3 dsdx, float3 dsdy) 結合導數值(derivatives)查詢三維紋理
Tex3Dproj(sampler3D tex, float4 szq) 查詢三維投影紋理,並進行深度值比較
texCUBE(samplerCUBE tex, float3 s) 查詢立方體紋理
texCUBE (samplerCUBE tex, float3 s, float3 dsdx, float3 dsdy) 結合導數值(derivatives)查詢立方體紋理
texCUBEproj (samplerCUBE tex, float4 sq) 查詢投影立方體紋理

所有這些函數返回四元向量值

s:一元、二元、三元紋理坐標

z:使用深度比較的值

q:一個透視值(其實就是透視投影后得到的齊次坐標的最后一位),這個值被用來除以紋理坐標(s),得到新的紋理坐標(已歸一化)然后用於紋理查詢

偏導函數
ddx(a) 近似a關於屏幕空間x軸的偏導數
ddy(a) 近似a關於屏幕空間y軸的偏導數
  1. 函數 ddx和ddy用於求取相鄰像素間 屬性的差值;

  2. 函數 ddx和ddy的輸入參數通常是紋理坐標;

  3. 函數 ddx和ddy返回相鄰像素鍵的屬性差值;

調試函數
void debug(float4 x) 如果在編譯時設置了DEBUG,片段着 色程序中調用該函數可以將值x作為COLOR語義的最終輸出;否則該函數什么也不做。

這個函數寫到這里只是表示有這么一個函數,實際上這個函數並不能幫助我們多少。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM