Slightly altered MandelBox

  • 0 Replies
  • 201 Views

0 Members and 1 Guest are viewing this topic.

Offline kosalos

  • *
  • Fractal Friend
  • **
  • Posts: 16
« 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
45 Views
Last post October 10, 2018, 08:42:33 AM
by mclarekin
xx
MandelBox Tango

Started by gurroa on Fractal movie gallery

0 Replies
124 Views
Last post December 28, 2017, 03:33:57 PM
by gurroa
clip
MandelBox 3D display

Started by kosalos on Fractal Image Gallery

0 Replies
23 Views
Last post November 30, 2018, 02:02:02 AM
by kosalos
xx
Mandelbox Negative Scale

Started by Sabine62 on Fractal Image Gallery

1 Replies
43 Views
Last post November 03, 2018, 04:56:40 PM
by Sabine62
xx
Gears n' Dice Mandelbox

Started by greentexas on Share a fractal

1 Replies
291 Views
Last post September 12, 2017, 10:59:33 PM
by WAUthethird