讓粒子可以在白色背景顯示 [Blending Shader 實操]


 Unity3D 提供了粒子特效的各種shader,今天要說的是 Additive(因為項目最初就是用了Additive 發生了問題.. ε=ε=ε=┏(゜ロ゜;)┛)

Additive Particle Shader 其Blending 方式是 Blend SrcAlpha one。至於Blend 的操作可以看這篇文章 [轉] SHADER BLENDING,此處不再詳述。

其原理很簡單,其實就是在原圖的基礎上使用加法將顏色進行疊加。[注:Blend SrcAlpha one的方式(Blend 方式具體不詳述)]

其Shader 大概如下:

    fixed4 frag(PixelInput I):COLOR
    {
        fixed4 c = tex2D (_MainTex, I.uv_MainTex) * I.color;
        return c;
    }
    
    Pass
    {
        Blend SrcAlpha one
        
        CGPROGRAM
        #pragma vertex vert
        #pragma fragment frag
        ENDCG
        //  下面使用固定渲染管線的寫法能達到同樣效果
        //SetTexture [_MainTex] { combine texture *  previous }
    }

但是單純使用 Additive 的話,會導致 在白色的背景上,Particle 會"消失"

問題圖:

   

而 放在暗處便可以看得清楚些(越暗越明顯)

 理想效果圖:

所以要讓Particle 在黑白底上都能現實清楚,所以不能單單使用Additive。

具體方法是 作2次Pass,2次Pass 使用不同的Blend 方式

第一次Pass [Blend SrcAlpha OneMinusSrcAlpha] 
第二次Pass [Blend SrcAlpha one] // Additive

 

下面這段存粹是根據視角效果調整的參數,不是唯一的方法。

 

Blend SrcAlpha one Blend SrcAlpha OneMinusSrcAlpha 
 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 根據上圖我們發覺 單純使用 SrcAlpha one 會有"過曝光"的感覺(在黑暗部分沒問題),而SrcAlpha OneMinusSrcAlpha 的話 給人的感覺是"太實",而且沒有發光的感覺。

SrcAlpha OneMinusSrcAlpha 中導致太實的原因是透明度太低,而針對沒有發光的感覺,可以適當地將 整體調"亮"一點。

 感覺視覺效果調整的算法如下:

fixed4 c = tex2D (_MainTex, I.uv_MainTex) * I.color;
c.rgb+= 0.2; //變白一點
c.a = min(c.a, 0.3); // 透明一點
return c;
Blend SrcAlpha OneMinusSrcAlpha +調整算法 Blend SrcAlpha OneMinusSrcAlpha +調整算法 + Blend SrcAlpha one

  哪怕調亮了一點 給人的感覺還是沒有光的感覺 這是 Blend 的原因

 

 [最終效果] = 左邊的效果 再 加 Pass 一次 Blend SrcAlpha one(Additive) 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

需要注意的是,每多一個Pass 其實就是多畫了一遍。可以檢查下 游戲畫面的三角形數 明顯是相對於單純的 Additive  是多了1倍的三角形,這就是多個Pass導致的,效果和性能需要平衡一下。

 

下面是Shader 源碼:) 

Shader "Custom/MyParticlesAdditive" {
  Properties {
    _MainTex ("Particle Texture", 2D) = "white" {}
  }
  SubShader { 
    Tags { "QUEUE"="Transparent" "IGNOREPROJECTOR"="true" "RenderType"="Transparent" }
    BindChannels {
        Bind "vertex", Vertex
        Bind "color", Color
        Bind "texcoord", TexCoord
    }
    ZWrite Off
    Cull Off
    Fog {
        Color (0,0,0,0)
    }
    
    
    CGINCLUDE
    #include "UnityCG.cginc"

    sampler2D _MainTex;
    float4 _MainTex_ST;
    
    struct VertexInput {
        float4 position:POSITION;
        fixed2 coord:TEXCOORD0;
        fixed4 color : COLOR;
    };
    struct PixelInput
    {
        float4 position:POSITION;
        fixed2 uv_MainTex:TEXCOORD;
        fixed4 color : COLOR;
    };
    
    PixelInput vert(VertexInput I)
    {
        PixelInput O;
        O.position=mul(UNITY_MATRIX_MVP,I.position);
        O.uv_MainTex=  TRANSFORM_TEX(I.coord,_MainTex);
        O.color = I.color;

        return O;
    }
    fixed4 frag(PixelInput I):COLOR
    {
        fixed4 c = tex2D (_MainTex, I.uv_MainTex) * I.color;
        return c;
    }
    
    fixed4 grayscale(PixelInput I): COLOR
    {
        fixed4 c = tex2D (_MainTex, I.uv_MainTex) * I.color;
        c.rgb+= 0.2;
        c.a = min(c.a, 0.3);
        return c;
    }
    ENDCG
    
    Pass 
        {
        Blend SrcAlpha OneMinusSrcAlpha

        CGPROGRAM        
        #pragma vertex vert
        #pragma fragment grayscale
        ENDCG
    }

    
    
    Pass
    {
        Blend SrcAlpha one
        SetTexture [_MainTex] { combine texture *  previous }
        //CGPROGRAM
        //#pragma vertex vert
        //#pragma fragment frag
        //ENDCG
    }
  }
}

細心的話,在所謂的最終效果圖 中發現還存在一些瑕疵,就是有些地方有黑邊,這個問題是 圖片的原因 解決方法會在下一篇文章介紹【圖片去黑底】

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM