unity shader shaderLab 手冊

本文出處:http://blog.csdn.net/lcbcsdn/article/details/46848125

(1)數學函數

函數 功能描述
abs(x) 返回輸入參數的絕對值
acos(x) 反餘切函數,輸入參數範圍爲[-1,1], 返回[0,π]區間的角度值
all(x) 如果輸入參數均不爲0,則返回ture; 否則返回flase。&&運算
any(x) 輸入參數只要有其中一個不爲0,則返回true。
asin(x) 反正弦函數,輸入參數取值區間爲,返回角度值範圍爲, 
atan(x) 反正切函數,返回角度值範圍爲
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的餘弦值。返回值範圍爲
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) 計算的值,e=2.71828182845904523536
exp2(x) 計算的值
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分解爲尾數和指數,即, 返回m,並將指數存入i中;如果x爲0,則尾數和指數都返回0
isfinite(x) 判斷標量或者向量中的每個數據是否是有限數,如果是返回true;否則返回false;
isinf(x) 判斷標量或者向量中的每個數據是否是無限,如果是返回true;否則返回false;
isnan(x) 判斷標量或者向量中的每個數據是否是非數據(not-a-number NaN),如果是返回true;否則返回false;
ldexp(x, n) 計算的值
lerp(a, b, f) 計算或者的值。即在下限a和上限b之間進行插值,f表示權值。注意,如果a和b是向量,則權值f必須是標量或者等長的向量。
lit(NdotL, NdotH, m) N表示法向量;
L表示入射光向量;
H表示半角向量;
m表示高光係數。 
函數計算環境光、散射光、鏡面光的貢獻,返回的4元向量。 
X位表示環境光的貢獻,總是1.0; 
Y位代表散射光的貢獻,如果 ,則爲0;否則爲 
Z位代表鏡面光的貢獻,如果 或者,則位0;否則爲;
W位始終位1.0
log(x) 計算的值,x必須大於0
log2(x) 計算的值,x必須大於0
log10(x) 計算的值,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)  
radians(x) 函數將角度值轉換爲弧度值
round(x) 返回四捨五入值。
rsqrt(x) x的平方根的倒數,x必須大於0
saturate(x) 把x限制到[0,1]之間
sign(x) 如果則返回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在兩者之間,按照下列公式返回數據:
step(a, x) 如果,返回0;否則,返回1
sqrt(x) 求x的平方根,,x必須大於0
tan(x) 計算x正切值
tanh(x) 計算x的雙曲線切線
transpose(M) 矩陣M的轉置矩陣
如果M是一個AxB矩陣,M的轉置是一個BxA矩陣,它的第一列是M的第一行,第二列是M的第二行,第三列是M的第三行,等等

 

(2)幾何函數

函數 功能描述
distance(pt1, pt2) 兩點之間的歐幾里德距離(Euclidean distance)
faceforward(N,I,Ng) 如果,返回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)。
只對三元向量有效

 

(3)紋理映射函數

函數 功能描述
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)。

當你使用的紋理函數允許你指定一個深度比較值的時候,與之相關聯的紋理單元必須被設置成深度比較紋理。否則,深度比較實際上不會被執行。 
 

(4)偏導函數

函數 功能描述
ddx(a) 近似a關於屏幕空間x軸的偏導數
ddy(a) 近似a關於屏幕空間y軸的偏導數

 

(5)調試函數

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

 

 

Unity ShaderLab學習總結

Why Bothers?

爲什麼已經有ShaderForge這種可視化Shader編輯器、爲什麼Asset Store已經有那麼多炫酷的Shader組件可下載,還是有必要學些Shader的編寫?

2014-0718-1607-11-33.png

  • 因爲上面這些Shader工具/組件最終都是以Shader文件的形式而存在。
  • 需要開發人員/技術美術有能力對Shader進行功能分析、效率評估、選擇、優化、兼容、甚至是Debug。
  • 對於特殊的需求,可能還是直接編寫Shader比較實際、高效。

總之,Shader編寫是重要的;但至於緊不緊急,視乎項目需求。

涉及範圍

本文只討論Unity ShaderLab相關的知識和使用方法。但,

  • 既不討論渲染相關的基礎概念;
    • 基礎概念可參考Rendering Pipeline Overview等文章。
    • 作爲移動設備GPU和桌面GPU的最大不同點,tile-based deferred rendering (WikiPowerVR/Mali/Adreno)也是重要的概念。
      其大幅減少帶寬消耗、會進行Early-Z測試嘗試減少Overdraw(依賴於渲染物體提交順序由前至後)。
      其中PowerVR的Hidden Surface Removal做到像素級別的Overdraw減少(不用依賴於渲染物體提交順序由前至後)。
  • 也不討論具體的渲染技巧

參考資源

  • Youtube:https://www.youtube.com/watch?v=hDJQXzajiPg (包括part1-6)。視頻是最佳的入門方式沒有之一,所以牆裂建議就算不看下文的所有內容,都要去看一下part1。
  • 書籍:《Unity 3D ShaderLab開發實戰詳解》
  • Unity各種官方文檔

使用Shader

2014-0720-1007-25-36.png


如上圖,一句話總結:

  1. GameObject裏有MeshRenderer,
  2. MeshRenderer裏有Material列表,
  3. 每個Material裏有且只有一個Shader;
  4. Material在編輯器暴露該Shader的可調屬性。

所以關鍵是怎麼編寫Shader。

Shader基礎

編輯器

使用MonoDevelop這反人類的IDE來編寫Shader居然是讓人滿意的。有語法高亮,無語法提示。
如果習慣VisualStudio,可以如下實現.Shader文件的語法高亮。

  • 下載作者donaldwu自己添加的關鍵詞文件usertype.dat。其包括了Unity ShaderLab的部分關鍵字,和HLSL的所有關鍵字。關鍵字以後持續添加中。
  • 將下載的usertype.dat放到Microsoft Visual Studio xx.x\CommonX\IDE\文件夾下;
  • 打開VS,工具>選項>文本編輯器>文件擴展名,擴展名裏填“shader”,編輯器選VC++,點擊添加;
  • 重啓VS,Done。

