Force Field效果的實現(xiàn)

斧式雷基恩的護盾效果

下圖是 異界鎖鏈 斧式雷基恩的護盾效果:

image

趁著有空,我做了一個類似的實現(xiàn),丟到 github 上去了,地址:https://github.com/fatdogsp/Unity-Force-Field-Effect。

這個效果不難做,我們只需要檢測出護盾的 邊緣 以及護盾和場景的 交界,并依此來調整護盾的 透明度 即可。

下圖是我的第一版實現(xiàn):

image

異界鎖鏈 相比,三角形背面的交界沒了。

如果需要顯示背面交界,我們首先需要 Cull Off,然后把背面的 邊緣強度 設置為 0,只保留背面的 交界強度。

下圖是我添加背面交界后的效果:

image

好了,下面來看看實現(xiàn)細節(jié)。

透明度的計算公式

我們需要一個 半透明 的shader,邊緣交界 的透明度低,其他地方透明度高。

這里 透明度 的計算方式有參考 Brackeys的教程,有興趣的可以先看一下視頻。

整體流程用 surface shader 來寫的話,代碼如下:

void surf (Input IN, inout SurfaceOutputStandard o)
{
    half alpha = ForceFieldAlpha(IN, o);

    o.Albedo = half3(0, 0, 0);
    o.Metallic = _Metallic;
    o.Smoothness = _Smoothness;
    o.Occlusion = 1;
    o.Emission = _EmissionColor.rgb;
    o.Alpha = alpha;
}

ForceFieldAlpha 函數(shù)主要用來計算 透明度,其他都是常規(guī)操作,顏色主要依靠 自發(fā)光。

ForceFieldAlpha 代碼如下:

half ForceFieldAlpha(Input IN, inout SurfaceOutputStandard o)
{
    half depthDelta = ComputeDepthDelta(IN);
    half fresnel = ComputeFresnel(IN);
    half pattern = ComputePattern(IN);

    return (depthDelta + fresnel) * pattern * _AlphaStrength;
}

這里涉及到如下三個函數(shù):

  • ComputeDepthDelta:計算 交界強度。

  • ComputeFresnel:計算 邊緣強度

  • ComputePattern:計算 整體強度 的貼圖效果和UV動畫。

ComputeDepthDelta

我們可以用 當前像素的深度背景像素的深度 做比較,如果深度相距較近,則可以認為是 交界,代碼如下:

inline half ComputeDepthDelta(Input IN)
{
    float2 screenUV = IN.screenPos.xy / IN.screenPos.w;
    float screenDepth = LinearEyeDepth(SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, screenUV));

    float depth = IN.screenPos.w - _DepthOffset;
    float depthDelta = abs(screenDepth - depth);
    depthDelta = 1 - depthDelta;

    return smoothstep(0, 1, depthDelta);
}

這里提供一個 _DepthOffset,可以對 深度距離 做額外偏移,從而調整 交界 區(qū)域的大小。

ComputeFresnel

關于 邊緣強度 的計算,我們要區(qū)分是正面還是背面,背面的 邊緣強度 永遠為 0

如果是 fragment shader,我們可以通過 VFace 來區(qū)分正面背面:

fixed4 frag (fixed facing : VFACE) : SV_Target
{
    // VFACE input positive for frontbaces,
    // negative for backfaces. Output one
    // of the two colors depending on that.
    return facing > 0 ? _ColorFront : _ColorBack;
}

可惱的是,surface shader 我沒找到類似的設值,這里我通過 dot(IN.viewDir, IN.worldNormal)正負 來判斷正面背面。

當然,這樣判斷有一定的瑕疵,具體可以參考 這篇帖子,不過做為示例,這樣已經(jīng)OK了,下面貼代碼:

只考慮正面

Cull Back
inline half ComputeFresnel(Input IN)
{
    half rim = 1 - saturate(dot(IN.viewDir, IN.worldNormal));
    return pow(rim, _FresnelPower);
}

正面背面都考慮

Cull Off
inline half ComputeFresnel(Input IN)
{
    half rim = dot(IN.viewDir, IN.worldNormal);
    rim = lerp(1 - saturate(rim), 0, rim < 0);
    return pow(rim, _FresnelPower);
}

ComputePattern

計算出 邊緣強度邊界強度 后,我們把這2個值相加,就可以得到 整體透明度。

這里我們還可以對 整體透明度 做一些貼圖效果,比如下圖:

image

原理很簡單,把 ComputePattern 的結果和 整體透明度乘法 即可,ComputePattern 的代碼如下:

inline half ComputePattern(Input IN)
{
    float2 uv = IN.uv_PatternTex + half2(_PatternOffsetU, _PatternOffsetV) * _Time.y * _ScrollSpeed;
    return tex2D(_PatternTex, uv).r;
}

結尾

只要明白原理,代碼還是很簡單的。

當然,這只是基礎功能,如果需要更多特性,可以參考Unity商店的 ForceField Effects 這個插件。

個人主頁

本文的個人主頁鏈接:https://baddogzz.github.io/2020/02/21/Force-Field/。

好了,拜拜!

?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

  • 轉載自VR設計云課堂[http://www.itdecent.cn/u/c7ffdc4b379e]Unity S...
    水月凡閱讀 1,172評論 0 0
  • Unity中兩種方法實現(xiàn)透明效果: 1.透明度測試(Alpha Test),無法得到真正半透明效果,另外一種是透明...
    李偌閑閱讀 807評論 0 0
  • 昨天發(fā)現(xiàn)如果臨在心不在焉地,也會很容易被帶離臨在,回到頭腦世界中。 我不想接觸人,喜歡一個人很安靜很...
    誼君閱讀 196評論 0 0
  • 在接觸傳播學之前,我對其印象一直停留在"新聞報道"的狹窄層面,對于其準確的定義與其他深層的涵義并沒有做過了解。 《...
    17汪凌宇閱讀 274評論 0 1
  • 你曾經(jīng)為了一個人,去過另一座城市嗎?也許是短暫的停留。也許是放棄現(xiàn)有的環(huán)境,做一次費力而嚴肅地遷徙。也...
    賣小妞的餅干閱讀 268評論 0 0

友情鏈接更多精彩內(nèi)容