Thursday, March 24, 2016

sprites - How to make a 2D neon-like trail effect in Unity


Recently I've been toying around with neon-ish effects for a game I'm making and wanted to share my results with you.


If you guys have any other methods of achieving this result, please be sure to share.



Answer



To achieve this effect my friend has created a custom sprite, we played around with all sorts of sprites and you can customize this part to your liking. The shader I've written for this effect, takes in the sprite, makes the sprite grayscale, uses the color to make a colored version and uses the grayscale version together with the colored version to color the parts that are gray.


First of all, your sprite doesn't really need to be grayscale, but it will probably be better for grayscale sprites. The trail effect that I've used stretches the sprite horizontally, so making the sprite horizontal is quite necessary.


This is the sprite we've used in game (it has built in alpha which is necessary for the glow effect): enter image description here


This is the shader I've made for the effect:


Shader "Trail/Neon"

{
Properties
{
[PerRendererData] _MainTex("Sprite Texture", 2D) = "white" {}
_Color("Tint", Color) = (1,1,1,1)
_MainTexture("Sprite", 2D) = "white" {}
[MaterialToggle] PixelSnap("Pixel snap", Float) = 0
}

SubShader

{
Tags
{
"Queue" = "Transparent"
"IgnoreProjector" = "True"
"RenderType" = "Transparent"
"PreviewType" = "Plane"
"CanUseSpriteAtlas" = "True"
}


Cull Off
Lighting Off
ZWrite Off
Blend One OneMinusSrcAlpha

Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag

#pragma target 2.0
#pragma multi_compile _ PIXELSNAP_ON
#pragma multi_compile _ ETC1_EXTERNAL_ALPHA
#include "UnityCG.cginc"

struct appdata_t
{
float4 vertex : POSITION;
float4 color : COLOR;
float2 texcoord : TEXCOORD0;

UNITY_VERTEX_INPUT_INSTANCE_ID
};

struct v2f
{
float4 vertex : SV_POSITION;
fixed4 color : COLOR;
float2 texcoord : TEXCOORD0;
UNITY_VERTEX_OUTPUT_STEREO
};


fixed4 _Color;

v2f vert(appdata_t IN)
{
v2f OUT;
UNITY_SETUP_INSTANCE_ID(IN);
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(OUT);
OUT.vertex = UnityObjectToClipPos(IN.vertex);
OUT.texcoord = IN.texcoord;

OUT.color = IN.color * _Color;
#ifdef PIXELSNAP_ON
OUT.vertex = UnityPixelSnap(OUT.vertex);
#endif

return OUT;
}

sampler2D _MainTexture;
sampler2D _AlphaTex;


fixed4 SampleSpriteTexture(float2 uv)
{
fixed4 color = tex2D(_MainTexture, uv);

#if ETC1_EXTERNAL_ALPHA
// get the color from an external texture (usecase: Alpha support for ETC1 on android)
color.a = tex2D(_AlphaTex, uv).r;
#endif //ETC1_EXTERNAL_ALPHA


return color;
}

fixed4 frag(v2f IN) : SV_Target
{
//standard sprite shader, only this part is different.
//takes the sprite in
fixed4 s = SampleSpriteTexture(IN.texcoord);

//makes a colored version of the sprite

fixed4 c = s * IN.color;

//makes the grayscale version
fixed n = (s.g + s.r + s.b) / 3;

//So, I've scrapped the previous calculation in favor of this I'll leave the previous one in too, just for reference
c = (c*3 + n*c.a)*c.a;
//Adds the grayscale version on top of the colored version
//The alpha multiplications give the neon effect feeling
//c.g = (c.g + n * c.a) * c.a;

//c.r = (c.r + n * c.a) * c.a;
//c.b = (c.b + n * c.a) * c.a;
// You can add c.a multiplications of colors
//(i.e. turn c.g to c.g*c.a) for less color in your effect
//this saturates the insides a bit too much for my liking

return c;
}
ENDCG
}

}
}

You will have to make separate materials for each different color because of how Unity works with shaders (if there's a way to overcome this, please do tell).


So, you make a new material, pick the shader for that material, change the color and the sprite input, and you've got yourself a neon-like effect.


enter image description here


And the effect achieved in a gif:


enter image description here


Effect on different sprites:


enter image description here



No comments:

Post a Comment

Simple past, Present perfect Past perfect

Can you tell me which form of the following sentences is the correct one please? Imagine two friends discussing the gym... I was in a good s...