Shader


 
  1. Shader "ShaderLab Tutorials/TestShader"

  2. {

  3. // ...

  4. }

2014-0720-1707-17-42.png


Shader的名字會直接決定shader在material裏出現的路徑

SubShader


 
  1. Shader "ShaderLab Tutorials/TestShader" {

  2. SubShader

  3. {

  4. //...

  5. }

  6. }

一個Shader有多個SubShader。一個SubShader可理解爲一個Shader的一個渲染方案。即SubShader是爲了針對不同的渲染情況而編寫的。每個Shader至少1個SubShader、理論可以無限多個,但往往兩三個就足夠。
一個時刻只會選取一個SubShader進行渲染,具體SubShader的選取規則包括:

  • 從上到下選取
  • SubShader的標籤、Pass的標籤
    • 是否符合當前的“Unity渲染路徑”
    • 是否符合當前的ReplacementTag
  • SubShader是否和當前的GPU兼容

按此規則第一個被選取的SubShader將會用於渲染,未被選取的SubShader在這次渲染將被忽略。

SubShader的Tag


 
  1. Shader "ShaderLab Tutorials/TestShader" {

  2. SubShader

  3. {

  4. Tags { "Queue"="Geometry+10" "RenderType"="Opaque" }

  5. //...

  6. }

  7. }

SubShader內部可以有標籤(Tags)的定義。Tag指定了這個SubShader的渲染順序(時機),以及其他的一些設置。

  • "RenderType"標籤。Unity可以運行時替換符合特定RenderType的所有Shader。Camera.RenderWithShaderCamera.SetReplacementShader配合使用。Unity內置的RenderType包括:
    • "Opaque":絕大部分不透明的物體都使用這個;
    • "Transparent":絕大部分透明的物體、包括粒子特效都使用這個;
    • "Background":天空盒都使用這個;
    • "Overlay":GUI、鏡頭光暈都使用這個;
    • 用戶也可以定義任意自己的RenderType這個標籤所取的值。
    • 應注意,Camera.RenderWithShaderCamera.SetReplacementShader不要求標籤只能是RenderTypeRenderType只是Unity內部用於Replace的一個標籤而已,你也可以自定義自己全新的標籤用於Replace。
      比如,你爲自己的ShaderA.SubShaderA1(會被Unity選取到的SubShader,常爲Shader文件中的第一個SubShader)增加Tag爲"Distort"="On",然後將"Distort"作爲參數replacementTag傳給函數。此時,作爲replacementShader實參的ShaderB.SubShaderB1中若有也有一模一樣的"Distort"="On",則此SubShaderB1將代替SubShaderA1用於本次渲染。
    • 具體可參考Rendering with Replaced Shaders
  • "Queue"標籤。定義渲染順序。預製的值爲
    • "Background"。值爲1000。比如用於天空盒。
    • "Geometry"。值爲2000。大部分物體在這個隊列。不透明的物體也在這裏。這個隊列內部的物體的渲染順序會有進一步的優化(應該是從近到遠,early-z test可以剔除不需經過FS處理的片元)。其他隊列的物體都是按空間位置的從遠到近進行渲染。
    • "AlphaTest"。值爲2450。已進行AlphaTest的物體在這個隊列。
    • "Transparent"。值爲3000。透明物體。
    • "Overlay"。值爲4000。比如鏡頭光暈。
    • 用戶可以定義任意值,比如"Queue"="Geometry+10"
  • "ForceNoShadowCasting",值爲"true"時,表示不接受陰影。
  • "IgnoreProjector",值爲"true"時,表示不接受Projector組件的投影。

另,關於渲染隊列和Batch的非官方經驗總結是,一幀的渲染隊列的生成,依次決定於每個渲染物體的:

  • Shader的RenderType tag,
  • Renderer.SortingLayerID,
  • Renderer.SortingOrder,
  • Material.renderQueue(默認值爲Shader裏的"Queue"),
  • Transform.z(ViewSpace)(默認爲按z值從前到後,但當Queue是“Transparent”的時候,按z值從後到前)。

這個渲染隊列決定了之後(可能有dirty flag的機制?)渲染器再依次遍歷這個渲染隊列,“同一種”材質的渲染物體合到一個Batch裏。

Pass


 
  1. Shader "ShaderLab Tutorials/TestShader" {

  2. SubShader {

  3. Pass

  4. {

  5. //...

  6. }

  7. }

  8. }

一個SubShader(渲染方案)是由一個個Pass塊來執行的。每個Pass都會消耗對應的一個DrawCall。在滿足渲染效果的情況下儘可能地減少Pass的數量。

Pass的Tag


 
  1. Shader "ShaderLab Tutorials/TestShader" {

  2. SubShader {

  3. Pass

  4. {

  5. Tags{ "LightMode"="ForwardBase" }

  6. //...

  7. }

  8. }

  9. }

和SubShader有自己專屬的Tag類似,Pass也有Pass專屬的Tag。
其中最重要Tag是 "LightMode",指定Pass和Unity的哪一種渲染路徑(“Rendering Path”)搭配使用。除最重要的ForwardBaseForwardAdd外,這裏需額外提醒的Tag取值可包括:

  • Always,永遠都渲染,但不處理光照
  • ShadowCaster,用於渲染產生陰影的物體
  • ShadowCollector,用於收集物體陰影到屏幕座標Buff裏。

其他渲染路徑相關的Tag詳見下面章節“Unity渲染路徑種類”。
具體所有Tag取值,可參考ShaderLab syntax: Pass Tags

FallBack


 
  1. Shader "ShaderLab Tutorials/TestShader"{

  2. SubShader { Pass {} }

  3.  
  4. FallBack "Diffuse" // "Diffuse"即Unity預製的固有Shader

  5. // FallBack Off //將關閉FallBack

  6. }

當本Shader的所有SubShader都不支持當前顯卡,就會使用FallBack語句指定的另一個Shader。FallBack最好指定Unity自己預製的Shader實現,因其一般能夠在當前所有顯卡運行。

