Nicolas Winkler před 6 roky
rodič
revize
343d925877

+ 9 - 3
Almond.cpp

@@ -4,6 +4,7 @@
 #include <QMessageBox>
 #include <QGradient>
 #include "benchmarkdialog.h"
+#include "gradientchoosedialog.h"
 
 #include <cmath>
 
@@ -34,11 +35,13 @@ void Almond::on_pushButton_clicked()
         mi.bWidth = dialog.getWidth();
         mi.bHeight = dialog.getHeight();
         mi.view.adjustAspectRatio(mi.bWidth, mi.bHeight);
-        mnd::Generator& g = mandelContext.getDefaultGenerator();
+        mnd::Generator& g = mandelContext.getCpuGeneratorFloat();
         auto fmap = Bitmap<float>(mi.bWidth, mi.bHeight);
         g.generate(mi, fmap.pixels.get());
-        auto bitmap = fmap.map<RGBColor>([](float i) { return i < 0 ? RGBColor{ 0,0,0 } : RGBColor{ uint8_t(cos(i * 0.015f) * 127 + 127), uint8_t(sin(i * 0.01f) * 127 + 127), uint8_t(i) }; });//uint8_t(::sin(i * 0.01f) * 100 + 100), uint8_t(i) }; });
-        QImage img((unsigned char*)bitmap.pixels.get(), bitmap.width, bitmap.height, bitmap.width * 3, QImage::Format_RGB888);
+        auto bitmap = fmap.map<RGBColor>([&mi, this] (float i) {
+            return i >= mi.maxIter ? RGBColor{ 0,0,0 } : mw->getGradient().get(i);
+        });
+        QImage img((unsigned char*) bitmap.pixels.get(), bitmap.width, bitmap.height, bitmap.width * 3, QImage::Format_RGB888);
         img.save(dialog.getPath());
     }
 }
@@ -71,6 +74,8 @@ void Almond::on_maxIterations_editingFinished()
 void Almond::on_chooseGradient_clicked()
 {
     QGradient qg;
+    GradientChooseDialog gcd;
+    auto response = gcd.exec();
 }
 
 void Almond::on_exportVideo_clicked()
@@ -78,6 +83,7 @@ void Almond::on_exportVideo_clicked()
     ExportVideoInfo evi;
     evi.start = mnd::MandelViewport::standardView();
     evi.end = mw->getViewport();
+    evi.gradient = mw->getGradient();
     ExportVideoDialog dialog(this, evi);
     //dialog.show();
     auto response = dialog.exec();

+ 8 - 3
Almond.pro

@@ -4,7 +4,7 @@
 #
 #-------------------------------------------------
 
-QT       += core gui opengl
+QT       += core gui opengl xml
 
 greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
 
@@ -28,30 +28,35 @@ CONFIG += c++17
 SOURCES += \
         Almond.cpp \
         Bitmap.cpp \
+        Gradient.cpp \
         MandelVideoGenerator.cpp \
         MandelWidget.cpp \
         SectionManager.cpp \
         VideoStream.cpp \
         benchmarkdialog.cpp \
         exportdialogs.cpp \
+        gradientchoosedialog.cpp \
         main.cpp
 
 HEADERS += \
         Almond.h \
         Bitmap.h \
         Color.h \
+        Gradient.h \
         MandelVideoGenerator.h \
         MandelWidget.h \
         SectionManager.h \
         VideoStream.h \
         benchmarkdialog.h \
-        exportdialogs.h
+        exportdialogs.h \
+        gradientchoosedialog.h
 
 FORMS += \
         Almond.ui \
         benchmarks.ui \
         exportimagedialog.ui \
-        exportvideodialog.ui
+        exportvideodialog.ui \
+        gradientchooser.ui
 
 
 # Default rules for deployment.

+ 165 - 0
Gradient.cpp

