数学可视化(08)——分形Fractal

  1. 1. 分形Fractal的概念和定义
  2. 2. 分形维数与拓扑维数
  3. 3. 实时渲染用的分形

 

分形Fractal的概念和定义

  • 分形Fractal最早是由数学家曼德波罗在《统计自相似性和分数维度》的论文中提出的
  • 与随机、噪声等混沌状态不同,分形具有递归性定义
  • 分形是以非整数维形式填充空间、对空间占有的特定形式
  • 具有自相似性

分形维数与拓扑维数

  • 拓扑维数:通过空间中的一个点需要几个变量定义来确定
  • 如:地球表面一个点,只需要经度纬度就可定义,因此地球表面实际的拓扑维数是二维
  • 分形维数:在拓扑维数下定义的一个图形,把它拆成更小的形状,需要几个更小的形状才能拼回原来的图形

E=2

  • 分形维数公式:D=logN / logE,其中N为拼回原图形需要的小图形的个数,E为原图形被缩小为原来的几分之一的倒数

  • 分形维数与原图形填充是可以有直观上的对比映射的
  • 如:分形维数在1~2区间时,越接近1,图形越向一维线段的填充;越接近2时,越像二维图形的填充;而越接近3时,越接近三维几何体填充

实时渲染用的分形

  • 最常用的是分形布朗运动(Fractual Brownian Motion,fbm)
  • 简称fbm,是布朗运动的拓展
  • 通过将不同频率和振幅的噪声函数进行叠加操作
  • 布朗运动:布朗运动是一种随机运动,粒子的运动方向随时改变,其运动轨迹是一条处处连续但处处不可微的曲线,是一种无规分形曲线,也具有统计性质的自相似性

  • 一般fbm公式为每级噪声函数,其振幅缩减为上一级的1/2,频率增加为上一级的一倍,并通过参数控制fbm由几级噪声函数叠加而成。这里的噪声函数可以是任意噪声函数
  • 公式: fbm = noise(uv) + 0.5 * noise(2*uv)+ 0.25 * noise(4*uv)…
  • fbm变种:
    • 湍流(Turbulence ),在fbm中对噪声函数取绝对值,使噪声值在0时发生突变,产生湍流纹理,fbm = |noise(uv)| + 0.5 *|noise(2*uv)| + 0.25*|noise ( 4*uv)|…
    • 翘曲域(Domain Wrapping),翘曲域噪声用来模拟卷曲、螺旋状纹理,如烟雾、大理石等,f(p) = fbm( p + fbm( p + fbm( p )))
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
//随机数
float random (in half2 uv)
{
return frac(sin(dot(uv.xy, float2(12.9898,78.233)))*43758.5453123);
}
float2 random2( in half2 uv )
{
return frac(sin(float2(dot(uv.xy, float2(127.1,311.7)),dot(uv.xy,float2(269.5,183.3))))*43758.5453);
}
//梯度化噪声
float gradientNoise (in half2 uv)
{
half2 iuv = floor(uv);
half2 fuv = frac(uv);
float a = random(iuv);
float b = random(iuv + half2(1.0, 0.0));
float c = random(iuv + half2(0.0, 1.0));
float d = random(iuv + half2(1.0, 1.0));
half2 u = fuv*fuv*(3.0-2.0*fuv);
return lerp(a, b, u.x) +
(c - a)* u.y * (1.0 - u.x) +
(d - b) * u.x * u.y;
}
//voronoi噪声,计算最小距离
float voronoiNoise(in half2 uv)
{
half2 iuv = floor(uv);
half2 fuv = frac(uv);

float minDist = 1.; //最小距离

for (int y= -1; y <= 1; y++) {
for (int x= -1; x <= 1; x++) {
// 邻居网格节点
float2 neighbor = float2(float(x),float(y));

// 在网格内从current+neighor位置来随机位置
float2 pt = random2(iuv + neighbor);

// 移动特征点
pt = 0.5 + 0.5*sin(time + 6.2831*pt);

// 像素到特征点的矢量
float2 diff = neighbor + pt - fuv;

// 计算到特征点的距离
float dist = length(diff);

// 计算最小距离
minDist = min(minDist, dist);
}
}
// 返回最小距离
return minDist;
}
  • 通过调整算法和噪声函数,可以组合出各种各样的分形噪声效果
  • 因此fbm常被用作生成程序化纹理中
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
//分形布朗运动
#define OCTAVES 6 // 定义有几级噪声函数
float fbm (in half2 uv) {
// Initial values
float value = 0.0;
float amplitude = .5;

// Loop of octaves
for (int i = 0; i < OCTAVES; i++) {
//value += amplitude * gradientNoise(uv);

//湍流
value += amplitude * abs(voronoiNoise(uv)*2 - 1);
//
uv *= 2.;
amplitude *= .5;
}
// Sharpness
//value = 1.0 - clamp(0, 1, value);
//value = value * value;
//
return value;
}
//翘曲域
#define IterNum 3
float domainWarping(in half2 uv)
{
float value = 0.0;
for (int i = 0; i < IterNum; i++)
value = fbm( uv +value );
return value;
}
half3 PixelColor(float2 uv)
{
half3 c = half3(0, 0, 0);
//
uv = uv*10;
//分形布朗运动
//c = fbm(uv + time);
//翘曲域
c = domainWarping(uv + time);
//
return c;
}