Properties


 
  1. Shader "ShaderLab Tutorials/TestShader"

  2. {

  3. Properties {

  4. _Range ("My Range", Range (0.02,0.15)) = 0.07 // sliders

  5. _Color ("My Color", Color) = (.34, .85, .92, 1) // color

  6. _2D ("My Texture 2D", 2D) = "" {} // textures

  7. _Rect("My Rectangle", Rect) = "name" { }

  8. _Cube ("My Cubemap", Cube) = "name" { }

  9. _Float ("My Float", Float) = 1

  10. _Vector ("My Vector", Vector) = (1,2,3,4)

  11.  
  12. // Display as a toggle.

  13. [Toggle] _Invert ("Invert color?", Float) = 0

  14. // Blend mode values

  15. [Enum(UnityEngine.Rendering.BlendMode)] _Blend ("Blend mode", Float) = 1

  16. //setup corresponding shader keywords.

  17. [KeywordEnum(Off, On)] _UseSpecular ("Use Specular", Float) = 0

  18. }

  19.  
  20. // Shader

  21. SubShader{

  22. Pass{

  23. //...

  24. uniform float4 _Color;

  25. //...

  26. float4 frag() : COLOR{ return fixed4(_Color); }

  27. //...

  28. #pragma multi_compile __ _USESPECULAR_ON

  29. }

  30. }

  31.  
  32. //fixed pipeline

  33. SubShader {

  34. Pass{

  35. Color[_Color]

  36. }

  37. }

  38. }

  • Shader在Unity編輯器暴露給美術的參數,通過Properties來實現。
  • 所有可能的參數如上所示。主要也就Float、Vector和Texture這3類。
  • 除了通過編輯器編輯Properties,腳本也可以通過Material的接口(比如SetFloatSetTexture編輯)
  • 之後在Shader程序通過[name](固定管線)或直接name(可編程Shader)訪問這些屬性。
  • 在每一個Property前面也能類似C#那樣添加Attribute,以達到額外UI面板功能。詳見MaterialPropertyDrawer.html

Shader中的數據類型

有3種基本數值類型:floathalffixed
這3種基本數值類型可以再組成vector和matrix,比如half3是由3個half組成、float4x4是由16個float組成。

  • float:32位高精度浮點數。
  • half:16位中精度浮點數。範圍是[-6萬, +6萬],能精確到十進制的小數點後3.3位。
  • fixed:11位低精度浮點數。範圍是[-2, 2],精度是1/256。

數據類型影響性能

  • 精度夠用就好。
    • 顏色和單位向量,使用fixed
    • 其他情況,儘量使用half(即範圍在[-6萬, +6萬]內、精確到小數點後3.3位);否則才使用float

ShaderLab中的Matrix

當提到“Row-Major”、“Column-Major”,根據不同的場合,它們可能指不同的意思:

  • 數學上的,主要是指矢量V是Row Vector、還是Column Vector。引用自[Game Engine Architecture 2nd Edition, 183]。留意到V和M的乘法,當是Row Vector的時候,數學上寫作VM,Matrix在右邊,Matrix的最下面一行表示Translate;當是Column Vector的時候,數學上寫作MtVt,Matrix在左邊並且需要轉置,Matrix最右面一列表示Translate。
  • 訪問接口上的:Row-Major即MyMatrix[Row][Column]、Column-Major即MyMatrix[Column][Row]。HLSL/CG的訪問接口都是Row-Major,比如MyMatrix[3]返回的是第3行;GLSL的訪問接口是Column-Major,比如MyMatrix[3]返回的是第3列。
  • 寄存器存儲上的:每個元素是按行存儲在寄存器中、還是按列存儲在寄存器中。需要關注它的一般情況舉例是,float2x3的MyMatrix,到底是佔用2個寄存器(Row-Major)、還是3個寄存器(Column-Major)。在HLSL裏,可以通過#pragmapack_matrix設定row_major或者column_major。

上述情況,互不相干。
然後,ShaderLab中,數學上是Column Vector、訪問接口上是Row-Major、存儲上是(尚未查明)。另外,ShaderLab在World Space是左手座標系、View Space是右手座標系、在Normalized Device Coordinates裏是左手座標系。


 
  1. v2f vert (appdata v)

  2. {

  3. v2f o;

  4. o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);

  5. // 1 、2、3是等價的,和4是不等價的

  6. // 因爲是M在左、V在右,所以是Column Vector

  7. // 因爲是HLSL/CG語言,所以是訪問方式是Row-Major

  8. o.rootInView = mul(UNITY_MATRIX_MV, float4(0, 0, 0, 1)); // 1

  9. o.rootInView = float4(UNITY_MATRIX_MV[0].w, UNITY_MATRIX_MV[1].w, UNITY_MATRIX_MV[2].w, 1); // 2

  10. o.rootInView = UNITY_MATRIX_MV._m03_m13_m23_m33; // 3

  11. //o.rootInView = UNITY_MATRIX_MV[3]; // 4

  12.  
  13. return o;

  14. }

  15.  
  16. fixed4 frag (v2f i) : SV_Target

  17. {

  18. // 因爲是ViewSpace是右手座標系,所以當root在view前面的時候,z是負數,所以需要-z才能正確顯示顏色

  19. fixed4 col = fixed4(i.rootInView.x, i.rootInView.y, -i.rootInView.z, 1);

  20. return col;

  21. }

  22.  
  23. struct appdata

  24. {

  25. float4 vertex : POSITION;

  26. };

  27. struct v2f

  28. {

  29. float4 rootInView : TEXCOORD0;

  30. float4 vertex : SV_POSITION;

  31. };

Shader形態

Shader形態之1:固定管線

固定管線是爲了兼容老式顯卡。都是頂點光照。之後固定管線可能是被Unity拋棄的功能,所以最好不學它、當它不存在。特徵是裏面出現了形如下面Material塊、沒有CGPROGRAMENDCG塊。


 
  1. Shader "ShaderLab Tutorials/TestShader"

  2. {

  3. Properties {

  4. _Color ("My Color", Color) = (.34, .85, .92, 1) // color

  5. }

  6.  
  7. // Fixed Pipeline

  8. SubShader

  9. {

  10. Pass

  11. {

  12. Material{

  13. Diffuse [_Color]

  14. Ambient [_Color]

  15. }

  16.  
  17. Lighting On

  18. }

  19. }

  20. }

