Files
2025-06-09 23:23:13 +08:00

168 lines
4.5 KiB
HLSL

#ifndef __NOISE__
#define __NOISE__
#define PI 3.14159265358979
#define DECLARENOISEKEYWORDS(_PRE) #pragma shader_feature_local _ _PRE##NOISE _PRE##FBM _PRE##WORLEY _PRE##WORM _PRE##WORMFBM _PRE##NOISETEXTURE
#define DECLARENOISEVARS(_PRE) Texture2D _PRE##NoiseTexture; float4 _PRE##NoiseTexture_ST; float4 _PRE##Noise; int _PRE##NoiseChannel;
float Hash12(float2 p)
{
float3 p3 = frac(float3(p.xyx) * .1031);
p3 += dot(p3, p3.yzx + 33.33);
return frac((p3.x + p3.y) * p3.z);
}
float2 Hash2D( float2 x )
{
float2 k = float2( 0.3183099, 0.3678794 );
x = x*k + k.yx;
return -1.0 + 2.0*frac( 16.0 * k*frac( x.x*x.y*(x.x+x.y)) );
}
float3 Erode(float2 p, float2 dir)
{
float2 ip = floor(p);
float2 fp = frac(p);
float f = 2.*PI;
float3 va = 0;
float wt = 0.0;
for (int i=-2; i<=1; i++)
{
for (int j=-2; j<=1; j++)
{
float2 o = float2(i, j);
float2 h = Hash2D(ip - o)*0.5;
float2 pp = fp +o - h;
float d = dot(pp, pp);
float w = exp(-d*2.0);
wt +=w;
float mag = dot(pp,dir);
va += float3(cos(mag*f), -sin(mag*f)*(pp+dir))*w;
}
}
return va/wt;
}
float ErosionNoise(float2 uv, float3 n)
{
float2 dir = n.zx * float2(1.0, -1.0);
float3 h = 0;
float a = 0.7;
float f = 1.0;
for (int xx=0;xx<5;xx++)
{
float3 eros = Erode(uv*f, dir+h.zy*float2(1.0, -1.0));
h += float3(1.0, f, f) * eros * a;
a*=0.4;
f*=2.0;
}
return abs(h.x);
}
float Noise2D(float2 p )
{
float2 i = floor( p );
float2 f = frac( p );
float2 u = f*f*(3.0-2.0*f);
return lerp( lerp( dot( Hash2D( i + float2(0.0,0.0) ), f - float2(0.0,0.0) ),
dot( Hash2D( i + float2(1.0,0.0) ), f - float2(1.0,0.0) ), u.x),
lerp( dot( Hash2D( i + float2(0.0,1.0) ), f - float2(0.0,1.0) ),
dot( Hash2D( i + float2(1.0,1.0) ), f - float2(1.0,1.0) ), u.x), u.y);
}
float2 WorleyHash2D(float2 p)
{
return frac(cos(mul(p, float2x2(-64.2,71.3,81.4,-29.8)))*8321.3);
}
float WorleyNoise2D(float2 p)
{
float dist = 1;
float2 i = floor(p);
float2 f = frac(p);
for(int x = -1;x<=1;x++)
{
for(int y = -1;y<=1;y++)
{
float d = length(WorleyHash2D(i+float2(x,y))+float2(x,y) - f);
dist = min(dist,d);
}
}
return sqrt(dist);
}
float FBM2D(float2 uv)
{
float f = 0.5000*Noise2D( uv ); uv *= 2.01;
f += 0.3300*Noise2D( uv ); uv *= 1.96;
f += 0.170*Noise2D( uv );
return f;
}
float2 Hash22( float2 n ) { return sin(n.x*n.y+float2(0,1.571)); }
float WormNoise(float2 p)
{
const float kF = 6.0;
float2 i = floor(p) + 77;
float2 f = frac(p);
f = f*f*(3.0-2.0*f);
return lerp(lerp(sin(kF*dot(p,Hash22(i+float2(0,0)))),
sin(kF*dot(p,Hash22(i+float2(1,0)))),f.x),
lerp(sin(kF*dot(p,Hash22(i+float2(0,1)))),
sin(kF*dot(p,Hash22(i+float2(1,1)))),f.x),f.y);
}
float WormNoiseFBM(float2 uv)
{
const float2x2 m = float2x2( 1.6, 1.2, -1.2, 1.6 );
float f = 0.5000*WormNoise( uv ); uv = mul(uv, m);
f += 0.3300*WormNoise( uv ); uv = mul(uv, m);
f += 0.1700*WormNoise( uv );
return f;
}
float Noise(float2 uv, float4 param)
{
return ((Noise2D(uv * param.x + param.z) - param.w) * param.y);
}
float NoiseFBM(float2 uv, float4 param)
{
return ((FBM2D(uv * param.x + param.z) - param.w) * param.y);
}
float NoiseWorley(float2 uv, float4 param)
{
return ((WorleyNoise2D(uv * param.x + param.z) - param.w) * param.y);
}
float NoiseWorm(float2 uv, float4 param)
{
return ((WormNoise(uv * param.x + param.z) - param.w) * param.y);
}
float NoiseWormFBM(float2 uv, float4 param)
{
return ((WormNoiseFBM(uv * param.x + param.z) - param.w) * param.y);
}
float NoiseErosion(float2 uv, float4 param, float3 normal)
{
return ((ErosionNoise(uv * param.x + param.z, normal) - param.w) * param.y);
}
#endif