• 让粒子可以在白色背景显示 [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
        }
      }
    }

    细心的话,在所谓的最终效果图 中发现还存在一些瑕疵,就是有些地方有黑边,这个问题是 图片的原因 解决方法会在下一篇文章介绍【图片去黑底】

     

  • 相关阅读:
    C# 利用TTS实现文本转语音
    Windows10提示“没有权限使用网络资源”的解决方案
    INSPIRED启示录 读书笔记
    INSPIRED启示录 读书笔记
    phpfpm的配置
    session 的工作原理
    MySQL 事务
    Redis各种数据类型的使用场景
    JavaScript 和Ajax跨域问题
    如何做URL静态化 和页面的静态化
  • 原文地址:https://www.cnblogs.com/godzza/p/7241898.html
Copyright © 2020-2023  润新知