就是跟著這影片打的:
以下是自己對語法的學習筆記:
展示: (我還是不懂為甚麼是倒過來的
)
先發比較短的C# 腳本。
傳參數給Shader變數可用(例如) Shader.SetGlobalFloat( shader內宣告的變數名稱, 值);
>> 或 << 是 位元移動運算子。 因為是2進位, x << 1 等於 x * 2, x << 2 等於 x * 4。
這篇文章比較詳細。
在這裡是讓攝影機像素/ 2^_downResFacter,達到模糊感(
南部畫質特效)。
接下來都是Shader的事情:
一開始以為變數也要宣告在Properties,後來才發現若是用外部腳本傳進來的參數,是不能設成外顯的。
雖然影片中有說COLOR的值是從SpriteRender傳入的,但我手癢把COLOR改成隨便的語意,例TEXCOORD都還是通,亂玩一通發現就POSITION不能改成其他的 (改了位置就跑掉了)。 我還要想想這是為甚麼....
拍謝註解一堆
這篇#2有對世界座標轉換順序方法與順序做比較好的解釋,我就抓個大概:
第一步:
o.vertex = UnityObjectToClipPos(v.vertex);
把點從模型空間轉到剪裁空間。剪裁空間可以想成是一種投影或screen space。
第二步:
float4 worldPos = mul(unity_ObjectToWorld, v.vertex);
unity_ObjectToWorld是Unity內建的轉換矩陣。
在shader中,float3會被當成是"方向"而非"位置",需要float4的w值才是個完整的"位置"資訊。
w的概念是齊次座標(Homogeneous Coordinate),這個影片講得還不錯。
簡單來講是用w當成縮放值,在orthographic模式下會=1,但在透視模式下需做第59行的處理,我個人對它的理解是"深度",物體離開、接近鏡頭時縮放用(?。
至於NDC(標準化設備坐標),我找到
這篇的解釋,3D的場景最終都要呈現在2D的螢幕畫面上,螢幕的座標就是要展示在的NDC。
第73行,tex2D(),根據
這篇#4,是回傳該uv位置上的貼圖顏色,且一定是float 4。(會自動補0)。
tex2D(_MainTex,i.uv) * i.color; 意思是貼圖顏色 * sprite render的color,做到color tint
第75行,將normal map改成世界座標
float2 offset = mul( unity_ObjectToWorld, tex2D(_OffsetTex,i.uv).xy * 2 - 1);
意思是將normalMap位移的值轉成世界座標位移的量。 (*2-1)是將範圍[0~1]的uv轉成範圍[-1~1]
第77行
float4 ambient= tex2D(_AmbientTex, (i.screenuv + offset + _GlobalRefractionMag * 5 )* 2);
放進背景貼圖,更有融入感。 後面的乘數是影片作者加的,單純讓效果好一點。
第78行
float4 worldRef1= tex2D(_GlobalRefractionTex, i.screenuv + offset.xy *_GlobalRefractionMag);
將相機傳入的texture放到加了位移的uv座標上。
_GlobalRefractionMag只是個很小的乘數,讓offset不要太強。
最後就是rgb加一加,透明度乘一乘輸出。
其中第82、83行我好奇測試screenuv和uv差在哪, screenuv會隨著自己在螢幕上移動時改變,uv則是固定的。
若兩個camera重疊,則玩家物件會剛好跟倒影重疊,影片開頭將倒影攝影機往旁邊移動一點是為了讓成像的screenuv的原點與mainCamera錯開。