找回密码
 立即注册
查看: 275|回复: 1

Unity Shader 片段舍弃实现溶解效果(附源码)

[复制链接]
发表于 2022-2-16 14:21 | 显示全部楼层 |阅读模式
大家好,我是老莫,今天分享一下溶解效果的制作方法。
首先定义clip和color属性
_MainTex ("Texture", 2D) = "white" {}
        _Color ("Color",Color) =(1,1,1,1)
        _Clip("Clip",Range(0,1)) = 0
因为我们要做片段舍弃,所以将Clip运算放在片段着色器中



X代表一个数值,当X<0时,则舍弃掉此片段.

括号中的X就是我们要舍弃掉的片段值,当X<0时,该片段舍弃



只有当x<0,片段才会舍弃

当X为某个数值时,只能实现所有像素的取舍,那么我们想要部分像素舍弃,达到溶解效果,就需要这样一张噪波图。



网上随意找一张噪波图即可

这样做的原理是,噪波图中数值代表了一个Range(0,1),任何一个像素都被限制在这个范围内,并且随机分布,此时我们将噪波图减去一个Range(0,1),就可以控制最终的值了。
属性面板添加一个-DissolveTex,在片段着色器采样它,然后使用采样后的图减去Clip值
fixed4 tex = tex2D(_MainTex,i.uv);

                fixed4 dissolveTex = tex2D(_DissolveTex,i.uv);
                clip(dissolveTex-_Clip);



不同Clip值所产生的的效果

现在对该效果进行优化,增加一个溶解边缘
我们需要这样一张贴图 _RampTex



PS中随便制作一个即可

我们做这张图的目的在于,将_DissolveTex中从0到1(黑到白)与_RampTex中从左到右对应,听起来有点莫名其妙,慢慢往下看。
使用_DissolveTex采样上图
fixed4 tex = tex2D(_MainTex,i.uv);
                fixed4 dissolve = tex2D(_DissolveTex,i.uv);
                fixed4 ramptex = tex2D(_RampTex,dissolve);
                clip(dissolve-_Clip);
                fixed4 c = tex * _Color+ramptex;
                return c;


创建一个平面可以更直观地看到效果,请注意现在我们已完成了_DissolveTex中从0到1(黑到白)与_RampTex中从左到右对应。但是目前边缘没有随着溶解的值变化,这里我们需要用到unity内置函数smoothstep。
如果 x 比min 小,返回 0;如果 x 比max 大,返回 1;如果 x 处于范围 [min,max]中,则返回 0 和 1 之间的值(按值在min和max间的比例取平滑值)。
smoothstep(min,max,x)

我们将_Clip设为最小值,再配合_Clip值变化,就可以使溶解边缘始终都是从_RampTex的最左边开始采样
                fixed4 tex = tex2D(_MainTex,i.uv);
                fixed4 dissolve = tex2D(_DissolveTex,i.uv);
                fixed4 ramptex = tex2D(_RampTex,smoothstep(_Clip,1,dissolve));
                clip(dissolve-_Clip);
                fixed4 c = tex * _Color+ramptex;


这时我们的溶解边缘正确了,但是_RampTex覆盖了主纹理.
在上一步中,我们将最小值设为_Clip,得以控制边缘,现在我们把最大值设为_Clip+0.1,这样使得我们只在_clip 和_clip+0.1之间采样_RampTex



clip=0.2

划重点
现在我们实现了溶解效果,基本了解了原理,但是以上方法计算量较大(smoothstep),现在我们讲讲如何优化。首先我们看一下smoothstep 的原理
float smoothstep (float min, float max, float x)
{
        float t = saturate ((x - min) / (max - min));
        return t * t * (3.0 - (2.0 * t));
}
其中return t * t *(3.0-(2.0* t));是为了使最终值平滑,运算量太大,我们可以把这一步省掉,直接手写差值,使用saturate
fixed4 tex = tex2D(_MainTex,i.uv);

                fixed4 dissolveTex = tex2D(_DissolveTex,i.uv);
                clip(dissolveTex-_Clip);
                fixed dissolvevalue = saturate(dissolveTex-_Clip)/(_Clip+0.1-_Clip);
                fixed4 ramptex = tex2D(_RampTex,dissolvevalue);
                fixed4 c = tex * _Color+ramptex;
                return c;



到这里unity shader中的溶解效果就完成了,收工。

最后附上源码
Shader "Unlit/rongjie"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
        _Color ("Color",Color) =(1,1,1,1)
        _Clip("Clip",Range(0,1)) = 0
        _DissolveTex("DissolveTex",2D) = "white"{}
        _RampTex ("RampTex",2D) = "white"{}
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 100

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "UnityCG.cginc"

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

            struct v2f
            {
                float2 uv : TEXCOORD0;
                float4 pos : SV_POSITION;
            };

            sampler2D _MainTex;
            sampler2D _DissolveTex;
            sampler2D _RampTex;
            float4 _MainTex_ST;
            fixed4 _Color;
            float _Clip;

            v2f vert (appdata v)
            {
                v2f o;
                o.pos = UnityObjectToClipPos(v.vertex);
                o.uv = v.uv;
               
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                fixed4 tex = tex2D(_MainTex,i.uv);

                fixed4 dissolveTex = tex2D(_DissolveTex,i.uv);
                clip(dissolveTex-_Clip);
                fixed dissolvevalue = saturate(dissolveTex-_Clip)/(_Clip+0.1-_Clip);
                fixed4 ramptex = tex2D(_RampTex,dissolvevalue);
                fixed4 c = tex * _Color+ramptex;
                return c;
            }
            ENDCG
        }
    }
}

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
发表于 2022-2-16 14:30 | 显示全部楼层
进我收藏夹吃会[思考]
懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Unity开发者联盟 ( 粤ICP备20003399号 )

GMT+8, 2024-9-22 19:36 , Processed in 0.102216 second(s), 26 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表