buddhi1980 / mandelbulber2

Official repository for Mandelbulber v2
GNU General Public License v3.0
909 stars 115 forks source link

custom formulas part2 #794

Open mclarekin opened 4 years ago

mclarekin commented 4 years ago

a) implement choose different DE function and method for boolean mode slots b) ability to write inline functions

buddhi1980 commented 4 years ago

ad a) it need to be implemented ad b) You can write inline functions. Example, where I defined absolute() function just before formula code:

/**
 * Mandelbulber v2, a 3D fractal generator  _%}}i*<.        ____                _______
 * Copyright (C) 2019 Mandelbulber Team   _>]|=||i=i<,     / __ \___  ___ ___  / ___/ /
 *                                        \><||i|=>>%)    / /_/ / _ \/ -_) _ \/ /__/ /__
 * This file is part of Mandelbulber.     )<=i=]=|=i<>    \____/ .__/\__/_//_/\___/____/
 * The project is licensed under GPLv3,   -<>>=|><|||`        /_/
 * see also COPYING file in this folder.    ~+{i%+++
 *
 * Menger Sponge formula created by Knighty
 * @reference
 * http://www.fractalforums.com/ifs-iterated-function-systems/kaleidoscopic-(escape-time-ifs)/

 * This file has been autogenerated by tools/populateUiInformation.php
 * from the file "fractal_menger_sponge.cpp" in the folder formula/definition
 * F E E L   F R E E    T O    E D I T    T H I S    F I L E !
 */

float4 absolute(float4 in)
{
    float4 out;
    out.x = fabs(in.x);
    out.y = fabs(in.y);
    out.z = fabs(in.z);
    out.w = fabs(in.w);
    return out;
}

REAL4 CustomIteration(REAL4 z, __constant sFractalCl *fractal, sExtendedAuxCl *aux)
{
    z = absolute(z);

    if (z.x - z.y < 0.0f)
    {
        REAL temp = z.x;
        z.x = z.y;
        z.y = temp;
    }
    if (z.x - z.z < 0.0f)
    {
        REAL temp = z.x;
        z.x = z.z;
        z.z = temp;
    }
    if (z.y - z.z < 0.0f)
    {
        REAL temp = z.y;
        z.y = z.z;
        z.z = temp;
    }

    z *= fractal->transformCommon.scale3;

    z.x -= 2.0f;
    z.y -= 2.0f;
    if (z.z > 1.0f) z.z -= 2.0f;

    aux->DE *= fractal->transformCommon.scale3;
    return z;
}
mclarekin commented 4 years ago

b) can i bring a parameter or an aux. into the inline function (i tried but failed)

mclarekin commented 4 years ago

I tried harder and could bring the parameter in :) so that is OK question is it possible to have inlines in the c++ setup?

buddhi1980 commented 4 years ago

You can use any parameters. See this example where I moved SphericalFold to separate function. It has several paremeters: z, r2, fractal and aux.

/**
 * Mandelbulber v2, a 3D fractal generator  _%}}i*<.        ____                _______
 * Copyright (C) 2020 Mandelbulber Team   _>]|=||i=i<,     / __ \___  ___ ___  / ___/ /
 *                                        \><||i|=>>%)    / /_/ / _ \/ -_) _ \/ /__/ /__
 * This file is part of Mandelbulber.     )<=i=]=|=i<>    \____/ .__/\__/_//_/\___/____/
 * The project is licensed under GPLv3,   -<>>=|><|||`        /_/
 * see also COPYING file in this folder.    ~+{i%+++
 *
 * Mandelbox fractal known as AmazingBox or ABox, invented by Tom Lowe in 2010
 * @reference
 * http://www.fractalforums.com/ifs-iterated-function-systems/amazing-fractal/msg12467/#msg12467
 * This formula contains aux.color

 * This file has been autogenerated by tools/populateUiInformation.php
 * from the file "fractal_mandelbox.cpp" in the folder formula/definition
 * F E E L   F R E E    T O    E D I T    T H I S    F I L E !
 */

REAL4 SphericalFold(REAL4 z, REAL r2, __constant sFractalCl *fractal, sExtendedAuxCl *aux)
{
    if (r2 < fractal->mandelbox.mR2)
    {
        z *= fractal->mandelbox.mboxFactor1;
        aux->DE *= fractal->mandelbox.mboxFactor1;
        aux->color += fractal->mandelbox.color.factorSp1;
    }
    else if (r2 < fractal->mandelbox.fR2)
    {
        REAL tglad_factor2 = fractal->mandelbox.fR2 / r2;
        z *= tglad_factor2;
        aux->DE *= tglad_factor2;
        aux->color += fractal->mandelbox.color.factorSp2;
    }
    return z;
}

