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