Shader學習參考資料
流水線:
1.應用階段:(CPU)輸出渲染圖元,粗粒度剔除等 比如完全不在相機範圍內的需要剔除,檔案系統的粒子系統實現就用到粗粒度剔除。
2.幾何階段:(GPU)把頂點座標轉換到螢幕空間,包含了模型空間 到世界空間 到觀察空間(相機視角view) 到齊次裁剪空間(投影project2維空間,四維矩陣,通過-w<x<w判斷是否在裁剪空間)
到歸一化裝置座標NDC(四維矩陣通過齊次除法,齊次座標的w除以xyz實現歸一化) 到螢幕空間(通過螢幕寬高和歸一化座標計算)。
a.頂點著色器:座標變換和逐頂點光照,將頂點空間轉換到齊次裁剪空間。
b.曲面細分著色器:可選
c.幾何著色器:可選
d.裁剪:通過齊次裁剪座標的-w<x<w判斷不在視野範圍內的部分或者全部裁剪,歸一化。
e.螢幕對映:把NDC座標轉換為螢幕座標
3.光柵化階段:(GPU)把幾何階段傳來的資料來產生螢幕上的畫素,計算每個圖元覆蓋了哪些畫素,計算他們的顏色、
a.三角形設定:計算網格的三角形表示式
b.三角形遍歷:檢查每個畫素是否被網格覆蓋,被覆蓋就生成一個片元。
c.片元著色器:對片元進行渲染操作
d.逐片元操作:模板測試,深度測試 混合等
e.螢幕影象
矩陣:
M*A=A*M的轉置(M是矩陣,A是向量,該公式不適合矩陣與矩陣)
座標轉換:
o.pos = mul(UNITY_MATRIX_MVP, v.vertex);頂點位置模型空間到齊次空間
o.worldNormal = mul((float3x3)_Object2World,v.normal);//遊戲中正常的法向量轉換,轉換後法向量可能不與原切線垂直,但是不影響遊戲顯示,而且大部分顯示也是差不多的。一般用這個就行了。
o.worldNormal = mul(v.normal, (float3x3)_World2Object);頂點法向量從模型空間轉換到世界空間的精確演算法,公式是用_Object2World該矩陣的逆轉置矩陣去轉換法線。然後通過換算得到該行。
API:
UNITY_MATRIX_MVP 將頂點方向向量從模型空間變換到裁剪空間
UNITY_MATRIX_MV 將頂點方向向量從模型空間變換到觀察空間
UNITY_MATRIX_V 將頂點方向向量從世界空間變換到觀察空間
UNITY_MATRIX_P 將頂點方向向量從觀察空間變換到裁剪空間
UNITY_MATRIX_VP 將頂點方向向量從世界空間變換到裁剪空間
UNITY_MATRIX_T_MV UNITY_MATRIX_MV的轉置矩陣(所謂轉置矩陣就是將矩陣的行轉換成相應的列)
UNITY_MATRIX_IT_MV UNITY_MATRIX_MV的逆轉置矩陣,用於將法線從模型空間轉換到觀察空間
UNITY_MATRIX_TEXTURE0 UNITY_MATRIX_TEXTURE3 紋理變換矩陣
_Object2World將頂點方向向量從模型空間轉換到世界空間
_World2Object將頂點方向向量從世界空間變換到模型空間,矩陣。
模型空間到世界空間的矩陣簡稱M矩陣,世界空間到View空間的矩陣簡稱V矩陣,View到Project空間的矩陣簡稱P矩陣。
_WorldSpaceCameraPos該攝像機在世界空間中的座標
_ProjectionParams 投影引數。x=1,如果投影反轉則x = -1;y是camera近裁剪平面;z是camera遠裁剪平面;w是1/遠裁剪平面
_ScreenParams 螢幕引數:x=螢幕寬度,y=螢幕高度,z = 1+1.0/螢幕寬度,w = 1 + 1.0/螢幕高度
_ZBufferParams 用於線性化z buffer(z buffer用於去除隱藏面)
unity_OrthoParams 正交攝像機的相關引數,w值1時是正交投影,0時是透視投影
unity_CameraProjection 攝像機的投影矩陣
unity_CameraInvProjection 攝像機的投影矩陣的逆矩陣
unity_CameraWorldClipPlanes[6] 攝像機在世界座標下的6個剪裁面,分別是左右上下近遠。
表面著色器:
void surf (Input IN, inout SurfaceOutput o) {}表面著色器,unity特殊封裝的著色器
Input IN:可以引用外部定義輸入引數
inout SurfaceOutput o:輸出引數
struct SurfaceOutput//普通光照
{
half3 Albedo;//紋理,反射率,是漫反射的顏色值
half3 Normal;//法線座標
half3 Emission;//自發光顏色
half Specular;//高光,鏡面反射係數
half Gloss;//光澤度
half Alpha;//alpha通道
}
基於物理的光照模型:
金屬工作流SurfaceOutputStandard 高光工作流SurfaceOutputStandardSpecular
half3,half4代表rgba或者xyz,可以分開用 Albedo.xy=1.或Albedo.ga=1
#pragma surface surfname lightModel op - 指出函式surfname 表面著色器。
lightModel的光照模型和可選op操作,還可以新增頂點修改函式vertex和顏色修改函式finalcolor。
#pragma surface surf CustomLambert vertex:myvert finalcolor:mycolor addshadow exclude_path:deferred exclude_path:prepass nometa
#pragma vertex name - 指出函式name 是頂點著色器。
#pragma fragment name - 指出函式name 是片段著色器。
#pragma fragmentoption option - 新增option 到編輯的OpenGL片段程式。參看ARB fragment program說明書瞭解被允許的選項列表。這個指示在頂點程式或者編輯到非OpenGL targets的程式沒有影響。
#pragma multi_compile_builtin - 為了pixel-lit shaders;;這個將告知Unity去編輯大量的這個著色器程式數列以支援所有的照明種類,和所有的陰影選項。
#pragma multi_compile_builtin_noshadows - 對於pixel-lit 著色器,不接受陰影。這將告知Unity去編輯幾個該著色器程式的數列來支援所有的照明種類。這比multi_compile_builtin pragma可以更快的編輯,而且結果著色器也更小。
#pragma target name - 那個著色器target 去編輯。細節參看shader targets。
#pragma only_renderers space separated names - 只為給定的渲染器編輯著色器。預設情況下,著色器為所有的渲染器被編輯。細節參看 renderers。
#pragma exclude_renderers space separated names - 不為給定的渲染器編輯著色器。預設情況下,著色器為所有的渲染器被編輯。細節參看 renderers。
頂點著色器:
struct appdata_full {//vertex輸入
float4 vertex : POSITION;//must
float4 tangent : TANGENT;//切線
float3 normal : NORMAL;
float4 texcoord : TEXCOORD0;//該頂點的紋理座標,第一組紋理座標uv 也就是第一張貼圖的座標、為了實現多重紋理貼圖,比如子彈打在牆上的彈痕等
float4 texcoord1 : TEXCOORD1;//n的數量和shadermodel版本有關
float4 texcoord2 : TEXCOORD2;
fixed4 color : COLOR;//頂點顏色
};
片段著色器:
struct v2f{//vertec的輸出和frag的輸入
float4 vertex :SV_POSITION;//must
float3 color0:COLOR0;
float3 color1:COLOR1;
float4:texcoord:TEXCOORD0;//TEXCOORD0-TEXCOORD7自定義紋理座標
}
SV_Tatget //frag的輸出,輸出float4的顏色
光照:
1.逐頂點光照:在頂點著色器階段計算光照,效率高但是效果不好,在邊緣畫素對映的時候插值可能會產生鋸齒。
2.逐畫素光照:在片元著色器階段計算光照,計算量大,但是邊緣表現效果好。
3.半蘭伯特模型:處理無光照的地方,也讓其有光,不然可能是全黑。經驗模型。
#include "Lighting.cginc"
Tags { "LightMode"="ForwardBase" }
WorldSpaceViewDir(float4 v) 輸入模型空間中的頂點座標,返回世界空間中從該點到攝像機的觀察方向
UnityWorldSpaceViewDir(float4 v) 輸入世界空間中的頂點座標,返回世界空間中從該點到攝像機的觀察方向
ObjSpaceViewDir(float4 v)輸入模型空間中的頂點座標,返回模型空間中從該點到攝像機的觀察方向
WorldSpaceLightDir()僅用於前向渲染,輸入模型空間中的頂點座標,返回世界空間中從該點到光源光照方向,沒有歸一化。
UnityWorldSpaceLightDir()僅用於前向渲染,輸入世界空間中的頂點座標,返回世界空間中從該點到光源光照方向,沒有歸一化。
ObjSpaceLightDir()僅用於前向渲染,輸入模型空間中的頂點座標,返回模型空間中從該點到光源光照方向,沒有歸一化。
UnityObjectToWorldNormal(float3 v)把法線從模型空間轉換到世界空間
UnityObjectToWorldDir(float3 v)把方向向量從模型空間轉換到世界空間
UnityWorldToObjectDir(float3 v)把方向向量從世界空間轉換到模型空間
_WorldSpaceLightPos0.xyz獲取平行光光源方向,或者點光源的光源位置
_LightColor0.rgb獲取當前pass的光源顏色和強度
UNITY_LIGHTMODEL_AMBIENT.xyz; 環境光
normalize(_WorldSpaceCameraPos.xyz - worldPos.xyz); 視覺方向 UnityWorldSpaceViewDir
a.漫反射公式:
diff=C*max(0,cos<L,N>);//C是顏色和強度_LightColor0.rgb
程式碼: diff=max(0,dot(i.normal,i.lightDir))//i的單位向量and單位法向量
c=tex2D(tex,i.uv)*_LightColor0*diff//_LightColor0表示的是場景中平行光的顏色和強度
b.高光反射公式:
Spec=pow(max(0,cos(R,V),gloss))//R 單位反射向量reflect(ray,normal)函式獲取,V視線單位方向向量 ,gloss光色度
程式碼: Spec=pow(max(0),dot(reflect(-i.lightDir,i.normal),32))
c=c**_LightColor0*(diff+Spec)
紋理 uv座標是頂點儲存了圖片上的座標
_MainTex ("Main Tex", 2D) = "white" {}
sampler2D _MainTex;
float4 _MainTex_ST;//Unity中 紋理_ST來預設宣告該紋理的屬性_MainTex_ST.xy表示Scale, Till縮放,_MainTex_ST.zw表示Transform 偏移
o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);//vs輸入紋理座標和紋理值輸出UV,ps對uv進行紋理取樣和計算。UV通常在0-1範圍,等於o.uv = v.texcoord.xy * _MainTex_ST.xy + _MainTex_ST.zw;
fixed3 albedo = tex2D(_MainTex, i.uv).rgb * _Color.rgb;//反射率
法線貼圖:
xyz對映存成rgb值。一般存在切線空間,z軸法線方向,x軸切線方向,y軸副(法)切線方向
TANGENT_SPACE_ROTATION;//Unity來獲取rotation矩陣,從模型空間到切線空間變換的矩陣。僅存在旋轉和平移時,一個矩陣的轉置矩陣等於他的逆矩陣。
自己實現:
float3 binormal = cross( normalize(v.normal), normalize(v.tangent.xyz) ) * v.tangent.w; //切線空間的w分量用來儲存負法線向內還是向外
float3x3 rotation = float3x3(v.tangent.xyz, binormal, v.normal);//float3x3是按行儲存
float3 tangentNormal = UnpackNormal(packedNormal);Unity將法線貼圖紋理座標0,1對映到正常法線座標-1,1,返回切線空間下的法線方向。法線貼圖要設定成Normal格式。該設定unity有優化 rgb值不再是法線xyz的映射了,如果不設定的話要自己算 該公式不能用。
自己實現:
tangentNormal.xy = (packedNormal.xy * 2 - 1) * _BumpScale;//座標反對映,自己計算的方法
tangentNormal.z = sqrt(1.0 - saturate(dot(tangentNormal.xy, tangentNormal.xy)));//通過xy計算z
透明度測試AlphaTest:
只要有一個片元的透明度不滿足條件就被剪裁,用來優化顯示。
AlphaTest Greater AlphaValue//僅渲染 alpha 值大於 AlphaValue 的畫素。AlphaValue :0-1
AlphaTest GEqual AlphaValue//僅渲染 alpha 值大於或等於 AlphaValue 的畫素。
AlphaTest LessAlphaValue//僅渲染 alpha 值小於 AlphaValue 的畫素。
AlphaTest LEqual AlphaValue//僅渲染 alpha 值小於或等於 AlphaValue 的畫素。
AlphaTest Equal AlphaValue//僅渲染 alpha 值等於 AlphaValue 的畫素。
AlphaTest NotEqual AlphaValue//僅渲染 alpha 值不等於 AlphaValue 的畫素。
AlphaTest Always //渲染所有畫素。這在功能上相當於 Alpha 測試關 (AlphaTest Off)。
AlphaTest Never//不渲染任何畫素。
模板測試:
Stencil如果開啟了模板測試,GPU會首先會讀取模板緩衝區的值,然後把該值和讀取的參考值ref進行比較,比較方式由Comp指定,比如大於Greater就表示通過模板測試,
然後由Pass Fail ZFail去指定通過和不通過模板和深度測試後對緩衝區的值進行的Operation處理。
Stencil
{Ref 2 //設定模板參考值為2
Comp equal//比較方式,有8種比較方式。
Pass Operation //這個是當stencil測試和深度測試都通過的時候,進行的stencilOperation操作方法
Fail Operation //這個是在stencil測試通過的時候執行的stencilOperation方法
ZFail Operation//這個是在stencil測試通過,但是深度測試沒有通過的時候執行的stencilOperation方法。
ReadMask readMask//readMask預設是255,一般不用該功能,設定隱碼後 讀取ref和buff值都需要與該碼進行與操作。(0-255)
WriteMask writeMask//寫操作進行與操作
}
Comp 的引數包括Greater/GEqual/Less/LEqual/Equal/NotEqual/Always/Never
Operation的引數包括:
Keep保持
Zero歸零
Replace拿比較的參考值替代原來buffer的值
IncrSat值增加1,但是不溢位,如果是255,就不再加
DecrSat值減少1,不溢位,到0就不再減
Invert翻轉所有的位,所以1會變成254
IncrWrap值增加1,會溢位,所以255會變成0
DecrWrap值減少1,會溢位,所以0會變成255
clip(x) //x的任何分量小於0 被裁剪掉
discard//捨棄當前片元
ZWrite Off//關閉深入寫入
ColorMask RGB|A|0 //設定顏色通道的寫掩碼,為0表示該pass不進行顏色輸出。
深度測試ZTEST:
一個片元離攝像機的遠近,渲染後會進行深度寫入,通常會判斷快取深度和當前片元深度 可知前後關係。
ZTest Always //指的是直接將當前畫素顏色(不是深度)寫進顏色緩衝區中 相當於ZTest Off
ZTest Never//而Never指的是不要將當前畫素顏色寫進顏色緩衝區中,相當於消失。
ZTest Greater/GEqual/Less/LEqual/Equal/NotEqual/Always/Never/Off,預設值為LEqual 即當物體深度小於或等於快取深度值時(越遠深度越大),該物體渲染,就是預設的先後順序渲染。
透明度混合AlphaBlending:
該片元需要關閉深度寫入,不關閉深度測試。會導致片元之間深度穿插。可以採用2個pass,第一個pass只用來做深度寫入ZWrite On,第二個pass只用來輸出顏色ZWrite Off,這樣深度和顏色效果才會正確
Blend Off//關閉混合,只有blend開啟後ps輸出a通道才有意義
Blend SrcFactor DstFactor//用同樣的因子對rgba進行混合(預設都開啟混合)第一個引數對源顏色(當前片元顏色,ps輸出的顏色)*SrcFactor混合,
第二個引數對目標顏色(當前讀到的緩衝區顏色)*DstFactor混合,混合後預設相加後會重新寫入緩衝區(相加後超過1的自動截斷到1)。混合包括RABG值。結果都是源顏色和目標顏色與各自因子相乘後再加起來作為輸出顏色。
shader裡邊的向量相乘不同於點乘叉乘,相當於各項分別相乘。
Blend SrcFactor DstFactor,SrcFactorA DstFactorA//把rgb和a的混合因子分開。
混合因子
One //因子是1
Zero //因子是0
SrcColor//因子為源顏色值,當前片元顏色,對應rgba分量分別與SrcColor分量相乘
SrcCAlpha//因子為源顏色透明值值,對應rgba分別與SrcCAlpha相乘。
DstColor//因子為目標顏色值,當前讀到的緩衝區顏色
DstAlpha//因子為目標顏色透明值值
OneMinusSrcColor//因子為1-源顏色
OneMinusSrcAlpha//因子為1-源alpha
OneMinusDstColor//因子為1-目標顏色
OneMinusDstAlpha//因子為1-目標alpha
例子:
Blend SrcAlpha OneMinusSrcAlpha// Alpha混合,正常的透明度混合
Blend OneMinusDstColor One //柔和相加Soft Additive
Blend One One // Additive相加 線性減淡
Blend One OneMinusDstColor // Soft Additive比較柔和的相加
Blend DstColor Zero // Multiplicative乘法
Blend DstColor SrcColor // 2x Multiplicative2倍乘法
BlendOp OP//對源和目標顏色進行其他操作,而不是預設的相加,op操作包括:
Add //相加
Sub//源顏色減目標顏色
RevSub//目標顏色減源顏色
Min //使用2者較小的值
Max //使用2者較大的值
chen
BlendOp Min
Blend One One //組合變暗
雙面渲染:
一般採用多個pass分別渲染正面和背面
Cull Back|Front|Off
Cull Back預設的背對相機圖元不渲染
Cull Front朝向相機圖元不渲染,只顯示背面
Cull Off關閉剔除功能 全部渲染 效能低,但是可以實現比如看見物體內部結構。
不透明物體有深度測試,先渲前後沒有關係,但是先渲染近的效率會更高,因為遠的會被深度測試自動剔除不用渲染。
透明物體一般要先渲遠的,再渲近的才能保證視覺順序正確。
SubShader的Tag{}標籤型別:
Queue:渲染順序,保證渲染順序小的先渲 大的後渲
RenderType:Unity可以執行時替換符合特定RenderType的所有Shader,著色器分類
ForceNoShadowCasting:值為”true”時,表示不接受陰影。
IgnoreProjector:值為”true”時,表示不接受Projector元件的投影。常用語半透明物體
DisableBatching:是否對subshader進行批處理,當shader中需要對頂點進行偏移的時候,該項設定為true
CanUseSpriteAtlas:當該subshader用於sprite時 該標籤設為false
PreviewType:指明材質麵包怎麼預覽材質 比如 "PreviewType"="Plane"
LightMode : 渲染路徑 ,pass的標籤型別
渲染佇列:
"Queue"="Transparent"
Background:1000 //該宣告的物體最先被渲染
Geometry:2000//預設的不透明物體使用的渲染佇列
AlphaTest:2450//透明度測試,預設不透明物體渲染完後就渲染該物體
Transparent:3000//透明物體,在Geometry和AlphaTest後渲染,保證不透明物體渲染完了再渲染透明的。
Overlay:4000//該佇列用來實現疊加效果,該物體會在最後被渲染。
RenderType:
Opaque:絕大部分不透明的物體都使用這個;
Transparent:絕大部分透明的物體、包括粒子特效都使用這個;
Background:天空盒都使用這個;
Overlay:GUI、鏡頭光暈都使用這個
渲染路徑:
Tag{ "LightMode" = "ForwardBase"}//為每個pass指定渲染路徑
LightMode包括:
Always:所有渲染路徑該pass都會渲染,但不計算光照
ForwardBase:前向渲染,該pass會計算環境光,最重要的平行光,逐頂點光和 Lightmaps
ForwardAdd:前向渲染,該pass會計算額外的逐畫素光源,每個pass對應一個光源。光源多該pass會被多次呼叫 效率變低。
Deferred:延時渲染,該Pass會渲染G-buffer
ShadowCaster:把物體的深度資訊渲染到陰影對映紋理或深度紋理中
PrepassBase:遺留的延遲渲染,該pass會渲染法線和高光反射的指數部分、
PrepassFinal:遺留的延遲渲染,該pass通過合併紋理 光照 自發光來渲染得到最後的顏色
Vertex:遺留的頂點照明渲染
前向渲染:
包括ForwardBase型別渲染常用光照和ForwardAdd額外光照
#pragma multicompile_fwdbase //ForwardBase中用來保證光照衰減等引數正確賦值。
#pragma multicompile_fwdadd //ForwardAdd中用來保證可以訪問到正確的光照變數.
#pragma multicompile_fwdadd_fullshadows //ForwardAdd中用來計算陰影效果
USING_DIRECTIONAL_LIGHT//平行光的巨集定義
_LightColor0//該pass的桌畫素光照顏色
_WorldSpaceLightPos0//獲取平行光光源方向,或者點光源的光源位置
_LightMatrix0//世界空間到光源空間(光源位置為座標原點的座標系)的變換矩陣
_LightTexture0//光照衰減紋理
...........
tips:光源的RendeMode引數設定為Important unity會自動採用畫素光源,如果不重要就是頂點光源。還有qualitysetting裡邊的PixelLIghtCount,超過這個數也會用頂點光照
光照衰減:
float3 lightCoord = mul(_LightMatrix0, float4(i.worldPos, 1)).xyz;
fixed atten = tex2D(_LightTexture0, dot(lightCoord, lightCoord).rr).UNITY_ATTEN_CHANNEL;//UNITY_ATTEN_CHANNEL獲得衰減值所在的分量
float shadow=SHADOW_ATTENUATION(i);//負值使用SHADOW_COORDS對相關紋理進行取樣,返回值為陰影。關閉陰影的狀態是等於1
return fixed4(ambient + (diffuse + specular) * atten * shadow, 1.0);//atten為衰減,shadow為陰影
------計算別人投到自己身上的陰影和衰減
SHADOW_COORDS(n)//宣告一個_ShadowCoord的陰影紋理座標 ps輸入座標,n的值是宣告TEXCOORD0-7座標使用的個數
TRANSFER_SHADOW(o);//用於在頂點著色器中計算上一步宣告中的陰影紋理座標 並傳向ps階段。
float shadow=SHADOW_ATTENUATION(i);//負值使用SHADOW_COORDS對相關紋理進行取樣,返回值為陰影。關閉陰影的狀態是等於1
UNITY_LIGHT_ATTENUATION(atten,v2f i, i.worldPos);//計算別人投影到身上的陰影#include "AutoLight.cginc" Unity會將光照衰減和陰影相乘後存在第一個引數中,並自動宣告atten變數。第二個引數結構體包含SHADOW_COORDS,第三個引數世界空間座標
return fixed4((diffuse + specular) * atten, 1.0);//UNITY_LIGHT_ATTENUATION出的atten為衰減和陰影
-----計算陰影投影到別人身上,自己的陰影
V2F_SHADOW_CASTER//unity裡邊定義陰影投射需要定義的變數
TRANSFER_SHADOW_CASTER_NORMALOFFSET(0)//unity對頂點進行自動處理
SHADOW_CASTER_FRAGMENT(i)//unity自動完成陰影投射部分,把結果輸出到深度圖和陰影對映紋理中
--ds2的陰影採用的是屏幕後處理的方式去計算陰影,延遲渲染
2.頂點照明渲染:過時的渲染方式。效果差。
3.延遲渲染:通常2個pass,第一個pass計算哪些片元可見,第二個pass計算真實光照。
-------------------------------------------------------
1.反射o.worldRefl = reflect(-o.worldViewDir, o.worldNormal);//入射光線,表面法線
2.折射o.worldRefr = refract(-normalize(o.worldViewDir), normalize(o.worldNormal), _RefractRatio);//入射光線,表面法線,介質比
3.鏡子效果:使用相機的RenderTexture來設定渲染紋理。o.uv.x = 1 - o.uv.x;座標需要翻轉一下。
4.玻璃效果:反射和折射使用cubemap進行取樣 是天空盒的cubemap,然後反射需要取樣的是周圍環境的光照和紋理。
GrabPass { "_RefractionTex" }//會把螢幕輸出到_RefractionTex的texture中, _RefractionTex_TexelSize 可以得到該紋理紋素大小,例如255*255的紋素是(1/255,1/255)
GrabPass{} //然後用_GrabTexture直接訪問螢幕影象,但是這樣效率比較低,推薦要上面需要宣告的方法。
o.scrPos = ComputeGrabScreenPos(o.pos);//得到對應被抓取的螢幕影象的取樣座標
反射和折射需要顯示環境的效果,所以需要對環境的cubemap進行取樣。先用反射和折射的公式計算出光線,然後對環境貼圖進行取樣texCUBE(_Cubemap, i.worldRefl).rgb就可以得到具體效果了。
反射skybox 3d取樣,折射螢幕抓取影象2d取樣。
時間變數:
_Time:float4 //t是自該場景載入開始所經過的時間,4個分量是(t/20,t,2t,3t)
_SinTime:float4//t是時間的正玄弦值,四個分量的值分別是(t/8,t/4,t/2,t)
_CosTime:float4//t是時間的餘玄弦值,四個分量的值分別是(t/8,t/4,t/2,t)
unity_DeltaTime:float4// dt是時間增量,4個分量分別是(dt,1/dt,smoothDt,1/smoothDt)
序列幀動畫:時間去控制uv座標對映轉換。uv座標的xy是頂點座標,對映到小格子裡邊,和UItexture的xy和寬高不一樣。
背景偏移動畫:時間控制uv座標偏移。
水流動畫:通過時間和正弦函式去控制頂點偏移,通過時間控制uv移動。設定DisableBatching=true
廣告牌BillBoarding:根據視覺方向來旋轉被紋理著色的多邊形。頂點動畫
屏幕後處理:
void OnRenderImage(RenderTexture src, RenderTexture dest){}//全部渲染完後將呼叫,螢幕紋理存在src上,用來計算後通過dest返回,新增[ImageEffectOpaque]屬性,可使不透明物體(AlphaTest)被渲染完後立即呼叫.
Graphics.Blit(src, dest);//直接copy紋理。src是螢幕當前或上一步渲染的紋理,dest是目標紋理
Graphics.Blit(src, dest, material,pass=-1);//將把src傳到shader的material的_MainTex紋理。經過material(shader)的處理後輸出到dest渲染到螢幕.pass預設是-1會呼叫所有pass,否則只調用給定順序的pass。指定pass渲染很重要。
基於顏色變化的邊緣檢測:Sobel卷積演算法,對邊緣點進行取樣計算 和特定矩陣卷積相乘。
高斯模糊:多次取樣紋理混合 消耗較大
Bloom效果:把較亮區域提取出來進行高斯模糊 模擬擴散效果,然後再與原紋理混合。
運動模糊:將上一幀的螢幕影象存到renderTexture中,然後執行Graphics.Blit(src, renderTexture, material),shader將開啟混合Blend SrcAlpha OneMinusSrcAlpha把src紋理和目標緩衝紋理renderTexture進行混合,然後再Blit輸出到dst進行渲染。就得到了運動模糊效果。
深度和法線紋理:
float linearDepth = LinearEyeDepth(SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, i.uv_depth));
_CameraDepthNormalsTexture //unity中呼叫camera.depthTextureMode=DepthTextureMode.Depth/DepthNormal;這句話後可以通過該變數訪問深度紋理或者深度和法線紋理,project空間
float depth=SAMPLE_DEPTH_TEXTURE(tex,uv)//對深度紋理進行取樣,返回project空間下非線性深度值。和tex2D類似 只是封裝了平臺。自動將NDC座標下的深度對映(0,1)需要轉換到(-1,1)veiw空間去計算
LinearEyeDepth(depth)負責把深度紋理的取樣結果轉換到視角view空間下的線性深度值
Linear01Depth(depth)則會返回一個範圍在0,1的線性深度值
half4 sample1 = tex2D(_CameraDepthNormalsTexture, i.uv);
half2 centerNormal = DecodeViewNormalStereo(sample1);//center.xy存的法線的對映值
float centerDepth = DecodeFloatRG(center.zw);//zw深度
DecodeDepthNormal(sample1,out centerNormal,out centerDepth)//獲取取樣的法線和深度
Camera.worldToCameraMatrix //世界轉相機矩陣 world2view
Camera.cameraToWorldMatrix //相機轉世界矩陣
Camera.projectionMatrix //get投影矩陣viewToproject 視角空間到2維投影空間矩陣,set自定義的投影矩陣。如果你改變這個矩陣,相機的渲染不再基於它的fieldOfView更新,直到呼叫ResetProjectionMatrix
預設把view2project矩陣叫成project矩陣,預設把World2view矩陣叫做view矩陣。比如ViewProject就是world 2 project矩陣
全域性霧效
深度霧效:通過每個頂點的深度值計算出該點到攝像機的距離d,然後把距離d進行參與公式計算得到霧效圖(遠的霧濃 rgb值大,近的霧淡 rgb值小),再把原圖和霧效圖進行混合。一般用線性,指數,指數平方公式,ds採用指數平方。
地面霧效:通過深度值和攝像機的方向向量計算該點到攝像機的偏移量,再加上攝像機的位置得到該頂點在世界空間中的座標,然後把該座標的y值參與霧效計算。如果用座標z參與計算和深度霧類似。
#pragma multi_compile_fog
基於法線的邊緣檢測:防止陰影等資訊干擾檢測,判斷臨近的4個點的法線和深度值是否是近似,如果差距過大則是邊緣roberts演算法。(屏幕後處理)
---
渲染輪廓線:第一個pass對頂點進行法線方向擴散渲染,第二個pass用真實渲染實際光照,覆蓋第一次,對擴散的頂點未被覆蓋的畫素就產生了輪廓效果。(模型輪廓)
---------------------------------------------------------------------------------
噪聲:
消融效果:怪物消失漸散的效果,把某個畫素值小於閾值的裁剪掉,閾值附近的值用burncolor進行混合。陰影的pass裡邊算陰影時也把該項給clip掉,這樣陰影就動態變化了//clip(burn.r - _BurnAmount);
水面擾動效果:用時間去控制偏移距離,然後對該頂點的uv偏移兩點的法線平均值來代替該點的法線值。水面=反射+折射+繞動
float2 speed = _Time.y * float2(_WaveXSpeed, _WaveYSpeed);
/ Get the normal in tangent space
fixed3 bump1 = UnpackNormal(tex2D(_WaveMap, i.uv.zw + speed)).rgb;
fixed3 bump2 = UnpackNormal(tex2D(_WaveMap, i.uv.zw - speed)).rgb;
fixed3 bump = normalize(bump1 + bump2);
全域性(動態)霧效:通過時間控制噪聲紋理的偏移距離,然後根據噪聲顏色值來參與計算霧效濃度,然後計算霧效,就有了流動和淡濃的效果。
伽馬空間 線性空間(伽馬矯正) HDR