REAL4 CustomIteration(REAL4 z, __constant sFractalCl *fractal, sExtendedAuxCl *aux)
{
    if (fractal->mandelbox.rotationsEnabled)
    {
        REAL4 zRot;
        // cast vector to array pointer for address taking of components in opencl
        REAL *zRotP = (REAL *)&zRot;
        __constant REAL *colP = (__constant REAL *)&fractal->mandelbox.color.factor;
        for (int dim = 0; dim < 3; dim++)
        {
            // handle each dimension x, y and z sequentially in pointer var dim
            REAL *rotDim = (dim == 0) ? &zRotP[0] : ((dim == 1) ? &zRotP[1] : &zRotP[2]);
            __constant REAL *colorFactor = (dim == 0) ? &colP[0] : ((dim == 1) ? &colP[1] : &colP[2]);

            zRot = Matrix33MulFloat4(fractal->mandelbox.rot[0][dim], z);
            if (*rotDim > fractal->mandelbox.foldingLimit)
            {
                *rotDim = fractal->mandelbox.foldingValue - *rotDim;
                z = Matrix33MulFloat4(fractal->mandelbox.rotinv[0][dim], zRot);
                aux->color += *colorFactor;
            }
            else
            {
                zRot = Matrix33MulFloat4(fractal->mandelbox.rot[1][dim], z);
                if (*rotDim < -fractal->mandelbox.foldingLimit)
                {
                    *rotDim = -fractal->mandelbox.foldingValue - *rotDim;
                    z = Matrix33MulFloat4(fractal->mandelbox.rotinv[1][dim], zRot);
                    aux->color += *colorFactor;
                }
            }
        }
    }
    else
    {
        if (fabs(z.x) > fractal->mandelbox.foldingLimit)
        {
            z.x = sign(z.x) * fractal->mandelbox.foldingValue - z.x;
            aux->color += fractal->mandelbox.color.factor.x;
        }
        if (fabs(z.y) > fractal->mandelbox.foldingLimit)
        {
            z.y = sign(z.y) * fractal->mandelbox.foldingValue - z.y;
            aux->color += fractal->mandelbox.color.factor.y;
        }
        if (fabs(z.z) > fractal->mandelbox.foldingLimit)
        {
            z.z = sign(z.z) * fractal->mandelbox.foldingValue - z.z;
            aux->color += fractal->mandelbox.color.factor.z;
        }
    }

    REAL r2 = dot(z, z);

    z += fractal->mandelbox.offset;

    z = SphericalFold(z, r2, fractal, aux);

    z -= fractal->mandelbox.offset;

    if (fractal->mandelbox.mainRotationEnabled) z = Matrix33MulFloat4(fractal->mandelbox.mainRot, z);

    z = z * fractal->mandelbox.scale;
    aux->DE = aux->DE * fabs(fractal->mandelbox.scale) + 1.0f;
    return z;
}
buddhi1980 commented 4 years ago

In C++ code you can do the same. You only need to create functions with unique names.

mclarekin commented 4 years ago

That is great news, as i have implemented some fractals laterly that will benefit by this method, as my current code is repeating the same calculation (i will try it out) and i did not want to add a lot to void sFractal::RecalculateFractalParams() for calculations that are only used by one formula

mclarekin commented 4 years ago

Ignore last thing i wrote as i was confusing myself

i can shorten the code a lot for some fractal if i use inline e.g mandalays where same function is written six times

but i could use void sFractal::RecalculateFractalParams() for this T>DIFS polyhedra // this block does not use z so could be a precalc REAL cospin = M_PI / (REAL)(Type); cospin = cos(cospin); REAL scospin = sqrt(0.75 - cospin * cospin); REAL4 nc = (REAL4)(-0.5, -cospin, scospin, 0.0); REAL4 pab = (REAL4)(0.0, 0.0, 1.0, 0.0); REAL4 pbc = normalize((REAL4)(scospin, 0.0, 0.5, 0.0)); REAL4 pca = normalize((REAL4)(0.0, scospin, cospin, 0.0));

currently i am repeating this calc for every point, with a constant input "Type" however the complete formula is fast so maybe not clutter up void sFractal::RecalculateFractalParams() by putting it there

mclarekin commented 3 years ago

c) add aux-> options to drop down menu

mclarekin commented 2 years ago

d) allow int to have negative value

mclarekin commented 1 year ago

e) editable parameter names