Shader形態之2:可編程Shader


 
  1. Shader "ShaderLab Tutorials/TestShader"

  2. {

  3. Properties {}

  4.  
  5. SubShader

  6. {

  7. Pass

  8. {

  9. // ... the usual pass state setup ...

  10.  
  11. CGPROGRAM

  12. // compilation directives for this snippet, e.g.:

  13. #pragma vertex vert

  14. #pragma fragment frag

  15.  
  16. // the Cg/HLSL code itself

  17. float4 vert(float4 v:POSITION) : SV_POSITION{

  18. return mul(UNITY_MATRIX_MVP, v);

  19. }

  20. float4 frag() : COLOR{

  21. return fixed4(1.0, 0.0, 0.0, 1.0);

  22. }

  23. ENDCG

  24. // ... the rest of pass setup ...

  25. }

  26. }

  27. }

  • 功能最強大、最自由的形態。
  • 特徵是在Pass裏出現CGPROGRAMENDCG
  • 編譯指令#pragma。詳見官網Cg snippets。其中重要的包括:
編譯指令 示例/含義
#pragma vertex name
#pragma fragment name
替換name,來指定Vertex Shader函數、Fragment Shader函數。
#pragma target name 替換name(爲2.03.0等)。設置編譯目標shader model的版本。
#pragma only_renderers name name ...
#pragma exclude_renderers name name...
#pragma only_renderers gles gles3
#pragma exclude_renderers d3d9 d3d11 opengl
只爲指定渲染平臺(render platform)編譯
  • 引用庫。通過形如#include "UnityCG.cginc"引入指定的庫。常用的就是UnityCG.cginc了。其他庫詳見官網Built-in shader include files
  • ShaderLab內置值。Unity給Shader程序提供了便捷的、常用的值,比如下面例子中的UNITY_MATRIX_MVP就代表了這個時刻的MVP矩陣。詳見官網ShaderLab built-in values
  • Shader輸入輸出參數語義(Semantics)。在管線流程中每個階段之間(比如Vertex Shader階段和FragmentShader階段之間)的輸入輸出參數,通過語義字符串,來指定參數的含義。常用的語義包括:COLORSV_PositionTEXCOORD[n]。完整的參數語義可見HLSL Semantic(由於是HLSL的連接,所以可能不完全在Unity裏可以使用)。
  • 特別地,因爲Vertex Shader的的輸入往往是管線的最開始,Unity爲此內置了常用的數據結構:
數據結構 含義
appdata_base vertex shader input with position, normal, one texture coordinate.
appdata_tan vertex shader input with position, normal, tangent, one texture coordinate.
appdata_full vertex shader input with position, normal, tangent, vertex color and two texture coordinates.
appdata_img vertex shader input with position and one texture coordinate.

Shader形態之3:SurfaceShader


 
  1. Shader "ShaderLab Tutorials/TestShader"

  2. {

  3. Properties { }

  4.  
  5. // Surface Shader

  6. SubShader {

  7. Tags { "RenderType" = "Opaque" }

  8. CGPROGRAM

  9. #pragma surface surf Lambert

  10. struct Input {

  11. float4 color : COLOR;

  12. };

  13. void surf (Input IN, inout SurfaceOutput o) {

  14. o.Albedo = 1;

  15. }

  16. ENDCG

  17. }

  18. FallBack "Diffuse"

  19. }

  • SurfaceShader可以認爲是一個光照Shader的語法糖、一個光照VS/FS的生成器。減少了開發者寫重複代碼的需要。
  • 在手遊,由於對性能要求比較高,所以不建議使用SurfaceShader。因爲SurfaceShader是一個比較“通用”的功能,而通用往往導致性能不高。
  • 特徵是在SubShader裏出現CGPROGRAMENDCG塊。(而不是出現在Pass裏。因爲SurfaceShader自己會編譯成多個Pass。)
  • 編譯指令是:
    #pragma surface surfaceFunction lightModel [optionalparams]
    • surfaceFunction:surfaceShader函數,形如void surf (Input IN, inout SurfaceOutput o)
    • lightModel:使用的光照模式。包括Lambert(漫反射)和BlinnPhong(鏡面反射)。
      • 也可以自己定義光照函數。比如編譯指令爲#pragma surface surf MyCalc
  • 你定義輸入數據結構(比如上面的Input)、編寫自己的Surface函數處理輸入、最終輸出修改過後的SurfaceOutput。SurfaceOutput的定義爲
    
     
    1. struct SurfaceOutput {

    2. half3 Albedo; // 紋理顏色值(r, g, b)

    3. half3 Normal; // 法向量(x, y, z)

    4. half3 Emission; // 自發光顏色值(r, g, b)

    5. half Specular; // 鏡面反射度

    6. half Gloss; // 光澤度

    7. half Alpha; // 不透明度

    8. };

Shader形態之4:Compiled Shader

