shader製作可循環的噪聲與FBM (Tiled **Noise/**Fbm)

雖然噪聲和Fbm可以實時計算出來,但是計算量大,可以將噪聲和Fbm作爲貼圖信息來使用,這個時候就要解決信息的不重複問題。

第一步,實現隨機,效果如下:

代碼如下:

Shader "Unlit/testTiledNoise"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 100

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            // make fog work
            #pragma multi_compile_fog

            #include "UnityCG.cginc"
            
            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
            };

            struct v2f
            {
                float2 uv : TEXCOORD0;
                UNITY_FOG_COORDS(1)
                float4 vertex : SV_POSITION;
            };

            sampler2D _MainTex;
            float4 _MainTex_ST;
            
            float hash12(float2 p)
            {
	            float3 p3  = frac(float3(p.xyx)*0.1031);
                p3 += dot(p3, p3.yzx + 19.19);
                return frac((p3.x + p3.y) * p3.z);
            }
            
            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = TRANSFORM_TEX(v.uv, _MainTex);
                UNITY_TRANSFER_FOG(o,o.vertex);
                return o;
            }

            float4 frag (v2f i) : SV_Target
            {
                float col = hash12(i.uv);
                return col;
            }
            ENDCG
        }
    }
}

第二步,實現噪聲,額外加上了輔助線, 效果如下:

代碼如下:

Shader "Unlit/testTiledNoise"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 100

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            // make fog work
            #pragma multi_compile_fog

            #include "UnityCG.cginc"
            
            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
            };

            struct v2f
            {
                float2 uv : TEXCOORD0;
                UNITY_FOG_COORDS(1)
                float4 vertex : SV_POSITION;
            };

            sampler2D _MainTex;
            float4 _MainTex_ST;
            
            float hash12(float2 p)
            {
	            float3 p3  = frac(float3(p.xyx)*0.1031);
                p3 += dot(p3, p3.yzx + 19.19);
                return frac((p3.x + p3.y) * p3.z);
            }
            
            float mix1d(float x,float y,float p)
            {
                return x*(1.0-p)+y*p;
            }
            
            float noise12(float2 p)
            {
                float2 id = floor(p);
                float2 lv = smoothstep(0.0,1.0,frac(p));
                float self = hash12(id);
                float forward = hash12(id+float2(1.0,0.0));
                float up = hash12(id+float2(0.0,1.0));
                float upForward = hash12(id+float2(1.0,1.0));
                return mix1d(mix1d(self,forward,lv.x),mix1d(up,upForward,lv.x),lv.y);                
            }
            
            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = TRANSFORM_TEX(v.uv, _MainTex);
                UNITY_TRANSFER_FOG(o,o.vertex);
                return o;
            }

            float4 frag (v2f i) : SV_Target
            {
                float lineX = step(0.499,i.uv.x)-step(0.501,i.uv.x);
                float lineY = step(0.499,i.uv.y)-step(0.501,i.uv.y);
                float lineXY = max(lineX,lineY);
                
                float col = mix1d(noise12(i.uv*2),0.5,lineXY);
                return col;
            }
            ENDCG
        }
    }
}

通過上圖看到,uv擴大了2倍,範圍變成了[0-2],則該圖可以劃分爲4個區域,但是這4個區域並沒有互相之間無縫連接,接下來要修改代碼,讓這四個區域無縫連接。

效果如下:

代碼如下:

Shader "Unlit/testTiledNoise"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 100

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            // make fog work
            #pragma multi_compile_fog

            #include "UnityCG.cginc"
            
            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
            };

            struct v2f
            {
                float2 uv : TEXCOORD0;
                UNITY_FOG_COORDS(1)
                float4 vertex : SV_POSITION;
            };

            sampler2D _MainTex;
            float4 _MainTex_ST;
            
            float hash12(float2 p,float scale)
            {
                p = fmod(p,scale);
	            float3 p3  = frac(float3(p.xyx)*0.1031);
                p3 += dot(p3, p3.yzx + 19.19);
                return frac((p3.x + p3.y) * p3.z);
            }
            
            float mix1d(float x,float y,float p)
            {
                return x*(1.0-p)+y*p;
            }
            
            float noise12(float2 p,float scale)
            {
                p*=scale;
                float2 id = floor(p);
                float2 lv = smoothstep(0.0,1.0,frac(p));
                float self = hash12(id,scale);
                float forward = hash12(id+float2(1.0,0.0),scale);
                float up = hash12(id+float2(0.0,1.0),scale);
                float upForward = hash12(id+float2(1.0,1.0),scale);
                return mix1d(mix1d(self,forward,lv.x),mix1d(up,upForward,lv.x),lv.y);                
            }
            
            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = TRANSFORM_TEX(v.uv, _MainTex);
                UNITY_TRANSFER_FOG(o,o.vertex);
                return o;
            }

            float4 frag (v2f i) : SV_Target
            {
                float lineX = step(0.499,i.uv.x)-step(0.501,i.uv.x);
                float lineY = step(0.499,i.uv.y)-step(0.501,i.uv.y);
                float lineXY = max(lineX,lineY);
                
                float col = mix1d(noise12(i.uv*2,6),0.5,lineXY);
                return col;
            }
            ENDCG
        }
    }
}

最後是生成能無縫連接的分型布朗運動圖

最終代碼如下:

Shader "Unlit/testTiledNoise"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 100

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            // make fog work
            #pragma multi_compile_fog

            #include "UnityCG.cginc"
            
            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
            };

            struct v2f
            {
                float2 uv : TEXCOORD0;
                UNITY_FOG_COORDS(1)
                float4 vertex : SV_POSITION;
            };

            sampler2D _MainTex;
            float4 _MainTex_ST;
            
            float hash12(float2 p,float scale)
            {
                p = fmod(p,scale);
	            float3 p3  = frac(float3(p.xyx)*0.1031);
                p3 += dot(p3, p3.yzx + 19.19);
                return frac((p3.x + p3.y) * p3.z);
            }
            
            float mix1d(float x,float y,float p)
            {
                return x*(1.0-p)+y*p;
            }
            
            float noise12(float2 p,float scale)
            {
                p*=scale;
                float2 id = floor(p);
                float2 lv = smoothstep(0.0,1.0,frac(p));
                float self = hash12(id,scale);
                float forward = hash12(id+float2(1.0,0.0),scale);
                float up = hash12(id+float2(0.0,1.0),scale);
                float upForward = hash12(id+float2(1.0,1.0),scale);
                return mix1d(mix1d(self,forward,lv.x),mix1d(up,upForward,lv.x),lv.y);                
            }
            
            float fbm12(float2 p,float scale)
            {
                float c = 0;
                c+= 0.5*noise12(p*1.0,scale);
                c+= 0.5*0.5*noise12(p*1.0*2.0,scale*scale);
                c+= 0.5*0.5*0.5*noise12(p*1.0*2.0*2.0,scale*scale*scale);
                c+= 0.5*0.5*0.5*0.5*noise12(p*1.0*2.0*2.0*2.0,scale*scale*scale*scale);
                return c;
            }
            
            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = TRANSFORM_TEX(v.uv, _MainTex);
                UNITY_TRANSFER_FOG(o,o.vertex);
                return o;
            }

            float4 frag (v2f i) : SV_Target
            {
                float col = fbm12(i.uv*2,6);
                return col;
            }
            ENDCG
        }
    }
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章