Shader, um die Silhouette durch Alpha-gemischte Sprites zu sehen

12

Ich möchte in Unity einen durchsichtigen Effekt wie in den folgenden Beispielen erzielen:

In meinem speziellen Szenario gibt es einige Anforderungen:

  • Sprites verwenden Alpha-Blending und Sprites haben transparente Bereiche.
  • Es gibt zwei Arten von Elementen, die den Charakter verdecken. Einer sollte den Silhouette-Effekt erzeugen und der andere sollte sich wie normal verhalten.

Zum Verschließen von Elementen, die die Silhouette erstellen, aktiviere ich ZWrite und deaktiviere es für Elemente, die dies nicht tun.

Für den Charakter habe ich versucht, die Warteschlange des Shaders auf transparent + 1 zu setzen und diesen Durchgang hinzugefügt:

Pass
{
    ZTest Greater
    Lighting Off
    Color [_Color]
}

Und der Effekt funktioniert teilweise:

  • Die Silhouette wird über den gesamten Charakter gezeichnet, auch über die Teile, die transparent sind. Transparente Teile sollten keine Silhouette bilden.

  • Die Silhouette wird erstellt, wenn sich der Charakter hinter einem Sprite befindet, auch wenn dieser Teil des Sprites transparent ist. Hinter einem transparenten Teil des Sprites zu stehen, sollte die Silhouette nicht erzeugen.

  • Der Charakter erscheint vor den restlichen Elementen, auch wenn er sich hinter ihnen befindet. Ich denke, das liegt daran, dass die Warteschlange auf Transparent + 1 gesetzt wurde. Aber wenn ich es als Transparent belasse, wird das Zeichen in der richtigen Reihenfolge gezeichnet, aber die Silhouette wird nie gesehen.

Ich habe versucht, die folgenden Tipps zu befolgen, die mir jemand gegeben hat, aber ich kann sie nicht zum Laufen bringen:

1) Lassen Sie den Pass, der die Sprites rendert, unverändert.

2) Fügen Sie einen Durchgang hinzu, der in den Z-Puffer schreibt, aber einen Shader hat, der clip () verwendet, um auf Alpha basierende Pixel zu verwerfen. Sie können den Z-Puffer nicht verwenden, um weiche Z-Tests durchzuführen, ohne MSAA und Alpha-to-Coverage zu verwenden. Die Qualität davon wird nicht großartig sein, aber es ist das Beste, was Sie tun können. Eine schnellere Alternative ist eine Muster- oder Rauschschwankung oder eine gute altmodische Schwelle, wenn Ihre Sprites alle ziemlich scharfe Kanten haben.

3) Fügen Sie okkludierbaren Objekten, die die Okklusionsfarbe mit dem Z-Test zeichnen, einen dritten Durchgang hinzu und stellen Sie sicher, dass dieser als letzter Durchgang gezeichnet wurde.

Ich bin ein bisschen neu für Shader, besonders in Unity, und ich kann einfach nicht herausfinden, wie es richtig funktioniert.

Löwe
quelle
Ihr zweites Beispiel sieht einfach aus wie ein durchscheinendes grünes Sprite, das über dem Charakter platziert ist. Vielleicht möchten Sie diesen loswerden und einfach den zweiten verlassen, wenn Sie danach suchen.
Steve Harding

Antworten:

1

Deckt dieses Video die Grundlagen ab? Es ist ein Beispiel dafür, wie aus den bereits veröffentlichten Shadern verschiedene Stile für Umrisse und Konturen erstellt werden.

https://www.youtube.com/watch?v=00qMZlacZQo

Es ist ein Beispiel für die Verwendung eines Shaders, der im Unity-Wiki veröffentlicht wurde, um so ziemlich das zu tun, wonach Sie suchen. Der Inhalt des Shaders ist unten, obwohl ich denke, dass der umrandete Teil des Shaders in U5 möglicherweise nicht wie erwartet funktioniert.

Shader "Outlined/Silhouetted Diffuse" {
Properties {
    _Color ("Main Color", Color) = (.5,.5,.5,1)
    _OutlineColor ("Outline Color", Color) = (0,0,0,1)
    _Outline ("Outline width", Range (0.0, 0.03)) = .005
    _MainTex ("Base (RGB)", 2D) = "white" { }
}

CGINCLUDE
#include "UnityCG.cginc"

struct appdata {
    float4 vertex : POSITION;
    float3 normal : NORMAL;
};

struct v2f {
    float4 pos : POSITION;
    float4 color : COLOR;
};

uniform float _Outline;
uniform float4 _OutlineColor;

v2f vert(appdata v) {
// just make a copy of incoming vertex data but scaled according to normal direction
    v2f o;
    o.pos = mul(UNITY_MATRIX_MVP, v.vertex);

    float3 norm   = mul ((float3x3)UNITY_MATRIX_IT_MV, v.normal);
    float2 offset = TransformViewToProjection(norm.xy);

    o.pos.xy += offset * o.pos.z * _Outline;
    o.color = _OutlineColor;
    return o;
}
ENDCG

SubShader {
    Tags { "Queue" = "Transparent" }

    // note that a vertex shader is specified here but its using the one above
    Pass {
        Name "OUTLINE"
        Tags { "LightMode" = "Always" }
        Cull Off
        ZWrite Off
        ZTest Always
        ColorMask RGB // alpha not used

        // you can choose what kind of blending mode you want for the outline
        Blend SrcAlpha OneMinusSrcAlpha // Normal
        //Blend One One // Additive
        //Blend One OneMinusDstColor // Soft Additive
        //Blend DstColor Zero // Multiplicative
        //Blend DstColor SrcColor // 2x Multiplicative

CGPROGRAM
#pragma vertex vert
#pragma fragment frag

half4 frag(v2f i) :COLOR {
    return i.color;
}
ENDCG
    }

    Pass {
        Name "BASE"
        ZWrite On
        ZTest LEqual
        Blend SrcAlpha OneMinusSrcAlpha
        Material {
            Diffuse [_Color]
            Ambient [_Color]
        }
        Lighting On
        SetTexture [_MainTex] {
            ConstantColor [_Color]
            Combine texture * constant
        }
        SetTexture [_MainTex] {
            Combine previous * primary DOUBLE
        }
    }
}

SubShader {
    Tags { "Queue" = "Transparent" }

    Pass {
        Name "OUTLINE"
        Tags { "LightMode" = "Always" }
        Cull Front
        ZWrite Off
        ZTest Always
        ColorMask RGB

        // you can choose what kind of blending mode you want for the outline
        Blend SrcAlpha OneMinusSrcAlpha // Normal
        //Blend One One // Additive
        //Blend One OneMinusDstColor // Soft Additive
        //Blend DstColor Zero // Multiplicative
        //Blend DstColor SrcColor // 2x Multiplicative

        CGPROGRAM
        #pragma vertex vert
        #pragma exclude_renderers gles xbox360 ps3
        ENDCG
        SetTexture [_MainTex] { combine primary }
    }

    Pass {
        Name "BASE"
        ZWrite On
        ZTest LEqual
        Blend SrcAlpha OneMinusSrcAlpha
        Material {
            Diffuse [_Color]
            Ambient [_Color]
        }
        Lighting On
        SetTexture [_MainTex] {
            ConstantColor [_Color]
            Combine texture * constant
        }
        SetTexture [_MainTex] {
            Combine previous * primary DOUBLE
        }
    }
}

Fallback "Diffuse"
}
Steve Harding
quelle