雖然噪聲和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
}
}
}