Shader untuk melihat siluet melalui sprite alpha blended

12

Saya ingin mencapai di Unity efek tembus seperti yang ada dalam contoh ini:

Dalam skenario spesifik saya ada beberapa persyaratan:

  • Sprite menggunakan alpha blending, dan sprite memiliki area transparan.
  • Ada 2 jenis elemen yang menyumbat karakter. Yang satu harus menciptakan efek siluet, dan yang lain harus berperilaku seperti biasa.

Untuk elemen oklusi yang membuat siluet saya mengaktifkan ZWrite, dan menonaktifkannya untuk elemen yang tidak.

Untuk karakter saya mencoba mengatur antrian shader menjadi transparan + 1, dan menambahkan pass ini:

Pass
{
    ZTest Greater
    Lighting Off
    Color [_Color]
}

Dan efeknya bekerja sebagian:

  • Siluet digambar di seluruh karakter, bahkan bagian-bagian yang transparan. Bagian transparan seharusnya tidak membuat siluet.

  • Siluet dibuat ketika karakter berada di belakang sprite, bahkan jika bagian sprite itu transparan. Berada di belakang bagian transparan sprite seharusnya tidak menciptakan siluet.

  • Karakter muncul di depan elemen-elemen lainnya, bahkan jika ada di belakangnya. Saya kira ini karena mengatur antrian ke Transparan +1. Tetapi jika saya membiarkannya Transparan, karakternya digambar dalam urutan yang benar, tetapi siluetnya tidak pernah terlihat.

Saya mencoba mengikuti tips yang diberikan seseorang kepada saya, tetapi saya tidak dapat membuatnya berfungsi:

1) Biarkan pass yang membuat sprite seperti apa adanya.

2) Tambahkan pass yang menulis ke buffer-z, tetapi memiliki shader yang menggunakan clip () untuk membuang piksel berdasarkan alpha. Anda tidak dapat menggunakan z-buffer untuk membuat soft z-tes tanpa menggunakan cakupan MSAA dan alpha-to. Kualitas itu tidak akan bagus, tetapi itu yang terbaik yang bisa Anda lakukan. Alternatif yang lebih cepat adalah pola atau noise dither, atau ambang kuno yang baik jika semua sprite Anda memiliki tepi yang cukup tajam.

3) Tambahkan lintasan ketiga ke objek yang dapat ditutup kembali yang menarik warna oklusi menggunakan uji-z dan pastikan lis tersebut digambar sebagai lintasan terakhir.

Saya agak baru di shader, khususnya di Unity, dan saya tidak tahu bagaimana cara membuatnya bekerja dengan baik.

Leo
sumber
Contoh ke-2 Anda hanya terlihat sprite hijau transparan ditempatkan di atas karakter. Anda mungkin ingin menyingkirkan yang itu dan hanya meninggalkan yang ke-2, jika itu yang Anda cari.
Steve Harding

Jawaban:

1

Apakah video ini membahas dasar-dasarnya? Ini adalah ilustrasi untuk membuat beberapa gaya garis besar dan siluet yang berbeda dari shader yang sudah diterbitkan orang.

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

Ini adalah contoh menggunakan shader yang diterbitkan di Unity Wiki untuk melakukan cukup banyak apa yang Anda cari. Konten shader ada di bawah, meskipun saya pikir bagian garis besar shader mungkin tidak berfungsi seperti yang diharapkan di 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
sumber