|
|
@ -0,0 +1,95 @@
|
|
|
1
|
/*
|
|
|
2
|
* A "Mandelbulb", i.e. a mandelbrot fractal in 3d.
|
|
|
3
|
*
|
|
|
4
|
* Adapted for Fragmentarium from [1].
|
|
|
5
|
*
|
|
|
6
|
* [1]: http://2008.sub.blue/blog/2009/12/13/mandelbulb.html
|
|
|
7
|
*/
|
|
|
8
|
#include "3D.frag"
|
|
|
9
|
|
|
|
10
|
#group Mandelbulb
|
|
|
11
|
uniform float MinimumDistance; slider[0.0,0.01,10.0]
|
|
|
12
|
uniform int MaximumRaySteps; slider[1,10,200]
|
|
|
13
|
uniform int MaxIterations; slider[1,2,30]
|
|
|
14
|
uniform float bailout; slider[0.5,4.0,12.0]
|
|
|
15
|
uniform float power; slider[-20.0,8.0,20.0]
|
|
|
16
|
uniform float phaseX; slider[-2.0,0.0,2.0]
|
|
|
17
|
uniform float phaseY; slider[-2.0,0.0,2.0]
|
|
|
18
|
|
|
|
19
|
// Defined later, must be forward declared for use in `trace`.
|
|
|
20
|
float DistanceEstimator(vec3 pos);
|
|
|
21
|
|
|
|
22
|
float trace(vec3 from, vec3 direction) {
|
|
|
23
|
float totalDistance = 0.0;
|
|
|
24
|
int steps;
|
|
|
25
|
for (steps=0; steps < MaximumRaySteps; steps++) {
|
|
|
26
|
vec3 p = from + totalDistance * direction;
|
|
|
27
|
float distance = DistanceEstimator(p);
|
|
|
28
|
totalDistance += distance;
|
|
|
29
|
if (distance < MinimumDistance) break;
|
|
|
30
|
}
|
|
|
31
|
return 1.0-float(steps)/float(MaximumRaySteps);
|
|
|
32
|
}
|
|
|
33
|
|
|
|
34
|
float DistanceEstimator(vec3 z0) {
|
|
|
35
|
vec3 c = z0;
|
|
|
36
|
vec3 z = z0;
|
|
|
37
|
float pd = power - 1.0; // power for derivative
|
|
|
38
|
|
|
|
39
|
// Convert z to polar coordinates
|
|
|
40
|
float r = length(z);
|
|
|
41
|
float th = atan(z.y, z.x);
|
|
|
42
|
float ph = asin(z.z / r);
|
|
|
43
|
|
|
|
44
|
vec3 dz;
|
|
|
45
|
float ph_dz = 0.0;
|
|
|
46
|
float th_dz = 0.0;
|
|
|
47
|
float r_dz = 1.0;
|
|
|
48
|
float powR, powRsin;
|
|
|
49
|
|
|
|
50
|
// Iterate to compute the distance estimator.
|
|
|
51
|
for (int n = 0; n < MaxIterations; n++) {
|
|
|
52
|
// Calculate derivative of
|
|
|
53
|
powR = power * pow(r, pd);
|
|
|
54
|
powRsin = powR * r_dz * sin(ph_dz + pd*ph);
|
|
|
55
|
dz.x = powRsin * cos(th_dz + pd*th) + 1.0;
|
|
|
56
|
dz.y = powRsin * sin(th_dz + pd*th);
|
|
|
57
|
dz.z = powR * r_dz * cos(ph_dz + pd*ph);
|
|
|
58
|
|
|
|
59
|
// polar coordinates of derivative dz
|
|
|
60
|
r_dz = length(dz);
|
|
|
61
|
th_dz = atan(dz.y, dz.x);
|
|
|
62
|
ph_dz = acos(dz.z / r_dz);
|
|
|
63
|
|
|
|
64
|
// z iteration
|
|
|
65
|
powR = pow(r, power);
|
|
|
66
|
powRsin = sin(power*ph);
|
|
|
67
|
z.x = powR * powRsin * cos(power*th);
|
|
|
68
|
z.y = powR * powRsin * sin(power*th);
|
|
|
69
|
z.z = powR * cos(power*ph);
|
|
|
70
|
z += c;
|
|
|
71
|
|
|
|
72
|
r = length(z);
|
|
|
73
|
if (r > bailout) break;
|
|
|
74
|
|
|
|
75
|
th = atan(z.y, z.x) + phaseX;
|
|
|
76
|
ph = acos(z.z / r) + phaseY;
|
|
|
77
|
|
|
|
78
|
}
|
|
|
79
|
|
|
|
80
|
// Return the distance estimation value which determines the next raytracing
|
|
|
81
|
// step size, or if whether we are within the threshold of the surface.
|
|
|
82
|
return 0.5 * r * log(r)/r_dz;
|
|
|
83
|
}
|
|
|
84
|
|
|
|
85
|
vec3 color(vec3 pos, vec3 direction) {
|
|
|
86
|
float dist = trace(pos, direction);
|
|
|
87
|
return vec3(dist, dist, dist);
|
|
|
88
|
}
|
|
|
89
|
|
|
|
90
|
#preset Default
|
|
|
91
|
Eye = 0.0,0.0,2.0
|
|
|
92
|
Target 0.0,0.0,1.0
|
|
|
93
|
MinimumDistance=0.00001
|
|
|
94
|
MaximumRaySteps=100
|
|
|
95
|
MaxIterations=4
|