噪波纹理分析(2):分形函数

分形函数

1.1 分形噪波函数

​​​  fbmMulti-fractalHetero TerrainHybrid Multi-fractalRidged Multi-fractal是五种基于分形噪声的算法类型,每种通过不同的方式叠加噪声的“八度”(octaves)来生成不同特性的纹理。他们有一些共同的控制参数如下。

  • 八度数(Detail):控制噪声的层级细节,增加八度会提升复杂度但降低性能。
  • 粗糙度(Roughness):调整噪声的锐利度,值越大峰值越尖锐。
  • 维度(Dimensions):1D/2D/3D/4D影响噪声的空间特性,更高维度计算成本更高。
  • 间隙度(Lacunarity):控制分形噪声中连续八度之间的频率倍增比例。数值越大,高频细节的尺度差异越明显,生成的结构越粗糙。
  • 最大距离(Max_distance):定义距离衰减效应的最大范围,超出此距离后声音或噪声的强度不再衰减(用于空间音频或体积效果)。

1.1.1 Fractal Brownian Motion 噪波函数

  • 算法原理:通过线性叠加多个Perlin噪声的八度(octaves),每个八度的频率倍增(如2倍、4倍等),振幅递减(如1/2、1/4等)。最终结果是所有八度的加权和。

  • 数学表达

    \[\text{fBM}(x) = \sum_{i=0}^{n} \frac{\text{Noise}(2^i x)}{2^i} \]

    其中 n是八度数。

  • 特性:生成均匀且各向同性的噪声,适合模拟自然现象如云层、平滑地形。

  • 应用场景:基础地形、云层纹理或通用随机图案。

#define float2 vec2
#define float3 vec3
#define float4 vec4
#define int2 ivec2
#define int3 ivec3
#define FLT_MAX 1e20
#define FLOORFRAC(x, x_int, x_fract) { float x_floor = floor(x); x_int = int(x_floor); x_fract = x - x_floor; }
#define rot(x, k) (((x) << (k)) | ((x) >> (32 - (k))))

#define mix(a, b, c) \
  { \
    a -= c; \
    a ^= rot(c, 4); \
    c += b; \
    b -= a; \
    b ^= rot(a, 6); \
    a += c; \
    c -= b; \
    c ^= rot(b, 8); \
    b += a; \
    a -= c; \
    a ^= rot(c, 16); \
    c += b; \
    b -= a; \
    b ^= rot(a, 19); \
    a += c; \
    c -= b; \
    c ^= rot(b, 4); \
    b += a; \
  }

#define final(a, b, c) \
  { \
    c ^= b; \
    c -= rot(b, 14); \
    a ^= c; \
    a -= rot(c, 11); \
    b ^= a; \
    b -= rot(a, 25); \
    c ^= b; \
    c -= rot(b, 16); \
    a ^= c; \
    a -= rot(c, 4); \
    b ^= a; \
    b -= rot(a, 14); \
    c ^= b; \
    c -= rot(b, 24); \
  }
uint hash_uint2(uint kx, uint ky)
{
  uint a, b, c;
  a = b = c = 0xdeadbeefu + (2u << 2u) + 13u;

  b += ky;
  a += kx;
  final(a, b, c);

  return c;
}
uint hash_int2(int kx, int ky)
{
  return hash_uint2(uint(kx), uint(ky));
}
float bi_mix(float v0, float v1, float v2, float v3, float x, float y)
{
  float x1 = 1.0f - x;
  return (1.0f - y) * (v0 * x1 + v1 * x) + y * (v2 * x1 + v3 * x);
}
float fade(float t)
{
  return t * t * t * (t * (t * 6.0f - 15.0f) + 10.0f);
}

float negate_if(float value, uint condition)
{
  return (condition != 0u) ? -value : value;
}

float noise_grad(uint hash, float x, float y)
{
  uint h = hash & 7u;
  float u = h < 4u ? x : y;
  float v = 2.0f * (h < 4u ? y : x);
  return negate_if(u, h & 1u) + negate_if(v, h & 2u);
}

float noise_perlin(float2 vec)
{
  int X, Y;
  float fx, fy;

  FLOORFRAC(vec.x, X, fx);
  FLOORFRAC(vec.y, Y, fy);

  float u = fade(fx);
  float v = fade(fy);

  float r = bi_mix(noise_grad(hash_int2(X, Y), fx, fy),
                   noise_grad(hash_int2(X + 1, Y), fx - 1.0f, fy),
                   noise_grad(hash_int2(X, Y + 1), fx, fy - 1.0f),
                   noise_grad(hash_int2(X + 1, Y + 1), fx - 1.0f, fy - 1.0f),
                   u,
                   v);

  return r;
}


float noise_scale2(float result)
{
  return 0.6616f * result;
}

