Unity-2D畫素晶格化消融

小紫蘇發表於2022-07-16

效果展示:

ShaderLab

Shader功能:影像變白+根據頂點的y值作透明裁剪;

才是可操作屬性:

image-20220716151322205

IsDead: 控制畫素變白,片元著色階段IsDead小於0將顏色改為白色;

Percent: 透明剔除分界線,也是圖片展示百分比;在頂點計算階段,記錄Percent - vertex.y值,傳入片元著色器,直接裁剪;

Revert:反轉percent結果;(粒子顯示效果和圖片遮擋效果正好相反)

調整shader中Percent得到如下結果:

使用該shader建立兩個材質,spriterenderer和ParticalSystemRenderer分別使用,ParticalSystem勾選Revert;

完整shader:

Shader "PixelDisappear"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
        _IsDead("IsDead",float) = 1
        _Percent("Percent",Range(-8,10))=0
        _Revert("Revert",float) = 1
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
            };

            struct v2f
            {
                float3 uv : TEXCOORD0;
                float4 vertex : SV_POSITION;
            };

            sampler2D _MainTex;
            float4 _MainTex_ST;
            float _Percent;
            float _IsDead;
            float _Revert;


            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv.xy = TRANSFORM_TEX(v.uv, _MainTex);
                if(_Revert > 0)
                    o.uv.z = _Percent - v.vertex.y;
                else
                    o.uv.z = -_Percent + v.vertex.y;
                
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                clip(i.uv.z);
                fixed4 col;
                if(_IsDead < 0)
                    col = float4(1,1,1,1);
                else
                    col = tex2D(_MainTex, i.uv);
                
                return col;
            }
            ENDCG
        }
    }
}

ParticalSystem

基礎屬性設定:

maxparticle控制最大粒子數量;

stopaction決定粒子非loop結束後是disable還是銷燬;

gravitymodifier新增一點重力,負值向上移動粒子;

image-20220716164358386

粒子新增shape元件;

選擇SpriteRender,需要晶格化的gameobject賦值給Sprite;

Clip裁剪透明通道;

image-20220716163429687

Emisson元件,選擇隨時間,或者Burst都可;

粒子數量不能高於MaxParicles的設定(高了也沒用);

Noise元件設定固定滾動速度;

Quality選2D;

image-20220716164013821

Renderer元件中,新增上面寫好的shader材質;

size設定粒子大小;

使用時,程式碼控制兩個材質的percent屬性;

public class Test : MonoBehaviour
{
    public SpriteRenderer SP;
    public ParticleSystem PS;
    private bool isDead;
    private float curTime;
    private float offset;
    private float speed = 6.5f;
    Material  matPS;

    [SerializeField]private float startVal = 10;
    private void Start()
    {
        matPS = PS.GetComponent<Renderer>().sharedMaterial;
        matPS.SetFloat("_Percent", startVal );
        SP.sharedMaterial.SetFloat("_Percent", startVal );
        SP.sharedMaterial.SetFloat("_IsDead",1);
    }
    
    void Update()
    {
        if (Input.GetKeyDown(KeyCode.P))
        {
            isDead = true;
            matPS.SetFloat("_Percent", startVal );
            SP.sharedMaterial.SetFloat("_Percent", startVal );
            matPS.SetFloat("_IsDead",-1);
            var mainModule = PS.main;
            mainModule.loop = true;
            PS.gameObject.SetActive(true);
            offset = 0;
        }

        if (isDead)
        {
            offset += Time.deltaTime * speed;
            matPS.SetFloat("_Percent", startVal - offset);
            SP.sharedMaterial.SetFloat("_Percent", startVal - offset);

            if (matPS.GetFloat("_Percent") < -10)
            {
                isDead = false;
                var mainModule = PS.main;
                mainModule.loop = false;
            }
        }
    }
}

image-20220716165009750

相關文章