Unity UGUI界面溶解效果

@Unity

#基于Shader实现UGUI界面的溶解效果

前段时间要做一个类似的界面的切换效果,发现用溶解实现比较不错;
网上关于溶解效果的实现原理比较多,这里也不做过多的赘述,核心的思路就是对像素进行剔除,实在找不到的可以去这里看看。因为我们要做的效果是一个固定方向开始的效果,所以要在溶解的同时设定起始的一个坐标!
定义一个fixed2 的坐标 _NoiseCentrePos;需要注意的一点是,我们实际是和uv的坐标做运算,所以_NoiseCentrePos的取值范围也是[0 - 1]。

fixed2 _NoiseCentrePos;

要记得我们在声明这个变量的时候,这是一个verctor类型的数据。

_NoiseCentrePos("NoiseCentrePos", Vector) = (0.5, 0.5, 0) 			// 溶解的起始坐标

在这里我们暂且设定为从中心点开始溶解;下边开始介绍代码:
首先是Properties部分

	Properties
	{
		_MainTex ("Texture", 2D) = "white" {} 								// 基础纹理
		_NoiseTex("NoiseTex", 2D) = "white" {} 								// 溶解纹理
		_Threshold("Threshold", float) = 1.3				 				// 阈值

		_NoiseCentrePos("NoiseCentrePos", Vector) = (0.5, 0.5, 0) 			// 溶解的起始坐标
		_FirstBroderColor("FirstBroderColor", Color) = (1, 1, 1, 1) 	// 第一组边缘颜色
		_SecondBroderColor("SecondBroderColor", Color) = (1, 1, 1, 1)  // 第二组边缘颜色
		_ColorFactor("ColorFactor", Range(0, 1)) = 0.7
		_DissoveEdge("DissoveEdge", Range(0, 1)) = 0.8
	}

其次是我们的Tags,设置渲染队列

		Tags 
		{
			"Queue"="Transparent"
			"IgnoreProjector"="True" 
			"RenderType"="Transparent" 
			"PreviewType"="Plane"
			"CanUseSpriteAtlas"="True"
		}

当然很重要的一点,我们知道溶解的原理是剔除像素,所以一定要混合透明度,使用最常用的就可以;当然也有其他的shaderlab的一些混合因子,也很感谢大佬的总结!

Blend SrcAlpha OneMinusSrcAlpha

至于pass部分就是我们需要用到的数据的声明和函数的定义了,例如:

			#pragma vertex vert
			#pragma fragment frag
			#include "UnityCG.cginc"
			....
			sampler2D _MainTex;
			float4 _MainTex_ST;
			....

在顶点着色器中,我们不做过多的处理,就是简单的坐标转换,纹理的采样;这里我 使用的输入数据是“UnityCG.cginc” 中官方为我们定义好的appdata_base,当然我们也可以自己定义(我就是偷懒)

			v2f vert (appdata_base v)
			{
				v2f o;
				UNITY_SETUP_INSTANCE_ID(v);
				UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);  // 实例化处理

				o.vertex = UnityObjectToClipPos(v.vertex);
				o.uv.xy = TRANSFORM_TEX(v.texcoord, _MainTex);
				o.uv.zw = TRANSFORM_TEX(v.texcoord, _NoiseTex);
				return o;
			}

接下来要处理的是片段着色器部分;这部分主要处理溶解的方向和溶解边缘的一些颜色;

			fixed4 frag (v2f i) : COLOR
			{
				fixed4 col = tex2D(_MainTex, i.uv.xy);
				fixed4 nTex = tex2D(_NoiseTex, i.uv.zw);

				// 设置溶解的方向
				half dissove = nTex.r;
				half dist = distance(_NoiseCentrePos, i.uv.zw);
				dissove = dissove + dist;
				col.a *= step(_Threshold, dissove);
				clip(col.a - 0.01);

				// 处理颜色部分
				fixed t = _Threshold / dissove;
				half lerpEdge = sign(t - _ColorFactor - _DissoveEdge);
				fixed3 edgeColor = lerp(_FirstBroderColor.rgb, _SecondBroderColor.rgb, saturate(lerpEdge));
				half lerpOut = sign(t - _ColorFactor);
				fixed3 colorOut = lerp(col.rgb, edgeColor.rgb, saturate(lerpOut));

				return fixed4(colorOut, col.a);
				return col;
			}

需要注意的是,在片段着色器中,我们尽量不要使用逻辑判断和for循环;至于原因这位大佬讲的就很详细;

到这里,如果你的界面上没有文字的话,这个shader就已经足够使用了,只需要你不断的变换shader的阈值就好了。
但是我在实际的应用中还需要用到Text 组件,需要连同Text中的内容一起溶解掉,所以使用了比较取巧的办法,那就是把界面的内容存储在一张Texture中,然后去溶解这个Texture就可以了;幸运的是,在Unity 中是可以这么去做的!我们只需要使用Texture2D这个类去实现。
下面简单的写一下C#代码

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class Test : MonoBehaviour
{
    public RawImage mRawImage;
    private Texture2D mTex;
    public Button onClick;

    void Start()
    {
        mTex = new Texture2D(Screen.width, Screen.height / 2, TextureFormat.RGB24, false);
        onClick.onClick.AddListener(() => {
            StartCoroutine(Coroutine());
        });
    }
    
    void Update()
    {

    }

    /// 
    ///  定义协程
    /// 
    /// 
    public IEnumerator Coroutine()
    {
        yield return new WaitForEndOfFrame();
        var rect = new Rect(0, 0, Screen.width, Screen.height / 2);
        mTex.ReadPixels(rect, 0, 0);
        mTex.Apply();

        mRawImage.texture = mTex;
        mRawImage.SetNativeSize();

    }
}

这里需要介绍的是WaitForEndOfFrame这个协程指令,这个类似于是在等待摄像机渲染完成,如果不使用这个指令的话,就会出现下边的情况;这位大佬讲解的就比较详细
在这里插入图片描述
大概意思就是要从缓冲区去读取像素,而不是从绘图框架里;简单说就是,你的图应该先在Camera渲染完,存进缓冲之后再ReadPixels。

好了,接下来我们运行我们在程序,然后点击按钮看看会出现什么情况。
点击按钮之前我们在视图是这样的:
Unity UGUI界面溶解效果_第1张图片
点击之后可以看到,我们已经把截图的一部分赋值给了rawimage中;
Unity UGUI界面溶解效果_第2张图片
接下来就是把我们的RawImage中的Material 修改成我们的溶解材质,然后在代码中修改他的阈值就好了;我们可以使用计时器,或者在update中去处理;因为比较简单,这里就不写这部分代码了,直接看一下最后在实际项目中的效果:
Unity UGUI界面溶解效果_第3张图片
因为在实际项目中是要从左下角开始溶解,所以我们就把_NoiseCentrePos的值设置为(0,0)就好了。

以上就是实现UGUI界面溶解效果的所有内容了,如果有任何的错误或者其他问题也欢迎各位大佬提出指正,总结不易,转载请注明出处:
https://blog.csdn.net/weixin_41767333/article/details/116791329

你可能感兴趣的:(Shader,shader)