有一種新的生成隨機的方式能替代正弦曲線生成隨機,參考地址:https://www.shadertoy.com/view/4djSRW
刪掉正弦曲線相關的代碼,並替換爲新的隨機代碼,正弦曲線的相關概念在接下來會繼續適用於分型布朗運動模型。
生成的效果如下,與上一篇文章最後生成的效果是類似的:
修改後的代碼如下:
Shader "Unlit/sinFunc"
{
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 remap1d(float fromx,float fromy,float tox,float toy,float p)
{
return (p-fromx)/(fromy - fromx)*(toy - tox) + tox;
}
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;
}
float doHashFunc12(float2 p)
{
float HASHSCALE1 = 0.1031;
float3 p3 = frac(float3(p.xyx) * HASHSCALE1);
p3 += dot(p3, p3.yzx + 19.19);
return frac((p3.x + p3.y) * p3.z);
}
float doRandomFunc(float2 xy)
{
return frac(69250*doHashFunc12(xy));
}
float mix1d(float x,float y,float p)
{
return x*(1.0-p)+y*p;
}
float doNoiseFunc(float2 xy)
{
float2 id = floor(xy);
float2 lv = smoothstep(float2(0,0),float2(1.0,1.0),frac(xy));
float orign = doRandomFunc(id);
float forward = doRandomFunc(id+float2(1.0,0.0));
float up = doRandomFunc(id+float2(0.0,1.0));
float upForward = doRandomFunc(id+float2(1.0,1.0));
return mix1d(mix1d(orign,forward,lv.x),mix1d(up,upForward,lv.x),lv.y);
}
float clamp1d(float fromx,float fromy,float tox,float toy,float p)
{
return (p-fromx)/(fromy-fromx)*(toy-tox)+tox;
}
fixed4 frag (v2f i) : SV_Target
{
i.uv+=float2(-0.5,-0.5);
i.uv*=float2(20,20);
float progress = 0;
float2 pos = i.uv.xx+float2(_Time.y,_Time.y)*0.5;
progress += doNoiseFunc(pos)*0.5;
progress += doNoiseFunc(pos*2.0)*0.25;
progress += doNoiseFunc(pos*4.0)*0.125;
progress += doNoiseFunc(pos*8.0)*0.0625;
progress = clamp1d(0,1,-1,1,progress);
float2x2 beveling = float2x2(1,0,
progress,1);
i.uv = mul(beveling,i.uv);
float outOfX = max(step(i.uv.x,0.0),step(1.0,i.uv.x));
float outOfY = max(step(i.uv.y,0.0),step(1.0,i.uv.y));
float outOfArea = max(outOfX,outOfY);
if(outOfArea == 1.0)
{
discard;
}
// sample the texture
fixed4 col = tex2D(_MainTex, i.uv);
// apply fog
UNITY_APPLY_FOG(i.fogCoord, col);
return col;
}
ENDCG
}
}
}
爲了更好的觀察分型布朗運動的運動趨勢,將其變化過程繪製爲線路圖
效果如下:
代碼如下:
Shader "Unlit/sinFunc"
{
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 remap1d(float fromx,float fromy,float tox,float toy,float p)
{
return (p-fromx)/(fromy - fromx)*(toy - tox) + tox;
}
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;
}
float doHashFunc12(float2 p)
{
float HASHSCALE1 = 0.1031;
float3 p3 = frac(float3(p.xyx) * HASHSCALE1);
p3 += dot(p3, p3.yzx + 19.19);
return frac((p3.x + p3.y) * p3.z);
}
float doRandomFunc(float2 xy)
{
return frac(69250*doHashFunc12(xy));
}
float mix1d(float x,float y,float p)
{
return x*(1.0-p)+y*p;
}
float doNoiseFunc(float2 xy)
{
float2 id = floor(xy);
float2 lv = smoothstep(float2(0,0),float2(1.0,1.0),frac(xy));
float orign = doRandomFunc(id);
float forward = doRandomFunc(id+float2(1.0,0.0));
float up = doRandomFunc(id+float2(0.0,1.0));
float upForward = doRandomFunc(id+float2(1.0,1.0));
return mix1d(mix1d(orign,forward,lv.x),mix1d(up,upForward,lv.x),lv.y);
}
float clamp1d(float fromx,float fromy,float tox,float toy,float p)
{
return (p-fromx)/(fromy-fromx)*(toy-tox)+tox;
}
fixed4 frag (v2f i) : SV_Target
{
i.uv+=float2(-0.5,-0.5);
i.uv*=float2(20,20);
float progress = 0;
float2 pos = i.uv.xx+float2(_Time.y,_Time.y)*0.5;
progress += 1.0*0.5* doNoiseFunc(pos*1.0);
progress += 1.0*0.5*0.5* doNoiseFunc(pos*1.0*2.0);
progress += 1.0*0.5*0.5*0.5* doNoiseFunc(pos*1.0*2.0*2.0);
progress += 1.0*0.5*0.5*0.5*0.5*doNoiseFunc(pos*1.0*2.0*2.0*2.0);
//progress = clamp1d(0,1,-1,1,progress);
//繪製分型布朗運動生成的1D曲線
float isY = smoothstep(progress-0.1,progress,i.uv.y) - smoothstep(progress,progress+0.1,i.uv.y) ;
return isY;
}
ENDCG
}
}
}
觀察上面的代碼,在progress變量累加的那部分是有規律的。
將規律設定爲progress+= A*doNoiseFunc(B*pos);
其中A代表振幅,B代表頻率。
每次對progress累加,都以同樣的規律對A和B進行變換,這裏對A進行了縮小0.5倍,對B放大2倍。
將相關參數改爲可設置的變量,通過調整變量的值,似乎隨機可控制了,效果如下:
代碼如下:
Shader "Unlit/sinFunc"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
A("振幅",Float) = 1.0
B("頻率",Float) = 1.0
gain("拉伸",Float) = 0.5
lacunarity("不均勻性",Float) = 2.0
}
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 A;
float B;
float gain;
float lacunarity;
float remap1d(float fromx,float fromy,float tox,float toy,float p)
{
return (p-fromx)/(fromy - fromx)*(toy - tox) + tox;
}
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;
}
float doHashFunc12(float2 p)
{
float HASHSCALE1 = 0.1031;
float3 p3 = frac(float3(p.xyx) * HASHSCALE1);
p3 += dot(p3, p3.yzx + 19.19);
return frac((p3.x + p3.y) * p3.z);
}
float doRandomFunc(float2 xy)
{
return frac(69250*doHashFunc12(xy));
}
float mix1d(float x,float y,float p)
{
return x*(1.0-p)+y*p;
}
float doNoiseFunc(float2 xy)
{
float2 id = floor(xy);
float2 lv = smoothstep(float2(0,0),float2(1.0,1.0),frac(xy));
float orign = doRandomFunc(id);
float forward = doRandomFunc(id+float2(1.0,0.0));
float up = doRandomFunc(id+float2(0.0,1.0));
float upForward = doRandomFunc(id+float2(1.0,1.0));
return mix1d(mix1d(orign,forward,lv.x),mix1d(up,upForward,lv.x),lv.y);
}
float clamp1d(float fromx,float fromy,float tox,float toy,float p)
{
return (p-fromx)/(fromy-fromx)*(toy-tox)+tox;
}
fixed4 frag (v2f i) : SV_Target
{
i.uv+=float2(-0.5,-0.5);
i.uv*=float2(20,20);
float progress = 0;
float2 pos = i.uv.xx+float2(_Time.y,_Time.y)*0.5;
progress += A* doNoiseFunc(pos*B);
progress += A*gain* doNoiseFunc(pos*B*lacunarity);
progress += A*gain*gain* doNoiseFunc(pos*B*lacunarity*lacunarity);
progress += A*gain*gain*gain*doNoiseFunc(pos*B*lacunarity*lacunarity*lacunarity);
//progress = clamp1d(0,1,-1,1,progress);
//繪製分型布朗運動生成的1D曲線
float isY = smoothstep(progress-0.1,progress,i.uv.y) - smoothstep(progress,progress+0.1,i.uv.y) ;
return isY;
}
ENDCG
}
}
}
累加的次數應該也是可以控制的,設置累加的次數可控制,代碼如下:
Shader "Unlit/sinFunc"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
Loops("累加次數",Float) = 10
A("振幅",Float) = 1.0
B("頻率",Float) = 1.0
gain("拉伸",Float) = 0.5
lacunarity("不均勻性",Float) = 2.0
}
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 A;
float B;
float gain;
float lacunarity;
float Loops;
float remap1d(float fromx,float fromy,float tox,float toy,float p)
{
return (p-fromx)/(fromy - fromx)*(toy - tox) + tox;
}
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;
}
float doHashFunc12(float2 p)
{
float HASHSCALE1 = 0.1031;
float3 p3 = frac(float3(p.xyx) * HASHSCALE1);
p3 += dot(p3, p3.yzx + 19.19);
return frac((p3.x + p3.y) * p3.z);
}
float doRandomFunc(float2 xy)
{
return frac(69250*doHashFunc12(xy));
}
float mix1d(float x,float y,float p)
{
return x*(1.0-p)+y*p;
}
float doNoiseFunc(float2 xy)
{
float2 id = floor(xy);
float2 lv = smoothstep(float2(0,0),float2(1.0,1.0),frac(xy));
float orign = doRandomFunc(id);
float forward = doRandomFunc(id+float2(1.0,0.0));
float up = doRandomFunc(id+float2(0.0,1.0));
float upForward = doRandomFunc(id+float2(1.0,1.0));
return mix1d(mix1d(orign,forward,lv.x),mix1d(up,upForward,lv.x),lv.y);
}
float clamp1d(float fromx,float fromy,float tox,float toy,float p)
{
return (p-fromx)/(fromy-fromx)*(toy-tox)+tox;
}
fixed4 frag (v2f i) : SV_Target
{
i.uv+=float2(-0.5,-0.5);
i.uv*=float2(20,20);
float progress = 0;
float2 pos = i.uv.xx+float2(_Time.y,_Time.y)*0.5;
for(float j =0.0;j<Loops;j+=1.0)
{
progress += A*pow(gain,j)*doNoiseFunc(pos*B*pow(lacunarity,j));
}
//progress = clamp1d(0,1,-1,1,progress);
//繪製分型布朗運動生成的1D曲線
float isY = smoothstep(progress-0.1,progress,i.uv.y) - smoothstep(progress,progress+0.1,i.uv.y) ;
return isY;
/*
float2x2 beveling = float2x2(1,0,
progress,1);
i.uv = mul(beveling,i.uv);
float outOfX = max(step(i.uv.x,0.0),step(1.0,i.uv.x));
float outOfY = max(step(i.uv.y,0.0),step(1.0,i.uv.y));
float outOfArea = max(outOfX,outOfY);
if(outOfArea == 1.0)
{
discard;
}
// sample the texture
fixed4 col = tex2D(_MainTex, i.uv);
// apply fog
UNITY_APPLY_FOG(i.fogCoord, col);
return col;
*/
}
ENDCG
}
}
}
如開篇所看到的一樣,圖片的抖動效果有時是非常突兀的,爲了讓圖片的抖動變得平滑,需要調試這相關的4個參數:
平滑效果爲:
將其應用到圖片,效果爲:
最終收尾代碼爲:
Shader "Unlit/sinFunc"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
Loops("累加次數",Float) = 10
A("振幅",Float) = 1.0
B("頻率",Float) = 1.0
gain("拉伸",Float) = 0.5
lacunarity("不均勻性",Float) = 2.0
}
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 A;
float B;
float gain;
float lacunarity;
float Loops;
float remap1d(float fromx,float fromy,float tox,float toy,float p)
{
return (p-fromx)/(fromy - fromx)*(toy - tox) + tox;
}
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;
}
float doHashFunc12(float2 p)
{
float HASHSCALE1 = 0.1031;
float3 p3 = frac(float3(p.xyx) * HASHSCALE1);
p3 += dot(p3, p3.yzx + 19.19);
return frac((p3.x + p3.y) * p3.z);
}
float doRandomFunc(float2 xy)
{
return frac(69250*doHashFunc12(xy));
}
float mix1d(float x,float y,float p)
{
return x*(1.0-p)+y*p;
}
float doNoiseFunc(float2 xy)
{
float2 id = floor(xy);
float2 lv = smoothstep(float2(0,0),float2(1.0,1.0),frac(xy));
float orign = doRandomFunc(id);
float forward = doRandomFunc(id+float2(1.0,0.0));
float up = doRandomFunc(id+float2(0.0,1.0));
float upForward = doRandomFunc(id+float2(1.0,1.0));
return mix1d(mix1d(orign,forward,lv.x),mix1d(up,upForward,lv.x),lv.y);
}
float clamp1d(float fromx,float fromy,float tox,float toy,float p)
{
return (p-fromx)/(fromy-fromx)*(toy-tox)+tox;
}
fixed4 frag (v2f i) : SV_Target
{
i.uv+=float2(-0.5,-0.5);
i.uv*=float2(20,20);
float progress = 0;
float2 pos = i.uv.xx+float2(_Time.y,_Time.y);
for(float j =0.0;j<Loops;j+=1.0)
{
progress += A*pow(gain,j)*doNoiseFunc(pos*B*pow(lacunarity,j));
}
progress = clamp1d(0,1,-0.5,0.5,progress);
//繪製分型布朗運動生成的1D曲線
//float isY = smoothstep(progress-0.1,progress,i.uv.y) - smoothstep(progress,progress+0.1,i.uv.y) ;
//return isY;
float2x2 beveling = float2x2(1,0,
progress,1);
i.uv = mul(beveling,i.uv);
float outOfX = max(step(i.uv.x,0.0),step(1.0,i.uv.x));
float outOfY = max(step(i.uv.y,0.0),step(1.0,i.uv.y));
float outOfArea = max(outOfX,outOfY);
if(outOfArea == 1.0)
{
discard;
}
// sample the texture
fixed4 col = tex2D(_MainTex, i.uv);
// apply fog
UNITY_APPLY_FOG(i.fogCoord, col);
return col;
}
ENDCG
}
}
}