主題

【Unity Shader 學習筆記】水晶效果

趴趴鼠Loading | 2020-12-22 03:41:52

就是跟著這影片打的:

以下是自己對語法的學習筆記:

展示: (我還是不懂為甚麼是倒過來的 )


先發比較短的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
xyz或rgb都可以用。

第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錯開。




212 巴幣: 40

創作回應

is樂小呈
想到之前也遇到反轉的問題,翻了一下舊專案,我當初是這樣修的可以參考一下
2020-12-22 10:43:22
is樂小呈
o.uvgrap = ComputeGrabScreenPos(o.vertex);
2020-12-22 10:43:26
is樂小呈
fixed4 col = tex2Dproj(_GrabTexture, i.uvgrap);
2020-12-22 10:43:41
is樂小呈
我們的做法不太依樣,僅供參考 XD
2020-12-22 10:44:45
趴趴鼠Loading
看起來是從FrameBuffer中copy一份紋理的做法?,grabpass好像有效能問題,LWRP貌似要用其他方法取代它
2020-12-22 21:47:44
教授加博士先生
vs裡面計算screenuv完把它flip一下就好了 o.screen.y = 1.0 - o.screenuv.y;
寫shader有時候會遇到, 通常是因為directx opengl等平台差異
screenuv一個是左上角當0,0一個是左下當0,0 很瞎
2020-12-22 14:43:15
趴趴鼠Loading
成功了!!! 大感謝,選你正解XD
2020-12-22 21:50:56
追蹤 創作集

作者相關創作

更多創作