float snoise(float2 p)
{
  return noise_scale2(noise_perlin(p));
}



 float noise_fbm(vec2 co, 
                  float detail, 
                  float roughness, 
                  float lacunarity, 
                  float offset, 
                  float gain, 
                  bool normalize) 
  { 
    vec2 p = co; 
    float fscale = 1.0f; 
    float amp = 1.0f; 
    float maxamp = 0.0f; 
    float sum = 0.0f; 

    for (int i = 0; i <= int(detail); i++) { 
      float t = snoise(fscale * p); 
      sum += t * amp; 
      maxamp += amp; 
      amp *= roughness; 
      fscale *= lacunarity; 
    } 
    float rmd = detail - floor(detail); 
    if (rmd != 0.0f) { 
      float t = snoise(fscale * p); 
      float sum2 = sum + t * amp; 
      if(normalize)
      {
          float a=0.5f * sum / maxamp + 0.5f;
          float b=0.5f * sum2 / (maxamp + amp) + 0.5f;
          return (1.0-rmd)*a+rmd*b;
      }
      else {
      return (1.0-rmd)*sum+rmd*sum2;
      }
      
    } 
    else { 
      return normalize ? 0.5f * sum / maxamp + 0.5f : sum; 
    } 
  }

void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
    vec2 uv = fragCoord/iResolution.xy;

    
    float col=noise_fbm(uv*10.0,2.0,0.5,2.0,0.0,0.0,true);

    // Output to screen
    fragColor = vec4(vec3(col),1.0);
}

fbm

1.1.2 Multi-fractal 噪波函数

  • 算法原理:与fBM不同,Multi-fractal通过乘法叠加噪声八度,而非加法。每个八度的噪声值相乘,导致结果更不均匀,局部可能出现极值。

  • 数学表达

    \[\text{Multi-fractal}(x) = \prod_{i=0}^{n} \text{Noise}(2^i x) \]

  • 特性:产生非均匀分布的噪声,类似真实地形的起伏变化,适合模拟崎岖地貌或复杂表面。

  • 应用场景:山地、岩石表面等细节丰富的自然纹理。

float noise_multi_fractal(vec2 co, 
                            float detail, 
                            float roughness, 
                            float lacunarity, 
                            float offset, 
                            float gain, 
                            bool normalize) 
  { 
    vec2 p = co; 
    float value = 1.0f; 
    float pwr = 1.0f; 

    for (int i = 0; i <= int(detail); i++) { 
      value *= (pwr * snoise(p) + 1.0f); 
      pwr *= roughness; 
      p *= lacunarity; 
    } 

    float rmd = detail - floor(detail); 
    if (rmd != 0.0f) { 
      value *= (rmd * pwr * snoise(p) + 1.0f); /* correct? */ 
    } 

    return value; 
  }

mf

1.1.3 Hybrid Multi-fractal 噪波函数

  • 算法原理:结合加法和乘法叠加。首个八度使用加法,后续八度通过乘法调整,形成既有平滑基底又有尖锐峰值的混合效果。

  • 数学表达

    \[\text{Hybrid}(x) = \text{Noise}(x) + \sum_{i=1}^{n} \text{Noise}(2^i x) \cdot \prod_{j=1}^{i} \text{Noise}(2^j x) \]

  • 特性:生成多尺度细节,如山脉从平原中隆起的效果,兼具平滑区域和陡峭变化。

  • 应用场景:复杂地形(如山脉与平原过渡)。

float noise_hybrid_multi_fractal(vec2 co, 
                                   float detail, 
                                   float roughness, 
                                   float lacunarity, 
                                   float offset, 
                                   float gain, 
                                   bool normalize) 
  { 
    vec2 p = co; 
    float pwr = 1.0f; 
    float value = 0.0f; 
    float weight = 1.0f; 

    for (int i = 0; (weight > 0.001f) && (i <= int(detail)); i++) { 
      if (weight > 1.0f) { 
        weight = 1.0f; 
      } 

      float signal = (snoise(p) + offset) * pwr; 
      pwr *= roughness; 
      value += weight * signal; 
      weight *= gain * signal; 
      p *= lacunarity; 
    } 

    float rmd = detail - floor(detail); 
    if ((rmd != 0.0f) && (weight > 0.001f)) { 
      if (weight > 1.0f) { 
        weight = 1.0f; 
      } 
      float signal = (snoise(p) + offset) * pwr; 
      value += rmd * weight * signal; 
    } 

    return value; 
  }

hbfpng

1.1.4 Ridged Multi-fractal 噪波函数

  • 算法原理:对每个八度的噪声取绝对值,再通过反转(如 1−Noise)生成尖锐的“脊状”结构。后续八度叠加时保留这一特征。

  • 数学表达

    \[\text{Ridged}(x) = \sum_{i=0}^{n} \frac{| \text{Noise}(2^i x) |}{2^i} \]

    通常结合反转操作。

  • 特性:产生尖锐的峰谷结构,类似峡谷或熔岩地形的裂缝。

  • 应用场景:极端地貌(如峡谷、冰川裂隙)。

