Shader pour voir la silhouette à travers des sprites mélangés alpha

12

Je veux obtenir dans Unity un effet transparent comme celui de ces exemples:

Dans mon scénario spécifique, il y a quelques exigences:

  • Les sprites utilisent le mélange alpha et les sprites ont des zones transparentes.
  • Il y a 2 types d'éléments qui occlus le personnage. L'un doit créer l'effet silhouette et l'autre doit se comporter comme d'habitude.

Pour occlure des éléments qui créent la silhouette, j'active ZWrite et le désactive pour les éléments qui ne le font pas.

Pour le personnage, j'ai essayé de définir la file d'attente du shader sur transparent + 1, et j'ai ajouté ce passage:

Pass
{
    ZTest Greater
    Lighting Off
    Color [_Color]
}

Et l'effet fonctionne partiellement:

  • La silhouette est dessinée sur tout le personnage, même les parties transparentes. Les parties transparentes ne doivent pas créer de silhouette.

  • La silhouette est créée lorsque le personnage se trouve derrière un sprite, même si cette partie du sprite est transparente. Être derrière une partie transparente du sprite ne doit pas créer la silhouette.

  • Le personnage apparaît devant les autres éléments, même s'il est derrière eux. Je suppose que c'est parce que la configuration de la file d'attente est Transparent + 1. Mais si je le laisse transparent, le personnage est dessiné dans le bon ordre, mais la silhouette n'est jamais vue.

J'ai essayé de suivre ces conseils que quelqu'un m'a donnés, mais je n'arrive pas à le faire fonctionner:

1) Laissez le col qui rend les sprites tels quels.

2) Ajoutez une passe qui écrit dans le z-buffer, mais qui a un shader qui utilise clip () pour éliminer les pixels basés sur alpha. Vous ne pouvez pas utiliser le z-buffer pour effectuer des tests z doux sans utiliser la couverture MSAA et alpha-to. La qualité ne sera pas excellente, mais c'est le mieux que vous puissiez faire. Une alternative plus rapide est un tramage de motif ou de bruit, ou un bon seuil à l'ancienne si vos sprites ont tous des bords assez nets.

3) Ajoutez une troisième passe aux objets occluables qui dessine la couleur d'occlusion à l'aide du test z et assurez-vous qu'elle est dessinée comme une passe finale.

Je suis un peu nouveau pour les shaders, spécialement dans Unity, et je n'arrive pas à comprendre comment le faire fonctionner correctement.

Leo
la source
Votre 2ème exemple ressemble simplement à un sprite vert translucide placé sur le personnage. Vous voudrez peut-être vous débarrasser de celui-ci et quitter le 2e, si c'est ce que vous recherchez.
Steve Harding

Réponses:

1

Cette vidéo couvre-t-elle les bases? C'est une illustration de la création de différents styles de contour et de silhouette à partir des shaders que les gens ont déjà publiés.

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

C'est un exemple d'utilisation d'un shader publié dans le Wiki Unity pour faire à peu près ce que vous recherchez. Le contenu du shader est ci-dessous, bien que je pense que la partie du shader ne fonctionne pas comme prévu dans 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
la source