Here's my weird plancton formula with three colorful presets. Let it render in continuous mode with at least 20 subframes.
This formula produces lots of whipped cream if you're not careful. High iteration counts generally lead to a lot of pixel noise that does not seem to disappear even when letting it render many subframes. A nice combination is low power with higher iteration counts (see Parrot preset).
Generally vary theta and phi in the RotaBulb parameters. For theta = 0 and theta = 180 degrees, this formula converges towards a mandelbulb - anything else is uncharted territory.
Here's my code, save it as RotaBulb.frag
#info Mandelbulb without Distance Estimator
#define providesInside
#include "Brute-Raytracer.frag"
#include "MathUtils.frag"
#include "Complex.frag"
#group RotaBulb
// Number of fractal iterations.
uniform int Iterations; slider[0,10,100]
// Number of color iterations.
uniform int ColorIterations; slider[0,5,100]
// Mandelbulb exponent (8 is standard)
uniform float Power; slider[-10,3,10]
// Bailout radius
uniform float Bailout; slider[0,2,30]
uniform float theta; slider[0.0,0,180]
uniform float phi; slider[0.0,0,360]
/*
vec3 color(vec3 p) {
return abs(vec3(p));
}
*/
#define D2R 0.01745329251994329576923690768489
// return what I call the "pole vector"
vec3 PVec()
{
return vec3(cos(D2R*phi)*sin(D2R*theta), sin(D2R*phi)*sin(D2R*theta), cos(D2R*theta));
}
vec3 QVec()
{
return vec3(1.0, 0.0, 0.0);
}
vec3 RVec()
{
return vec3(0.0, 0.0, 1.0);
}
// create quaternion from rotation axis v and the given angle
vec4 describe_rotation(in vec3 v, in float angle)
{
float sina_2 = sin(angle/2.0);
float cosa_2 = cos(angle/2.0);
return vec4(cosa_2, sina_2*v.x, sina_2*v.y, sina_2*v.z);
}
// perform a rotation of vector v using the given quaternion q
vec3 rotate(in vec3 v, in vec4 q)
{
float t2 = q.x*q.y;
float t3 = q.x*q.z;
float t4 = q.x*q.w;
float t5 = -q.y*q.y;
float t6 = q.y*q.z;
float t7 = q.y*q.w;
float t8 = -q.z*q.z;
float t9 = q.z*q.w;
float t10 = -q.w*q.w;
return vec3(2.0*( (t8 + t10)*v.x + (t6 - t4)*v.y + (t3 + t7)*v.z ) + v.x,
2.0*( (t4 + t6)*v.x + (t5 + t10)*v.y + (t9 - t2)*v.z ) + v.y,
2.0*( (t7 - t3)*v.x + (t2 + t9)*v.y + (t5 + t8)*v.z ) + v.z);
}
vec3 powN(in vec3 z, float magnitude, vec3 P) {
orbitTrap=10000;
vec3 z_power = z;
float costheta = dot(z, P) / magnitude;
float costheta2 = costheta * costheta;
float sintheta2 = 1.0 - costheta2;
float sintheta = sqrt(sintheta2);
vec3 N = cross(P, z) / (magnitude * sintheta);
// Step 1
// generate a vector that is situated in the plane spanned by
// origin, the pole and z and has an resulting angle of power*theta
// with respect to the pole.
float theta = acos(costheta);
vec4 rot = describe_rotation( N, (Power-1.0)*theta );
z_power = rotate(z_power, rot) * pow(magnitude, Power-1.0);
// Step 2: Perform rotation around pole axis by an angle of (power-1)*phi
vec3 z_normal = z_power - RVec() * dot(z_power, RVec());
float cosphi = dot(z_normal, QVec()) / length(z_normal);
float phi = acos(cosphi);
if ( dot(cross(QVec(), z_normal), RVec()) < 0.0 )
phi = 6.2831853071 - phi; // 2*PI - phi
vec4 rot2 = describe_rotation( RVec(), Power*phi - phi );
z_power = rotate(z_power, rot2);
return z_power;
}
bool inside(vec3 z) {
vec3 P = PVec();
vec3 c=z;
float r=length(z);
int i=0;
while(r<Bailout && (i<Iterations)) {
z = powN(z,r,P) + c;
i++;
r=length(z);
if (i<ColorIterations) orbitTrap = min(orbitTrap, abs(vec4(z.x,z.y,z.z,r*r)));
}
return (r<Bailout);
}
#preset Default
FOV = 0.77
Eye = 0,0,2
Target = 0,0,0
Up = 0,1,0
EquiRectangular = false
Gamma = 1
ToneMapping = 1
Exposure = 1
Brightness = 1
Contrast = 1
Saturation = 1
NormalScale = 1
AOScale = 1
Glow = 0
AOStrength = 1
Samples = 50
Stratify = true
DebugInside = false
CentralDifferences = true
SampleNeighbors = true
Near = 0
Far = 5
ShowDepth = false
DebugNormals = false
Specular = 0.5208
SpecularExp = 20
SpotLight = 1,1,1,0.23529
SpotLightDir = -0.18518,-0.18518
CamLight = 1,1,1,0
CamLightMin = 0
Fog = 0
BaseColor = 1,1,1
OrbitStrength = 1
X = 0.333333,0,0,1
Y = 0.333333,0.333333,0,1
Z = 0.666667,0.333333,0,1
R = 1,1,1,0
BackgroundColor = 1,1,1
GradientBackground = 0.97825
CycleColors = false
Cycles = 14.0735
Iterations = 4
ColorIterations = 100
Power = 3
Bailout = 2
theta = 80
phi = 90
#endpreset
#preset Parrot
FOV = 0.5
Eye = 0.153051,0.144426,0.599367
Target = -0.758841,-1.3586,-2.21299
Up = 0.274098,0.953879,0.12241
EquiRectangular = false
Gamma = 1
ToneMapping = 1
Exposure = 1
Brightness = 1
Contrast = 1
Saturation = 1
NormalScale = 1
AOScale = 1
Glow = 0
AOStrength = 1
Samples = 50
Stratify = true
DebugInside = false
CentralDifferences = true
SampleNeighbors = true
Near = 0
Far = 5
ShowDepth = false
DebugNormals = false
Specular = 1
SpecularExp = 18
SpotLight = 1,1,1,0.25
SpotLightDir = 0.35802,0.50618
CamLight = 1,1,1,0
CamLightMin = 0
Fog = 0
BaseColor = 1,1,1
OrbitStrength = 0.8
X = 0.333333,0.666667,0.498039,1
Y = 1,0.666667,0,1
Z = 1,0,0,1
R = 1,1,1,0
BackgroundColor = 1,1,1
GradientBackground = 1.08695
CycleColors = false
Cycles = 1
Iterations = 60
ColorIterations = 99
Power = 1.1
Bailout = 2
theta = 40
phi = 250
#endpreset
#preset Fossil
FOV = 0.5
Eye = 0.907837,0.501134,1.85441
Target = -0.35304,-1.11791,-0.751134
Up = 0.76982,0.637907,0.0212406
EquiRectangular = false
Gamma = 1
ToneMapping = 1
Exposure = 1
Brightness = 1
Contrast = 1
Saturation = 1
NormalScale = 1
AOScale = 1
Glow = 0
AOStrength = 1
Samples = 50
Stratify = true
DebugInside = false
CentralDifferences = true
SampleNeighbors = true
Near = 0
Far = 5
ShowDepth = false
DebugNormals = false
Specular = 1
SpecularExp = 18
SpotLight = 1,1,1,0.25
SpotLightDir = 0.35802,0.50618
CamLight = 1,1,1,0
CamLightMin = 0
Fog = 0
BaseColor = 1,1,1
OrbitStrength = 0.8
X = 0.666667,0,0,1
Y = 0,0.666667,1,1
Z = 1,1,0.498039,1
R = 1,1,1,0
BackgroundColor = 1,1,1
GradientBackground = 1.08695
CycleColors = false
Cycles = 1
Iterations = 11
ColorIterations = 99
Power = 1.35
Bailout = 2
theta = 51.4278
phi = 129.229
#endpreset