Shader, aby zobaczyć sylwetkę przez sprite mieszane alfa

12

Chcę osiągnąć w Unity efekt przezroczystości, taki jak w tych przykładach:

W moim konkretnym scenariuszu jest kilka wymagań:

  • Duszki używają mieszania alfa, a duszki mają przezroczyste obszary.
  • Istnieją 2 rodzaje elementów, które zakrywają postać. Trzeba stworzyć efekt sylwetki, a drugi powinien zachowywać się normalnie.

Aby zasłaniać elementy, które tworzą sylwetkę, włączam ZWrite i wyłączam dla elementów, które tego nie robią.

Dla postaci próbowałem ustawić kolejkę modułu cieniującego na transparent + 1 i dodałem następujące hasło:

Pass
{
    ZTest Greater
    Lighting Off
    Color [_Color]
}

Efekt działa częściowo:

  • Sylwetka jest rysowana na całej postaci, nawet na przezroczystych częściach. Przezroczyste części nie powinny tworzyć sylwetki.

  • Sylwetka jest tworzona, gdy postać znajduje się za duchem, nawet jeśli ta część duszka jest przezroczysta. Przebywanie za przezroczystą częścią duszka nie powinno tworzyć sylwetki.

  • Postać pojawia się przed resztą żywiołów, nawet jeśli jest za nimi. Chyba dlatego, że ustawiłem kolejkę na Przezroczysty + 1. Ale jeśli pozostawię przezroczysty, postać zostanie narysowana we właściwej kolejności, ale sylwetka nigdy nie będzie widoczna.

Próbowałem postępować zgodnie z tymi wskazówkami, które ktoś mi dał, ale nie jestem w stanie sprawić, by zadziałało:

1) Zostaw przepustkę, która renderuje duszki bez zmian.

2) Dodaj hasło, które zapisuje do bufora Z, ale ma moduł cieniujący, który używa clip () do odrzucania pikseli opartych na alfa. Nie można używać bufora Z do wykonywania miękkich testów Z bez użycia MSAA i zasięgu alfa. Jakość tego nie będzie świetna, ale to najlepsze, co możesz zrobić. Szybszą alternatywą jest rozproszenie wzoru lub szumu, albo staroświecki próg, jeśli wszystkie duszki mają dość ostre krawędzie.

3) Dodaj trzecie przejście do obiektów okludowalnych, które rysują kolor okluzji za pomocą testu Z i upewnij się, że jest narysowane jako ostatnie przejście.

Jestem trochę nowy dla shaderów, szczególnie w Unity, i po prostu nie mogę wymyślić, jak to zrobić poprawnie.

Lew
źródło
Twój drugi przykład wygląda po prostu na przezroczystego zielonego duszka umieszczonego nad postacią. Możesz się go pozbyć i po prostu opuścić drugi, jeśli tego właśnie szukasz.
Steve Harding,

Odpowiedzi:

1

Czy ten film wideo obejmuje podstawy? Jest to ilustracja tworzenia kilku różnych stylów konturu i sylwetki z shaderów, które ludzie już opublikowali.

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

To przykład użycia shadera opublikowanego na Unity Wiki do robienia tego, czego szukasz. Zawartość modułu cieniującego znajduje się poniżej, choć myślę, że opisująca część modułu cieniującego może nie działać zgodnie z oczekiwaniami w U5.

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
źródło