float noise_ridged_multi_fractal(vec2 co, 
                                   float detail, 
                                   float roughness, 
                                   float lacunarity,
                                   float offset, 
                                   float gain, 
                                   bool normalize) 
  { 
    vec2 p = co; 
    float pwr = roughness; 

    float signal = offset - abs(snoise(p)); 
    signal *= signal; 
    float value = signal; 
    float weight = 1.0f; 

    for (int i = 1; i <= int(detail); i++) { 
      p *= lacunarity; 
      weight = clamp(signal * gain, 0.0f, 1.0f); 
      signal = offset - abs(snoise(p)); 
      signal *= signal; 
      signal *= weight; 
      value += signal * pwr; 
      pwr *= roughness; 
    } 

    return value; 
  }

rmf

1.1.5 Hetero Terrain 噪波函数

  • 算法原理:类似Hybrid Multi-fractal,但通过调整八度的权重和偏移量,模拟河流侵蚀异质地貌。噪声值可能被偏移(如 Noise+offset)以形成通道状结构。
  • 特性:生成非均匀侵蚀效果,如河道或风蚀地形,局部细节更复杂。
  • 应用场景:河流网络、风蚀岩石等。
float noise_hetero_terrain(vec2 co, 
                             float detail, 
                             float roughness, 
                             float lacunarity, 
                             float offset, 
                             float gain, 
                             bool normalize) 
  { 
    vec2 p = co; 
    float pwr = roughness; 

    /* first unscaled octave of function; later octaves are scaled */ 
    float value = offset + snoise(p); 
    p *= lacunarity; 

    for (int i = 1; i <= int(detail); i++) { 
      float increment = (snoise(p) + offset) * pwr * value; 
      value += increment; 
      pwr *= roughness; 
      p *= lacunarity; 
    } 

    float rmd = detail - floor(detail); 
    if (rmd != 0.0f) { 
      float increment = (snoise(p) + offset) * pwr * value; 
      value += rmd * increment; 
    } 

    return value; 
  }

ht

1.2 分形Voronoi函数

1.2.1 F1模式

VoronoiOutput fractal_voronoi_x_fx(VoronoiParams params, float2 coord)
{
  float amplitude = 1.0f;
  float max_amplitude = 0.0f;
  float scale = 1.0f;

  VoronoiOutput Output;
  Output.Distance = 0.0f;
  Output.Color = float3(0.0f, 0.0f, 0.0f);
  Output.Position = float4(0.0f, 0.0f, 0.0f, 0.0f);
  bool zero_input = params.detail == 0.0f || params.roughness == 0.0f;

  for (float i = 0.0; i <= ceil(params.detail); ++i) {
    VoronoiOutput octave;
    octave = voronoi_f1(params, coord * scale);

    if (zero_input) {
      max_amplitude = 1.0f;
      Output = octave;
      break;
    }
    else if (i <= params.detail) {
      max_amplitude += amplitude;
      Output.Distance += octave.Distance * amplitude;
      Output.Color += octave.Color * amplitude;
      Output.Position = mix(Output.Position, octave.Position / scale, amplitude);
      scale *= params.lacunarity;
      amplitude *= params.roughness;
    }
    else {
      float remainder = params.detail - floor(params.detail);
      if (remainder != 0.0f) {
        max_amplitude = mix(max_amplitude, max_amplitude + amplitude, remainder);
        Output.Distance = mix(
            Output.Distance, Output.Distance + octave.Distance * amplitude, remainder);
        Output.Color = mix(Output.Color, Output.Color + octave.Color * amplitude, remainder);
        Output.Position = mix(
            Output.Position, mix(Output.Position, octave.Position / scale, amplitude), remainder);
      }
    }
  }

  if (params.normalize) {
    Output.Distance /= max_amplitude * params.max_distance;
    Output.Color /= max_amplitude;
  }

  Output.Position = Output.Position/params.scale;

  return Output;
}

voronoiFF1

1.2.2 Distance to Edge模式

float fractal_voronoi_distance_to_edge(VoronoiParams params, vec2 coord) 
{ 
float amplitude = 1.0f; 
float max_amplitude = params.max_distance; 
float scale = 1.0f; 
float distance = 8.0f; 

bool zero_input = params.detail == 0.0f || params.roughness == 0.0f; 

for (float i = 0.0; i <= ceil(params.detail); ++i) { 
  float octave_distance = voronoi_distance_to_edge(params, coord * scale); 

  if (zero_input) {
    distance = octave_distance; 
    break; 
  } 
  else if (i <= params.detail) { 
    max_amplitude = mix(max_amplitude, params.max_distance / scale, amplitude); 
    distance = mix(distance, min(distance, octave_distance / scale), amplitude); 
    scale *= params.lacunarity; 
    amplitude *= params.roughness; 
  } 
  else { 
    float remainder = params.detail - floor(params.detail); 
    if (remainder != 0.0f) { 
      float lerp_amplitude = mix(max_amplitude, params.max_distance / scale, amplitude); 
      max_amplitude = mix(max_amplitude, lerp_amplitude, remainder); 
      float lerp_distance = mix(distance, min(distance, octave_distance / scale), amplitude); 
      distance = mix(distance, min(distance, lerp_distance), remainder); 
    } 
  } 
} 

if (params.normalize) { 
  distance /= max_amplitude; 
} 

return distance; 
}

voronoiFFD

posted @ 2025-08-19 13:52  王小于的啦  阅读(77)  评论(0)    收藏  举报