# 【Shader练习-扭曲直线】

可以实现类似连线,抽血等效果。

全屏显示

包括了以下练习内容:

  1. 绘制直线。
  2. 程序噪声 (opens new window)
  3. UV扭曲。

WraplineShader.shader

Shader "Unlit/WraplineShader"
{
    Properties
    {
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 100

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
            };

            struct v2f
            {
                float2 uv : TEXCOORD0;
                float4 vertex : SV_POSITION;
            };

            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = v.uv;
                return o;
            }

            // 画一条直线
            fixed4 getline(float2 st)
            {
                float l = step(0.495,st.y);
                float r = step(0.505,st.y);
                return max(l - r,0);
            }

            float hash(float2 p)
            {
                p  = 50.0*frac( p*0.3183099 + float2(0.71,0.113));
                return -1.0+2.0*frac( p.x*p.y*(p.x+p.y) );
            }

            // 程序噪声
            float noise(float2 p)
            {
                int2 i = int2(floor( p ));
                float2 f =  frac( p );
                float2 u = f*f*(3.0-2.0*f);
                return lerp( lerp( hash( i + int2(0,0) ), 
                            hash( i + int2(1,0) ), u.x),
                            lerp( hash( i + int2(0,1) ), 
                            hash( i + int2(1,1) ), u.x), u.y);
            }

            // 分形噪声
            float fractalnoise(float2 uv)
            {
                float f = 0.0;
                uv *= 16.0;
                float2x2 m = float2x2( 1.6,  1.2, -1.2,  1.6 );
                f  = 0.5000*noise( uv ); uv = mul(m,uv);
                f += 0.2500*noise( uv ); uv = mul(m,uv);
                f += 0.1250*noise( uv ); uv = mul(m,uv);
                f += 0.0625*noise( uv ); uv = mul(m,uv);
                return f;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                float2 moveuv = i.uv + float2(_Time.y * 0.25,0);
                // 静止的噪声
                float noise = fractalnoise(i.uv);
                // 移动的噪声
                float mnoise = fractalnoise(moveuv);
                // uv扰动
                float2 noiseuv = frac(i.uv + float2(mnoise*0.01,mnoise*0.01) + float2(noise*0.01,noise*0.01));
                // 根据扰动的uv来生成扭曲直线
                return getline(noiseuv);
            }
            ENDCG
        }
    }
}