1. 程式人生 > >Unity Shader (二)Cg語言

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=m∗2i, 返回m,並將指數存入i中;如果x為0,則尾數和指數都返回0
isfinite(x) 判斷標量或者向量中的每個資料是否是有限數,如果是返回true;否則返回false;
isinf(x) 判斷標量或者向量中的每個資料是否是無限,如果是返回true;否則返回false;
isnan(x) 判斷標量或者向量中的每個資料是否是非資料(not-a-number NaN),如果是返回true;否則返回false;
ldexp(x, n) 計算x∗2n的值
lerp(a, b, f) 計算(1−f)∗a+b∗f或者a+f∗(b−a)的值。即在下限a和上限b之間進行插值,f表示權值。注意,如果a和b是向量,則權值f必須是標量或者等長的向量。
lit(NdotL, NdotH, m) N表示法向量;
L表示入射光向量;
H表示半形向量;
m表示高光係數。 
函式計算環境光、散射光、鏡面光的貢獻,返回的4元向量。 
X位表示環境光的貢獻,總是1.0; 
Y位代表散射光的貢獻,如果 N∙L<0,則為0;否則為N∙L 
Z位代表鏡面光的貢獻,如果N∙L<0 或者N∙H<0,則位0;否則為(N∙L)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∗(x−minmax−min)3+3∗(x−minmax−min)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) 如果Ng∙I<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語義的最終輸出;否則該函式什麼也不做。

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

相關推薦

Unity Shader Cg語言