點擊a.shader文件的“Compile and show code”,可以看到該文件的“編譯”過後的ShaderLab shader文件,文件名形如Compiled-a.shader
其依然是ShaderLab文件,其包含最終提交給GPU的shader代碼字符串。
先就其結構進行簡述如下,會發現和上述的編譯前ShaderLab結構很相似。


 
  1. // Compiled shader for iPhone, iPod Touch and iPad, uncompressed size: 36.5KB

  2. // Skipping shader variants that would not be included into build of current scene.

  3. Shader "ShaderLab Tutorials/TestShader"

  4. {

  5. Properties {...}

  6. SubShader {

  7. // Stats for Vertex shader:

  8. // gles : 14 avg math (11..19), 1 avg texture (1..2)

  9. // metal : 14 avg math (11..17)

  10. // Stats for Fragment shader:

  11. // metal : 14 avg math (11..19), 1 avg texture (1..2)

  12. Pass {

  13. Program "vp" // vertex program

  14. {

  15. SubProgram "gles" {

  16. // Stats: 11 math, 1 textures

  17. Keywords{...} // keywords for shader variants ("uber shader")

  18.  
  19. //shader codes in string

  20. "

  21. #ifdef VERTEX

  22. vertex shader codes

  23. #endif

  24.  
  25. // Note, on gles, fragment shader stays here inside Program "vp"

  26. #ifdef FRAGMENT

  27. fragment shader codes

  28. #endif

  29. "

  30. }

  31.  
  32. SubProgram "metal" {

  33. some setup

  34. Keywords{...}

  35.  
  36. //vertex shader codes in string

  37. "..."

  38. }

  39. }

  40.  
  41. Program "fp" // fragment program

  42. {

  43. SubProgram "gles" {

  44. Keywords{...}

  45. "// shader disassembly not supported on gles" //(because gles fragment shader codes are in Program "vp")

  46. }

  47.  
  48. SubProgram "metal" {

  49. common setup

  50. Keywords{...}

  51.  
  52. //fragment shader codes in string

  53. "..."

  54. }

  55. }

  56. }

  57. }

  58.  
  59. ...

  60. }

Unity渲染路徑(Rendering Path)種類

概述

開發者可以在Unity工程的PlayerSettings設置對渲染路徑進行3選1:

  • Deferred Lighting,延遲光照路徑。3者中最高質量地還原光照陰影。光照性能只與最終像素數目有關,光源數量再多都不會影響性能。
  • Forward Rendering,順序渲染路徑。能發揮出Shader全部特性的渲染路徑,當然也就支持像素級光照。最常用、功能最自由,性能與光源數目*受光照物體數目有關,具體性能視乎其具體使用到的Shader的複雜度。
  • Vertex Lit,頂點光照路徑。頂點級光照。性能最高、兼容性最強、支持特性最少、品質最差。

渲染路徑的內部階段和Pass的LightMode標籤

每個渲染路徑的內部會再分爲幾個階段。
然後,Shader裏的每個Pass,都可以指定爲不同的LightMode。而LightMode實際就是說:“我希望這個Pass在這個XXX渲染路徑的這個YYY子階段被執行”。

Deferred Ligting

渲染路徑內部子階段 對應的LightMode 描述
Base Pass "PrepassBase" 渲染物體信息。即把法向量、高光度到一張ARGB32的物體信息紋理上,把深度信息保存在Z-Buff上。
Lighting Pass 無對應可編程Pass 根據Base Pass得出的物體信息,在屏幕座標系下,使用BlinnPhong光照模式,把光照信息渲染到ARGB32的光照信息紋理上(RGB表示diffuse顏色值、A表示高光度)
Final Pass "PrepassFinal" 根據光照信息紋理,物體再渲染一次,將光照信息、紋理信息和自發光信息最終混合。LightMap也在這個Pass進行。

Forward Rendering

渲染路徑內部子階段 對應的LightMode 描述
Base Pass "ForwardBase" 渲染:最亮一個的方向光光源(像素級)和對應的陰影、所有頂點級光源、LightMap、所有LightProbe的SH光源(Sphere Harmonic,球諧函數,效率超高的低頻光)、環境光、自發光。
Additional Passes "ForwardAdd" 其他需要像素級渲染的的光源

注意到的是,在Forward Rendering中,光源可能是像素級光源、頂點級光源或SH光源。其判斷標準是:

  • 配製成“Not Important”的光源都是頂點級光源和SH光源
  • 最亮的方向光永遠都是像素級光源
  • 配置成“Important”的都是像素級光源
  • 上面2種情況加起來的像素級光源數目小於“Quality Settings”裏面的“Pixel Light Count”的話,會把第1種情況的光源補爲額外的像素級光源。

另外,配置成“Auto”的光源有更復雜的判斷標註,截圖如下:

2014-0720-1607-31-40.png


具體可參考Forward Rendering Path Details

Vertex Lit

渲染路徑內部子階段 對應的LightMode 描述
Vertex "Vertex" 渲染無LightMap物體
VertexLMRGBM "VertexLMRGBM" 渲染有RGBM編碼的LightMap物體
VertexLM "VertexLM" 渲染有雙LDR編碼的LightMap物體

不同LightMode的Pass的被選擇

一個工程的渲染路徑是唯一的,但一個工程裏的Shader是允許配有不同LightMode的Pass的。
在Unity,策略是“從工程配置的渲染路徑模式開始,按Deferred、Forward、VertxLit的順序,搜索最匹配的LightMode的一個Pass”。
比如,在配置成Deferred路徑時,優先選有Deferred相關LightMode的Pass;找不到纔會選Forward相關的Pass;還找不到,纔會選VertexLit相關的Pass。
再比如,在配置成Forward路徑時,優先選Forward相關的Pass;找不到纔會選VertexLit相關的Pass。

 

 

 

原文鏈接:http://www.jianshu.com/p/7b9498e58659

 

 

************轉http://www.tuicool.com/articles/ABNbyi*******************

因爲Unity中基礎的固定功能Shader的知識點基本上講完,下期開始就要準備講表面着色器(Surface Shader)了,所以在文章開頭,讓我們複習和更深入瞭解一下Unity中Shader的三種形態。

在Unity中,Shader便可以分成如下三種基本類型:

1. 固定功能着色器(FixedFunction Shader)

2. 表面着色器(SurfaceShader)

3. 頂點着色器&片段着色器(Vertex Shader & Fragment Shader)

顧名思義,其中的固定功能着色器便是我們所說的固定功能渲染管線(fixed-functionrenderingpipelines)的具體表現,而表面着色器、頂點着色器以及片段着色器便屬於可編程渲染管線。下面分別對其進行簡單的介紹。

1.1   Unity中的Shader形態之一:固定功能Shader

