Kürzlich habe ich für ein Spiel, das ich mache, mit neonfarbenen Effekten herumgespielt und wollte meine Ergebnisse mit Ihnen teilen.
Wenn Sie andere Methoden haben, um dieses Ergebnis zu erzielen, teilen Sie diese bitte unbedingt mit.
quelle
Kürzlich habe ich für ein Spiel, das ich mache, mit neonfarbenen Effekten herumgespielt und wollte meine Ergebnisse mit Ihnen teilen.
Wenn Sie andere Methoden haben, um dieses Ergebnis zu erzielen, teilen Sie diese bitte unbedingt mit.
Um diesen Effekt zu erzielen, hat mein Freund ein benutzerdefiniertes Sprite erstellt. Wir haben mit allen Arten von Sprites herumgespielt und Sie können diesen Teil nach Ihren Wünschen anpassen. Der Shader, den ich für diesen Effekt geschrieben habe, nimmt das Sprite auf, erstellt das Sprite in Graustufen, verwendet die Farbe, um eine farbige Version zu erstellen, und verwendet die Graustufenversion zusammen mit der farbigen Version, um die Teile zu färben, die grau sind.
Zunächst muss Ihr Sprite nicht unbedingt Graustufen sein, aber es ist wahrscheinlich besser für Graustufen-Sprites. Der von mir verwendete Trail-Effekt streckt das Sprite horizontal, sodass es durchaus erforderlich ist, das Sprite horizontal zu gestalten.
Dies ist das Sprite, das wir im Spiel verwendet haben (es hat Alpha eingebaut, das für den Glow-Effekt erforderlich ist):
Dies ist der Shader, den ich für den Effekt erstellt habe:
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
}
}
}
Aufgrund der Funktionsweise von Unity mit Shadern müssen Sie für jede Farbe separate Materialien erstellen (wenn es eine Möglichkeit gibt, dies zu überwinden, teilen Sie dies bitte mit).
Sie erstellen also ein neues Material, wählen den Shader für dieses Material aus, ändern die Farbe und die Sprite-Eingabe und erzielen einen neonähnlichen Effekt.
Und der Effekt, der in einem GIF erzielt wird:
Wirkung auf verschiedene Sprites:
n
für jedes Texel in jedem einzelnen Frame immer wieder neu zu berechnen ? Wäre es nicht schneller, die Textur beim Laden in ein Ein-Byte-pro-Pixel-Format umzuwandeln und stattdessen dieses zu verwenden?