The default particle texture is setup to be used with a premultiplied blend, and can look funny with some other blend types when fading out if you don’t know what to expecting. It is a texture with a white center that fades to black with an alpha that matches the linear falloff. You can look at the texture itself and see that.
As for the various particle shaders, I suggest looking into blend modes. All of those (with the exception of the Alpha Blended Premultiply) work exactly as they should. The main issue with the current Alpha Blended Premultiply is that it becomes slightly additive as it fades out. A real straight premultiplied alpha shader would actually be even more additive as it faded out, but would at least be working like that blend mode is supposed to.
I’m going to touch on two of the blend modes quickly, Additive and Alpha Blended, as together they parts of how premultiplied alpha blending is supposed to work. I’m also going to talk about the hardware blend mode.
The blend mode describes the way the “src” (“source”: the shader output) and “dst” (“destination”: the existing pixel color) are handled. In the default opaque case this blend is Blend One Zero which is:
FinalColor.rgb = (Src.rgb * 1.0) + (Dst.rgb * 0.0)
The result is the output of a shader using this blend is it completely replaces what’s been rendered before.
For additive it does just what it says. It adds. If the background is a lighter color, and that plus the color of the particle is greater than white, it’s white. It’s great for making bright, glowing looking stuff. This blend mode is described as
**Blend One One** though Unity actually uses **Blend SrcAlpha One** for reasons I’ll get to another time. However for the most part both Additive and Additive (Soft) work perfectly fine with the default texture. Additive blending Blend One One is:
FinalColor.rgb = (Src.rgb * 1.0) + (Dst.rgb * 1.0)
The result is the output of the shader is just added to scene color, hence additive.
For alpha blend it takes the alpha of the texture and uses that to blend between the background and the color. The blend mode for that is Blend SrcAlpha OneMinusSrcAlpha. Using the default particle texture with this can look a little odd as the bright center has a “shadow” of sorts due to the texture simultaneously fading out and going black. Alpha blending Blend ScrAlpha OneMinusSrcAlpha is:
FinalColor.rgb = (Src.rgb * Scr.a) + (Dst.rgb * (1.0 - Src.a))
The result is anywhere the shader’s out alpha value is 1.0 it’s just the color the shader outputs, if it’s 0.0 it’s the scene color, and in between is a blend of the two depending on the alpha, hence alpha blend.
Premultiplied is so named because the Color * Alpha is done before and stored in the texture, so the blend just has to be Blend One OneMinusSrcAlpha:
FinalColor.rgb = (Src.rgb * 1.0) + (Dst.rgb * (1.0 - Src.a))
Premultiplied exists originally because it’s one less math operation as the * 1.0 can just be skipped, so you get the same result as alpha blending for slightly cheaper. This is why the default particle texture both fades to black and has alpha, but also why it doesn’t work as well with the other blend modes. Today it’s less of an issue, but it also has the benefit of being able to do both additive and alpha blend.
The problem with the default particle material and the current Particle/Alpha Blended Premultipy shader is in how you have to handle fading out for each of these blend modes.
Additive you just need to darken the color and it fades out, as adding a color of “black” does nothing. I mentioned earlier that Unity uses Blend SrcAlpha One instead of Blend One One. This means you can also just animate the alpha color or use a white texture with an alpha channel and get the same result as darkening the color. Unity’s shader just takes the texture color and multiplies it by the particle color and that’s the shader’s output, or “Src” color.
For Alpha Blending you only need to animate the alpha. Darkening the color ends up darkening the result. However again Unity just multiplies the texture color and particle color and that’s the shader output.
For Alpha Blending Premultiply you need to animate both the color and the alpha at the same time, otherwise it’ll just change from an alpha blend particle to an additive particle. This can be really useful for certain kinds of effects, but if you don’t know to do this it can be really confusing as animating the alpha works as you would expect with both the additive and alpha blend shaders. At some point someone was likely tasked with fixing this so it wasn’t as confusing for new users. They could have converted over the default particle material and texture to be a regular alpha blended shader, but that would mean changing the default particle texture to be all white with just alpha which might cause problems for people using that texture for other stuff. Instead they just modified the shader so the alpha also effects the color, and voila, just animating the alpha makes it fade out!
But who ever made the change did it wrong. The shader multiplies both the rgb color and alpha with the particle alpha. That means the output alpha changes faster than the color and it “brightens” before it fades out.
Pseudo Shader example code:
OutputColor = TextureColor.rgba * ParticleColor.rgba * ParticleColor.a;
So if the texture is fully white and has an opaque alpha channel, and if the particle color is also white but the alpha is 0.5 the end result is an output color of 0.5 and an alpha of 0.25, when what you’d want is both to be 0.5 so that the Blend One OneMinusSrcAlpha results in a proper alpha blend.
The correct fix would have been:
OutputColor.rgb = TextureColor.rgb * ParticleColor.rgb * ParticleColor.a;
OutputColor.a = TextureColor.a * ParticleColor.a;
Then under the same scenario as above the output of the color and alpha are 0.5, and you get a proper alpha blend with no additional unwanted brightening, but it works with the original premultiplied texture.