這裏的固定功能着色器可以說是Unity爲Shader的書寫自帶的一層殼,Unity已經在內部爲我們做了大量的工作,我們只要稍微記住一些關鍵字、一些規範就可以實現出很多不錯的效果。固定功能着色器是我們初學Unity Shader的最近幾篇文章中的主要學習對象。而後面的表面着色器、頂點着色器以及片段着色器就是在固定功能着色器的基礎上嵌套了CG語言的代碼而成的更加複雜的着色器。我們來看看他們的一些基本概念。

固定管線是爲了兼容老式顯卡。都爲頂點光照,就是我們前四篇文章加上這篇文章中講到的內容。

其特徵是裏面的核心是下面Material材質屬性塊、沒有CGPROGRAM和ENDCG塊,以及各種頂點着色和片段着色的宏命令。

一個光照材質完備版的固定功能Shader示例如下:

Shader "淺墨Shader編程/Volume5/固定功能的Shader示例"   
{  
  //-------------------------------【屬性】-----------------------------------------  
  Properties   
  {  
    _Color ("主顏色", Color) = (1,1,1,0)  
    _SpecColor ("高光顏色", Color) = (1,1,1,1)  
    _Emission ("自發光顏色", Color) = (0,0,0,0)  
    _Shininess ("光澤度", Range (0.01, 1)) = 0.7  
    _MainTex ("基本紋理", 2D) = "white" {}  
  }  
  //--------------------------------【子着色器】--------------------------------  
  SubShader  
  {  
    //----------------通道---------------  
    Pass  
    {  
      //-----------材質------------  
      Material  
      {  
        //可調節的漫反射光和環境光反射顏色  
        Diffuse [_Color]  
        Ambient [_Color]  
        //光澤度  
        Shininess [_Shininess]  
        //高光顏色  
        Specular [_SpecColor]  
        //自發光顏色  
        Emission [_Emission]  
      }  
      //開啓光照  
      Lighting On  
      //開啓獨立鏡面反射  
      SeparateSpecular On  
      //設置紋理並進行紋理混合  
      SetTexture [_MainTex]   
      {  
        Combine texture * primary DOUBLE, texture * primary  
      }  
    }  
  }  
}

  1.2 Unity中的Shader形態之二:表面着色器SurfaceShader

這部分算是Unity微創新自創的一套着色器標準。

表面着色器(Surface Shader)這個概念更多的只是在Unity中聽說,可以說是Unity自己發揚光大的一項使Shader的書寫門檻降低和更易用的技術。我們會在接下來的學習中逐漸意識到Unity是如何爲我們把Shader的複雜性包裝起來,使其書寫的過程更便捷和易用

的。一些特性如下:

•      SurfaceShader可以認爲是一個光照Shader的語法塊、一個光照VS/FS的生成器。減少了開發者寫重複代碼的需要。

•      特徵是在SubShader裏出現CGPROGRAM和ENDCG塊。(而不是出現在Pass裏。因爲SurfaceShader自己會編譯成多個Pass。)

•      編譯指令是:

#pragma surface surfaceFunction lightModel[optionalparams]

o     surfaceFunction:surfaceShader函數,形如void surf (Input IN, inoutSurfaceOutput o)

o     lightModel:使用的光照模式。包括Lambert(漫反射)和BlinnPhong(鏡面反射)。

     也可以自己定義光照函數。比如編譯指令爲#pragma surface surf MyCalc

     在Shader裏定義half4 LightingMyCalc (SurfaceOutputs, 參數略)函數進行處理(函數名在簽名加上了“Lighting”)。

•      我們自己定義輸入數據結構(比如上面的Input)、編寫自己的Surface函數處理輸入、最終輸出修改過後的SurfaceOutput。而SurfaceOutput的定義爲:

struct SurfaceOutput
{
 	half3 Albedo; // 紋理顏色值(r, g, b)
 	half3 Normal; // 法向量(x, y, z)
 	half3 Emission; // 自發光顏色值(r, g, b)
 	half Specular; // 鏡面反射度
 	half Gloss; // 光澤度
 	half Alpha; // Alpha不透明度
};

上面是一些特性總結,讓我們看一個具體Shader示例:

Shader "淺墨Shader編程/Volume5/表面Shader示例 "   
{  
  //-------------------------------【屬性】-----------------------------------------  
  Properties   
  {  
    _MainTex ("【紋理】Texture", 2D) = "white" {}  
    _BumpMap ("【凹凸紋理】Bumpmap", 2D) = "bump" {}  
    _RimColor ("【邊緣顏色】Rim Color", Color) = (0.17,0.36,0.81,0.0)  
    _RimPower ("【邊緣顏色強度】Rim Power", Range(0.6,9.0)) = 1.0  
  }  
  //----------------------------【開始一個子着色器】---------------------------  
  SubShader   
  {  
    //渲染類型爲Opaque,不透明  
    Tags { "RenderType" = "Opaque" }  
    //-------------------開始CG着色器編程語言段-----------------  
    CGPROGRAM  
    //使用蘭伯特光照模式  
    #pragma surface surf Lambert  
    //輸入結構  
    struct Input   
    {  
      float2 uv_MainTex;//紋理貼圖  
      float2 uv_BumpMap;//法線貼圖  
      float3 viewDir;//觀察方向  
    };  
    //變量聲明  
    sampler2D _MainTex;//主紋理  
    sampler2D _BumpMap;//凹凸紋理  
    float4 _RimColor;//邊緣顏色  
    float _RimPower;//邊緣顏色強度  
    //表面着色函數的編寫  
    void surf (Input IN, inout SurfaceOutput o)  
    {  
      //表面反射顏色爲紋理顏色  
      o.Albedo = tex2D (_MainTex, IN.uv_MainTex).rgb;  
      //表面法線爲凹凸紋理的顏色  
      o.Normal = UnpackNormal (tex2D (_BumpMap, IN.uv_BumpMap));  
      //邊緣顏色  
      half rim = 1.0 - saturate(dot (normalize(IN.viewDir), o.Normal));  
      //邊緣顏色強度  
      o.Emission = _RimColor.rgb * pow (rim, _RimPower);  
    }  
    //-------------------結束CG着色器編程語言段------------------  
    ENDCG  
  }   
  //“備胎”爲普通漫反射  
  Fallback "Diffuse"  
}

  1.3 Unity中的Shader形態之三:可編程Shader

