Shader para ver la silueta a través de sprites alfa mezclados

12

Quiero lograr en Unity un efecto transparente como el de estos ejemplos:

En mi escenario específico hay un par de requisitos:

  • Los sprites están usando la mezcla alfa, y los sprites tienen áreas transparentes.
  • Hay 2 tipos de elementos que ocluyen el personaje. Uno debería crear el efecto de silueta, y el otro debería comportarse como normal.

Para ocluir elementos que crean la silueta, habilito ZWrite y lo deshabilito para elementos que no lo hacen.

Para el personaje, intenté establecer la cola del sombreador en transparente + 1, y agregué este pase:

Pass
{
    ZTest Greater
    Lighting Off
    Color [_Color]
}

Y el efecto funciona parcialmente:

  • La silueta se dibuja por todo el personaje, incluso las partes que son transparentes. Las partes transparentes no deberían crear una silueta.

  • La silueta se crea cuando el personaje está detrás de un sprite, incluso si esa parte del sprite es transparente. Estar detrás de una parte transparente del sprite no debería crear la silueta.

  • El personaje aparece enfrente del resto de los elementos, incluso si está detrás de ellos. Supongo que esto se debe a establecer la cola en Transparente + 1. Pero si lo dejo como Transparente, el personaje se dibuja en el orden correcto, pero la silueta nunca se ve.

Traté de seguir estos consejos que alguien me dio, pero no puedo hacer que funcione:

1) Deje el pase que representa los sprites como está.

2) Agregue un pase que escriba en el z-buffer, pero que tenga un sombreador que use clip () para descartar píxeles basados ​​en alfa. No puede usar el búfer z para hacer pruebas z suaves sin usar MSAA y cobertura alfa-to. La calidad de eso no será excelente, pero es lo mejor que puedes hacer. Una alternativa más rápida es un patrón o tramado de ruido, o un buen umbral a la antigua, si todos sus sprites tienen bordes bastante afilados.

3) Agregue el tercer pase a los objetos ocluibles que dibujan el color de la oclusión utilizando la prueba z y asegúrese de que se dibuje como un pase final.

Soy un poco nuevo en los sombreadores, especialmente en Unity, y no puedo entender cómo hacerlo funcionar correctamente.

León
fuente
Su segundo ejemplo simplemente parece un sprite verde translúcido colocado sobre el personaje. Es posible que desee deshacerse de ese y simplemente dejar el segundo, si eso es lo que está buscando.
Steve Harding

Respuestas:

1

¿Este video cubre lo básico? Es una ilustración de la creación de algunos estilos diferentes de contorno y silueta a partir de los sombreadores que la gente ya ha publicado.

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

Es un ejemplo del uso de un sombreador publicado en Unity Wiki para hacer más o menos lo que buscas. El contenido del sombreador está debajo, aunque creo que la parte del contorno del sombreador puede no funcionar como se esperaba en 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
fuente