Unity Shader-利用噪声图实现类似水面的效果

  • 下图为静态的图片和噪声图

  • 先把问题简化,让纹理产生扭曲的效果:
// 在片元着色器
fixed4 frag(v2f i) : SV_Target
{
    // 采集到噪声图在该片元的颜色的r通道值
    float r = tex2D(_NoiseTex, i.uv_Noise).r;
    // 将r转换为主纹理采样的偏移值offset
    fixed2 offset = fixed2(r, r);
    // 修正,防止纹理边缘产生扭曲的效果
    offset -= _NoiseBrightOffset;
    // 将offset乘以自定义参数,方便我们控制
    offset *= fixed2(_NoiseScaleX, _NoiseScaleY);
    // 在采集纹素时,将偏移值offset附加到uv上
    fixed4 col = tex2D(_MainTex, i.uv + offset); // 加上扰动UV后再采样主纹理
    return col;
}

 

  • 至此我们可以得到一个静态的扭曲的图片

 

  • 那么如何让画面动起来呢?
    1. 如果让噪声图随时间移动,图片便会随着时间产生不同的扭曲效果。
    2. 很容易想到,我们可以去调整噪声图的偏移Offset。

 

 

  • 这里我们使用内置变量_Time来影响噪声图的偏移。如下图,_Time变量可以方便我们在Shader中访问运行时间,实现各种动画效果。《Unity Shader入门精要-时间篇》

 

  • 如下方代码,我们可以得到一个动态的扭曲的图片
    // 顶点着色器
    v2f vert(appdata v)
    {
        v2f o;
        // 顶点着色器的基本操作
        o.vertex = UnityObjectToClipPos(v.vertex);
        // 将顶点的UV传递给片元着色器
        o.uv = v.uv;
        // 将噪声图Noise的偏移Offset加上时间
        // 这里我们将时间_Time乘以了自定义参数,更方便我们控制水流的速度
        _NoiseTex_ST.zw += _Time * fixed2(_NoiseSpeedX, _NoiseSpeedY);
        // 计算出经过缩放和偏移后的纹理坐标
        o.uv_Noise = TRANSFORM_TEX(v.texcoord, _NoiseTex);
        return o;
    }

完整代码参考

  • Shader "Unlit/PerlinNoiseApp"
    {
        Properties
        {
            [NoScaleOffset] _MainTex ("MainTex", 2D) = "white" {} // 主纹理
            _NoiseTex ("NoiseTex", 2D) = "white" {} // 噪点图
            _NoiseScaleX ("NoiseScaleX", Range(0, 1)) = 0.1 // 水平噪点放大系数
            _NoiseScaleY ("NoiseScaleY", Range(0, 1)) = 0.1 // 垂直放大系数
            _NoiseSpeedX ("NoiseSpeedX", Range(0, 10)) = 1 // 水平扰动速度
            _NoiseSpeedY ("NoiseSpeedY", Range(0, 10)) = 1 // 垂直扰动速度
            _NoiseBrightOffset ("NoiseBrightOffset", Range(0, 0.9)) = 0.25 // 噪点图整体的数值偏移
        }
        SubShader
        {
            Pass
            {
                CGPROGRAM
                #pragma vertex vert
                #pragma fragment frag
                #include "UnityCG.cginc"
    
                struct appdata
                {
                    float4 vertex : POSITION;
                    float2 uv : TEXCOORD0;
                    float4 texcoord : TEXCOORD1;
                };
    
                struct v2f
                {
                    float4 vertex : SV_POSITION;
                    float2 uv : TEXCOORD0;
                    float2 uv_Noise : TEXCOORD1;
                };
    
                // 主纹理
                sampler2D _MainTex;
                // 噪声图
                sampler2D _NoiseTex;
                // 噪声图
                fixed4 _NoiseTex_ST;
                // 干扰在X方向上的缩放倍数
                fixed _NoiseScaleX;
                // 干扰在Y方向上的缩放倍数
                fixed _NoiseScaleY;
                // X方向的水流速度
                fixed _NoiseSpeedX;
                // Y方向的水流速度
                fixed _NoiseSpeedY;
                // 噪声图的起始偏移,防止纹理边缘产生扭曲的效果
                fixed _NoiseBrightOffset;
    
                v2f vert(appdata v)
                {
                    v2f o;
                    // 顶点着色器的基本操作
                    o.vertex = UnityObjectToClipPos(v.vertex);
                    // 将顶点的UV传递给片元着色器
                    o.uv = v.uv;
                    // 将噪声图Noise的偏移Offset加上时间
                    // 这里我们将时间_Time乘以了自定义参数,更方便我们控制水流的速度
                    _NoiseTex_ST.zw += _Time * fixed2(_NoiseSpeedX, _NoiseSpeedY);
                    // 计算出经过缩放和偏移后的纹理坐标
                    o.uv_Noise = TRANSFORM_TEX(v.texcoord, _NoiseTex);
                    return o;
                }
    
                fixed4 frag(v2f i) : SV_Target
                {
                    // 采集到噪声图在该片元的颜色的r通道值
                    float r = tex2D(_NoiseTex, i.uv_Noise).r;
                    // 将r转换为主纹理采样的偏移值offset
                    fixed2 offset = fixed2(r, r);
                    // 修正,防止纹理边缘产生扭曲的效果
                    offset -= _NoiseBrightOffset;
                    // 将offset乘以自定义参数,方便我们控制
                    offset *= fixed2(_NoiseScaleX, _NoiseScaleY);
                    // 在采集纹素时,将偏移值offset附加到uv上
                    fixed4 col = tex2D(_MainTex, i.uv + offset); // 加上扰动UV后再采样主纹理
                    return col;
                }
                ENDCG
            }
        }
        Fallback "Diffuse"
    }

  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值