可編程Shader其實就是頂點着色器和片段着色器,這一部分和DirectX系的HLSL和CG着色器語言聯繫緊密。其實就是Unity給HLSL和CG報了一個ShaderLab的殼。

研究過Direct3D和OpenGL着色器編程的童鞋們一定對頂點着色器和片段着色器不陌生。我們來簡單介紹一下他們的用途。

頂點着色器:產生紋理座標,顏色,點大小,霧座標,然後把它們傳遞給裁剪階段。

片段着色器:進行紋理查找,決定什麼時候執行紋理查找,是否進行紋理查找,及把什麼作爲紋理座標。

可編程Shader的特點爲:

    • 功能最強大、最自由的形態。
    • 特徵是在Pass裏出現CGPROGRAM和ENDCG塊
    • 編譯指令#pragma。詳見 官網Cg snippets 。其中重要的包括:

 

編譯指令

示例/含義

#pragma vertex name #pragma fragment name

替換name,來指定Vertex Shader函數、Fragment Shader函數。

#pragma target name

替換name(爲2.0、3.0等)。設置編譯目標shader model的版本。

#pragma only_renderers name name ... #pragma exclude_renderers name name...

#pragma only_renderers gles gles3, #pragma exclude_renderers d3d9 d3d11 opengl, 只爲指定渲染平臺(render platform)編譯

    • 關於引用庫。通過形如#include "UnityCG.cginc"引入指定的庫。常用的就是UnityCG.cginc了。其他庫詳見 官網Built-in shader include files 。
    • ShaderLab內置值。Unity給Shader程序提供了便捷的、常用的值,比如下面例子中的UNITY_MATRIX_MVP就代表了這個時刻的MVP矩陣。詳見 官網ShaderLab built-in values 。
    • Shader輸入輸出參數語義(Semantics)。在管線流程中每個階段之間(比如Vertex Shader階段和FragmentShader階段之間)的輸入輸出參數,通過語義字符串,來指定參數的含義。常用的語義包括:COLOR、SV_Position、TEXCOORD[n]。完整的參數語義可見 HLSL Semantic (由於是HLSL的連接,所以可能不完全在Unity裏可以使用)。
    • 特別地,因爲Vertex Shader的的輸入往往是管線的最開始,Unity爲此內置了常用的數據結構:

 

 

數據結構

含義

appdata_base

頂點着色器 輸入位置、法線以及一個紋理座標。

appdata_tan

頂點着色器 輸入位置、法線、切線以及一個紋理座標。

appdata_full

頂點着色器 輸入位置、法線、切線、頂點顏色以及兩個紋理座標。

appdata_img

頂點着色器 輸入位置以及一個紋理座標。

 

讓我們用一個可編程着色器Shader示例結束此部分的講解:

Shader "淺墨Shader編程/Volume5/可編程Shader示例" 
{
  //-------------------------------【屬性】--------------------------------------
  Properties 
  {
    _Color ("Color", Color) = (1.0,1.0,1.0,1.0)
    _SpecColor ("Specular Color", Color) = (1.0,1.0,1.0,1.0)
    _Shininess ("Shininess", Float) = 10
  }

  //--------------------------------【子着色器】--------------------------------
  SubShader 
  {
    //-----------子着色器標籤----------
    Tags { "LightMode" = "ForwardBase" }

    //----------------通道---------------
    Pass 
    {
      //-------------------開始CG着色器編程語言段-----------------  
      CGPROGRAM
      #pragma vertex vert
      #pragma fragment frag
      
      //---------------聲明變量--------------
      uniform float4 _Color;
      uniform float4 _SpecColor;
      uniform float _Shininess;
      
      //--------------定義變量--------------
      uniform float4 _LightColor0;
      
      //--------------頂點輸入結構體-------------
      struct vertexInput 
      {
        float4 vertex : POSITION;
        float3 normal : NORMAL;
      };

      //--------------頂點輸出結構體-------------
      struct vertexOutput 
      {
        float4 pos : SV_POSITION;
        float4 col : COLOR;
      };
      
      //--------------頂點函數--------------
      vertexOutput vert(vertexInput v)
      {
        vertexOutput o;
        
        //一些方向
        float3 normalDirection = normalize( mul( float4(v.normal, 0.0), _World2Object ).xyz );
        float3 viewDirection = normalize( float3( float4( _WorldSpaceCameraPos.xyz, 1.0) - mul(_Object2World, v.vertex).xyz ) );
        float3 lightDirection;
        float atten = 1.0;
        
        //光照
        lightDirection = normalize(_WorldSpaceLightPos0.xyz);
        float3 diffuseReflection = atten * _LightColor0.xyz * max( 0.0, dot( normalDirection, lightDirection ) );
        float3 specularReflection = atten * _LightColor0.xyz * _SpecColor.rgb * max( 0.0, dot( normalDirection, lightDirection ) ) * pow( max( 0.0, dot( reflect( -lightDirection, normalDirection ), viewDirection ) ), _Shininess );
        float3 lightFinal = diffuseReflection + specularReflection + UNITY_LIGHTMODEL_AMBIENT;
        
        //計算結果
        o.col = float4(lightFinal * _Color.rgb, 1.0);//顏色
        o.pos = mul(UNITY_MATRIX_MVP, v.vertex);//位置
        return o;
      }
      
      //--------------片段函數---------------
      float4 frag(vertexOutput i) : COLOR
      {
        return i.col;
      }

      //-------------------結束CG着色器編程語言段------------------
      ENDCG
    }
  }
  //備胎
  Fallback "Diffuse"
  
}

 

 

OK,下面我們來看本次文章的主角——blending操作。

二、混合操作(Blending)

我們直奔主題吧。混合操作最常見的用途便是用來製作透明物體、或者是進行紋理的混合。它是Shader渲染的最後一步:

