渲染彩色的mandelbrot(并使它看起来不错)

时间:2019-01-30 04:41:06

标签: c++ math graphics colors mandelbrot

我正在尝试将Mandelbrot设置为彩色并使其看起来不错。我想复制image from the Wikipedia page。 Wikipedia图像还包括Ultra Fractal 3参数文件。

import pandas as pd
import xml.etree.ElementTree as ET
import os
from collections import defaultdict, OrderedDict

tree = ET.parse('PowerChange_76.xml')
root = tree.getroot()
df_list = []

for i, child in enumerate(root): 
    for subchildren in child.findall('{raml20.xsd}header'):
        for subchildren in child.findall('{raml20.xsd}managedObject'):
            match_found = 0
            xml_class_name = subchildren.get('class')
            xml_dist_name = subchildren.get('distName')
            print(xml_class_name)

            df_dict = OrderedDict()                   
            for subchild in subchildren:
                header = subchild.attrib.get('name')
                df_dict['Class'] = xml_class_name
                df_dict['CellDN'] = xml_dist_name
                df_dict[header]=subchild.text

            df_list.append(df_dict)
df_cm = pd.DataFrame(df_list) 

我一直试图解密该文件,并编写一个程序来重现Wikipedia图像。这是我的最佳尝试:

Mandelbrot set

这是渲染器的一部分。这有点混乱,因为我在摆弄并重写大量的块,试图弄清楚这个问题。

mandelZoom00MandelbrotSet {
fractal:
  title="mandel zoom 00 mandelbrot set" width=2560 height=1920 layers=1
  credits="WolfgangBeyer;8/21/2005"
layer:
  method=multipass caption="Background" opacity=100
mapping:
  center=-0.7/0 magn=1.3
formula:
  maxiter=50000 filename="Standard.ufm" entry="Mandelbrot" p_start=0/0
  p_power=2/0 p_bailout=10000
inside:
  transfer=none
outside:
  density=0.42 transfer=log filename="Standard.ucl" entry="Smooth"
  p_power=2/0 p_bailout=128.0
gradient:
  smooth=yes rotation=29 index=28 color=6555392 index=92 color=13331232
  index=196 color=16777197 index=285 color=43775 index=371 color=3146289
opacity:
  smooth=no index=0 opacity=255
}

using real = double; using integer = long long; struct complex { real r, i; }; using grey = unsigned char; struct color { grey r, g, b; }; struct real_color { real r, g, b; }; grey real_to_grey(real r) { // converting to srgb didn't help much return std::min(std::max(std::round(r), real(0.0)), real(255.0)); } color real_to_grey(real_color c) { return {real_to_grey(c.r), real_to_grey(c.g), real_to_grey(c.b)}; } real lerp(real a, real b, real t) { return std::min(std::max(t * (b - a) + a, real(0.0)), real(255.0)); } real_color lerp(real_color a, real_color b, real t) { return {lerp(a.r, b.r, t), lerp(a.g, b.g, t), lerp(a.b, b.b, t)}; } complex plus(complex a, complex b) { return {a.r + b.r, a.i + b.i}; } complex square(complex n) { return {n.r*n.r - n.i*n.i, real{2.0} * n.r * n.i}; } complex next(complex z, complex c) { return plus(square(z), c); } real magnitude2(complex n) { return n.r*n.r + n.i*n.i; } real magnitude(complex n) { return std::sqrt(magnitude2(n)); } color lerp(real_color a, real_color b, real t) { return real_to_grey(lerp(a, b, t)); } struct result { complex zn; integer n; }; result mandelbrot(complex c, integer iterations, real bailout) { complex z = {real{0.0}, real{0.0}}; integer n = 0; real bailout2 = bailout * bailout; for (; n < iterations && magnitude2(z) <= bailout2; ++n) { z = next(z, c); } return {z, n}; } struct table_row { real index; real_color color; }; real invlerp(real value, real min, real max) { return (value - min) / (max - min); } color lerp(table_row a, table_row b, real index) { return lerp(a.color, b.color, invlerp(index, a.index, b.index)); } color mandelbrot_color(complex c, integer iterations, real bailout) { const result res = mandelbrot(c, iterations, bailout); if (res.n == iterations) { // in the set return {0, 0, 0}; } else { table_row table[] = { // colors and indicies from gradient section {28.0*0.1, {0x00, 0x07, 0x64}}, {92.0*0.1, {0x20, 0x6B, 0xCB}}, {196.0*0.1, {0xED, 0xFF, 0xFF}}, {285.0*0.1, {0xFF, 0xAA, 0x00}}, {371.0*0.1, {0x31, 0x02, 0x30}}, // interpolate towards black as we approach points that are in the set {real(iterations), {0, 0, 0}} }; // it should be smooth, but it's not const real smooth = res.n + real{1.0} - std::log(std::log2(magnitude(res.zn))); // I know what a for-loop is, I promise if (smooth < table[1].index) { return lerp(table[0], table[1], smooth); } else if (table[1].index <= smooth && smooth < table[2].index) { return lerp(table[1], table[2], smooth); } else if (table[2].index <= smooth && smooth < table[3].index) { return lerp(table[2], table[3], smooth); } else if (table[3].index <= smooth && smooth < table[4].index) { return lerp(table[3], table[4], smooth); } else { return lerp(table[4], table[5], smooth); } } } 部分中的颜色在gradient中的表中。 mandelbrot_color部分的索引也在表中,但我将它们乘以gradient。如果我不乘以0.1,颜色就会完全消失。

0.1部分包含formulamaxiter=50000。它们是代码中的p_bailout=10000iterations。我不知道bailout是什么意思。我不知道为什么在p_start=0/0 p_power=2/0部分中提到了不同的纾困方案,而且我也不知道outsidedensity=0.42transfer=none的含义。 transfer=log部分还提到了gradient,但我不知道如何旋转渐变。

我问这个问题的原因是,我不喜欢图像周围的白色条纹(我更希望像Wikipedia图像中那样平滑而发光)。我也不喜欢由向黑色插值(rotation=29表中的最后一行)而导致的深紫色皮肤。如果删除该行,则最终将显示深蓝色的皮肤。

我怀疑从mandelbrot_color部分的索引到迭代计数有某种映射。也许gradient是该映射的近似值,该映射有时会起作用。可能与* 0.1transferdensity有关。如果您希望我发布整个程序,请发表评论。它取决于rotation(单个标头图像编写库)。

作为旁注,我已经清理了这段代码并将其放入片段着色器中,它(通常来说)可能比在CPU上运行多线程更快吗?

0 个答案:

没有答案