Shader para ver a silhueta através de sprites alfa misturados

12

Eu quero alcançar no Unity um efeito transparente como o desses exemplos:

No meu cenário específico, existem alguns requisitos:

  • Os sprites estão usando a mistura alfa e os sprites têm áreas transparentes.
  • Existem 2 tipos de elementos que ocluem o personagem. Um deve criar o efeito de silhueta e o outro deve se comportar normalmente.

Para ocluir elementos que criam a silhueta, habilito o ZWrite e desabilito-o para elementos que não o fazem.

Para o personagem, tentei definir a fila do shader como transparente + 1 e adicionei este passe:

Pass
{
    ZTest Greater
    Lighting Off
    Color [_Color]
}

E o efeito funciona parcialmente:

  • A silhueta é desenhada em todo o personagem, até nas partes transparentes. Peças transparentes não devem criar uma silhueta.

  • A silhueta é criada quando o personagem está atrás de um sprite, mesmo que essa parte seja transparente. Estar atrás de uma parte transparente do sprite não deve criar a silhueta.

  • O personagem aparece na frente dos demais elementos, mesmo que esteja atrás deles. Eu acho que isso ocorre porque definir a fila como Transparente + 1. Mas se eu deixar como Transparente, o personagem é desenhado na ordem correta, mas a silhueta nunca é vista.

Tentei seguir estas dicas que alguém me deu, mas não consigo fazê-lo funcionar:

1) Deixe o passe que renderiza os sprites como estão.

2) Adicione um passe que grave no buffer z, mas tenha um sombreador que use clip () para descartar pixels com base em alfa. Você não pode usar o buffer z para fazer testes z suaves sem usar a cobertura MSAA e alpha-to. A qualidade disso não será ótima, mas é o melhor que você pode fazer. Uma alternativa mais rápida é um padrão ou pontilhamento de ruído ou um bom limiar à moda antiga, se todos os seus sprites tiverem bordas bastante nítidas.

3) Adicione um terceiro passe a objetos oclusáveis ​​que desenham a cor da oclusão usando o teste z e verifique se ele foi desenhado como um passe final.

Sou meio novo em shaders, especialmente no Unity, e simplesmente não consigo descobrir como fazê-lo funcionar corretamente.

Leo
fonte
Seu segundo exemplo simplesmente parece um sprite verde translúcido colocado sobre o personagem. Você pode se livrar dele e deixar o segundo, se é isso que você está procurando.
Steve Harding

Respostas:

1

Este vídeo cobre o básico? É uma ilustração da criação de alguns estilos diferentes de estrutura de tópicos e silhueta a partir dos shaders que as pessoas já publicaram.

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

É um exemplo de uso de um sombreador publicado no Unity Wiki para fazer praticamente o que você procura. O conteúdo do shader está abaixo, embora eu ache que a parte de contorno do shader pode não estar funcionando conforme o esperado no 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
fonte