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


12

Я хочу досягти в Єдності бачення ефекту, подібного до цього в цих прикладах:

У моєму конкретному сценарії є кілька вимог:

  • Для спрайтів використовується альфа-змішування, а у спрайтів прозорі ділянки.
  • Є 2 різновиди елементів, що окулюють персонажа. Один повинен створити силуетний ефект, а інший повинен вести себе як нормально.

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

Для персонажа я спробував встановити чергу шайдера на прозорий + 1, і додав цей пропуск:

Pass
{
    ZTest Greater
    Lighting Off
    Color [_Color]
}

І ефект працює частково:

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

  • Силует створюється, коли персонаж стоїть за спрайтом, навіть якщо ця частина спрайту прозора. Перебуваючи за прозорою частиною спрайту, не слід створювати силует.

  • Персонаж з'являється перед усіма елементами, навіть якщо він знаходиться за ними. Я думаю, це тому, що встановлення черги на Transparent + 1. Але якщо я залишу це як прозорий, персонаж намальований у правильному порядку, але силует ніколи не видно.

Я намагався дотримуватися цих порад, які хтось мені дав, але я не можу змусити його працювати:

1) Залиште пропуск, який надає спрайтів таким, як є.

2) Додайте пропуск, який пише в z-буфер, але має шейдер, який використовує clip () для відкидання пікселів на основі альфа. Ви не можете використовувати z-буфер для того, щоб робити м'які z-тести без використання MSAA та альфа-покриття. Якість цього не буде великою, але це найкраще, що ви можете зробити. Більш швидкою альтернативою є візерунок або шумовий шум або добрий старомодний поріг, якщо всі ваші спрайти мають досить гострі краї.

3) Додайте третій прохід до оклюзійних об'єктів, який малює колір оклюзії за допомогою z-тесту та переконайтеся, що він намальований як кінцевий прохід.

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


Ваш 2-й приклад просто виглядає напівпрозорим зеленим спрайтом, розміщеним над символом. Ви можете позбутися цього і просто залишити 2-е, якщо це те, що ви шукаєте.
Стів Хардінг

Відповіді:


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"
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.