Шейдер, чтобы увидеть силуэт через альфа-смешанные спрайты

12

Я хочу добиться в Unity сквозного эффекта, подобного приведенному в следующих примерах:

В моем конкретном сценарии есть пара требований:

  • Спрайты используют альфа-смешение, а спрайты имеют прозрачные области.
  • Есть 2 вида элементов, которые закрывают персонажа. Один должен создать эффект силуэта, а другой должен вести себя как обычно.

Для окклюзирующих элементов, которые создают силуэт, я включаю ZWrite и отключаю его для элементов, которые этого не делают.

Для персонажа я попытался установить очередь шейдера в + 1 и добавил этот проход:

Pass
{
    ZTest Greater
    Lighting Off
    Color [_Color]
}

И эффект работает частично:

  • Силуэт нарисован на всем протяжении персонажа, даже на прозрачных частях. Прозрачные части не должны создавать силуэт.

  • Силуэт создается, когда персонаж находится за спрайтом, даже если эта часть спрайта прозрачна. Нахождение за прозрачной частью спрайта не должно создавать силуэт.

  • Персонаж появляется перед остальными элементами, даже если он находится позади них. Я предполагаю, что это потому, что установка очереди в Прозрачный + 1. Но если я оставлю это как Прозрачный, персонаж будет нарисован в правильном порядке, но силуэт никогда не будет виден.

Я пытался следовать этим советам, которые кто-то дал мне, но я не могу заставить его работать:

1) Оставьте проход, который отображает спрайтов как есть.

2) Добавьте проход, который записывает в z-буфер, но имеет шейдер, который использует clip () для отбрасывания пикселей на основе альфа. Вы не можете использовать z-буфер для создания мягких z-тестов без использования MSAA и альфа-покрытия. Качество этого не будет отличным, но это лучшее, что вы можете сделать. Более быстрая альтернатива - шаблон или сглаживание шума, или старый добрый порог, если все ваши спрайты имеют довольно острые края.

3) Добавьте третий проход к окклюдируемым объектам, которые рисуют цвет окклюзии, используя z-тест, и убедитесь, что он нарисован как последний проход.

Я немного новичок в шейдерах, особенно в Unity, и я просто не могу понять, как заставить его работать должным образом.

Лео
источник
Ваш второй пример просто выглядит как полупрозрачный зеленый спрайт, помещенный над персонажем. Вы можете избавиться от этого и просто оставить второе, если это то, что вы ищете.
Стив Хардинг

Ответы:

1

Это видео охватывает основы? Это иллюстрация создания нескольких различных стилей контура и силуэта из шейдеров, которые уже опубликованы.

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

Это пример использования шейдера, опубликованного в Unity Wiki, для того, чтобы делать то, что вам нужно. Содержимое шейдера ниже, хотя я думаю, что выделенная часть шейдера может работать не так, как ожидалось в 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"
}
Стив Хардинг
источник