Mandelbrot Set渲染的平滑光谱

Nic*_*son 30 algorithm colors fractals mandelbrot

我目前正在编写一个程序来生成真正巨大的(65536x65536像素及以上)Mandelbrot图像,我想设计一种能够正义的光谱和着色方案.在维基百科特色的Mandelbrot图像似乎是一个很好的例子,调色板尤其是如何保持在序列中的所有缩放级别变化.不过,我不确定它是在旋转调色板还是做其他一些技巧来实现这一点.

我熟悉mandelbrot集的平滑着色算法,所以我可以避免使用条带,但我仍然需要一种方法来为此算法的输出值指定颜色.

我正在生成的图像是金字塔形的(例如,一系列图像,每个图像的尺寸都是前一个图像的一半),所以我可以使用某种旋转调色板,只要调色板之间的变化即可缩放级别不是太明显.

Per*_*son 32

这是平滑的颜色算法:

让我们说你从复数开始,z0迭代n次数直到它逃脱.让终点是zn.

一个平滑的价值

nsmooth := n + 1 - Math.log(Math.log(zn.abs()))/Math.log(2)
Run Code Online (Sandbox Code Playgroud)

这仅适用于mandelbrot,如果你想为julia集计算平滑函数,那么使用

Complex z = new Complex(x,y);
double smoothcolor = Math.exp(-z.abs());

for(i=0;i<max_iter && z.abs() < 30;i++) {
    z = f(z);
    smoothcolor += Math.exp(-z.abs());
}
Run Code Online (Sandbox Code Playgroud)

然后smoothcolor是在间隔(0,max_iter).

smoothcolormax_iter得到0和1之间的一个数值.

要从值中获得平滑的颜色:

这可以被调用,例如(在Java中):

Color.HSBtoRGB(0.95f + 10 * smoothcolor ,0.6f,1.0f);
Run Code Online (Sandbox Code Playgroud)

因为HSB颜色参数中的第一个值用于定义色环的颜色.

  • 感谢Julia Set光滑的颜色配方,在https://www.shadertoy.com/view/XssXDr中使用它 (8认同)

Spa*_*arr 5

使用平滑着色算法计算视口中的所有值,然后将调色板从最低值映射到最高值.因此,当您放大并且较高的值不再可见时,调色板也会缩小.对于n和B使用相同的常量,对于完全缩小的集合,最终会得到0.0到1.0的范围,但是在更深的缩放处,动态范围将缩小,例如在200%缩放时为0.0到0.1,0.0到0.0001 at 20000%变焦等


小智 5

这是一个天真的Mandelbrot发电机的典型内环.要获得平滑的颜色,您需要传递真实和复杂的"长度"以及您提供的迭代.我已经包含了Mandelbrot代码,因此您可以查看用于计算颜色的变量.

for (ix = 0; ix < panelMain.Width; ix++)
    {
    cx = cxMin + (double )ix * pixelWidth;
    // init this go 
    zx = 0.0;
    zy = 0.0;
    zx2 = 0.0;
    zy2 = 0.0;
    for (i = 0; i < iterationMax && ((zx2 + zy2) < er2); i++)
        {
        zy = zx * zy * 2.0 + cy;
        zx = zx2 - zy2 + cx;
        zx2 = zx * zx;
        zy2 = zy * zy;
        }
    if (i == iterationMax)
        {
        // interior, part of set, black
        // set colour to black
        g.FillRectangle(sbBlack, ix, iy, 1, 1);
        }
    else
        {
        // outside, set colour proportional to time/distance it took to converge
        // set colour not black
        SolidBrush sbNeato = new SolidBrush(MapColor(i, zx2, zy2));
        g.FillRectangle(sbNeato, ix, iy, 1, 1);
        }
Run Code Online (Sandbox Code Playgroud)

和MapColor如下:(请参阅此链接以获取ColorFromHSV函数)

 private Color MapColor(int i, double r, double c)
                {
                double di=(double )i;
                double zn;
                double hue;

                    zn = Math.Sqrt(r + c);
                    hue = di + 1.0 - Math.Log(Math.Log(Math.Abs(zn))) / Math.Log(2.0);  // 2 is escape radius
                    hue = 0.95 + 20.0 * hue; // adjust to make it prettier
                    // the hsv function expects values from 0 to 360
                    while (hue > 360.0)
                        hue -= 360.0;
                    while (hue < 0.0)
                        hue += 360.0;

                    return ColorFromHSV(hue, 0.8, 1.0);
                }
Run Code Online (Sandbox Code Playgroud)

MapColour正在"平滑"从0到1的救助值,然后可以用来映射颜色而不会出现可怕的条带.使用MapColour和/或hsv函数可以改变使用的颜色.


Nic*_*son 4

我最终的解决方案是创建一个美观(且相当大)的调色板,并将其作为常量数组存储在源中,然后使用平滑着色算法在其中的索引之间进行插值。调色板环绕(并且设计为连续的),但这似乎并不重要。