1.溶解原理
Ramp渐变贴图一张用来实现溶解的基础
2.smoothstep(限制在0-1区间内)
3.saturate (归一化)
4.实际实现思路过程
4.1-首先先写出溶解边缘效果的渐变贴图,完成他的纹理采样三步骤:定义-声明-采样
_RampTex("渐变效果(RGB)",2D) = "White" {}
sampler2D _RampTex;
fixed4 RampTex = tex2D(_RampTex,i.uv);
下面是片断着色器代码
fixed4 frag(v2f i):SV_TARGET
{
fixed4 c;
fixed4 tex = tex2D(_Tex,i.uv.xy);
c = tex;
c += _Color;
fixed4 dissolveUV = tex2D(_Dissolve,i.uv.zw);
clip(dissolveUV-_Clip);
fixed4 RampTex = tex2D(_RampTex,i.uv);
c += RampTex;
return c;
}
这样渐变贴图就叠加到了颜色贴图当中
4.2-在片断着色器中,把RampTex数据中的i.uv替换为dissolveTex的UV数据信息
fixed4 frag(v2f i):SV_TARGET
{
fixed4 c;
fixed4 tex = tex2D(_Tex,i.uv.xy);
c = tex;
c += _Color;
fixed4 dissolveUV = tex2D(_Dissolve,i.uv.zw);
clip(dissolveUV-_Clip);
fixed4 RampTex = tex2D(_RampTex,dissolveUV);
c += RampTex;
return c;
}
也就是说,RampTex纹理贴图中每一个像素点的UV数据等于dissolveTex中的每一个UV数据信息
(进一步解释一下:我们知道0为黑色,1为白色。那就是说颜色越黑的溶解遮罩贴图数值越小,越偏向与渐变贴图中亮的地方,越白的溶解这招数值越大,越偏向与渐变贴图中暗的地方)
4.3-使用smoothstep语法把数据限制在0-1区间,方便与clip进行计算和判断,从而实现边缘溶解的裁剪效果
fixed4 RampTex = tex2D(_RampTex,smoothstep(0,1,dissolveUV));
假设最小值为0最大值为1,x为溶解遮罩的uv数据,那我们最终得到的RampTex的片断数据会跟之前一样,效果也是一样的因为UV数据被强制限制在0-1区间
那么如果我们把滑块_Clip的值替换为min最小值,那么RampTex得到的UV数据信息就是在_Clip与1之间,clip值越大,所有小于clip值得UV数据会被强制归于Clip的值.
clip=0 clip=0.3 clip=0.5 clip=0.6 clip=1
如果我们不容易理解,可以先把clip那行注释掉,先不让他消失,来看颜色的变化,理解以后再加上clip的裁剪消失的效果,就会出现上图的效果了。
clip=0 clip=0.3 clip=0.5 clip=0.6 clip=1
例如当clip为0.5时,所有小于0.5的UV数据信息都会等于0.5,也就是消失的那部分。因为低于0.5的偏黑颜色都被限制在0.5或以上了,所以可以看到整体颜色画面会向着全白数值1接近的趋势。
4.4-最后由于我们最小值限制以后最大值并没有赋予一个动态的值,它默认是1所有颜色都不会被约束,所以要对RampTex的最大值进行约束。
fixed4 RampTex = tex2D(_RampTex,smoothstep(_Clip,_Clip+0.1,dissolveUV));
所有大于_Clip+0.1的值都会被限制在_Clip+0.1内,最终看到的就是一个(_Clip
5.代码优化
因为smoothstep的计算量比较大所以我们可以找到一种新的优化方案:
我们在UnityCG.cginc 中找到他的计算方法,并进行图像化
那结果很明显,我们只需要不带平滑的计算就可以实现我们的效果了,只需要选取计算saturate的部分即可。
fixed dissolveValue = saturate((dissolveUV-_Clip)/(_Clip+0.1-_Clip));
fixed4 RampTex = tex2D(_RampTex,dissolveValue);
要注意这个方法函数的计算过程都是一维向量,数据类型为fixed
然后下面这张贴图我们在计算和采样时发现,他的V坐标颜色数值都是一样,所以在声明时不需要采用2D贴图 用1D足矣,并不会影响计算过程和最终效果
因此修改代码如下
sampler _RampTex;
fixed4 rampTex = tex1D(_RampTex,dissolveValue);
6.整体代码展示
Shader "WSP/FrameWork7"
{
Properties
{
[Header(Base Color)]
[Space(10)]
_Color("Color",Color) = (0,0,0,0)
_Tex("MainTex",2D) = "White" {}
[Space(15)]
[Header(Dissolve)]
[Space(10)]
_Dissolve("DissolveTex",2D) = "White" {}
[NoScaleOffset]_RampTex("Ramp(RGB)",2D) = "White" {}
_Clip("Clip",Range(0,1)) = 0
}
SubShader
{
pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
sampler2D _Tex;
fixed4 _Color;
sampler2D _Dissolve;float4 _Dissolve_ST;
fixed _Clip;
sampler _RampTex;
struct appdata
{
float4 vertex :POSITION;
float4 uv :TEXCOORD;
};
struct v2f
{
float4 pos :POSITION;
float4 uv :TEXCOORD;
};
v2f vert(appdata v)
{
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
o.uv.xy = v.uv.xy;
//o.uv.zw = v.uv *_Dissolve_ST.xy+_Dissolve_ST.zw;
o.uv.zw = TRANSFORM_TEX(v.uv,_Dissolve);
return o;
}
fixed4 frag(v2f i):SV_TARGET
{
fixed4 c;
fixed4 tex = tex2D(_Tex,i.uv.xy);
c = tex;
c += _Color;
fixed4 dissolveUV = tex2D(_Dissolve,i.uv.zw);
clip(dissolveUV-_Clip);
fixed dissolveValue = saturate((dissolveUV-_Clip)/(_Clip+0.1-_Clip));
fixed4 rampTex = tex1D(_RampTex,dissolveValue);
c += rampTex;
return c;
}
ENDCG
}
}
}