Bagian 1: Pembubaran Shader
Shader pembubaran mengembalikan efek yang indah, apalagi, mudah dibuat dan dipahami; Hari ini kita akan membuatnya dalam 
Unity Shader Graph , dan juga menulis di 
HLSL .
Berikut ini contoh yang akan kami buat:
Bagaimana cara kerjanya
Untuk membuat shader 
terlarut , kita harus 
bekerja dengan nilai 
AlphaClipThreshold di shader "Shader Graph" atau menggunakan fungsi HLSL yang disebut 
clip .
Pada dasarnya, kami memberi tahu shader 
untuk tidak merender piksel berdasarkan 
tekstur dan 
nilai yang diteruskan. Kita perlu mengetahui hal berikut: bagian 
putih larut lebih cepat .
Kami akan menggunakan tekstur berikut:
Anda dapat membuat sendiri - garis lurus, segitiga, tetapi apa saja! Ingatlah bahwa bagian 
putih larut lebih cepat .
Saya membuat tekstur ini di Photoshop menggunakan filter Clouds.
Bahkan jika Anda hanya tertarik pada Grafik Shader dan Anda tidak tahu apa-apa tentang HLSL, saya masih merekomendasikan membaca bagian ini, karena berguna untuk memahami bagaimana Unity Shader Graph bekerja di dalam.
Hlsl
Dalam HLSL, kami menggunakan fungsi 
klip (x) . Fungsi 
klip (x) membuang semua piksel dengan nilai kurang dari 
nol . Karena itu, jika kita memanggil 
klip (-1) , kita akan yakin bahwa shader tidak akan pernah merender piksel ini. Anda dapat membaca lebih lanjut tentang 
klip di 
Microsoft Documents .
Sifat-sifat
Shader memerlukan dua properti, 
Dissolve Texture and 
Amount (yang akan menunjukkan proses eksekusi keseluruhan). Seperti halnya properti dan variabel lain, Anda dapat menyebutnya apa saja yang Anda suka.
Properties { //Your other properties //[...] //Dissolve shader properties _DissolveTexture("Dissolve Texture", 2D) = "white" {} _Amount("Amount", Range(0,1)) = 0 } 
Pastikan untuk menambahkan yang berikut setelah CGPROGRAM SubShader (dengan kata lain, mendeklarasikan variabel):
 sampler2D _DissolveTexture; half _Amount; 
Juga, jangan lupa. bahwa nama mereka harus cocok dengan nama di bagian Properties.
Fungsi
Kami memulai fungsi 
Permukaan atau 
Fragmen dengan mengambil sampel 
tekstur pembubaran dan mendapatkan 
nilai merah . PS Tekstur kami disimpan dalam 
skala abu-abu , yaitu nilainya 
R , 
G dan 
B sama, dan Anda dapat 
memilih salah satunya . Misalnya, 
putih adalah 
(1,1,1) , 
hitam adalah 
(0,0,0) .
Dalam contoh saya, saya menggunakan shader permukaan:
 void surf (Input IN, inout SurfaceOutputStandard o) { half dissolve_value = tex2D(_DissolveTexture, IN.uv_MainTex).r;  
Dan itu dia! Kita dapat menerapkan proses ini untuk shader yang ada dan mengubahnya menjadi 
shader pembubaran !
Ini adalah Surface Shader standar dari mesin Unity, yang diubah menjadi 
shader pembubaran dua sisi : Shader "Custom/DissolveSurface" { Properties { _Color ("Color", Color) = (1,1,1,1) _MainTex ("Albedo (RGB)", 2D) = "white" {} _Glossiness ("Smoothness", Range(0,1)) = 0.5 _Metallic ("Metallic", Range(0,1)) = 0.0 //Dissolve properties _DissolveTexture("Dissolve Texutre", 2D) = "white" {} _Amount("Amount", Range(0,1)) = 0 } SubShader { Tags { "RenderType"="Opaque" } LOD 200 Cull Off //Fast way to turn your material double-sided CGPROGRAM #pragma surface surf Standard fullforwardshadows #pragma target 3.0 sampler2D _MainTex; struct Input { float2 uv_MainTex; }; half _Glossiness; half _Metallic; fixed4 _Color; //Dissolve properties sampler2D _DissolveTexture; half _Amount; void surf (Input IN, inout SurfaceOutputStandard o) { //Dissolve function half dissolve_value = tex2D(_DissolveTexture, IN.uv_MainTex).r; clip(dissolve_value - _Amount); //Basic shader function fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color; o.Albedo = c.rgb; o.Metallic = _Metallic; o.Smoothness = _Glossiness; o.Alpha = ca; } ENDCG } FallBack "Diffuse" } 
Grafik shader
Jika kita perlu membuat efek ini menggunakan Unity 
Shader Graph , maka kita harus menggunakan nilai 
AlphaClipThreshold (yang bekerja secara berbeda dari 
klip (x) dari HLSL). Dalam contoh ini, saya membuat shader PBR.
Fungsi 
AlphaClipThreshold menginstruksikan shader untuk membuang semua piksel yang nilainya kurang dari nilai 
Alpha -nya. Misalnya, jika 
0.3f , dan nilai alfa kami adalah 
0.2f , maka shader 
tidak akan membuat piksel ini. Fungsi 
AlphaClipThreshold dapat ditemukan di 
dokumentasi Unity : 
PBR Master Node dan 
Unlit Master Node .
Ini shader yang sudah jadi:
Kami sampel 
tekstur pembubaran dan mendapatkan 
nilai merah , dan kemudian menambahkannya ke nilai 
Jumlah (yang merupakan properti yang saya tambahkan untuk menunjukkan proses eksekusi keseluruhan, nilai 1 berarti pembubaran lengkap) dan hubungkan ke 
AlphaClipThreshold . 
Selesai!Jika Anda ingin menerapkannya pada shader yang ada, maka cukup 
salin koneksi node ke 
AlphaClipThreshold (jangan lewatkan properti yang diperlukan!). Anda juga dapat membuatnya 
dua sisi dan mendapatkan hasil yang lebih indah!
Pengurai kontur kontur
Dan jika Anda mencoba menambahkan 
kontur ke dalamnya? Ayo lakukan!
Kami tidak dapat bekerja dengan piksel yang sudah terlarut, karena setelah menjatuhkannya, piksel tersebut 
menghilang selamanya . Sebagai gantinya, kita dapat bekerja dengan nilai-nilai "hampir larut"!
Di 
HLSL, ini sangat sederhana, cukup tambahkan beberapa baris kode setelah menghitung 
klip :
 void surf (Input IN, inout SurfaceOutputStandard o) { //[...] //After our clip calculations if (dissolve_value - _Amount < .05f) //outline width = .05f o.Emission = fixed3(1, 1, 1); //emits white color //Your shader body, you can set the Albedo etc. //[...] } 
Selesai!Saat bekerja dengan 
Grafik Shader, logikanya sedikit berbeda. Inilah shader yang sudah jadi:
Kita dapat membuat 
efek yang sangat 
keren dengan 
shader disolusi sederhana; Anda dapat bereksperimen dengan 
berbagai tekstur dan 
nilai , serta menghasilkan sesuatu yang lain!
Bagian 2: Dunia eksplorasi shader
Sebuah shader 
penjelajahan dunia (atau " 
shader pembubaran dunia , atau 
pembubaran global ") memungkinkan kita untuk sama-sama menyembunyikan semua objek dalam adegan berdasarkan jaraknya ke posisi; sekarang kita akan membuat shader seperti itu dalam 
Unity Shader Graph dan menuliskannya dalam 
HLSL .
Berikut ini contoh yang akan kami buat:
Jarak sebagai parameter
Misalkan kita perlu 
membubarkan sebuah objek dalam sebuah adegan jika 
terlalu jauh dari pemain . Kami telah mengumumkan parameter 
_Amount , yang mengontrol hilangnya / pembubaran objek, jadi kami harus menggantinya dengan jarak antara objek dan pemain.
Untuk melakukan ini, kita perlu mengambil posisi 
Player dan 
Object .
Posisi Pemain
Prosesnya akan serupa untuk 
Unity Shader Graph dan 
HLSL : kita perlu mentransfer posisi pemain dalam kode.
 private void Update() {  
Grafik shader
Posisi objek dan jarak ke sana
Menggunakan Grafik Shader, kita dapat menggunakan node Posisi dan Jarak.
PS Agar sistem ini berfungsi dengan Sprite Renderers, Anda perlu menambahkan properti _MainTex, sampel dan sambungkan ke albedo. Anda dapat membaca tutorial 
Spader shader difus saya sebelumnya (yang menggunakan grafik shader).
HLSL (permukaan)
Posisi Obyek
Dalam HLSL, kita dapat menambahkan variabel 
worldPos ke struktur 
Input kami untuk mendapatkan posisi simpul objek.
 struct Input { float2 uv_MainTex; float3 worldPos;  
Pada 
halaman dokumentasi Unity, Anda dapat mengetahui parameter bawaan apa yang diizinkan untuk ditambahkan ke struktur input.
Terapkan jarak
Kita perlu menggunakan jarak antara objek dan pemain sebagai jumlah pembubaran. Untuk melakukan ini, Anda dapat menggunakan fungsi 
jarak built-in ( 
dokumentasi Microsoft ).
 void surf (Input IN, inout SurfaceOutputStandard o) { half dissolve_value = tex2D(_DissolveTexture, IN.uv_MainTex).x; float dist = distance(_PlayerPos, IN.worldPos); clip(dissolve_value - dist/ 6f);  
Hasil (3D)
Hasil (2D)
Seperti yang Anda lihat, objek larut "lokal", kami tidak mendapatkan efek homogen, karena kami mendapatkan "nilai disolusi" dari tekstur sampel menggunakan UV dari masing-masing objek. (Dalam 2D, ini kurang terlihat).
3D LocalUV Melarutkan Shader di HLSL
 Shader "Custom/GlobalDissolveSurface" { Properties { _Color ("Color", Color) = (1,1,1,1) _MainTex ("Albedo (RGB)", 2D) = "white" {} _Glossiness("Smoothness", Range(0,1)) = 0.5 _Metallic("Metallic", Range(0,1)) = 0.0 _DissolveTexture("Dissolve texture", 2D) = "white" {} _Radius("Distance", Float) = 1 //distance where we start to reveal the objects } SubShader{ Tags { "RenderType" = "Opaque" } LOD 200 Cull off //material is two sided CGPROGRAM #pragma surface surf Standard fullforwardshadows #pragma target 3.0 sampler2D _MainTex; sampler2D _DissolveTexture; //texture where we get the dissolve value struct Input { float2 uv_MainTex; float3 worldPos; //Built-in world position }; half _Glossiness; half _Metallic; fixed4 _Color; float3 _PlayerPos; //"Global Shader Variable", contains the Player Position float _Radius; void surf (Input IN, inout SurfaceOutputStandard o) { half dissolve_value = tex2D(_DissolveTexture, IN.uv_MainTex).x; float dist = distance(_PlayerPos, IN.worldPos); clip(dissolve_value - dist/ _Radius); fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color; o.Albedo = c.rgb; o.Metallic = _Metallic; o.Smoothness = _Glossiness; o.Alpha = ca; } ENDCG } FallBack "Diffuse" } 
Sprite Diffuse - LocalUV Melarutkan Shader di HLSL
 Shader "Custom/GlobalDissolveSprites" { Properties { [PerRendererData] _MainTex("Sprite Texture", 2D) = "white" {} _Color("Tint", Color) = (1,1,1,1) [MaterialToggle] PixelSnap("Pixel snap", Float) = 0 [HideInInspector] _RendererColor("RendererColor", Color) = (1,1,1,1) [HideInInspector] _Flip("Flip", Vector) = (1,1,1,1) [PerRendererData] _AlphaTex("External Alpha", 2D) = "white" {} [PerRendererData] _EnableExternalAlpha("Enable External Alpha", Float) = 0 _DissolveTexture("Dissolve texture", 2D) = "white" {} _Radius("Distance", Float) = 1 //distance where we start to reveal the objects } SubShader { Tags { "Queue" = "Transparent" "IgnoreProjector" = "True" "RenderType" = "Transparent" "PreviewType" = "Plane" "CanUseSpriteAtlas" = "True" } Cull Off Lighting Off ZWrite Off Blend One OneMinusSrcAlpha CGPROGRAM #pragma surface surf Lambert vertex:vert nofog nolightmap nodynlightmap keepalpha noinstancing #pragma multi_compile _ PIXELSNAP_ON #pragma multi_compile _ ETC1_EXTERNAL_ALPHA #include "UnitySprites.cginc" struct Input { float2 uv_MainTex; fixed4 color; float3 worldPos; //Built-in world position }; sampler2D _DissolveTexture; //texture where we get the dissolve value float3 _PlayerPos; //"Global Shader Variable", contains the Player Position float _Radius; void vert(inout appdata_full v, out Input o) { v.vertex = UnityFlipSprite(v.vertex, _Flip); #if defined(PIXELSNAP_ON) v.vertex = UnityPixelSnap(v.vertex); #endif UNITY_INITIALIZE_OUTPUT(Input, o); o.color = v.color * _Color * _RendererColor; } void surf(Input IN, inout SurfaceOutput o) { half dissolve_value = tex2D(_DissolveTexture, IN.uv_MainTex).x; float dist = distance(_PlayerPos, IN.worldPos); clip(dissolve_value - dist / _Radius); fixed4 c = SampleSpriteTexture(IN.uv_MainTex) * IN.color; o.Albedo = c.rgb * ca; o.Alpha = ca; } ENDCG } Fallback "Transparent/VertexLit" } 
PS Untuk membuat shader terakhir, saya menyalin standar Unity Sprite-Diffuse shader dan menambahkan bagian "larut" yang dijelaskan sebelumnya di bagian artikel ini. Semua shader standar dapat ditemukan di 
sini .
Membuat efeknya homogen
Untuk membuat efek homogen, kita dapat menggunakan koordinat global (posisi di dunia) sebagai koordinat UV dari tekstur disolusi. Penting juga untuk mengatur 
Wrap = Ulangi dalam parameter tekstur pembubaran sehingga kita dapat mengulangi tekstur tanpa menyadarinya (pastikan teksturnya mulus dan diulang dengan baik!)
HLSL (permukaan)
 half dissolve_value = tex2D(_DissolveTexture, IN.worldPos / 4).x;  
Grafik shader
Hasil (2D)
Inilah hasilnya: kita dapat melihat bahwa tekstur pembubaran sekarang seragam untuk seluruh dunia.
Shader ini sudah 
ideal untuk gim 2D , tetapi untuk 
objek 3D perlu 
ditingkatkan .
Masalah dengan objek 3D
Seperti yang Anda lihat, shader tidak berfungsi untuk wajah "non-vertikal", dan sangat merusak tekstur. Inilah sebabnya mengapa itu terjadi. bahwa koordinat UV memerlukan nilai float2, dan jika kita melewati worldPos, maka hanya menerima X dan Y.
Jika kami memperbaiki masalah ini dengan menerapkan perhitungan untuk menampilkan tekstur pada semua wajah, kami akan menemukan masalah baru: ketika gelap, objek akan saling bersilangan, dan tidak akan tetap homogen.
Akan sulit bagi pemula untuk memahami solusinya: perlu untuk menghilangkan tekstur, menghasilkan suara tiga dimensi di dunia dan mendapatkan "nilai pembubaran" dari itu. Dalam posting ini saya tidak akan menjelaskan generasi noise 3D, tetapi Anda dapat menemukan banyak fungsi yang siap digunakan!
Berikut ini contoh noise shader: 
https://github.com/keijiro/NoiseShader . Anda juga dapat mempelajari cara menghasilkan noise di sini: 
https://thebookofshaders.com/11/ dan di sini: 
https://catlikecoding.com/unity/tutorials/noise/Saya akan mengatur fungsi permukaan saya dengan cara ini (dengan asumsi Anda sudah menulis bagian noise):
 void surf (Input IN, inout SurfaceOutputStandard o) { float dist = distance(_PlayerPos, IN.worldPos); //"abs" because you have to make sure that the noise is between the range [0,1] //you can remove "abs" if your noise function returns a value between [0,1] //also, replace "NOISE_FUNCTION_HERE" with your 3D noise function. half dissolve_value = abs(NOISE_FUNCTION_HERE(IN.worldPos)); if (dist > _Radius) { float clip_value = dissolve_value - ((dist - _Radius) / _Radius); clip(clip_value); if (clip_value < 0.05f) o.Emission = float3(1, 1, 1); } fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color; o.Albedo = c.rgb; o.Metallic = _Metallic; o.Smoothness = _Glossiness; o.Alpha = ca; } 
Pengingat singkat HLSL: sebelum menggunakan / memanggil fungsi, itu harus ditulis / dideklarasikan.
PS Jika Anda ingin membuat shader menggunakan Unity Shader Graph, Anda perlu menggunakan Custom Nodes (dan menghasilkan noise dengan menuliskan kode HLSL di dalamnya). Saya akan berbicara tentang Custom Nodes dalam tutorial mendatang.
Hasil (3D)
Menambahkan Kontur
Untuk menambahkan kontur, Anda perlu mengulangi proses dari bagian sebelumnya dari tutorial.
Efek terbalik
Dan jika kita ingin membalikkan efek ini? (Benda akan hilang jika pemain ada di dekatnya)
Cukup bagi kita untuk mengubah satu baris:
 float dist = _Radius - distance(_PlayerPos, IN.worldPos); 
(Proses yang sama berlaku untuk Grafik Shader).