Files
2026-05-08 15:34:53 +08:00

151 lines
3.8 KiB
HLSL

///////////PERLIN NOISE////////////////
//////// NOT USED ANYMORE ////////////
// Hash to get pseudo-random gradient direction
float2 hash2(float2 p)
{
// A simple 2D hash
p = frac(p * float2(127.1, 311.7));
p += dot(p, p + 74.7);
return normalize(frac(float2(p.x * p.y, p.x + p.y)) * 2.0 - 1.0);
}
// Quintic fade curve for smooth interpolation
float fade(float t)
{
return t * t * t * (t * (t * 6.0 - 15.0) + 10.0);
}
float penoise(float2 uv, float scale)
{
// Scale and wrap UVs to create tileable domain
float2 p = uv * scale;
// Integer cell coordinates
float2 i0 = floor(p);
float2 f = frac(p);
// Wrap to ensure seamless tiling
float2 i1 = fmod(i0 + 1.0, scale);
// Gradient vectors for the four cell corners
float2 g00 = hash2(fmod(i0, scale));
float2 g10 = hash2(float2(i1.x, i0.y));
float2 g01 = hash2(float2(i0.x, i1.y));
float2 g11 = hash2(i1);
// Distance vectors to corners
float2 d00 = f - float2(0.0, 0.0);
float2 d10 = f - float2(1.0, 0.0);
float2 d01 = f - float2(0.0, 1.0);
float2 d11 = f - float2(1.0, 1.0);
// Dot products
float n00 = dot(g00, d00);
float n10 = dot(g10, d10);
float n01 = dot(g01, d01);
float n11 = dot(g11, d11);
// Smooth interpolation
float2 u = fade(f);
float nx0 = lerp(n00, n10, u.x);
float nx1 = lerp(n01, n11, u.x);
float nxy = lerp(nx0, nx1, u.y);
// Normalize to [0,1]
return 0.5 + 0.5 * nxy;
}
float perlinFBM(float2 uv, float baseScale, int octaves, float gain, float lacun)
{
float total = 0.0;
float amp = 0.5; // starting amplitude
float freq = 1.0; // starting frequency
float weight = 0.0;
// Always wrap UV first to avoid precision drift
uv = frac(uv);
[unroll]
for (int i = 0; i < octaves; i++)
{
// Sample tileable perlin at increasing frequency
// Keep tiling domain proportional to frequency for seamless wrap
total += amp * penoise(uv * freq, baseScale * freq);
weight += amp;
freq *= lacun; // e.g. 2.0
amp *= gain; // e.g. 0.5
}
// Normalize to 0..1
return saturate(total / weight);
}
//////////////////////////////////////////
///////////WORLEY NOISE///////////////////
//////////////////////////////////////////
// Hash to generate a repeatable 0..1 value for integer coords
float hash21_stable(int2 p, int period)
{
uint2 pu = (uint2)(p + period * 4096); // shift into positive domain
pu = pu % (uint)period;
uint n = pu.x * 73856093u ^ pu.y * 19349663u;
return frac((float)n * 0.000000119f);
}
float2 hash22_stable(int2 p, int period)
{
float h1 = hash21_stable(p, period);
float h2 = hash21_stable(p + int2(17, 37), period);
return float2(h1, h2);
}
float Worley2D_Stable(float2 uv, int tileCount)
{
// Tile domain
float2 p = uv * tileCount;
int2 baseCell = int2(floor(p));
float2 f = frac(p);
float minDist = 1.0;
// Search 3x3 neighborhood
[unroll]
for (int y = -1; y <= 1; y++)
{
[unroll]
for (int x = -1; x <= 1; x++)
{
int2 neighbor = baseCell + int2(x, y);
float2 rand = hash22_stable(neighbor, tileCount);
float2 feature = float2(x, y) + rand;
float d = length(f - feature);
minDist = min(minDist, d);
}
}
return saturate(minDist);
}
float WorleyFBM2D(float2 uv, int baseTiles, float bias)
{
uv = frac(uv); // ensure [0,1] input
float n = 0.0;
float amp = 0.5;
int tiles = baseTiles;
[unroll]
for (int octave = 0; octave < 3; octave++)
{
n += amp * Worley2D_Stable(uv, tiles);
tiles *= 2; // double tiles per octave
amp *= 0.5; // halve amplitude
}
// Invert + bias for cloud-like coverage
n = pow(1.0 - n, bias);
return saturate(n);
}