@@ -0,0 +1,165 @@
+#include "Gradient.h"
+
+Gradient::Gradient()
+{
+    //addColor(RGBColor{255, 0, 0}, -100);
+    addColor(RGBColor{0, 0, 0}, 0);
+    addColor(RGBColor{ 37, 116, 153 }, 40);
+    addColor(RGBColor{ 69, 185, 225 }, 104);
+    addColor(RGBColor{ 171, 89, 117 }, 190);
+    addColor(RGBColor{ 102, 127, 46 }, 295);
+    addColor(RGBColor{ 36, 155, 169 }, 418);
+    addColor(RGBColor{ 233, 33, 79 }, 558);
+    addColor(RGBColor{ 254, 169, 63 }, 714);
+    addColor(RGBColor{ 227, 93, 201 }, 885);
+    addColor(RGBColor{ 188, 24, 161 }, 1071);
+    addColor(RGBColor{ 45, 225, 44 }, 1271);
+    addColor(RGBColor{ 52, 58, 250 }, 1485);
+    addColor(RGBColor{ 87, 93, 241 }, 1712);
+    addColor(RGBColor{ 6, 37, 208 }, 1952);
+    addColor(RGBColor{ 193, 164, 162 }, 2205);
+    addColor(RGBColor{ 49, 8, 90 }, 2471);
+    addColor(RGBColor{ 124, 149, 120 }, 2749);
+    addColor(RGBColor{ 56, 69, 6 }, 3039);
+    addColor(RGBColor{ 231, 177, 252 }, 3341);
+    addColor(RGBColor{ 36, 76, 95 }, 3655);
+    addColor(RGBColor{ 1, 99, 184 }, 3980);
+    addColor(RGBColor{ 74, 223, 199 }, 4316);
+    addColor(RGBColor{ 249, 125, 31 }, 4664);
+    addColor(RGBColor{ 28, 93, 214 }, 5023);
+    addColor(RGBColor{ 232, 117, 145 }, 5393);
+    addColor(RGBColor{ 208, 158, 49 }, 5773);
+    addColor(RGBColor{ 218, 109, 177 }, 6164);
+    addColor(RGBColor{ 139, 83, 177 }, 6565);
+    addColor(RGBColor{ 16, 36, 59 }, 6977);
+    addColor(RGBColor{ 194, 157, 26 }, 7399);
+    addColor(RGBColor{ 77, 236, 12 }, 7831);
+    addColor(RGBColor{ 124, 244, 151 }, 8273);
+    addColor(RGBColor{ 128, 195, 162 }, 8725);
+    addColor(RGBColor{ 66, 36, 194 }, 9187);
+    addColor(RGBColor{ 81, 151, 185 }, 9659);
+    addColor(RGBColor{ 173, 75, 175 }, 10140);
+    addColor(RGBColor{ 43, 182, 52 }, 10631);
+    addColor(RGBColor{ 14, 242, 141 }, 11131);
+    addColor(RGBColor{ 156, 203, 87 }, 11641);
+    addColor(RGBColor{ 147, 89, 150 }, 12160);
+    addColor(RGBColor{ 213, 199, 183 }, 12689);
+    addColor(RGBColor{ 186, 255, 52 }, 13227);
+    addColor(RGBColor{ 28, 158, 154 }, 13774);
+    addColor(RGBColor{ 5, 5, 116 }, 14330);
+    addColor(RGBColor{ 126, 123, 232 }, 14895);
+    addColor(RGBColor{ 43, 162, 251 }, 15469);
+    addColor(RGBColor{ 198, 143, 125 }, 16052);
+    addColor(RGBColor{ 201, 157, 178 }, 16644);
+    addColor(RGBColor{ 213, 151, 189 }, 17245);
+    addColor(RGBColor{ 188, 117, 169 }, 17854);
+    addColor(RGBColor{ 156, 189, 249 }, 18472);
+    addColor(RGBColor{ 62, 23, 33 }, 19099);
+    addColor(RGBColor{ 167, 205, 74 }, 19734);
+    addColor(RGBColor{ 161, 181, 210 }, 20378);
+    addColor(RGBColor{ 179, 167, 215 }, 21030);
+    addColor(RGBColor{ 204, 102, 126 }, 21691);
+    addColor(RGBColor{ 123, 49, 127 }, 22360);
+    addColor(RGBColor{ 178, 48, 136 }, 23037);
+    addColor(RGBColor{ 108, 112, 99 }, 23723);
+    addColor(RGBColor{ 250, 152, 78 }, 24417);
+    addColor(RGBColor{ 79, 167, 196 }, 25119);
+    addColor(RGBColor{ 149, 167, 8 }, 25829);
+    addColor(RGBColor{ 196, 29, 159 }, 26548);
+    addColor(RGBColor{ 128, 26, 20 }, 27275);
+    addColor(RGBColor{ 69, 49, 66 }, 28010);
+    addColor(RGBColor{ 12, 42, 198 }, 28753);
+    addColor(RGBColor{ 61, 62, 36 }, 29504);
+    addColor(RGBColor{ 27, 94, 114 }, 30263);
+    addColor(RGBColor{ 54, 218, 7 }, 31030);
+    addColor(RGBColor{ 105, 89, 170 }, 31804);
+    addColor(RGBColor{ 100, 110, 2 }, 32586);
+    addColor(RGBColor{ 208, 198, 148 }, 33376);
+    addColor(RGBColor{ 80, 208, 131 }, 34174);
+    addColor(RGBColor{ 176, 89, 59 }, 34980);
+    addColor(RGBColor{ 255, 64, 243 }, 35793);
+    addColor(RGBColor{ 39, 226, 232 }, 36614);
+    addColor(RGBColor{ 154, 100, 238 }, 37443);
+    addColor(RGBColor{ 53, 103, 192 }, 38279);
+    addColor(RGBColor{ 187, 41, 136 }, 39123);
+    addColor(RGBColor{ 33, 84, 227 }, 39974);
+    addColor(RGBColor{ 71, 167, 211 }, 40833);
+    addColor(RGBColor{ 55, 191, 255 }, 41699);
+    addColor(RGBColor{ 60, 165, 201 }, 42573);
+    addColor(RGBColor{ 231, 206, 192 }, 43454);
+    addColor(RGBColor{ 233, 224, 197 }, 44343);
+    addColor(RGBColor{ 255, 129, 13 }, 45239);
+    addColor(RGBColor{ 131, 222, 95 }, 46143);
+    addColor(RGBColor{ 155, 249, 72 }, 47054);
+    addColor(RGBColor{ 248, 129, 30 }, 47972);
+    addColor(RGBColor{ 48, 239, 206 }, 48898);
+    addColor(RGBColor{ 176, 224, 64 }, 49831);
+    addColor(RGBColor{ 155, 12, 162 }, 50771);
+    addColor(RGBColor{ 6, 144, 149 }, 51718);
+    addColor(RGBColor{ 231, 208, 16 }, 52672);
+    addColor(RGBColor{ 190, 66, 231 }, 53634);
+    addColor(RGBColor{ 19, 17, 253 }, 54603);
+    addColor(RGBColor{ 4, 34, 60 }, 55579);
+    addColor(RGBColor{ 101, 23, 88 }, 56562);
+    addColor(RGBColor{ 9, 191, 235 }, 57552);
+
+
+    max = 10000;
+    //addColor(RGBColor{255, 0, 255}, 1000000000.0f);
+}
+
+void Gradient::addColor(RGBColor c, float value)
+{
+    //colors.push_back({ c, value }); return;
+    for (std::vector<std::pair<RGBColor, float>>::iterator it = colors.begin();
+         it != colors.end(); ++it) {
+        if (it->second > value) {
+            colors.insert(it, { c, value });
+            return;
+        }
+    }
+    colors.push_back({ c, value });
+}
+
+RGBColor Gradient::get(float x) const
+{
+    /*while(x >= max) {
+        if (x < 2 * max)
+            x = 2 * max - x;
+        else
+            x -= max;
+    }*/
+    if (colors.empty())
+        return RGBColor();
+    const auto [left, right, lerp] = getNeighbors(x);
+    RGBColor lerped = lerpColors(left, right, lerp);
+    return lerped;
+    //RGBColor lerped = lerpColors(RGBColor{0, 0, 0}, RGBColor{255, 255, 255}, x / 2000.0f);
+    //printf("rgb: %d, %d, %d\n", left.r, left.g, left.b);
+    return RGBColor{uint8_t(::sin(x * 0.1) * 127 + 127), 0, 0};
+}
+
+RGBColor Gradient::lerpColors(RGBColor a, RGBColor b, float val)
+{
+    return RGBColor{
+        uint8_t(b.r * val + a.r * (1 - val)),
+        uint8_t(b.g * val + a.g * (1 - val)),
+        uint8_t(b.b * val + a.b * (1 - val))
+    };
+}
+
+std::tuple<RGBColor, RGBColor, float> Gradient::getNeighbors(float x) const
+{
+    for (auto it = colors.begin(); it != colors.end(); ++it) {
+        if (it->second > x) {
+            if (it == colors.begin()) {
+                return { it->first, it->first, 0 };
+            }
+            else {
+                float lerp = (x - (it - 1)->second) / (it->second - (it - 1)->second);
+                return { (it - 1)->first, it->first, lerp };
+            }
+        }
+    }
+    return { (colors.end() - 1)->first, (colors.end() - 1)->first, 0 };
+}

