噪声笔记#1 随机值和白噪声

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_38275140/article/details/83995872

噪声其实就是程序中的一些随机变量,所以想要生成噪声就先要有一个能够生成(伪)随机数的方法

生成随机数的一些方法

(1)HASH

hash函数是可以用来生成随机数 而且很常用,他会根据输入的种子数生成并返回对应的随机数,在图形学中,通常返回0-1


 常用HASH函数

·直接取余法:f(x):= x mod maxM ; maxM一般是不太接近 2^t 的一个质数。

·乘法取整法:f(x):=trunc((x/maxX)*maxlongit) mod maxM,主要用于实数。

·平方取中法:f(x):=(x*x div 1000 ) mod 1000000); 平方后取中间的,每位包含信息比较多


先来一个最简单地函数,修改P值来观察图像

y = fract(sin(x)*P)

P=10      随机函数P10

P=100    随机函数P100

P=100000 随机函数P100000

可以看到P=100000时已经很难直接判断每个x对应的y值了,通过fract函数不停的将数值打碎在[0,1]之间,就有了随机值的感觉

基于这个可以延展至二维、三维向量。

float Hash (vec2 p) {
    return fract(sin(dot(p.xy,vec2(12.9898,78.233)))*43758.5453123);
}

vec3 hash( vec3 p )
{
    p = vec3( dot(p,vec3(127.1,311.7, 74.7)),
              dot(p,vec3(269.5,183.3,246.1)),
              dot(p,vec3(113.5,271.9,124.6)));

    return fract(sin(p)*43758.5453123);
}

通过点乘(dot)二、三维向量可以得到一个[0,1]的一维浮点值,这样就把问题变成了根据一个种子求一个随机值,也就是一维的求随机值。

(2)其他随机数生成方式(做个记号,以后再了解)

线性同余发生器(LCG) :N(i) = (a*N(i-1)+c) % m

进位相乘法(Multiply With Carry MWC)

线性反馈移位寄存器法(Linear Feedback Shift Register,LFSR)

斐波那契LFSR(Fabonacci LFSR)

伽罗华LFSR(Galois LFSR)

Mersenne Twister(MT)


生成白噪声

知道了怎么得到随机值,就等于知道了怎么生成白噪声,白噪声其实就是在二维向量得到随机值

白噪声unity

下面是unityshader的代码

Shader "Custom/WhiteNoise2D" {
	Properties{
		_Scale("Scale",Range(10,500)) = 1
	}
	SubShader{
		Pass{
			CGPROGRAM
			#include "UnityCG.cginc"
			#pragma vertex vert
			#pragma fragment frag
			float _Scale;
			struct v2f {
				float4 pos:SV_POSITION;
				half2 uv:TEXCOORD1;
			};

			float WhiteNoise2D(float2 st) {
				return frac(sin(dot(st.xy,
				float2(12.9898, 78.233)))*
				43758.5453123);
			}

			v2f vert(appdata_base v) {
				v2f o;
				o.pos = UnityObjectToClipPos(v.vertex);
				o.uv = v.texcoord;
				return o;
			}
			fixed4 frag(v2f i) :SV_Target{
				half2 uv = floor(i.uv*_Scale)/_Scale;
				float random = WhiteNoise2D(uv);
				return fixed4(random,random,random,1);
			}
			ENDCG
		}
	}
	FallBack "Diffuse"
}

用白噪声做个屏幕效果

TVNoise

Shader "Custom/TVNoiseShader" {
	Properties{
		_MainTex("Base(RGB)",2D)="white"{}
		_Scale("Scale",Float) = 50
		_TimeRate("TimeRate", Float) = 0.5
		_Fade("Fade", Range(0, 1)) = 0.5
		_Fill("Fill",Range(0,1)) = 0.1

	}
	SubShader{
		Pass{
			CGPROGRAM
			#include "UnityCG.cginc"
			#pragma vertex vert 
			#pragma fragment frag
			sampler2D _MainTex;
			float4 _MainTex_TexelSize;// Vector4(1 / width, 1 / height, width, height)
			float _Scale;
			float _TimeRate;
			float _Fade;
			float _Fill;
			struct v2f {
				float4 pos:SV_POSITION;
				half2 uv:TEXCOORD0;
			};

			inline fixed hash(float p) {
				return frac(sin(p)*43758.5453123);
			}
			inline fixed hash3(float3 p)
			{
				float3  a = float3(dot(p, float3(127.1, 311.7, 74.7)),
					dot(p, float3(269.5, 183.3, 246.1)),
					dot(p, float3(113.5, 271.9, 124.6)));

				return hash(a.x);//这里简化 只算第一个了
			}
			v2f vert(appdata_img v) {
				v2f o;
				o.pos= UnityObjectToClipPos(v.vertex);
				o.uv = v.texcoord;
				return o;
			}
			fixed4 frag(v2f i) :SV_Target{

				//保证不会因为屏幕比例而产生拉伸
				half2 suv = i.uv*_MainTex_TexelSize.zw/100;
				fixed value = hash3(float3(floor(suv*_Scale),floor(_Time.y/_TimeRate)));
				fixed3 color = tex2D(_MainTex, i.uv.xy);
				fixed value2 = hash(i.uv.x);
				color = lerp(color,fixed3(value, value,value),_Fade*step(value2,_Fill));
				return fixed4(color, 1);
			}
			ENDCG
		}
	}
}

参考内容:https://thebookofshaders.com/10/?lan=ch

https://blog.csdn.net/yolon3000/article/details/75145035

猜你喜欢

转载自blog.csdn.net/qq_38275140/article/details/83995872