From 9f7f9e4124903fb34ed85bc61942b4998939798f Mon Sep 17 00:00:00 2001 From: Benjo Date: Thu, 3 Feb 2022 18:35:34 +0100 Subject: [PATCH] mandelbrot set is drawn in blue to red, added ui for iterations and diverge-threshold --- Fragment.glsl | 29 ++++++++++++++++++++++-- Vertex.glsl | 12 ++++++++-- headers/MainWindow.h | 2 +- headers/Mandelbrot.h | 6 +++-- headers/OutputWidget.h | 6 ++++- src/MainWindow.cpp | 50 ++++++++++++++++++++++++++++++++---------- src/Mandelbrot.cpp | 20 ++++++++++++++--- src/OutputWidget.cpp | 11 ++++------ 8 files changed, 106 insertions(+), 30 deletions(-) diff --git a/Fragment.glsl b/Fragment.glsl index 22308e6..bbe365f 100644 --- a/Fragment.glsl +++ b/Fragment.glsl @@ -1,6 +1,31 @@ #version 330 core out vec4 pixColor; +uniform int iterationCount; +uniform float divergeThreshold; + +in vec2 complexPos; + +vec2 mul(in vec2 a, in vec2 b) { + return vec2(a.x * b.x - a.y * b.y, a.y * b.x + a.x * b.y); +} + +vec3 getColor(in float value){ + vec3 red = vec3(0.5, 0, 0); + vec3 blue = vec3(0, 0, 0.5); + return value * red + (1 - value) * blue; +} + void main(){ - pixColor = vec4(1., 0., 0., 1); -} \ No newline at end of file + + vec2 z; + float stepsNeeded = 0; + while (stepsNeeded < iterationCount && length(z) < divergeThreshold){ + z = mul(z, z) + complexPos; + ++stepsNeeded; + } + + float value = stepsNeeded / iterationCount; + pixColor = vec4(getColor(value), 1); +} + diff --git a/Vertex.glsl b/Vertex.glsl index 42802cf..df34866 100644 --- a/Vertex.glsl +++ b/Vertex.glsl @@ -1,6 +1,14 @@ #version 330 core -layout (location = 0) in vec2 position; +layout (location = 0) in vec2 pos; + +uniform vec2 origin; +uniform vec2 size; + +out vec2 complexPos; void main(){ - gl_Position = vec4(position.x, position.y, 0.0, 1.); + vec2 offset = (pos + 1) / 2 * size; + offset.y *= -1; + complexPos = origin + offset; + gl_Position = vec4(pos.xy, 0.0, 1.); } \ No newline at end of file diff --git a/headers/MainWindow.h b/headers/MainWindow.h index 8466fff..45a808b 100644 --- a/headers/MainWindow.h +++ b/headers/MainWindow.h @@ -9,9 +9,9 @@ public: explicit MainWindow(); private slots: void iterationsSliderChanged(int); + void limitSliderChanged(int); private: void buildUI(); - OutputWidget* outputWidget = new OutputWidget(this); }; diff --git a/headers/Mandelbrot.h b/headers/Mandelbrot.h index 7b1332a..9f6cc6c 100644 --- a/headers/Mandelbrot.h +++ b/headers/Mandelbrot.h @@ -1,4 +1,3 @@ - #pragma once #include @@ -9,14 +8,17 @@ class Mandelbrot : public QObject, protected QOpenGLExtraFunctions { Q_OBJECT public: void init(); - void draw(GLuint, int, QOpenGLShaderProgram&); + void draw(GLuint, QOpenGLShaderProgram&); void zoom(double); public slots: void setIterations(int); + void updateLimit(int); private: int iterations = 0; + float divergeThreshold = 0; double scale = 1; QVector2D translation; + void setShaderValues(QOpenGLShaderProgram&); }; diff --git a/headers/OutputWidget.h b/headers/OutputWidget.h index 16eebf2..af4eeed 100644 --- a/headers/OutputWidget.h +++ b/headers/OutputWidget.h @@ -1,9 +1,11 @@ - #pragma once #include #include +#include +#include +#include #include "Mandelbrot.h" class OutputWidget : public QOpenGLWidget, protected QOpenGLExtraFunctions { @@ -22,6 +24,8 @@ private: void mouseReleaseEvent(QMouseEvent*) override; void keyPressEvent(QKeyEvent*) override; + QPoint mousePos; + void initShader(); static std::vector genVertices(); GLuint createVAO(); diff --git a/src/MainWindow.cpp b/src/MainWindow.cpp index 2ed7417..987e1fc 100644 --- a/src/MainWindow.cpp +++ b/src/MainWindow.cpp @@ -1,5 +1,6 @@ #include #include +#include #include #include "../headers/MainWindow.h" @@ -10,25 +11,45 @@ MainWindow::MainWindow() { void MainWindow::buildUI() { resize(700, 700); + auto iterationsCaption = new QLabel("Iteration count:"); + auto iterationsLabel = new QLabel; + //iterationsLabel->setAlignment(Qt::AlignRight); auto iterationsSlider = new QSlider(Qt::Horizontal); iterationsSlider->setRange(5, 300); - QSlider::connect( - iterationsSlider, - &QSlider::valueChanged, - this->outputWidget->getMandelbrot(), - &Mandelbrot::setIterations - ); - QSlider::connect( + connect( iterationsSlider, &QSlider::valueChanged, this, - &MainWindow::iterationsSliderChanged - ); - + [iterationsLabel, this](int value) -> void { + this->outputWidget->getMandelbrot()->setIterations(value); + this->outputWidget->update(); + iterationsLabel->setNum(value); + }); iterationsSlider->setValue(100); + auto limitCaption = new QLabel("Diverge threshold:"); + auto limitLabel = new QLabel; + //limitLabel->setAlignment(Qt::AlignRight); + auto limitSlider = new QSlider(Qt::Horizontal); + limitSlider->setRange(100, 500); + connect( + limitSlider, + &QSlider::valueChanged, + this, + [limitLabel, this](int value) -> void { + this->outputWidget->getMandelbrot()->updateLimit(value); + this->outputWidget->update(); + limitLabel->setNum(double(value) / 100); + }); + limitSlider->setValue(200); + auto controls = new QGridLayout; - controls->addWidget(iterationsSlider); + controls->addWidget(iterationsCaption, 1, 1); + controls->addWidget(iterationsLabel, 1, 2); + controls->addWidget(iterationsSlider, 1, 3); + controls->addWidget(limitCaption, 2, 1); + controls->addWidget(limitLabel, 2, 2); + controls->addWidget(limitSlider, 2, 3); auto lyt = new QVBoxLayout(this); lyt->addWidget(outputWidget); @@ -37,5 +58,10 @@ void MainWindow::buildUI() { void MainWindow::iterationsSliderChanged(int newValue) { //TODO update text label - update(); + outputWidget->update(); +} + +void MainWindow::limitSliderChanged(int newValue) { + //TODO update text label + outputWidget->update(); } diff --git a/src/Mandelbrot.cpp b/src/Mandelbrot.cpp index f005043..0686e28 100644 --- a/src/Mandelbrot.cpp +++ b/src/Mandelbrot.cpp @@ -1,17 +1,25 @@ - #include "../headers/Mandelbrot.h" void Mandelbrot::init() { initializeOpenGLFunctions(); } -void Mandelbrot::draw(GLuint vao, int vertCount, QOpenGLShaderProgram& shader) { +void Mandelbrot::draw(GLuint vao, QOpenGLShaderProgram& shader) { + glClear(GL_COLOR_BUFFER_BIT); shader.bind(); + setShaderValues(shader); glBindVertexArray(vao); - glDrawArrays(GL_QUADS, 0, vertCount); + glDrawArrays(GL_QUADS, 0, 4); glBindVertexArray(0); } +void Mandelbrot::setShaderValues(QOpenGLShaderProgram &shader) { + shader.setUniformValue("origin", QVector2D(-1, 1)); + shader.setUniformValue("size", QVector2D(2, 2)); + shader.setUniformValue("iterationCount", iterations); + shader.setUniformValue("divergeThreshold", divergeThreshold); +} + void Mandelbrot::zoom(double delta) { scale *= delta; } @@ -20,4 +28,10 @@ void Mandelbrot::setIterations(int value) { iterations = value; } +void Mandelbrot::updateLimit(int value) { + divergeThreshold = float(value) / 100; +} + + + diff --git a/src/OutputWidget.cpp b/src/OutputWidget.cpp index bc1a300..8a3d904 100644 --- a/src/OutputWidget.cpp +++ b/src/OutputWidget.cpp @@ -1,4 +1,3 @@ - #include #include #include "../headers/OutputWidget.h" @@ -16,18 +15,15 @@ void OutputWidget::initializeGL() { vao = createVAO(); - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glClearColor(0.5f, 0.5f, 0.5f, 1.0f); } void OutputWidget::paintGL() { - glClear(GL_COLOR_BUFFER_BIT); - getMandelbrot()->draw(vao, vertCount, shader); + getMandelbrot()->draw(vao, shader); } void OutputWidget::resizeGL(int w, int h) { - //glViewport(0, 0, w, h); + } GLuint OutputWidget::createVAO() { @@ -74,7 +70,8 @@ void OutputWidget::wheelEvent(QWheelEvent *e) { } void OutputWidget::mouseMoveEvent(QMouseEvent *e) { - + QPoint newMousePos = e->pos(); + QPoint diff = newMousePos - mousePos; } void OutputWidget::mousePressEvent(QMouseEvent *e) {