Slightly altered MandelBox

  • 0 Replies
  • 81 Views

0 Members and 1 Guest are viewing this topic.

Offline kosalos

  • *
  • Fractal Friend
  • **
  • Posts: 14
« on: October 03, 2018, 07:15:22 AM »
Bet you guys tried this idea years ago, but it is new to me, and it has some beautiful effects:
While doing the ray marching Distance Estimation for a Mandelbox,
alter the Box and Sphere fold values every time through the loop,
and for more control, also alter the delta fold values themselves every time through the loop.

Here's the relevant portions of my iPad app:

typedef struct {
    vector_float3 position;     // 0.01 ... 1
    float diffuse;              // 0.01 ... 1
    float specular;             // 0.01 ... 1
} Lighting;

typedef struct {
    vector_float3 camera;       // -10 ... 10
    vector_float3 focus;        // -10 ... 10
    vector_float3 viewVector,topVector,sideVector; // calculated by CPU before shader call
    float deFactor1,deFactor2;

    float zoom;                 // 0.2 ... 2
    float scaleFactor;          // -5 ... 5
    float epsilon;              // 0.00001 ... 0.005
   
    bool isJulia;               // Julia mode enbled?
    vector_float3 julia;        // -10 ... 10
   
    vector_float3 sphere;       // 0 ... 2
    float sphereMult;           // 0.1 ... 6
    vector_float3 box;          // 0.5 ... 2.5
   
    vector_float3 color;        // 0 ... 0.5
    Lighting lighting;
   
    bool isBurningShip;         // alternate MandelBox equation?
    float fog;                  // 0.7 ... 2
   
    vector_float3 dBox;         // 0.1 ... 2   alter box,sphere during DE iterations
    vector_float3 dSphere;
    vector_float3 ddBox;        // 0.1 ... 2   alter dBox,dSsphere
    vector_float3 ddSphere;
}  Control;

// ---------------------------------------------------------------------
// calculate before Shader call:

func toRectangular(_ sph:float3) -> float3 { let ss = sph.x * sin(sph.z); return float3( ss * cos(sph.y), ss * sin(sph.y), sph.x * cos(sph.z)) }
func toSpherical(_ rec:float3) -> float3 { return float3(length(rec), atan2(rec.y,rec.x), atan2(sqrt(rec.x*rec.x+rec.y*rec.y), rec.z)) }

c.viewVector = c.focus - c.camera
c.topVector = toSpherical(c.viewVector)
c.topVector.z += 1.5708
c.topVector = toRectangular(c.topVector)
c.sideVector = cross(c.viewVector,c.topVector)
c.sideVector = normalize(c.sideVector) * length(c.topVector)

c.deFactor1 = abs(c.scaleFactor - 1.0);
c.deFactor2 = pow( Float(abs(c.scaleFactor)), Float(1 - 10));

// ---------------------------------------------------------------------

constant int MAX_ITERS = 10;
constant int MAX_STEPS = 150;

float DE    // distance estimate
(
 float3 position,
 constant Control &control)
{
    float3 c = control.isJulia ? control.julia : position;
    float3 v = position;
    float dr = 1.5;
   
    Control cc = control;
   
    for (int i = 0; i < MAX_ITERS; i++) {
        v = clamp(v, -cc.box.x, cc.box.x) * cc.box.y - v;
        if(control.isBurningShip) v = -abs(v);
       
        float mag = dot(v, v);
        if(mag < cc.sphere.x) {
            v = v * control.sphereMult;
            dr = dr * control.sphereMult;
        }
        else if (mag < cc.sphere.y) {
            v = v / mag;
            dr = dr / mag;
        }
       
        v = v * control.scaleFactor + c;
        dr = dr * abs(control.scaleFactor) + 1.0;
       
        cc.box *= cc.dBox;
        cc.sphere *= cc.dSphere;
       
        cc.dBox *= cc.ddBox;
        cc.dSphere *= cc.ddSphere;
    }
   
    return (length(v) - control.deFactor1) / dr - control.deFactor2;
}

//MARK: -

float3 getNormal
(
 float3 position,
 constant Control &control)
{
    float4 eps = float4(0, control.epsilon, 2.0 * control.epsilon, 3.0 * control.epsilon);
    return normalize(float3(-DE(position - eps.yxx,control) + DE(position + eps.yxx,control),
                            -DE(position - eps.xyx,control) + DE(position + eps.xyx,control),
                            -DE(position - eps.xxy,control) + DE(position + eps.xxy,control)));
}

//MARK: -

float3 lighting
(
 float3 position,
 float distance,
 constant Control &control)
{
    float3 normal = getNormal(position,control);
    float3 color = normal * control.color;
   
    float3 L = normalize(control.lighting.position - position);
    float dotLN = dot(L, normal);
    if(dotLN >= 0) {
        color += control.lighting.diffuse * dotLN;
       
        float3 V = normalize(float3(distance));
        float3 R = normalize(reflect(-L, normal));
        float dotRV = dot(R, V);
        if(dotRV >= 0) color += control.lighting.specular * pow(dotRV, 2);
    }
   
    return color;
}

//MARK: -

float3 rayMarch
(
 float3 rayDir,
 constant Control &control)
{
    float de,distance = 0.0;
    float3 position;
    float ff = pow(control.fog,4);
   
    for(int i = 0; i < MAX_STEPS; ++i) {
        position = control.camera + rayDir * distance;
       
        de = DE(position, control);
        if(de < control.epsilon) break;
       
        distance += de;
        if(distance > ff) return float3();
    }
   
    float3 color = lighting(position,distance,control);
   
    color *= (1 - distance / ff);
    return color;
}

//MARK: -

kernel void mandelBoxShader
(
 texture2d<float, access::write> outTexture [[texture(0)]],
 constant Control &control [[buffer(0)]],
 uint2 p [[thread_position_in_grid]])
{
    if(p.x > uint(control.xSize) || p.y > uint(control.ySize)) return;
    uint2 srcP = p;
   
    float den = float(control.xSize);
    float dx =  control.zoom * (float(srcP.x)/den - 0.5);
    float dy = -control.zoom * (float(srcP.y)/den - 0.5);
   
    float3 direction = normalize((control.sideVector * dx) + (control.topVector * dy) + control.viewVector);
   
    outTexture.write(float4(rayMarch(direction,control),1),p);
}

------------------------
Here's the project on Github:  https://github.com/Kosalos/MandelBox2



xx
mandelbox

Started by mclarekin on Fractal Image Gallery

0 Replies
28 Views
Last post October 10, 2018, 08:42:33 AM
by mclarekin
xx
MandelBox Tango

Started by gurroa on Fractal movie gallery

0 Replies
111 Views
Last post December 28, 2017, 03:33:57 PM
by gurroa
xx
Mandelbox Meanderings M302

Started by mclarekin on Fractal Image Gallery

0 Replies
92 Views
Last post November 16, 2017, 08:15:32 AM
by mclarekin
xx
Gears n' Dice Mandelbox

Started by greentexas on Share a fractal

1 Replies
276 Views
Last post September 12, 2017, 10:59:33 PM
by WAUthethird
xx
Mandelbox Meanderings M300

Started by mclarekin on Fractal Image Gallery

0 Replies
101 Views
Last post September 28, 2017, 01:12:40 PM
by mclarekin