Unity3D Shader 入門
什麼是Shader
Shader(著色器)是一段能夠針對3D物件進行操作、並被GPU所執行的程式。Shader並不是一個統一的標準,不同的圖形介面的Shader並不相同。OpenGL的著色語言是GLSL, NVidia開發了Cg,而微軟的Direct3D使用高階著色器語言(HLSL)。而Unity的Shader 是將傳統的圖形介面的Shader(由 Cg / HLSL編寫)嵌入到獨有的描述性結構中而形成的一種程式碼生成框架,最終會自動生成各硬體平臺自己的Shader,從而實現跨平臺。
Unity Shader 其實並不難,初學者往往很迷惑是因為它有太多固定的命令和結構,而這些命令又需要我們對3D渲染有一定的瞭解才能知道它們是做什麼的。
Shader種類
OpenGL和Direct3D都提供了三類著色器:
- 頂點著色器:處理每個頂點,將頂點的空間位置投影在螢幕上,即計算頂點的二維座標。同時,它也負責頂點的深度緩衝(Z-Buffer)的計算。頂點著色器可以掌控頂點的位置、顏色和紋理座標等屬性,但無法生成新的頂點。頂點著色器的輸出傳遞到流水線的下一步。如果有之後定義了幾何著色器,則幾何著色器會處理頂點著色器的輸出資料,否則,光柵化器繼續流水線任務。
- 畫素著色器(Direct3D),常常又稱為片斷著色器(OpenGL):處理來自光柵化器的資料。光柵化器已經將多邊形填滿並通過流水線傳送至畫素著色器,後者逐畫素計算顏色。畫素著色器常用來處理場景光照和與之相關的效果,如凸凹紋理對映和調色。名稱片斷著色器似乎更為準確,因為對於著色器的呼叫和螢幕上畫素的顯示並非一一對應。舉個例子,對於一個畫素,片斷著色器可能會被呼叫若干次來決定它最終的顏色,那些被遮擋的物體也會被計算,直到最後的深度緩衝才將各物體前後排序。
- 幾何著色器:可以從多邊形網格中增刪頂點。它能夠執行對CPU來說過於繁重的生成幾何結構和增加模型細節的工作。Direct3D版本10增加了支援幾何著色器的API, 成為Shader Model 4.0的組成部分。OpenGL只可通過它的一個外掛來使用幾何著色器。
Unity Shader 分為 表面著色器(Surface Shader)和 頂點片段著色器(Vertex And Fragment Shader)。
- 表面著色器(Surface Shader)是Unity提出的一個概念。編寫著色器與光照的互動是複雜的,光源有很多型別,不同的陰影選項,不同的渲染路徑(正向和延時渲染),表面著色器將這一部分簡化。Unity建議使用表面著色器來編寫和光照有關的Shader。
- 頂點片段著色器(Vertex And Fragment Shader)和OpenGL,Direct3D中的頂點著色器和片段著色器沒有什麼區別。頂點片段著色器比表面著色器使用更自由也更強大,當然光照需要自行處理。Unity也允許在裡面編寫幾何著色器,一般用得不多。
Shader程式結構
Shader語法:
//Shader語法:
Shader "name" { [Properties] Subshaders [Fallback] [CustomEditor] }
//Properties 語法
Properties { Property [Property ...] }
// Subshader 語法
Subshader { [Tags] [CommonState] Passdef [Passdef ...] }
// Pass 語法
Pass { [Name and Tags] [RenderSetup] }
// Fallback 語法
Fallback "name"
- 屬性定義(Property Definition):定義Shader的輸入,這些輸入可以在材質編輯的時候指定
- 子著色器(SubShader):一個Shader可以有多個子著色器。這些子著色器互不相干且只有一個會在最終的平臺執行。編寫多個的目的是解決相容性問題。Unity會自己選擇相容終端平臺的Shader執行。
- 回滾(Fallback):如果子著色器在終端平臺上都無法執行,那麼使用Fallback指定的備用Shader,俗稱備胎。
- Pass:一個Pass就是一次繪製。對於表面著色器,只能有一個Pass,所以不存在Pass節。頂點片段著色器可以有多個Pass。多次Pass可以實現很多特殊效果,例如當人物被環境遮擋時還可以看到人物輪廓就可以用多Pass來實現。
- Cg程式碼:每個Pass中都可以包含自定義的Cg程式碼,從CGPROGRAM開始到ENDCG結束。
基本的表面著色器示例:
Shader "Custom/NewShader" {
Properties {
_MainTex ("Base (RGB)", 2D) = "white" {}
}
SubShader {
Tags { "RenderType" = "Opaque" }
LOD 200
CGPROGRAM
#pragma surface surf Lambert
sampler2D _MainTex;
struct Input {
float2 uv_MainTex;
};
void surf (Input IN, inout SurfaceOutput o) {
half4 c = tex2D (_MainTex, IN.uv_MainTex);
o.Albedo = c.rgb;
o.Alpha = c.a;
}
ENDCG
}
FallBack "Diffuse"
}
基本的頂點片段著色器示例:
Shader "VertexInputSimple" {
SubShader {
Pass {
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct v2f {
float4 pos : SV_POSITION;
fixed4 color : COLOR;
};
v2f vert (appdata_base v)
{
v2f o;
o.pos = mul (UNITY_MATRIX_MVP, v.vertex);
o.color.xyz = v.normal * 0.5 + 0.5;
o.color.w = 1.0;
return o;
}
fixed4 frag (v2f i) : SV_Target { return i.color; }
ENDCG
}
}
}
Shader 輸入
Shader的輸入有兩個來源,一是通過屬性定義,一是通過Shader.SetGlobalXXX方法全域性設定。
屬性定義變數:屬性定義中的變數是Shader引數的主要設定方式。 它是隨材質變化的,每個使用該Shader的材質都可以在Inspector或者指令碼中設定這些引數。這些引數除了在Shader的Properties段中定義外,還需要在Cg中宣告方可使用。例如上面表面著色器的例子中我們定義了_MainTex這個型別為2D的屬性,還需要在Cg中宣告 sampler2D _MainTex。
全域性變數:Shader有一組SetGlobalXXX方法,可以對Shader的在Cg中定義而沒有在屬性中定義的uniform變數進行設定。這個設定是全域性的,所有定義了該uniform的Shader都會受到影響。例如我們希望場景隨著時間變化而改變顏色,就可以給場景所使用到的Shader設定統一的全域性顏色變數,然後在指令碼中通過設定該顏色來改變場景的顏色。在角色釋放技能時場景變黑也可以使用這個方法。
Unity shader 中允許定義的屬性型別有:
關鍵字 | 型別 | 對應Cg型別 | 例 |
---|---|---|---|
Float | 浮點數 | float | _MyFloat (“My float”, Float) = 0.5 |
Range | 浮點數 (在指定範圍內) | float | _MyRange (“My Range”, Range(0.01, 0.5)) = 0.1 |
Color | 浮點四元組 | float4 | _MyColor (“Some Color”, Color) = (1,1,1,1) |
Vector | 浮點四元組 | float4 | _MyVector(“Some Vector”,Vector) = (1,1,1,1) |
2D | 2的階數大小的貼圖 | sampler2D | _MyTexture (“Texture”, 2D) = “white” {} |
Rect | 非2的階數大小的貼圖 | sampler2D | _MyRect(“My Rect”, Rect) = “white” {} |
CUBE | CubeMap | samplerCUBE | _MyCubemap (“Cubemap”, CUBE) = “” {} |
注:CubeMap 是6張有聯絡的2D貼圖的組合主要用來做反射效果(比如天空盒和動態反射)
SubShader
SubShader中除了Pass,有兩個標籤值得關注:LOD和Tags
LOD
LOD是 Level of Detail的簡寫,確切地說是Shader Level of Detail的簡寫,因為Unity中還有一個模型的LOD概念,這是兩個不同的東西。我們這裡只介紹Shader中LOD,模型的LOD請參考這裡。
Shader LOD 就是讓我們設定一個數值,這個數值決定了我們能用什麼樣的Shader。可以通過Shader.maximumLOD或者Shader.globalMaximumLOD 設定允許的最大LOD,當設定的LOD小於SubShader所指定的LOD時,這個SubShader將不可用。通過LOD,我們就可以為某個材質寫一組SubShader,指定不同的LOD,LOD越大則渲染效果越好,當然對硬體的要求也可能越高,然後根據不同的終端硬體配置來設定 globalMaximumLOD來達到兼顧效能的最佳顯示效果。
Unity內建Shader定義了一組LOD的數值,我們在實現自己的Shader的時候可以將其作為參考來設定自己的LOD數值
- VertexLit及其系列 = 100
- Decal, Reflective VertexLit = 150
- Diffuse = 200
- Diffuse Detail, Reflective Bumped Unlit, Reflective Bumped VertexLit = 250
- Bumped, Specular = 300
- Bumped Specular = 400
- Parallax = 500
- Parallax Specular = 600
Tag
SubShader可以被若干的標籤(tags)所修飾,而硬體將通過判定這些標籤來決定什麼時候呼叫該著色器。
比較常見的標籤有:
- Queue
這個標籤很重要,它定義了一個整數,決定了Shader的渲染的次序,數字越小就越早被渲染,早渲染就意味著可能被後面渲染的東西覆蓋掉看不見。
預定義的Queue有:
名字 | 值 | 描述 |
---|---|---|
Background | 1000 | 最早被呼叫的渲染,用來渲染天空盒或者背景 |
Geometry | 2000 | 這是預設值,用來渲染非透明物體(普通情況下,場景中的絕大多數物體應該是非透明的) |
AlphaTest | 2450 | 用來渲染經過Alpha Test的畫素,單獨為AlphaTest設定一個Queue是出於對效率的考慮 |
Transparent | 3000 | 以從後往前的順序渲染透明物體 |
Overlay | 4000 | 用來渲染疊加的效果,是渲染的最後階段(比如鏡頭光暈等特效) |
- RenderType
“Opaque”或”Transparent”是兩個常用的RenderType。如果輸出中都是非透明物體,那寫在Opaque裡;如果想渲染透明或者半透明的畫素,那應該寫在Transparent中。這個Tag主要用ShaderReplacement,一般情況下這Tag好像也沒什麼作用。
CommonState
SubShader中可以定義一組Render State,基本上就是一些渲染的開關選項,他們對該SubShader的所有的Pass都有效,所以稱Common。這些Render State也可以在每個Pass中分別定義,將在Pass中詳細介紹。
Pass
Render State
Render State主要就是控制渲染過程的一些開關選項,例如是否開啟alpha blending ,是否開啟depth testing。
常用的Render State有:
Cull
用法:Cull Back | Front | Off
多邊形表面剔除開關。Back表示背面剔除,Front表示正面剔除,Off表示關閉表面剔除即雙面渲染。有時候如裙襬,飄帶之類很薄的東西在建模時會做成一個面片,這就需要設定Cull Off來雙面渲染,否則背面會是黑色。ZWrite
用法:ZWrite On | Off
控制當前物件的畫素是否寫入深度緩衝區(depth buffer),預設是開啟的。一般來說繪製不透明物體的話ZWrite開啟,繪製透明或半透明物體則ZWrite關閉。
深度緩衝區:當圖形處理卡渲染物體的時候,每一個所生成的畫素的深度(即 z 座標)就儲存在一個緩衝區中。這個緩衝區叫作 z 緩衝區或者深度緩衝區,這個緩衝區通常組織成一個儲存每個螢幕畫素深度的 x-y 二維陣列。如果場景中的另外一個物體也在同一個畫素生成渲染結果,那麼圖形處理卡就會比較二者的深度,並且保留距離觀察者較近的物體。然後這個所保留的物體點深度儲存到深度緩衝區中。最後,圖形卡就可以根據深度緩衝區正確地生成通常的深度感知效果:較近的物體遮擋較遠的物體。
理解了深度緩衝區也就理解了為什麼繪製透明或半透明物體需要關閉ZWrite, 如果不關閉,透明物體的depth也會被寫入深度緩衝區,從而會剔除掉它後面的物體,後面的物體就不會被渲染,看不見後面的物體還能叫透明嗎?因此我們使用Alpha blending的時候需要設定ZWrite Off。ZTest
用法:ZTest (Less | Greater | LEqual | GEqual | Equal | NotEqual | Always)
控制如何進行深度測試,也就是上面說的圖形處理卡比較二者的深度的比較方法。預設是LEqual。
值得一提的是使用Aplha blending的時候ZWrite需要關閉但是ZTest是要開啟的,因為如果透明物體前面還有不透明物體,透明物體還是應該被遮擋剔除的。Blend
混合。控制了每個Shader的輸出如何和螢幕上已有的顏色混合。
用法:
Blend Off: 關閉混合
Blend SrcFactor DstFactor:最終顏色 = Shader產生的顏色 × SrcFactor + 螢幕上原來的顏色 × DstFactor
Blend SrcFactor DstFactor, SrcFactorA DstFactor:和上面一樣,只是Alpha通道使用後面兩個引數計算
常用的Blend模式有:
Blend SrcAlpha OneMinusSrcAlpha // Alpha blending
Blend One One // Additive
Blend OneMinusDstColor One // Soft Additive
Blend DstColor Zero // Multiplicative
Blend DstColor SrcColor // 2x Multiplicative
具體參考這裡
Unity5開始下列固定功能的Shader命令被標記為過時了,這些命令的功能現在建議在Shader(Cg)中通過程式碼來實現,這裡列出是為了方便閱讀以前寫的Shader:
- Lighting On | Off
- Material { Material Block }
- SeparateSpecular On | Off
- Color Color-value
- ColorMaterial AmbientAndDiffuse | Emission
- Fog { Fog Block }
- AlphaTest (Less | Greater | LEqual | GEqual | Equal | NotEqual | Always) CutoffValue
- SetTexture textureProperty { combine options }
Surface Shader
Surface Shader 隱藏了很多光照處理的細節,它的設計初衷是為了讓使用者僅僅使用一些指令(#pragma)就可以完成很多事情,並且封裝了很多常用的光照模型和函式。相比底層的Vertex And Fragment Shader,Suface Shader的限制比較多,它只能有一次Pass。如果做一些常規的功能又需要光照,可以用Surface Shader寫,比較快速便捷。如果要寫比較高階的Shader還是建議使用Vertex Shader 和 Fragment Shader。
Surface Shader主要有兩部分組成,一個是#pragma後面的指令,一個是surf函式。
pragma的語法是 #pragma surface surfaceFunction lightModel [optionalparams]
- surfaceFunction 通常就是名為surf的函式, 函式名可以自己取
surf函式原型是:void surf (Input IN, inout SurfaceOutput o)
- lightModel是Unity內建的光照模型,可以是Lambert,Blinn-Phong等。
- optionalparams: 包含很多指令 詳細引數參考這裡
surf函式主要有一個Input結構的輸入和SurfaceOutput結構的輸出。
Input
Input 結構需要在Shader中定義。它可以包含如下欄位, 如果你定義了這些欄位就可以在surf函式中使用它們(好神奇的黑科技)
- 多個貼圖的uv座標,名字必須符合格式uv+貼圖名。例如
float2 uv_MainTex
- float3 viewDir - 檢視方向( view direction)值。為了計算視差效果(Parallax effects),邊緣光照(rim lighting)等,需要包含檢視方向( view direction)值。
- float4 with COLOR semantic - 每個頂點(per-vertex)顏色的插值。
- float4 screenPos - 螢幕空間中的位置。 為了反射效果,需要包含螢幕空間中的位置資訊。比如在Dark Unity中所使用的 WetStreet著色器。
- float3 worldPos - 世界空間中的位置。
- float3 worldRefl - 世界空間中的反射向量。如果表面著色器(surface shader)不寫入法線(o.Normal)引數,將包含這個引數。 請參考這個例子:Reflect-Diffuse 著色器。
- float3 worldNormal - 世界空間中的法線向量(normal vector)。如果表面著色器(surface shader)不寫入法線(o.Normal)引數,將包含這個引數。
- float3 worldRefl; INTERNAL_DATA - 世界空間中的反射向量。如果表面著色器(surface shader)不寫入法線(o.Normal)引數,將包含這個引數。
- float3 worldNormal; INTERNAL_DATA -世界空間中的法線向量(normal vector)。如果表面著色器(surface shader)不寫入法線(o.Normal)引數,將包含這個引數。
SurfaceOutput
SurfaceOutput 描述了表面的特性(光照的顏色反射率、法線、散射、鏡面等),這個結構是固定的,不需要在Shader中再定義。
struct SurfaceOutput {
half3 Albedo; //反射率,一般就是在光照之前的原始顏色
half3 Normal; //法線
half3 Emission; //自發光,用於增強物體自身的亮度,使之看起來好像可以自己發光
half Specular; //鏡面
half Gloss; //光澤
half Alpha; //透明
};
Unity5 由於引入了基於物理的光照模型,所以新增加了兩個Output
struct SurfaceOutputStandard
{
fixed3 Albedo; // base (diffuse or specular) color
fixed3 Normal; // tangent space normal, if written
half3 Emission;
half Metallic; // 0=non-metal, 1=metal
half Smoothness; // 0=rough, 1=smooth
half Occlusion; // occlusion (default 1)
fixed Alpha; // alpha for transparencies
};
struct SurfaceOutputStandardSpecular
{
fixed3 Albedo; // diffuse color
fixed3 Specular; // specular color
fixed3 Normal; // tangent space normal, if written
half3 Emission;
half Smoothness; // 0=rough, 1=smooth
half Occlusion; // occlusion (default 1)
fixed Alpha; // alpha for transparencies
};
Unity提供了一些基本的SurfaceShader的例子,有助於我們理解輸入輸出是如何被使用的。
Unity提供的SurfaceShader的例子
Vertex Shader
如果不想使用Surface Shader而直接編寫opengl和Direct3D中常見的頂點著色器和片段著色器,可以通過Cg程式碼段嵌入到Pass中:
Pass {
// ... the usual pass state setup ...
CGPROGRAM
// compilation directives for this snippet, e.g.:
#pragma vertex vert
#pragma fragment frag
// the Cg/HLSL code itself
ENDCG
// ... the rest of pass setup ...
}
其中vert就是頂點著色器函式,frag就是片段著色器函式。一般來說,可以在頂點著色器中進行的計算就不應該放到片段著色器中去算,因為頂點著色器是逐頂點計算的而片段著色器是逐畫素計算的,一個模型頂點總比表明畫素少很多吧。
編寫頂點和片段著色器一般需要包含Unity預定義的一個幫助檔案UnityCG.cginc,裡面預定義了一些常用的結構和方法。Windows版Unity這個檔案位於({unity install path}/Data/CGIncludes/UnityCG.cginc
。 Mac版位於/Applications/Unity/Unity.app/Contents/CGIncludes/UnityCG.cginc
。
在程式碼中我們只需要新增 #include "UnityCG.cginc"
就可以使用裡面的結構和方法。
Input
頂點著色器的原型是 v2f vert (appdata v)
appdata 是輸入,可以自己定義也可以使用Unity預定義的。Unity在UnityCG.cginc預定義了三種常用的輸入結構:appdata_base,appdata_tan,appdata_full。
struct appdata_base {
float4 vertex : POSITION;
float3 normal : NORMAL;
float4 texcoord : TEXCOORD0;
};
struct appdata_tan {
float4 vertex : POSITION;
float4 tangent : TANGENT;
float3 normal : NORMAL;
float4 texcoord : TEXCOORD0;
};
struct appdata_full {
float4 vertex : POSITION;
float4 tangent : TANGENT;
float3 normal : NORMAL;
float4 texcoord : TEXCOORD0;
float4 texcoord1 : TEXCOORD1;
float4 texcoord2 : TEXCOORD2;
float4 texcoord3 : TEXCOORD3;
#if defined(SHADER_API_XBOX360)
half4 texcoord4 : TEXCOORD4;
half4 texcoord5 : TEXCOORD5;
#endif
fixed4 color : COLOR;
};
我們注意到這些結構的欄位和表面著色器中的欄位不同,後面多了一個冒號和一個標籤。這是該欄位的語義,用於告訴GPU這個欄位的資料應該去哪裡讀寫。GPU畢竟是為了圖形計算而特別設計的東西,很多東西都是固定的,我們只要記得有這麼幾個名字可以用行了。
型別 | 名字 | 標籤 | 備註 |
---|---|---|---|
float4 | vertex | POSITION | 頂點在模型座標系下的位置 |
float3 | normal | NORMAL | 頂點的法向量 |
float4 | tangent | TANGENT | 頂點的切向量 |
float4 | color | COLOR | 頂點色 |
float4 | texcoord | TEXCOORD0 | 頂點的第一個uv座標 |
float4 | texcoord1 | TEXCOORD1 | 頂點的第二個uv座標,最多可以到5 |
Output
頂點著色器的輸出是也是一個可以自己定義的結構,但是結構內容也是比較固定的,一般包含了頂點投影后的位置,uv,頂點色等,也可以加一些後面片段著色器需要用到但是需要在頂點著色器中計算的值。這個輸出就是後面片段著色器的輸入。
struct v2f
{
float4 pos : SV_POSITION;
half2 uv : TEXCOORD0;
};
可以使用的欄位有:
型別 | 標籤 | 描述 |
---|---|---|
float4 | SV_POSITION | 頂點在投影空間下的位置,注意和輸入的模型座標系下的位置不同,這個欄位必必須設定,這個座標轉換是頂點著色器的重要工作 |
float3 | NORMAL | 頂點在檢視座標系下的法向量 |
float4 | TEXCOORD0 | 第一張貼圖的uv座標 |
float4 | TEXCOORD1 | 第二張貼圖的uv座標 |
float4 | TANGENT | 切向量,主要用來修正法線貼圖Normal Maps |
fixed4 | COLOR | 第一個定點色 |
fixed4 | COLOR1 | 第二個定點色 |
Any | Any | 其他自定義的欄位 |
座標變換
頂點著色器有一項重要的工作就是進行座標變換。頂點著色器的輸入中的座標是模型座標系(ObjectSpace)下的座標,而最終繪製到螢幕上的是投影座標。
在我們Shader裡面只需要一句話就可以完成座標的轉換,這也是最簡單的頂點著色器:
v2f vert(appdata v) {
v2f o;
o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
return o;
}
用UNITY_MATRIX_MVP矩陣乘以頂點在模型座標系下的座標就得到投影座標。
UNITY_MATRIX_MVP是Unity內建的模型->視->投影矩陣, Unity內建矩陣如下:
- UNITY_MATRIX_MVP:當前模型->檢視->投影矩陣。(注:模型矩陣為 本地->世界)
- UNITY_MATRIX_MV:當前模型->檢視矩陣
- UNITY_MATRIX_V:當前檢視矩陣
- UNITY_MATRIX_P:當前投影矩陣
- UNITY_MATRIX_VP:當前檢視->投影矩陣
- UNITY_MATRIX_T_MV:轉置模型->檢視矩陣
- UNITY_MATRIX_IT_MV:逆轉置模型->視矩陣, 用於將法線從ObjectSpace旋轉到WorldSpace。為什麼法線變化不能和位置變換一樣用UNITY_MATRIX_MV呢?一是因為法線是3維的向量而- UNITY_MATRIX_MV是一個4x4矩陣,二是因為法線是向量,我們只希望對它旋轉,但是在進行空間變換的時候,如果發生非等比縮放,方向會發生偏移。
- UNITY_MATRIX_TEXTURE0 to UNITY_MATRIX_TEXTURE3:紋理變換矩陣
下面簡單介紹一下里面提到的幾個座標系:
模型座標系:也叫物體座標系,3D建模的時候每個模型都是在自己的座標系下建立的,如果一個人物模型腳底是(0,0,0) 點的話它的身上其它點的座標都是相對腳底這個原點的。
世界座標系:我們場景是一個世界,有自己的原點,模型放置到場景中後模型上的每個頂點就有了一個新的世界座標。這個座標可以通過模型矩陣×模型上頂點的模型座標得到。
檢視座標系:又叫觀察座標系,是以觀察者(相機)為原點的座標系。場景中的物體只有被相機觀察到才會繪製到螢幕上,相機可以設定視口大小和裁剪平面來控制可視範圍,這些都是相對相機來說的,所以需要把世界座標轉換到檢視座標系來方便處理。
投影座標系:場景是3D的,但是最終繪製到螢幕上是2D,投影座標系完成這個降維的工作,投影變換後3D的座標就變成2D的座標了。投影有平行投影和透視投影兩種,可以在Unity的相機上設定。
螢幕座標系 : 最終繪製到螢幕上的座標。螢幕的左下角為原點。
除了內建矩陣,Unity還內建了一些輔助函式也可以在頂點著色器裡面使用:
- float3 WorldSpaceViewDir (float4 v):根據給定的區域性空間頂點位置到相機返回世界空間的方向(非規範化的)
- float3 ObjSpaceViewDir (float4 v):根據給定的區域性空間頂點位置到相機返回區域性空間的方向(非規範化的)
- float2 ParallaxOffset (half h, half height, half3 viewDir):為視差法線貼圖計算UV偏移
- fixed Luminance (fixed3 c):將顏色轉換為亮度(灰度)
- fixed3 DecodeLightmap (fixed4 color):從Unity光照貼圖解碼顏色(基於平臺為RGBM 或dLDR)
- float4 EncodeFloatRGBA (float v):為儲存低精度的渲染目標,編碼[0..1)範圍的浮點數到RGBA顏色。
- float DecodeFloatRGBA (float4 enc):解碼RGBA顏色到float。
- float2 EncodeViewNormalStereo (float3 n):編碼檢視空間法線到在0到1範圍的兩個數。
- float3 DecodeViewNormalStereo (float4 enc4):從enc4.xy解碼檢視空間法線
Fragment Shader
// TODO
相關推薦
貓都能學會的Unity3D Shader入門指南(一)
val int 系列 opengl 概念 想要 ble 結果 shade 動機 自己使用Unity3D也有一段時間了,但是很多時候是流於表面,更多地是把這個引擎簡單地用作腳本控制,而對更深入一些的層次幾乎沒有了解。雖然說Unity引擎設計的初衷就是創建簡單的不需要開發者操
Unity3D Shader 入門
什麼是Shader Shader(著色器)是一段能夠針對3D物件進行操作、並被GPU所執行的程式。Shader並不是一個統一的標準,不同的圖形介面的Shader並不相同。OpenGL的著色語言是GLSL, NVidia開發了Cg,而微軟的Direct3D使用高
Unity3D Shader 入門之簡單案例的實現(通過法線實現顏色變化)
在沒有接觸Unity3D Shader 之前,總感覺shader特別神奇,因為聽說是對渲染流水線進行程式設計,就是對GPU進行程式設計。聽著特別高大上。這不,最近剛剛接觸Shader,學了幾個小案例,然後本文作為學習筆記將這個小案例的實現記錄下來。 筆者也是剛開始學習shader 沒幾天。在剛開
Unity3D shader專題
unity3d 總結 bsp shade com tar csdn 學習 htm Unity模型部分隱藏著色器 http://blog.csdn.net/milk713785/article/details/52550130 Unity3d 描邊shader介紹 ht
Unity3D Shader落雪效果
pragma shader obj 分享 imc ges rim pass main Shader "Custom/Snow" { Properties { _MainTex ("Base (RGB)", 2D) = "white" {}
Unity3D Shader圖像扭曲過場效果
mat 分享 col target lec ota dep 技術分享 腳本 把腳本掛在攝像機上 using UnityEngine; using System.Collections; [RequireComponent(typeof(Camera))] pub
Unity Shader入門精要學習筆記 - 第4章 學習 Shader 所需的數學基礎
旋轉矩陣 即使 模擬 能夠 一點 空間使用 虛擬 地板 金字塔 摘錄自 馮樂樂的《Unity Shader入門精要》 笛卡爾坐標系 1)二維笛卡爾坐標系 在遊戲制作中,我們使用的數學絕大部分都是計算位置、距離、角度等變量。而這些計算大部分都是在笛卡爾坐標系下進行的。 一個二
Unity Shader入門精要學習筆記 - 第3章 Unity Shader 基礎
但是 detail spa net 表示 part 文件 人的 text 來源作者:candycat http://blog.csdn.net/candycat1992/article/ 概述 總體來說,在Unity中我們需要配合使用材質和Unity Shader才能達
Unity Shader入門精要學習筆記 - 第11章 讓畫面動起來
位置 視覺效果 想要 朝向 系列 圖像 顏色 offset star 轉自 馮樂樂的 《Unity Shader入門精要》 Unity Shader 中的內置變量 動畫效果往往都是把時間添加到一些變量的計算中,以便在時間變化時畫面也可以隨之變化。Unity Shader 提
Unity Shader入門精要學習筆記 - 第16章 Unity中的渲染優化技術
也會 檢測 特點 著色器 版本 切換 代碼優化 學習 順序 轉自馮樂樂的 《Unity Shader 入門精要》 移動平臺的特點 為了盡可能一處那些隱藏的表面,減少overdraw(即一個像素被繪制多次),PowerVR芯片(通常用於ios設備和某些Android設備)使用
Unity Shader入門精要學習筆記 - 第14章非真實感渲染
只需要 遮擋 本質 lar 屏幕 準備 dot smo try 轉載自 馮樂樂的 《Unity Shader 入門精要》 盡管遊戲渲染一般都是以照相寫實主義作為主要目標,但也有許多遊戲使用了非真實感渲染(NPR)的方法來渲染遊戲畫面。非真實感渲染的一個主要目標是,使用一些渲
Unity Shader入門精要學習筆記 - 第10章 高級紋理
unp string math 計算 圖像繪制 兩種方法 內存 對象 交叉 轉載自 馮樂樂的 《Unity Shader入門精要》 立方體紋理 在圖形學中,立方體紋理是環境映射的一種實現方法。環境映射可以模擬物體周圍的環境,而使用了環境映射的物體可以看起來像鍍了層金屬一樣反
Unity3D Shader 高斯模糊
logs ++ sampler += form return turn gauss pub //Shader Shader "Hidden/GaussianBlur" { Properties { _MainTex ("Texture"
Shader 入門筆記(二) CPU和GPU之間的通信
draw drawcall 進行 時間 包含 spa 入門 光柵 著色器 渲染流水線的起點是CPU,即應用階段。 1)把數據加載到顯存中 2)設置渲染狀態,通俗說這些狀態定義了場景中的網格是怎樣被渲染的。 3)調用DrawCall,一個命令,CPU通知GPU。(
Unity3D -- shader光照常用函數和變量
ace mod 因子 htm cookie dbase final pac ase 上一篇記錄了shader常用函數和變量,這篇記錄一些光照計算時常用函數和變量 1、內置的光照變量 _LightColor0 float4 //該Pass處理的逐像素光源的顏色 _W
Unity3D -- shader常用函數和變量
erp unity blog 翻轉 修飾 osi view ase right 最近在學習Unity Shader,寫Shader的時候總是忘記Unity為我們提供的函數、變量怎麽寫的,這裏整理一下,方便自己查閱,也提供給網友,學習Shader不易。 1、函數 floa
unity shader 入門
div 技術分享 調用 pos sub 組件 matrix com chap 1.一個簡單的頂點/片元著色器基本結構 Shader "Unity Shaders Book/Chapter 5/Simple Shader" { } SubShader
Unity學習(三)Unity Shader入門(基礎知識篇)+線性代數複習(未完待續)
至於為什麼剛建立了指令碼,現在就要做Shader了。。說多了都是淚 1.建立一個新的材質 Material Assert -> Create -> Material 拖到Scene中的某個物體上 2.建立一個新的Shader Assert -> Create -
象素shader入門(Introduction to Pixel Shaders)
分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!  
獲取深度和法線紋理 背後的原理【Unity Shader入門精要13.1.1】
13.1.1背後的原理 什麼是深度紋理: 實際上就是一張渲染紋理,只不過它裡面儲存的畫素值不是顏色值,而是一個高精度的深度值,由於被儲存在一張紋理中,深度紋理裡的深度範圍是[0,1],而且通常是 非線性分佈的。 深度值來自頂點變換後得到的歸一化的裝置座標(Normali