前言
继透明贴图之后,今天再来说一下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站庄懂的技术美术入门课,感谢。
对待生命,你不妨大胆一点,
因为我们终究要失去它。
《不合时宜的沉思》
——尼采
评论
还没有任何评论,你来说两句吧!