如上圖所示,正被渲染的像素經過頂點光照、頂點着色器、剔除和深度測試,霧效、Alpha測試等一系列操作之後,最後一步便是混合操作。這個時候計算結果即將被輸出到幀緩衝中。而混合操作,就是管理如何將這些像素輸出到幀緩存中的這樣一個過程——是直接替換原來的,是一加一的混合,還是有Alpha參與的不等比地混合等等。

混合操作有兩個對象:源和目標,因此也有兩個對應的因子,即源因子和目標因子(對應於下面講解的Blend SrcFactor DstFactor操作)。

而如果我們把RGB顏色通道和Alpha通道分開來操作的話,混合就有了4個操作對象(對應於下面講解的Blend SrcFactor DstFactor,SrcFactorA DstFactorA操作)。

2.1 混合操作相關的句法

Blend Off

Turn off blending 關閉混合

Blend  SrcFactorDstFactor

基本的配置並啓動混操作。對產生的顏色乘以SrcFactor.對 已存在於屏幕的顏色乘以DstFactor,並且兩者將被疊加在一起。

Blend  SrcFactorDstFactor, SrcFactorA DstFactorA

同上,但是使用不同的要素來混合alpha通道,也就是有了4個操作對象

BlendOp  Add / Min | Max | Sub | RevSub

此操作不是Blend操作一樣添加混合顏色在一起,而是對它們做不同的操作。

而如下便是常用混合操作符(blend operations)的含義列舉:

 

Add

將源像素和目標像素相加.

Sub

用源像素減去目標像素

RevSub

用目標像素減去源像素

Min

取目標像素和源像素顏色的較小者作爲結果

Max

取目標像素和源像素顏色的較大者作爲結果

 

2.2 混合因子(Blend factors)列舉

以下所有的屬性都可作爲SrcFactor或DstFactor。其中,Source指的是被計算過的顏色,Destination是已經在屏幕上的顏色。

 

One 值爲1,使用此因子來讓幀緩衝區源顏色或是目標顏色完全的通過。
Zero 值爲0,使用此因子來刪除幀緩衝區源顏色或目標顏色的值。
SrcColor 使用此因子爲將當前值乘以幀緩衝區源顏色的值
SrcAlpha 使用此因子爲將當前值乘以幀緩衝區源顏色Alpha的值。
DstColor 使用此因子爲將當前值乘以幀緩衝區源顏色的值。
DstAlpha 使用此因子爲將當前值乘以幀緩衝區源顏色Alpha分量的值。
OneMinusSrcColor 使用此因子爲將當前值乘以(1 -幀緩衝區源顏色值)
OneMinusSrcAlpha 使用此因子爲將當前值乘以(1 -幀緩衝區源顏色Alpha分量的值)
OneMinusDstColor 使用此因子爲將當前值乘以(1 –目標顏色值)
OneMinusDstAlpha 使用此因子爲將當前值乘以(1 –目標Alpha分量的值)

2.3 常見的混合操作句法示例

上面都是一些句法和列表的列舉,往往會令人一頭霧水,下面這是一些示例,用其中的任何一句加在Pass中就可以實現對應的混合操作了:

Blend SrcAlpha OneMinusSrcAlpha    // Alpha混合
Blend One One                       // 相加
Blend One OneMinusDstColor         // 比較柔和的相加(SoftAdditive)
Blend DstColor Zero                  // 乘法
Blend DstColor SrcColor              // 2倍乘法

三、QianMo's Toolkit升級到v1.3

這次QianMo's Toolkit又迎來了新的特性——飛翔。

將腳本賦給Controller,並調整相應的速度,(並可以先禁掉之前的鼠標視角控制相關腳本)然後點運行,並可以在天空中自由地飛翔了。

其中用W、A、S、D控制前後左右,R、F控制上升下降。

其代碼如下:


 
  1. //-----------------------------------------------【腳本說明】-------------------------------------------------------

  2. // 腳本功能: 控制Contorller在場景中飛翔

  3. // 使用語言: C#

  4. // 開發所用IDE版本:Unity4.5 06f 、Visual Studio 2010

  5. // 2014年12月 Created by 淺墨

  6. // 更多內容或交流,請訪問淺墨的博客:http://blog.csdn.net/poem_qianmo

  7. //---------------------------------------------------------------------------------------------------------------------

  8. //-----------------------------------------------【使用方法】-------------------------------------------------------

  9. // 第一步:在Unity中拖拽此腳本到場景的Controller之上,或在Inspector中[Add Component]->[淺墨's Toolkit]->[SetMaxFPS]

  10. // 第二步:在面板中設置相關鼠標速度

  11. //---------------------------------------------------------------------------------------------------------------------

  12. using UnityEngine;

  13. using System.Collections;

  14. //添加組件菜單

  15. [AddComponentMenu("淺墨's Toolkit/FlyController")]

  16. public class FlyController : MonoBehaviour

  17. {

  18. //參數定義

  19. public float lookSpeed = 5.0f;

  20. public float moveSpeed = 1.0f;

  21. public float rotationX = 0.0f;

  22. public float rotationY = 0.0f;

  23. void Update()

  24. {

  25. //獲取鼠標偏移量

  26. rotationX += Input.GetAxis("Mouse X") * lookSpeed;

  27. rotationY += Input.GetAxis("Mouse Y") * lookSpeed;

  28. rotationY = Mathf.Clamp(rotationY, -90, 90);

  29. //鼠標控制視角

  30. transform.localRotation = Quaternion.AngleAxis(rotationX, Vector3.up);

  31. transform.localRotation *= Quaternion.AngleAxis(rotationY, Vector3.left);

  32. transform.position += transform.forward * moveSpeed * Input.GetAxis("Vertical");

  33. transform.position += transform.right * moveSpeed * Input.GetAxis("Horizontal");

  34. //I鍵,向上平移

  35. if (Input.GetKey(KeyCode.R))

  36. transform.position += transform.up * moveSpeed;

  37. //K鍵,向下平移

  38. if (Input.GetKey(KeyCode.F))

  39. transform.position -= transform.up * moveSpeed;

  40. }

  41. }

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章