+ 24 - 0
Gradient.h

@@ -0,0 +1,24 @@
+#ifndef GRADIENT_H
+#define GRADIENT_H
+
+#include <vector>
+#include "Color.h"
+
+
+class Gradient
+{
+    std::vector<std::pair<RGBColor, float>> colors;
+    float max;
+public:
+    Gradient();
+
+    void addColor(RGBColor c, float value);
+
+    RGBColor get(float x) const;
+
+private:
+    static RGBColor lerpColors(RGBColor a, RGBColor b, float val);
+    std::tuple<RGBColor, RGBColor, float> getNeighbors(float x) const;
+};
+
+#endif // GRADIENT_H

+ 2 - 2
MandelVideoGenerator.cpp

@@ -36,8 +36,8 @@ void MandelVideoGenerator::generate(void)
         if (bigW > 2 * w) {
             Bitmap<float> raw{ evi.width * 2, evi.height * 2 };
             gen.generate(mi, raw.pixels.get());
-            big = raw.map<RGBColor>([] (float x) { return
-                RGBColor{ uint8_t(::sin(x / 100) * 127 + 127), uint8_t(::sin(x / 213) * 127 + 127), uint8_t(::cos(x / 173) * 127 + 127) };
+            big = raw.map<RGBColor>([&mi, this] (float i) {
+                return i >= mi.maxIter ? RGBColor{ 0,0,0 } : evi.gradient.get(i);
             });
             /*mi.view.zoomCenter(0.5);
             gen.generate(mi, raw.pixels.get());

+ 2 - 0
MandelVideoGenerator.h

@@ -2,12 +2,14 @@
 #define MANDELVIDEOGENERATOR_H
 
 #include "Mandel.h"
+#include "Gradient.h"
 #include "Bitmap.h"
 
 struct ExportVideoInfo
 {
     mnd::MandelViewport start;
     mnd::MandelViewport end;
+    Gradient gradient;
 
     int width;
     int height;

+ 10 - 6
MandelWidget.cpp

@@ -88,8 +88,9 @@ void Texture::drawRect(float x, float y, float width, float height)
 }
 
 
-MandelView::MandelView(mnd::Generator& generator, MandelWidget* mWidget) :
+MandelView::MandelView(mnd::Generator& generator, Gradient &gradient, MandelWidget* mWidget) :
     generator{ &generator },
+    gradient{ gradient },
     mWidget{ mWidget }
     //context{ new QOpenGLContext(this) }
 {
@@ -144,12 +145,15 @@ void MandelView::loop(void)
             const MandelInfo& mi = toCalc.load();
             auto fmap = Bitmap<float>(mi.bWidth, mi.bHeight);
             generator->generate(mi, fmap.pixels.get());
-            auto* bitmap = new Bitmap<RGBColor>(fmap.map<RGBColor>([&mi](float i) { return i > mi.maxIter ?
+            auto* bitmap = new Bitmap<RGBColor>(fmap.map<RGBColor>([&mi, this](float i) {
+                return i >= mi.maxIter ? RGBColor{ 0, 0, 0 } : gradient.get(i);
+            }));
+                /*return i >= mi.maxIter ?
                             RGBColor{ 0,0,0 } :
                             RGBColor{ uint8_t(cos(i * 0.015f) * 127 + 127),
                                       uint8_t(sin(i * 0.01f) * 127 + 127),
                                       uint8_t(i) }; }));//uint8_t(::sin(i * 0.01f) * 100 + 100), uint8_t(i) }; });
-
+*/
             //hiddenWidget->makeCurrent();
             //Texture* tex = new Texture(bitmap);
             //hiddenWidget->doneCurrent();
@@ -216,7 +220,7 @@ void MandelView::adaptViewport(const MandelInfo mi)
 MandelWidget::MandelWidget(mnd::MandelContext& ctxt, QWidget* parent) :
     QGLWidget{ QGLFormat(QGL::SampleBuffers), parent },
     mndContext{ ctxt },
-    mv{ ctxt.getCpuGeneratorFloat(), this }
+    mv{ ctxt.getCpuGeneratorFloat(), gradient, this }
 {
     this->setContentsMargins(0, 0, 0, 0);
     this->setSizePolicy(QSizePolicy::Expanding,
@@ -224,11 +228,11 @@ MandelWidget::MandelWidget(mnd::MandelContext& ctxt, QWidget* parent) :
     QObject::connect(&mv, &MandelView::updated, this, &MandelWidget::viewUpdated, Qt::AutoConnection);
     QObject::connect(this, &MandelWidget::needsUpdate, &mv, &MandelView::adaptViewport, Qt::DirectConnection);
 
-    /*if (!ctxt.getDevices().empty()) {
+    if (!ctxt.getDevices().empty()) {
         if (auto* gen = ctxt.getDevices()[0].getGeneratorDouble(); gen) {
             mv.setGenerator(*gen);
         }
-    }*/
+    }
 }
 
 

+ 7 - 1
MandelWidget.h

@@ -11,6 +11,7 @@
 #include <qrubberband.h>
 
 #include "Bitmap.h"
+#include "Gradient.h"
 #include <Mandel.h>
 
 #include <future>
@@ -52,10 +53,11 @@ private:
     std::atomic_bool hasToCalc;
     std::atomic_bool finish;
     mnd::Generator* generator;
+    Gradient& gradient;
     MandelWidget* mWidget;
     //QOpenGLContext* context;
 public:
-    MandelView(mnd::Generator& generator, MandelWidget* mWidget);
+    MandelView(mnd::Generator& generator, Gradient& gradient, MandelWidget* mWidget);
     ~MandelView(void);
 
     void setGenerator(mnd::Generator &value);
@@ -78,6 +80,8 @@ private:
     //QLabel ql;
     mnd::MandelContext& mndContext;
 
+    Gradient gradient;
+
     bool initialized = false;
     int maxIterations = 2000;
 
@@ -98,6 +102,8 @@ public:
     {
     }*/
 
+    inline const Gradient& getGradient(void) const { return gradient; }
+
     void initializeGL(void) override;
 
     void resizeGL(int w, int h) override;

+ 36 - 0
gradientchoosedialog.cpp

@@ -0,0 +1,36 @@
+#include "gradientchoosedialog.h"
+
+#include <QtXml/QDomDocument>
+
+GradientChooseDialog::GradientChooseDialog()
+{
+    gcd.setupUi(this);
+    QFont f("unexistent");
+    f.setStyleHint(QFont::Monospace);
+    gcd.plainTextEdit->setFont(f);
+}
+
+void GradientChooseDialog::on_buttonBox_accepted()
+{
+    QDomDocument xsr;
+    xsr.setContent(gcd.plainTextEdit->toPlainText());
+    auto elem = xsr.documentElement();
+    auto colors = xsr.elementsByTagName("color");
+    for (int i = 0; i < colors.length(); ++i) {
+        auto child = colors.item(i).toElement();
+
+        uint8_t r = child.attributeNode("r").value().toInt();
+        uint8_t g = child.attributeNode("g").value().toInt();
+        uint8_t b = child.attributeNode("b").value().toInt();
+
+        printf("rgb (%s): %d, %d, %d\n", child.text().toUtf8().data(), r, g, b);
+    }
+    printf("yee: %s\n", elem.text().toUtf8().data());
+    fflush(stdout);
+}
+
+
+void GradientChooseDialog::on_buttonBox_clicked(QAbstractButton *button)
+{
+
+}

+ 19 - 0
gradientchoosedialog.h

@@ -0,0 +1,19 @@
+#ifndef GRADIENTCHOOSEDIALOG_H
+#define GRADIENTCHOOSEDIALOG_H
+
+#include <QDialog>
+#include "ui_gradientchooser.h"
+
+class GradientChooseDialog : public QDialog
+{
+    Q_OBJECT
+private:
+    Ui::GradientChooser gcd;
+public:
+    GradientChooseDialog();
+private slots:
+    void on_buttonBox_accepted();
+    void on_buttonBox_clicked(QAbstractButton *button);
+};
+
+#endif // GRADIENTCHOOSEDIALOG_H

+ 73 - 0
gradientchooser.ui

@@ -0,0 +1,73 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>GradientChooser</class>
+ <widget class="QDialog" name="GradientChooser">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>457</width>
+    <height>313</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Dialog</string>
+  </property>
+  <layout class="QVBoxLayout" name="verticalLayout_2">
+   <item>
+    <widget class="QPlainTextEdit" name="plainTextEdit">
+     <property name="font">
+      <font>
+       <pointsize>10</pointsize>
+      </font>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <widget class="QDialogButtonBox" name="buttonBox">
+     <property name="orientation">
+      <enum>Qt::Horizontal</enum>
+     </property>
+     <property name="standardButtons">
+      <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+     </property>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <resources/>
+ <connections>
+  <connection>
+   <sender>buttonBox</sender>
+   <signal>rejected()</signal>
+   <receiver>GradientChooser</receiver>
+   <slot>reject()</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>316</x>
+     <y>260</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>286</x>
+     <y>274</y>
+    </hint>
+   </hints>
+  </connection>
+  <connection>
+   <sender>buttonBox</sender>
+   <signal>accepted()</signal>
+   <receiver>GradientChooser</receiver>
+   <slot>accept()</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>248</x>
+     <y>254</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>157</x>
+     <y>274</y>
+    </hint>
+   </hints>
+  </connection>
+ </connections>
+</ui>

+ 4 - 4
libmandel/src/ClGenerators.cpp

@@ -183,7 +183,7 @@ std::string ClGeneratorFloat::getKernelCode(void) const
             "   float cb = b;"
             ""
             "   int n = 0;"
-            "   while (n < max) {"
+            "   while (n < max - 1) {"
             "       float aa = a * a;"
             "       float bb = b * b;"
             "       float ab = a * b;"
@@ -193,7 +193,7 @@ std::string ClGeneratorFloat::getKernelCode(void) const
             "       n++;"
             "   }\n"
                 // N + 1 - log (log  |Z(N)|) / log 2
-            "   if (n >= max)\n"
+            "   if (n >= max - 1)\n"
             "       A[index] = max;\n"
             "   else"
             "       A[index] = ((float)n) + 1 - log(log(a * a + b * b) / 2) / log(2.0f);\n"
@@ -259,7 +259,7 @@ std::string ClGeneratorDouble::getKernelCode(void) const
         "   double cb = b;"
         ""
         "   int n = 0;"
-        "   while (n < max) {"
+        "   while (n < max - 1) {"
         "       double aa = a * a;"
         "       double bb = b * b;"
         "       double ab = a * b;"
@@ -269,7 +269,7 @@ std::string ClGeneratorDouble::getKernelCode(void) const
         "       n++;"
         "   }\n"
         // N + 1 - log (log  |Z(N)|) / log 2
-        "   if (n >= max)\n"
+        "   if (n >= max - 1)\n"
         "       A[index] = max;\n"
         "   else"
         "       A[index] = ((float)n) + 1 - log(log(a * a + b * b) / 2) / log(2.0f);\n"

+ 12 - 4
libmandel/src/CpuGeneratorsAVX.cpp

@@ -32,6 +32,8 @@ void CpuGeneratorAvxFloat::generate(const mnd::MandelInfo& info, float* data)
 
             __m256 counter = {0, 0, 0, 0, 0, 0, 0, 0};
             __m256 adder = {1, 1, 1, 1, 1, 1, 1, 1};
+            __m256 resultsa;
+            __m256 resultsb;
 
             __m256 threshold = {16.0f, 16.0f, 16.0f, 16.0f, 16.0f, 16.0f, 16.0f, 16.0f};
 
@@ -45,10 +47,12 @@ void CpuGeneratorAvxFloat::generate(const mnd::MandelInfo& info, float* data)
                 __m256 abab = _mm256_mul_ps(a, b); abab = _mm256_add_ps(abab, abab);
                 a = _mm256_add_ps(_mm256_sub_ps(aa, bb), xs);
                 b = _mm256_add_ps(abab, ys);
-                __m256i cmp = _mm256_castps_si256(_mm256_cmp_ps(_mm256_add_ps(aa, bb), threshold, _CMP_LE_OQ));
-                adder = _mm256_and_ps(adder, _mm256_castsi256_ps(cmp));
+                __m256 cmp = _mm256_cmp_ps(_mm256_add_ps(aa, bb), threshold, _CMP_LE_OQ);
+                resultsa = _mm256_or_ps(_mm256_andnot_ps(cmp, resultsa), _mm256_and_ps(cmp, a));
+                resultsb = _mm256_or_ps(_mm256_andnot_ps(cmp, resultsb), _mm256_and_ps(cmp, b));
+                adder = _mm256_and_ps(adder, cmp);
                 counter = _mm256_add_ps(counter, adder);
-                if ((k & 0x7) == 0 && _mm256_testz_si256(cmp, cmp) != 0) {
+                if ((k & 0x7) == 0 && _mm256_testz_ps(cmp, cmp) != 0) {
                     break;
                 }
             }
@@ -62,10 +66,14 @@ void CpuGeneratorAvxFloat::generate(const mnd::MandelInfo& info, float* data)
 
             float resData[16];
             float* ftRes = alignVec(resData);
+            float* resa = (float*) &resultsa;
+            float* resb = (float*) &resultsb;
 
             _mm256_store_ps(ftRes, counter);
             for (int k = 0; k < 8 && i + k < info.bWidth; k++)
-                data[i + k + j * info.bWidth] = ftRes[k] > 0 ? ftRes[k] : info.maxIter;
+                data[i + k + j * info.bWidth] = ftRes[k] <= 0 ? info.maxIter :
+                                                ftRes[k] >= info.maxIter ? info.maxIter :
+                ((float)ftRes[k]) + 1 - log(log(resa[k] * resa[k] + resb[k] * resb[k]) / 2) / log(2.0f);
         }
     }
 }