前言
继透明贴图之后,今天再来说一下UV动态效果之UV流动和UV扰动的实现方式。
所谓的UV动态指的是UV随着时间进行特定的变化,因此在shader中需要获取游戏运行的时间,将时间数值进行一定的处理后作为偏移量加到UV上,再用偏移后的UV对Noise贴图进行采样,最后叠加到颜色贴图上。
在Unity中获取到的时间参数_Time,为float4类型,其中x、y、z、w四个分量分别代表t/20、 t、 t*2、 t*3,可根据需要选择使用。
UV流动
UV流动效果也被称为GhostFlow效果,如前面所说,需要对UV根据时间进行某个方向的偏移,再对Noise贴图进行采样。
Unity中的shader代码如下:
// shader的路径和名称 Shader "Shader Forge/UVflow" { // 暴露属性到面板 Properties { _MainTex("Main Texture", 2d) = "white"{} _Opacity("Opacity", range(0.0, 1.0)) = 0.5 _NoiseTex("Noise Texture", 2D) = "white"{} _NoiseMul("Noise Multiply", range(0.0,5.0)) = 1.0 _FlowSpeed("Flow Speed", range(-10.0,10.0)) = 5.0 } SubShader { Tags { "Queue"="Transparent" //调整渲染顺序 "RenderType"="Transparent" //透贴 "ForceNoShadowCasting"="True" //关闭阴影投射 "IgnoreProjector"="True" //不响应投射器 } Pass { Name "FORWARD" Tags { "LightMode"="ForwardBase" } Blend One OneMinusSrcAlpha //修改混合模式 CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" #pragma multi_compile_fwdbase_fullshadows #pragma target 3.0 // 声明变量 uniform sampler2D _MainTex; uniform half _Opacity; uniform sampler2D _NoiseTex; uniform float4 _NoiseTex_ST; uniform half _NoiseMul; uniform half _FlowSpeed; // 输入结构 struct VertexInput { float4 vertex : POSITION; float2 uv : TEXCOORD0; }; // 输出结构 struct VertexOutput { float4 pos : SV_POSITION; float2 uv0 : TEXCOORD0; //采样MainTex float2 uv1 : TEXCOORD1; //采样NoiseTex }; // 顶点shader VertexOutput vert (VertexInput v) { VertexOutput o = (VertexOutput)0; o.pos = UnityObjectToClipPos( v.vertex ); o.uv0 = v.uv; o.uv1 = TRANSFORM_TEX(v.uv, _NoiseTex); //UV1支持TillingOffset o.uv1.y = o.uv1.y + frac(-_Time.x * _FlowSpeed); //V轴方向随时间流动,frac()取余数 return o; } // 像素shader float4 frag(VertexOutput i) : COLOR { half4 var_MainTex = tex2D(_MainTex, i.uv0); half4 var_NoiseTex = tex2D(_NoiseTex, i.uv1); half3 finalRGB = var_MainTex.rgb; half noise = lerp(1.0, var_NoiseTex * 2.0, _NoiseMul); //remap范围 noise = max(0.0, noise); //截掉负值 half opacity = var_MainTex.a * _Opacity * noise; return half4(finalRGB * opacity, opacity); } ENDCG } } FallBack "Diffuse" }
效果如下:
如果感觉流动的效果比较呆板,纹理重复率较高,可以通过两张Noise贴图分别用不同的速度叠加成最终Noise贴图再使用的方式得到比较自然的Noise效果。
UV扰动
UV扰动也被称为GhostWarp,实现思路是在UV流动的基础上对UV进行扰动,先根据时间对UV进行某个方向的偏移,之后UV通过Warp贴图的R、G通道叠加上U、V轴向的扰动偏移量,最后也是再将偏移后的UV对Noise贴图进行采样。
而且为了减少采样贴图的数量,可以把Noise贴图整合到Warp贴图的B通道中使用。
// shader的路径和名称 Shader "Shader Forge/UVwarp" { // 暴露属性到面板 Properties { _MainTex("Main Texture", 2d) = "white"{} _Opacity("Opacity", range(0.0, 1.0)) = 0.5 _WarpTex("Warp Texture", 2D) = "white"{} //rg通道控制UV方向的扭曲,b通道为noise,这样可以少采样一张贴图 _WarpMul("Warp Multiply", range(0.0, 5.0)) = 1.0 _NoiseMul("Noise Multiply", range(0.0,5.0)) = 1.0 _FlowSpeed("Flow Speed", range(-10.0,10.0)) = 5.0 } SubShader { Tags { "Queue"="Transparent" //调整渲染顺序 "RenderType"="Transparent" //透贴 "ForceNoShadowCasting"="True" //关闭阴影投射 "IgnoreProjector"="True" //不响应投射器 } Pass { Name "FORWARD" Tags { "LightMode"="ForwardBase" } Blend One OneMinusSrcAlpha //修改混合模式 CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" #pragma multi_compile_fwdbase_fullshadows #pragma target 3.0 // 声明变量 uniform sampler2D _MainTex; uniform half _Opacity; uniform sampler2D _WarpTex; uniform float4 _WarpTex_ST; uniform half _WarpMul; uniform half _NoiseMul; uniform half _FlowSpeed; // 输入结构 struct VertexInput { float4 vertex : POSITION; float2 uv : TEXCOORD0; }; // 输出结构 struct VertexOutput { float4 pos : SV_POSITION; float2 uv0 : TEXCOORD0; //采样MainTex float2 uv1 : TEXCOORD1; //采样WarpTex }; // 顶点shader VertexOutput vert (VertexInput v) { VertexOutput o = (VertexOutput)0; o.pos = UnityObjectToClipPos( v.vertex ); o.uv0 = v.uv; o.uv1 = TRANSFORM_TEX(v.uv, _WarpTex); //UV1支持TillingOffset o.uv1.y = o.uv1.y + frac(-_Time.x * _FlowSpeed); //V轴方向随时间流动,frac()取余数 return o; } // 像素shader float4 frag(VertexOutput i) : COLOR { half3 var_WarpTex = tex2D(_WarpTex, i.uv1).rgb; float2 uvBias = (var_WarpTex.rg - 0.5) * _WarpMul; //计算UV偏移值,让扰动区间在-0.5~0.5 float2 uv0 = i.uv0 + uvBias; //应用UV偏移值 half4 var_MainTex = tex2D(_MainTex, uv0); //使用偏移UV采样MainTex half3 finalRGB = var_MainTex.rgb; half noise = lerp(1.0, var_WarpTex.b * 2.0, _NoiseMul); //remap范围 noise = max(0.0, noise); //截掉负值 half opacity = var_MainTex.a * _Opacity * noise; return half4(finalRGB * opacity, opacity); } ENDCG } } FallBack "Diffuse" }
效果如下:
本文同样参考自B站庄懂的技术美术入门课,感谢。
对待生命,你不妨大胆一点,
因为我们终究要失去它。
《不合时宜的沉思》
——尼采
评论
442343 90194Yay google is my world beater helped me to uncover this fantastic web web site ! . 147894
849224 78506There is noticeably a bundle to realize about this. I assume you produced various nice points in capabilities also. 597610
883693 622802Great post. I previousally to spend alot of my time water skiing and watching sports. It was quite possible the best sequence of my past and your content material kind of reminded me of that period of my life. Cheers 390061
692836 526653dog grooming could be the specialty of my sister, she genuinely loves grooming every dog in our house 194863
415418 414142Im glad I located your article. I would never have created sense of this topic on my own. Ive read some other articles on this subject, but I was confused until I read yours. 60536
147232 540228Exceptional weblog here! In addition your web site rather a great deal up rapidly! What host are you the usage of? Can I get your affiliate link to your host? I wish my site loaded up as fast as yours lol 866942