一、Cg基本資料型別 float 32位浮點數 half 16位浮點數 int 32位整型 fixed 12位定點數 bool 布林資料 simpler* 紋理物件的控制代碼( the handle to a text

Unity Shader 裁剪Culling

前言:unity當處理完頂點後,就會進入裁剪。為什麼是在這個時候呢? 因為下一個階段我們會進行片段程式(Fragment)的處理,而這個過程實際上是非常消耗的,所以我們這裡講的裁剪+深度測試(下文講)是對進入片段之前的頂點優化過程,減少片段處理的壓力。

圖形處理之Shader語言CG語法篇

Cg(C for Graphcis)語言,是NVIDIA與Microsoft合作研發,旨在為開發人員提供一套方便、跨平臺(良好的相容性),控制可程式設計圖形硬體的高階語言。 學習書籍  :GPU

JavaSE學習總結——Java語言基礎

默認 ase oid 64位 pac 交互 log 類型 blank 目錄 一、Java程序預覽 1.1、Hello World 1.2、Eclipse使用 1.2.1、項目位置 1.2.2、重置窗口布局 1.2.3、設置字體 1.2.4、修改控制臺字體 1.2.4

cpp學習C語言復習

char 兩個 手寫 匯編知識 c基礎 什麽 ada 發現 png 接下來復習一下C語言部分,畢竟C++與C語言本自同根生,並且在匯編層面C與C++可以說完全相同。假如你沒有C語言基礎的話,可以先暫停去學習一下C語言,C語言可以看“C語言之父”譚浩強的《C語言程序設計》或者

準備篇C語言

log https color c語言部分 ccf align col c語言 cat 因為C語言部分打算單獨維護,所以 -----x---------------x---------------x---------------x----- 傳送門 -----x----

Unity Shader 模板測試Stencil

模板測試的作用:對畫素進行一個全方位的輸出控制,這句話是我自己的理解。為什麼叫全方位的呢? why?? 我們不是有深度測試 和 alpha測試了嗎。 想想Alpha測試,他針對的是alpha值,而alpha值是美術的圖片控制的,有些場合你alpha值不透明但是你還是想他透明,

軟考總結---程式設計語言基礎知識

前言:下面和大家分享一下第二章的知識點,希望對大家有幫助。 (一)程式設計語言概述 1.編譯程式和解釋程式 基本方式:彙編、解釋、編譯 【1】 ①用某種高階語言或組合語言編寫的程式稱為【源程式】,不能直接在計算機上執行。 ②如果源程式是用【組合語言】編寫的,則需要一個【彙編

Java記憶體模型FAQ 其他語言,像C++,也有記憶體模型嗎?

譯者:Alex 大部分其他的語言,像C和C++,都沒有被設計成直接支援多執行緒。這些語言對於發生在編譯器和處理器平臺架構的重排序行為的保護機制會嚴重的依賴於程式中所使用的執行緒庫(例如pthreads),編譯器,以及程式碼所執行的平臺所提供的保障。 原文 Do other languag

go語言學習之路——go語言進行微信公眾號開發

學習教程地址:http://www.imooc.com/topic/golang?mc_marking=ed9ea9bd605fe0066c71d80cc8603806&mc_channel=bdgoyyzt&audience=230227github地址:h

c++學習筆記-- c語言基礎

c語言基礎 課程來源:coursera:程學設計與演算法(Peking University,北京大學) 課程連結:程式設計與演算法 本篇簡介:這一部分是系列課第一節的後半部分,主要總結了c語言的資料型別、運算成分和控制結構。 一. 從現實問題到計算機程式 1.1 結構化程式

【Unity3D基礎教程】給初學者看的Unity教程:所有指令碼元件的基類 -- MonoBehaviour的前世今生

引子 上一次我們講了GameObject,Compoent,Time,Input,Physics,其中Time,Input,Physics都是Unity中的全域性變數。GameObject是遊戲中的基本物件。GameObject是由Component組合而成的,GameObject本身必須有

matlab從入門到精通matlab語言基礎

1.變數與常量 變數名的組成:與C語言類似:下劃線,字母,數字,開頭必須為下劃線或字母 變數的初始化:(1)=  賦值(2)input(‘提示’) 與C語言區別可以不用初始化,直接賦值 常見常量: i

Unity Shader

初識 Shader 本篇介紹了在Unity中建立Shader的基本步驟,以及Shader的結構分析。 上篇連線(Shader基礎篇) 0x00 概述 啟動Unity並建立一個新專案: File>New Projec

Unity API:Input類

獲取鍵盤事件 Input.GetKey,某鍵被持續按下 Input.GetKeyDown,某鍵被按下 Input.GetkeyUp,某鍵被彈起         這些方法的引數是KeyCode型別,

07 編程語言介紹機器語言&匯編語言

存儲 字符串 asm 語言編程 編程 暫存 出錯 二進制 專業知識 機器語言: 由於計算機內部職能接受二進制代碼,因此,用二進制代碼0和1描述的指令稱為機器指令,全部機器指令的集合構成計算機的機器語言。機器語言屬於低級語言。 編出的程序全是些0和1的指令代碼,直

Unity Shader入門教程 :實現頂點和片元著色器之間的通訊

這篇文章將介紹Pass{}內的程式碼的編寫。我們先看如下Unity Shader程式碼:(此文部分採自《unity shader入門精要》) 關於頂點著色器和片元著色器不懂的學習可以自行搜尋概念的意思,這裡就不介紹了。 Shader "Custom/myTest" {

unity shader 入門之路sublime編譯器

研究了半天,在同事的指點下入了sublime的坑,VS2015寫unity shader太難受了,沒有高亮,沒有報錯,沒有智慧感應,很不爽,換了sub之後問題就解決了。 一個新的shader  來

Unity Shader學習筆記】最基本的頂點片段著色器

分享一個基本的頂點片段著色器,可以實現紋理取樣。目前沒有加入光照和陰影效果。 這個Shader可以作為基本的模板,進行更加細節的修改與開發。這裡就簡單分享一下吧。 Shader "Unlit/unl

【C語言天天練】statickeyword

修飾 weight () main函數 class code keyword spa tail 引言: statickeyword不僅能夠修飾變量。並且能夠修飾函數。了解它的使用方法,不僅對閱讀別人的代碼有幫助,也有助於自己寫出更加健壯的