最近项目里做到一个功能,需要用shader在两张贴图中切换,类似这种消融效果。在此记录下实现的基本思想,也许以后有用。
image
代码比较简单,就是算出每个片元(fragment)到y方向(也可以是x方向,z方向,我在这里用y)起始位置距离,通过一个offset变量来控制这个距离,让这个距离作为参数在两张贴图之间来回切换。
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
o.uv1 = TRANSFORM_TEX(v.uv1,_SecondTex);
o.uvNoise = TRANSFORM_TEX(v.uvNoise,_NoiseTex);
o.pos = v.vertex.y;//获取每个顶点y的位置,以便之后使用
UNITY_TRANSFER_FOG(o,o.vertex);
return o;
}
fixed4 frag (v2f i) : SV_Target
{
// sample the texture
fixed4 c1 = tex2D(_MainTex, i.uv);//获取第一张贴图颜色
fixed4 c2 = tex2D(_SecondTex, i.uv1);//获取第二张贴图颜色
fixed4 noise = tex2D(_NoiseTex,i.uvNoise);
fixed range = _Max - _Min;//mesh中起点到终点最大距离,这两个值最好具体通过遍历mesh来确定最大最小值再传入,我这里图方便直接取了-1和1
fixed dist = i.pos - _Min;//每个片元到起始位置的距离
fixed normalizeDist = saturate(dist / range);//归一化上一步得出的距离
fixed param = noise.r * (1 - _Curve) + normalizeDist * _Curve;
fixed degree = saturate((param - _Offset) / _EdgeLength);//通过offset来控制归一化的距离
fixed4 ramp = tex2D(_RampTex,fixed2(degree,degree));
fixed4 col = lerp(c1,c2 + ramp,degree);//在两张texture间切换
// apply fog
UNITY_APPLY_FOG(i.fogCoord, col);
return col;
}
在这里我为了在切换的时候那条分割线不要那么直和硬(其实也是美术希望这么做的,我都不在乎=_=!),用一张噪声图和一张渐变纹理把分割线弄成波浪形并且颜色服从渐变纹理的颜色。从代码上看就是:
-
fixed4 noise = tex2D(_NoiseTex,i.uvNoise);
获取噪声图 -
fixed param = noise.r * (1 - _Curve) + normalizeDist * _Curve;
用一个变量_Curve
来做lerp
所实现的事,如果_Curve
接近1则param
接近normalizeDist
,这条分割线就是条水平线(如图1),接近0就会取噪声图中r
通道的值,噪声图中的值比较杂乱无序,就会造成波浪形(如图2)。这种思想也是lerp
这个函数在做的事。 -
fixed degree = saturate((param - _Offset) / _EdgeLength);
再用一个_EdgeLength
来控制分割线的粗细程度 - 最后两张图之间切换时将得到的混合了渐变纹理颜色的分割线叠加到第二张贴图上,大功告成!
呃。。。我不会做动图,就截几张图顶替一下吧>_<
1 2 3 4
网友评论