Shader從入門到跑路:實作螢幕扭曲效果

遊資網發表於2020-03-20
Shader從入門到跑路:實作螢幕扭曲效果


前言

這次來實作上章提到的螢幕扭曲效果,需要用到這張圖(文章最後提供連結)

Shader從入門到跑路:實作螢幕扭曲效果
5.1位移圖

先稍微花點時間思考一下這張圖怎麼用。

Shader從入門到跑路:實作螢幕扭曲效果
5.2畫素取樣偏移方法

紋理中紅色的部分代表uv在x軸上的位移,而綠色則表示uv在y軸上的位移。


正文

為此我們的shader需要一個額外的二維紋理屬性用以儲存位移圖,以及一個magnitude屬性,用來調整我們的扭曲效果的強度。以上一章寫好的shader為基礎,加入以下程式碼:

  1. Properties{
  2.         _MainTex("Main Text", 2D) = "white" {}
  3.         _DisplacementTex("Displacement Texture", 2D) = "white" {}
  4.         _Magnitude("Magnitude", Range(0, 1)) = 0
  5. }
複製程式碼

新增一個二維的位移紋理,接著加上一個magnitude拖動條。記得在使用之前要先在CGPROGRAM裡面定義這些屬性:

sampler2D _MainTex;

sampler2D _DisplacementTex;

float _Magnitude;

接下來在frag函式裡面的運算可能有些複雜,看不懂記得來回看多幾遍:

  1. float4 frag(v2f i) : SV_Target
  2. {
  3.         float2 disp = tex2D(_DisplacementTex, i.uv).xy;
  4.         disp = ((disp * 2) - 1) * _Magnitude;
  5.         float4 color = tex2D(_MainTex, i.uv + disp);
  6.         return color;
  7. }
複製程式碼

首先第一步是定義了一個float2的disp來對位移圖進行取樣,下面一行做了一些數學上的轉換。因為從uv中獲取的值是介於0到1之間的,這樣的數值算出來的扭曲效果會不明顯,所以要讓值定位到-1到1之間,讓介面有飄來飄去的感覺,並乘上magnitude讓我們可以控制強度。最後,將我們的主紋理取樣為法向量,但這次,我們將uv加上位移的量

然後回到材質的皮膚,位移圖拖到displacement texture的位置,然後拖動magnitude的拖動條,得到下面的效果


Shader從入門到跑路:實作螢幕扭曲效果
5.3熱起來香菜都扭曲

其實如果你直接把這個效果放到遊戲裡面,也可以製造一些火焰山的感覺,熱到扭曲就是說的這個,連周邊的空氣都要與影像混合在一齊。

但是要手動拖動magnitude畢竟還是太遜了,我們不能給程式猿丟臉,得用程式碼從外部改變內部狀態。

我們可以用unity提供的一個叫_Time的引數,這個引數是寫在了UnityCG.cginc檔案裡的。_它有很多用法,比如_Time.x返回的是當前的時間的20分之一,_Time.y則是當前時間等等。

https://docs.unity3d.com/Manual/SL-UnityShaderVariables.html

在告訴你解法之前,我強烈建議你先遮住這一段下面的程式碼部分(伸手黨的同學可以跳過這一部分),自己好好想一想用_Time引數怎麼實現動態扭曲。首先思考一下剛才我們是怎麼實現扭曲的。我們將位移圖的取樣結果新增到uv上,在對主紋理(在這裡就是螢幕)取樣時使用偏移過的uv來進行取樣,便會得到渲染效果。(沒懂?劃上去看程式碼,依然沒懂翻前一章看OnRenderImage的程式碼)那麼,如果扭曲是動態的,就是說,一開始,uv值就隨著時間的推移而改變,我們在對位移圖進行取樣的時候,uv值就已經改變過了。到此為止,思路上的提示我已經給得差不多,現在到你思考了。

動態扭曲的程式碼:

  1. float4 frag (v2f i) : SV_Target
  2. {
  3.         float2 distuv = float2(i.uv.x + _Time.x * 2, i.uv.y + _Time.x * 2);

  4.         float2 disp = tex2D(_DisplacementTex, distuv).xy;
  5.         disp = ((disp * 2) - 1) * _Magnitude;

  6.         float4 col = tex2D(_MainTex, i.uv + disp);
  7.         return col;
  8. }
複製程式碼

隨便給magnitude設一個值就可以看到這樣的動態扭曲效果:

Shader從入門到跑路:實作螢幕扭曲效果
5.4美麗的香菜


Shader從入門到跑路:實作螢幕扭曲效果

位移圖連結:

https://pan.baidu.com/share/init?surl=dtMOiK5WstENYspRUyv0JQ

提取碼:ewjq

相關閱讀:
Shader從入門到跑路:樸實無華的圖形學基礎
Shader從入門到跑路:自定義紋理輸入
Shader從入門到跑路:螢幕後處理效果

作者:俊銘
https://zhuanlan.zhihu.com/p/86237202

相關文章