Files
Ipseity-Demo/Assets/_Content/Shaders/Include/Noises.hlsl
T

766 lines
25 KiB
HLSL
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// =============================================================================
// Noises.hlsl – Unity URP/HDRP Custom Function Noise Library
// All noise functions return values in [0, 1]
// Usage: #include "Noises.hlsl"
// =============================================================================
#ifndef NOISES_HLSL
#define NOISES_HLSL
// =============================================================================
// INTERNAL UTILITIES
// =============================================================================
// --- Hash (PCG – integer bit mixing, no periodicity) -------------------------
// Converts float cell coords to uint, runs PCG rounds, outputs [0, 1]
uint PcgHash(uint v)
{
v = v * 747796405u + 2891336453u;
v = ((v >> ((v >> 28u) + 4u)) ^ v) * 277803737u;
return (v >> 22u) ^ v;
}
float Hash1From2D(float2 p)
{
uint2 u = uint2(int2(p));
uint h = PcgHash(u.x ^ PcgHash(u.y));
return float(h) * (1.0 / 4294967296.0);
}
float2 Hash2D(float2 p)
{
uint2 u = uint2(int2(p));
uint hx = PcgHash(u.x ^ PcgHash(u.y));
uint hy = PcgHash(u.y ^ PcgHash(u.x + 1u));
return float2(hx, hy) * (1.0 / 4294967296.0);
}
float Hash1From3D(float3 p)
{
uint3 u = uint3(int3(p));
uint h = PcgHash(u.x ^ PcgHash(u.y ^ PcgHash(u.z)));
return float(h) * (1.0 / 4294967296.0);
}
float3 Hash3D(float3 p)
{
uint3 u = uint3(int3(p));
uint hx = PcgHash(u.x ^ PcgHash(u.y ^ PcgHash(u.z)));
uint hy = PcgHash(u.y ^ PcgHash(u.z ^ PcgHash(u.x + 1u)));
uint hz = PcgHash(u.z ^ PcgHash(u.x ^ PcgHash(u.y + 1u)));
return float3(hx, hy, hz) * (1.0 / 4294967296.0);
}
// --- Interpolation -----------------------------------------------------------
float2 SmootherStep2D(float2 t) { return t * t * t * (t * (t * 6.0 - 15.0) + 10.0); }
float3 SmootherStep3D(float3 t) { return t * t * t * (t * (t * 6.0 - 15.0) + 10.0); }
// --- Gradient ----------------------------------------------------------------
float Grad2D(float2 hash, float2 delta)
{
return dot(hash * 2.0 - 1.0, delta);
}
float Grad3D(float3 hash, float3 delta)
{
return dot(hash * 2.0 - 1.0, delta);
}
// --- LOD blend ---------------------------------------------------------------
// Shared logic for all 3D LOD variants.
// Returns scale0/scale1 to sample and w0/w1 weights (w0 + w1 == 1).
void LODBlend(float3 PositionWS, float Scale, float LODRatio,
out float scale0, out float scale1, out float w0, out float w1)
{
float logStep = log(LODRatio);
float dist = max(distance(_WorldSpaceCameraPos.xyz, PositionWS), 0.0001);
float t = log(dist / 1.0) / logStep;
float tFloor = floor(t);
float u = t - tFloor;
scale0 = Scale * pow(LODRatio, -tFloor);
scale1 = Scale * pow(LODRatio, -(tFloor + 1.0));
w1 = u * u * u * (u * (u * 6.0 - 15.0) + 10.0);
w0 = 1.0 - w1;
}
// =============================================================================
// WHITE NOISE
// =============================================================================
// --- 2D ----------------------------------------------------------------------
float WhiteNoise2D(
float2 UV) // Input UV coordinates
{
return Hash1From2D(UV);
}
void WhiteNoise2D_float(float2 UV, out float Out)
{
Out = WhiteNoise2D(UV);
}
// --- 3D ----------------------------------------------------------------------
float WhiteNoise3D(
float3 Position) // Input position in object space
{
return Hash1From3D(Position);
}
void WhiteNoise3D_float(float3 Position, out float Out)
{
Out = WhiteNoise3D(Position);
}
// =============================================================================
// VALUE NOISE
// =============================================================================
// --- 2D ----------------------------------------------------------------------
float ValueNoise2D(
float2 UV, // Input UV coordinates
float Scale) // Noise frequency
{
float2 p = UV * Scale;
float2 cell = floor(p);
float2 local = frac(p);
float2 smooth = SmootherStep2D(local);
float v00 = Hash1From2D(cell + float2(0, 0));
float v10 = Hash1From2D(cell + float2(1, 0));
float v01 = Hash1From2D(cell + float2(0, 1));
float v11 = Hash1From2D(cell + float2(1, 1));
return lerp(lerp(v00, v10, smooth.x), lerp(v01, v11, smooth.x), smooth.y);
}
void ValueNoise2D_float(float2 UV, float Scale, out float Out)
{
Out = ValueNoise2D(UV, Scale);
}
// --- 3D ----------------------------------------------------------------------
float ValueNoise3D(
float3 Position, // Input position in object space
float Scale) // Noise frequency
{
float3 p = Position * Scale;
float3 cell = floor(p);
float3 local = frac(p);
float3 smooth = SmootherStep3D(local);
float v000 = Hash1From3D(cell + float3(0, 0, 0));
float v100 = Hash1From3D(cell + float3(1, 0, 0));
float v010 = Hash1From3D(cell + float3(0, 1, 0));
float v110 = Hash1From3D(cell + float3(1, 1, 0));
float v001 = Hash1From3D(cell + float3(0, 0, 1));
float v101 = Hash1From3D(cell + float3(1, 0, 1));
float v011 = Hash1From3D(cell + float3(0, 1, 1));
float v111 = Hash1From3D(cell + float3(1, 1, 1));
float x0 = lerp(v000, v100, smooth.x);
float x1 = lerp(v010, v110, smooth.x);
float x2 = lerp(v001, v101, smooth.x);
float x3 = lerp(v011, v111, smooth.x);
return lerp(lerp(x0, x1, smooth.y), lerp(x2, x3, smooth.y), smooth.z);
}
void ValueNoise3D_float(float3 Position, float Scale, out float Out)
{
Out = ValueNoise3D(Position, Scale);
}
// --- 3D LOD ------------------------------------------------------------------
float ValueNoise3DLOD(
float3 PositionWS, // Surface position in world space
float3 PositionOS, // Surface position in world space
float Scale, // Noise frequency at reference distance
float LODRatio) // Scale ratio between layers (4 = wide transition)
{
float scale0, scale1, w0, w1;
LODBlend(PositionWS, Scale, LODRatio, scale0, scale1, w0, w1);
return ValueNoise3D(PositionOS, scale0) * w0
+ ValueNoise3D(PositionOS, scale1) * w1;
}
void ValueNoise3DLOD_float(float3 PositionWS, float Scale, float LODRatio, out float Out)
{
Out = ValueNoise3DLOD(PositionWS, PositionWS, Scale, LODRatio);
}
// =============================================================================
// PERLIN NOISE
// =============================================================================
// --- 2D ----------------------------------------------------------------------
float PerlinNoise2D(
float2 UV, // Input UV coordinates
float Scale) // Noise frequency
{
float2 p = UV * Scale;
float2 cell = floor(p);
float2 local = frac(p);
float2 smooth = SmootherStep2D(local);
float g00 = Grad2D(Hash2D(cell + float2(0, 0)), local - float2(0, 0));
float g10 = Grad2D(Hash2D(cell + float2(1, 0)), local - float2(1, 0));
float g01 = Grad2D(Hash2D(cell + float2(0, 1)), local - float2(0, 1));
float g11 = Grad2D(Hash2D(cell + float2(1, 1)), local - float2(1, 1));
float result = lerp(lerp(g00, g10, smooth.x), lerp(g01, g11, smooth.x), smooth.y);
return result * 0.5 + 0.5;
}
void PerlinNoise2D_float(float2 UV, float Scale, out float Out)
{
Out = PerlinNoise2D(UV, Scale);
}
// --- 3D ----------------------------------------------------------------------
float PerlinNoise3D(
float3 Position, // Input position in object space
float Scale) // Noise frequency
{
float3 p = Position * Scale;
float3 cell = floor(p);
float3 local = frac(p);
float3 smooth = SmootherStep3D(local);
float g000 = Grad3D(Hash3D(cell + float3(0,0,0)), local - float3(0,0,0));
float g100 = Grad3D(Hash3D(cell + float3(1,0,0)), local - float3(1,0,0));
float g010 = Grad3D(Hash3D(cell + float3(0,1,0)), local - float3(0,1,0));
float g110 = Grad3D(Hash3D(cell + float3(1,1,0)), local - float3(1,1,0));
float g001 = Grad3D(Hash3D(cell + float3(0,0,1)), local - float3(0,0,1));
float g101 = Grad3D(Hash3D(cell + float3(1,0,1)), local - float3(1,0,1));
float g011 = Grad3D(Hash3D(cell + float3(0,1,1)), local - float3(0,1,1));
float g111 = Grad3D(Hash3D(cell + float3(1,1,1)), local - float3(1,1,1));
float x0 = lerp(g000, g100, smooth.x);
float x1 = lerp(g010, g110, smooth.x);
float x2 = lerp(g001, g101, smooth.x);
float x3 = lerp(g011, g111, smooth.x);
float result = lerp(lerp(x0, x1, smooth.y), lerp(x2, x3, smooth.y), smooth.z);
return result * 0.5 + 0.5;
}
void PerlinNoise3D_float(float3 Position, float Scale, out float Out)
{
Out = PerlinNoise3D(Position, Scale);
}
// --- 3D Direction ------------------------------------------------------------
float3 PerlinColor3D(
float3 Position, // Input position in object space
float Scale) // Noise frequency
{
return float3(
PerlinNoise3D(Position, Scale),
PerlinNoise3D(Position + float3(127.1, 311.7, 74.7), Scale),
PerlinNoise3D(Position + float3(269.5, 183.3, 246.1), Scale)
);
}
void PerlinColor3D_float(float3 Position, float Scale, out float3 Out)
{
Out = PerlinColor3D(Position, Scale);
}
// --- 3D LOD ------------------------------------------------------------------
float PerlinNoise3DLOD(
float3 PositionWS, // Surface position in world space
float Scale, // Noise frequency at reference distance
float LODRatio) // Scale ratio between layers (4 = wide transition)
{
float scale0, scale1, w0, w1;
LODBlend(PositionWS, Scale, LODRatio, scale0, scale1, w0, w1);
return PerlinNoise3D(PositionWS, scale0) * w0
+ PerlinNoise3D(PositionWS, scale1) * w1;
}
void PerlinNoise3DLOD_float(float3 PositionWS, float Scale, float LODRatio, out float Out)
{
Out = PerlinNoise3DLOD(PositionWS, Scale, LODRatio);
}
// =============================================================================
// SIMPLEX NOISE
// =============================================================================
// --- 2D ----------------------------------------------------------------------
float SimplexNoise2D(
float2 UV, // Input UV coordinates
float Scale) // Noise frequency
{
const float F2 = 0.366025403; // (sqrt(3) - 1) / 2
const float G2 = 0.211324865; // (3 - sqrt(3)) / 6
float2 p = UV * Scale;
float s = (p.x + p.y) * F2;
float2 i = floor(p + s);
float t = (i.x + i.y) * G2;
float2 x0 = p - (i - t);
float2 i1 = (x0.x > x0.y) ? float2(1, 0) : float2(0, 1);
float2 x1 = x0 - i1 + G2;
float2 x2 = x0 - 1.0 + 2.0 * G2;
float3 m = max(0.5 - float3(dot(x0,x0), dot(x1,x1), dot(x2,x2)), 0.0);
m = m * m * m * m;
float3 gx = float3(Grad2D(Hash2D(i), x0),
Grad2D(Hash2D(i + i1), x1),
Grad2D(Hash2D(i + float2(1,1)), x2));
return dot(m, gx) * 70.0 * 0.5 + 0.5;
}
void SimplexNoise2D_float(float2 UV, float Scale, out float Out)
{
Out = SimplexNoise2D(UV, Scale);
}
// --- 3D ----------------------------------------------------------------------
float SimplexNoise3D(
float3 Position, // Input position in object space
float Scale) // Noise frequency
{
const float F3 = 0.333333333;
const float G3 = 0.166666667;
float3 p = Position * Scale;
float s = (p.x + p.y + p.z) * F3;
float3 i = floor(p + s);
float t = (i.x + i.y + i.z) * G3;
float3 x0 = p - (i - t);
float3 i1, i2;
if (x0.x >= x0.y)
{
if (x0.y >= x0.z) { i1 = float3(1,0,0); i2 = float3(1,1,0); }
else if (x0.x >= x0.z) { i1 = float3(1,0,0); i2 = float3(1,0,1); }
else { i1 = float3(0,0,1); i2 = float3(1,0,1); }
}
else
{
if (x0.y < x0.z) { i1 = float3(0,0,1); i2 = float3(0,1,1); }
else if (x0.x < x0.z) { i1 = float3(0,1,0); i2 = float3(0,1,1); }
else { i1 = float3(0,1,0); i2 = float3(1,1,0); }
}
float3 x1 = x0 - i1 + G3;
float3 x2 = x0 - i2 + 2.0 * G3;
float3 x3 = x0 - 1.0 + 3.0 * G3;
float4 m = max(0.6 - float4(dot(x0,x0), dot(x1,x1), dot(x2,x2), dot(x3,x3)), 0.0);
m = m * m * m * m;
float4 gx = float4(Grad3D(Hash3D(i), x0),
Grad3D(Hash3D(i + i1), x1),
Grad3D(Hash3D(i + i2), x2),
Grad3D(Hash3D(i + float3(1,1,1)), x3));
return dot(m, gx) * 32.0 * 0.5 + 0.5;
}
void SimplexNoise3D_float(float3 Position, float Scale, out float Out)
{
Out = SimplexNoise3D(Position, Scale);
}
// --- 3D LOD ------------------------------------------------------------------
float SimplexNoise3DLOD(
float3 PositionWS, // Surface position in world space
float Scale, // Noise frequency at reference distance
float LODRatio) // Scale ratio between layers (4 = wide transition)
{
float scale0, scale1, w0, w1;
LODBlend(PositionWS, Scale, LODRatio, scale0, scale1, w0, w1);
return SimplexNoise3D(PositionWS, scale0) * w0
+ SimplexNoise3D(PositionWS, scale1) * w1;
}
void SimplexNoise3DLOD_float(float3 PositionWS, float Scale, float LODRatio, out float Out)
{
Out = SimplexNoise3DLOD(PositionWS, Scale, LODRatio);
}
// =============================================================================
// WORLEY / CELLULAR NOISE
// =============================================================================
// --- 2D ----------------------------------------------------------------------
float WorleyNoise2D(
float2 UV, // Input UV coordinates
float Scale, // Noise frequency
float Jitter) // Feature point randomness [0 = grid, 1 = random]
{
float2 p = UV * Scale;
float2 cell = floor(p);
float minD = 8.0;
for (int y = -1; y <= 1; y++)
for (int x = -1; x <= 1; x++)
{
float2 neighbor = cell + float2(x, y);
float2 offset = neighbor + Hash2D(neighbor) * Jitter;
minD = min(minD, distance(p, offset));
}
return saturate(minD);
}
void WorleyNoise2D_float(float2 UV, float Scale, float Jitter, out float Out)
{
Out = WorleyNoise2D(UV, Scale, Jitter);
}
// --- 3D ----------------------------------------------------------------------
float WorleyNoise3D(
float3 Position, // Input position in object space
float Scale, // Noise frequency
float Jitter) // Feature point randomness [0 = grid, 1 = random]
{
float3 p = Position * Scale;
float3 cell = floor(p);
float minD = 8.0;
for (int z = -1; z <= 1; z++)
for (int y = -1; y <= 1; y++)
for (int x = -1; x <= 1; x++)
{
float3 neighbor = cell + float3(x, y, z);
float3 offset = neighbor + Hash3D(neighbor) * Jitter;
minD = min(minD, distance(p, offset));
}
return saturate(minD);
}
void WorleyNoise3D_float(float3 Position, float Scale, float Jitter, out float Out)
{
Out = WorleyNoise3D(Position, Scale, Jitter);
}
// --- 3D LOD ------------------------------------------------------------------
float WorleyNoise3DLOD(
float3 PositionWS, // Surface position in world space
float Scale, // Noise frequency at reference distance
float Jitter, // Feature point randomness [0 = grid, 1 = random]
float LODRatio) // Scale ratio between layers (4 = wide transition)
{
float scale0, scale1, w0, w1;
LODBlend(PositionWS, Scale, LODRatio, scale0, scale1, w0, w1);
return WorleyNoise3D(PositionWS, scale0, Jitter) * w0
+ WorleyNoise3D(PositionWS, scale1, Jitter) * w1;
}
void WorleyNoise3DLOD_float(float3 PositionWS, float Scale, float Jitter, float LODRatio, out float Out)
{
Out = WorleyNoise3DLOD(PositionWS, Scale, Jitter, LODRatio);
}
// =============================================================================
// VORONOI NOISE
// =============================================================================
// --- 2D ----------------------------------------------------------------------
float VoronoiNoise2D(
float2 UV, // Input UV coordinates
float Scale, // Noise frequency
float Jitter, // Feature point randomness [0 = grid, 1 = random]
float CellBlend, // 0 = F1 distance, 1 = F2-F1 (border emphasis)
out float CellID) // Unique ID of the nearest cell [0, 1]
{
float2 p = UV * Scale;
float2 cell = floor(p);
float minF1 = 8.0, minF2 = 8.0;
float2 minCell = 0;
for (int y = -1; y <= 1; y++)
for (int x = -1; x <= 1; x++)
{
float2 neighbor = cell + float2(x, y);
float2 offset = neighbor + Hash2D(neighbor) * Jitter;
float d = distance(p, offset);
if (d < minF1) { minF2 = minF1; minF1 = d; minCell = neighbor; }
else if (d < minF2) { minF2 = d; }
}
CellID = Hash1From2D(minCell);
return saturate(lerp(minF1, minF2 - minF1, CellBlend));
}
void VoronoiNoise2D_float(float2 UV, float Scale, float Jitter, float CellBlend, out float Out, out float CellID)
{
Out = VoronoiNoise2D(UV, Scale, Jitter, CellBlend, CellID);
}
// --- 3D ----------------------------------------------------------------------
float VoronoiNoise3D(
float3 Position, // Input position in object space
float Scale, // Noise frequency
float Jitter, // Feature point randomness [0 = grid, 1 = random]
float CellBlend, // 0 = F1 distance, 1 = F2-F1 (border emphasis)
out float CellID) // Unique ID of the nearest cell [0, 1]
{
float3 p = Position * Scale;
float3 cell = floor(p);
float minF1 = 8.0, minF2 = 8.0;
float3 minCell = 0;
for (int z = -1; z <= 1; z++)
for (int y = -1; y <= 1; y++)
for (int x = -1; x <= 1; x++)
{
float3 neighbor = cell + float3(x, y, z);
float3 offset = neighbor + Hash3D(neighbor) * Jitter;
float d = distance(p, offset);
if (d < minF1) { minF2 = minF1; minF1 = d; minCell = neighbor; }
else if (d < minF2) { minF2 = d; }
}
CellID = Hash1From3D(minCell);
return saturate(lerp(minF1, minF2 - minF1, CellBlend));
}
void VoronoiNoise3D_float(float3 Position, float Scale, float Jitter, float CellBlend, out float Out, out float CellID)
{
Out = VoronoiNoise3D(Position, Scale, Jitter, CellBlend, CellID);
}
// --- 3D LOD ------------------------------------------------------------------
// CellID is blended as a weighted average – loses sharp cell identity
// across the transition zone, which is an acceptable tradeoff for LOD.
float VoronoiNoise3DLOD(
float3 PositionWS, // Surface position in world space
float Scale, // Noise frequency at reference distance
float Jitter, // Feature point randomness [0 = grid, 1 = random]
float CellBlend, // 0 = F1 distance, 1 = F2-F1 (border emphasis)
float LODRatio, // Scale ratio between layers (4 = wide transition)
out float CellID)
{
float scale0, scale1, w0, w1;
LODBlend(PositionWS, Scale, LODRatio, scale0, scale1, w0, w1);
float cellID0, cellID1;
float v0 = VoronoiNoise3D(PositionWS, scale0, Jitter, CellBlend, cellID0);
float v1 = VoronoiNoise3D(PositionWS, scale1, Jitter, CellBlend, cellID1);
CellID = cellID0 * w0 + cellID1 * w1;
return v0 * w0 + v1 * w1;
}
void VoronoiNoise3DLOD_float(float3 PositionWS, float Scale, float Jitter, float CellBlend, float LODRatio, out float Out, out float CellID)
{
Out = VoronoiNoise3DLOD(PositionWS, Scale, Jitter, CellBlend, LODRatio, CellID);
}
// =============================================================================
// FBM (Fractal Brownian Motion) – built on Perlin
// =============================================================================
// --- 2D ----------------------------------------------------------------------
float FBMNoise2D(
float2 UV, // Input UV coordinates
float Scale, // Base noise frequency
int Octaves, // Number of noise layers
float Lacunarity, // Frequency multiplier per octave (typically 2.0)
float Gain) // Amplitude multiplier per octave (typically 0.5)
{
float value = 0.0;
float amplitude = 0.5;
float frequency = Scale;
float maxValue = 0.0;
for (int i = 0; i < Octaves; i++)
{
value += PerlinNoise2D(UV, frequency) * amplitude;
maxValue += amplitude;
amplitude *= Gain;
frequency *= Lacunarity;
}
return value / maxValue;
}
void FBMNoise2D_float(float2 UV, float Scale, float Octaves, float Lacunarity, float Gain, out float Out)
{
Out = FBMNoise2D(UV, Scale, (int)Octaves, Lacunarity, Gain);
}
// --- 3D ----------------------------------------------------------------------
float FBMNoise3D(
float3 Position, // Input position in object space
float Scale, // Base noise frequency
int Octaves, // Number of noise layers
float Lacunarity, // Frequency multiplier per octave (typically 2.0)
float Gain) // Amplitude multiplier per octave (typically 0.5)
{
float value = 0.0;
float amplitude = 0.5;
float frequency = Scale;
float maxValue = 0.0;
for (int i = 0; i < Octaves; i++)
{
value += PerlinNoise3D(Position, frequency) * amplitude;
maxValue += amplitude;
amplitude *= Gain;
frequency *= Lacunarity;
}
return value / maxValue;
}
void FBMNoise3D_float(float3 Position, float Scale, float Octaves, float Lacunarity, float Gain, out float Out)
{
Out = FBMNoise3D(Position, Scale, (int)Octaves, Lacunarity, Gain);
}
// --- 3D LOD ------------------------------------------------------------------
float FBMNoise3DLOD(
float3 PositionWS, // Surface position in world space
float Scale, // Base noise frequency at reference distance
int Octaves, // Number of noise layers
float Lacunarity, // Frequency multiplier per octave (typically 2.0)
float Gain, // Amplitude multiplier per octave (typically 0.5)
float LODRatio) // Scale ratio between layers (4 = wide transition)
{
float scale0, scale1, w0, w1;
LODBlend(PositionWS, Scale, LODRatio, scale0, scale1, w0, w1);
return FBMNoise3D(PositionWS, scale0, Octaves, Lacunarity, Gain) * w0
+ FBMNoise3D(PositionWS, scale1, Octaves, Lacunarity, Gain) * w1;
}
void FBMNoise3DLOD_float(float3 PositionWS, float Scale, float Octaves, float Lacunarity, float Gain, float LODRatio, out float Out)
{
Out = FBMNoise3DLOD(PositionWS, Scale, (int)Octaves, Lacunarity, Gain, LODRatio);
}
// =============================================================================
// RIDGED NOISE – |FBM| folded to produce sharp ridges
// =============================================================================
// --- 2D ----------------------------------------------------------------------
float RidgedNoise2D(
float2 UV, // Input UV coordinates
float Scale, // Base noise frequency
int Octaves, // Number of noise layers
float Lacunarity, // Frequency multiplier per octave (typically 2.0)
float Gain) // Amplitude multiplier per octave (typically 0.5)
{
float value = 0.0;
float amplitude = 0.5;
float frequency = Scale;
float maxValue = 0.0;
for (int i = 0; i < Octaves; i++)
{
float n = 1.0 - abs(PerlinNoise2D(UV, frequency) * 2.0 - 1.0);
value += n * n * amplitude;
maxValue += amplitude;
amplitude *= Gain;
frequency *= Lacunarity;
}
return value / maxValue;
}
void RidgedNoise2D_float(float2 UV, float Scale, float Octaves, float Lacunarity, float Gain, out float Out)
{
Out = RidgedNoise2D(UV, Scale, (int)Octaves, Lacunarity, Gain);
}
// --- 3D ----------------------------------------------------------------------
float RidgedNoise3D(
float3 Position, // Input position in object space
float Scale, // Base noise frequency
int Octaves, // Number of noise layers
float Lacunarity, // Frequency multiplier per octave (typically 2.0)
float Gain) // Amplitude multiplier per octave (typically 0.5)
{
float value = 0.0;
float amplitude = 0.5;
float frequency = Scale;
float maxValue = 0.0;
for (int i = 0; i < Octaves; i++)
{
float n = 1.0 - abs(PerlinNoise3D(Position, frequency) * 2.0 - 1.0);
value += n * n * amplitude;
maxValue += amplitude;
amplitude *= Gain;
frequency *= Lacunarity;
}
return value / maxValue;
}
void RidgedNoise3D_float(float3 Position, float Scale, float Octaves, float Lacunarity, float Gain, out float Out)
{
Out = RidgedNoise3D(Position, Scale, (int)Octaves, Lacunarity, Gain);
}
// --- 3D LOD ------------------------------------------------------------------
float RidgedNoise3DLOD(
float3 PositionWS, // Surface position in world space
float Scale, // Base noise frequency at reference distance
int Octaves, // Number of noise layers
float Lacunarity, // Frequency multiplier per octave (typically 2.0)
float Gain, // Amplitude multiplier per octave (typically 0.5)
float LODRatio) // Scale ratio between layers (4 = wide transition)
{
float scale0, scale1, w0, w1;
LODBlend(PositionWS, Scale, LODRatio, scale0, scale1, w0, w1);
return RidgedNoise3D(PositionWS, scale0, Octaves, Lacunarity, Gain) * w0
+ RidgedNoise3D(PositionWS, scale1, Octaves, Lacunarity, Gain) * w1;
}
void RidgedNoise3DLOD_float(float3 PositionWS, float Scale, float Octaves, float Lacunarity, float Gain, float LODRatio, out float Out)
{
Out = RidgedNoise3DLOD(PositionWS, Scale, (int)Octaves, Lacunarity, Gain, LODRatio);
}
#endif