So erstellen Sie in Unity einen neonähnlichen 2D-Trail-Effekt

7

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.

John Hamilton
quelle

Antworten:

10

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): Geben Sie hier die Bildbeschreibung ein

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.

Geben Sie hier die Bildbeschreibung ein

Und der Effekt, der in einem GIF erzielt wird:

Geben Sie hier die Bildbeschreibung ein

Wirkung auf verschiedene Sprites:

Geben Sie hier die Bildbeschreibung ein

John Hamilton
quelle
Vielen Dank für das Teilen. Shader-Programmierung ist nicht mein Fachgebiet, aber ist es wirklich notwendig, den Wert nfü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?
Philipp
Ich habe mich mit der Sache befasst und keinen besseren Weg gefunden, dies umzusetzen. Ich habe bereits die Berechnungen des eingebauten Shaders verwendet, nur ein paar Zahlen geändert, damit er keinen größeren Einfluss auf die Leistung hat als ein Standard-Shader. (Ich bin mir immer noch nicht sicher über den Pass, aber ich denke, Sie sind in dieser Hinsicht richtig, es ist eher pro Frame als einmal.) Ich lösche meine anderen Kommentare, weil dies einer Diskussion zu nahe kommt :) @Philipp
John Hamilton
Ich habe versucht, Ihren Shader zu verwenden, und konnte ihn mit mäßigem Erfolg zum Laufen bringen. Da ich meine eigenen Sprites verwenden möchte, habe ich in Photoshop mit einer anderen Einstellung experimentiert, die nicht wirklich funktioniert hat. Ich habe Probleme, diesen Abschnitt Ihres Beitrags bezüglich der Erstellung eigener Sprites mit Ihrem Shader zu verstehen: "Zunächst einmal Ihr Sprite muss nicht unbedingt Graustufen sein ... "Können Sie genauer erklären, wie das Sprite auf die Arbeit mit diesem Shader vorbereitet sein sollte?
JustIlom
@JustIlom Dieser Shader färbt das Sprite, das Sie haben, ziemlich stark und gibt dem Alpha-Wert mehr Macht darüber, wie das Sprite aussehen wird. Probieren Sie den Shader mit einem Verlaufseffekt aus, der von Weiß mit vollem Alpha zu Schwarz mit Null Alpha reicht (Sie müssen ihn in einem Format speichern, das Alpha-Werte unterstützt). Es wird deutlicher, was er tut. (Das Beispiel Sprite, das ich oben eingefügt habe, sollte damit funktionieren, aber ich weiß nicht, ob imgur die Alpha-Werte geändert hat.)
John Hamilton
John Hamilton, Funktioniert dieser Shader in einem Zeilenrenderer oder nur in Sprites?
Nitecki