瀏覽代碼

trying opengl

Nicolas Winkler 5 年之前
父節點
當前提交
b4b907ecc5
共有 4 個文件被更改,包括 117 次插入46 次删除
  1. 88 33
      MandelWidget.cpp
  2. 9 8
      MandelWidget.h
  3. 14 5
      libalmond/include/Gradient.h
  4. 6 0
      libalmond/src/Gradient.cpp

+ 88 - 33
MandelWidget.cpp

@@ -12,12 +12,15 @@ using namespace mnd;
 #include <cstdio>
 #include <cstdio>
 
 
 
 
-Texture::Texture(QOpenGLFunctions& gl, const Bitmap<RGBColor>& bitmap, GLint param) :
+Texture::Texture(QOpenGLFunctions& gl, const Bitmap<float>& bitmap, GLint param) :
     gl{ gl }
     gl{ gl }
 {
 {
     gl.glGenTextures(1, &id);
     gl.glGenTextures(1, &id);
+    gl.glActiveTexture(GL_TEXTURE0);
     gl.glBindTexture(GL_TEXTURE_2D, id);
     gl.glBindTexture(GL_TEXTURE_2D, id);
 
 
+    Bitmap<float> copy = bitmap.map<float>([](float x) { return x / 500; });
+
     //int lineLength = (bitmap.width * 3 + 3) & ~3;
     //int lineLength = (bitmap.width * 3 + 3) & ~3;
 
 
     /*std::unique_ptr<unsigned char[]> pixels = std::make_unique<unsigned char[]>(lineLength * bitmap.height);
     /*std::unique_ptr<unsigned char[]> pixels = std::make_unique<unsigned char[]>(lineLength * bitmap.height);
@@ -30,7 +33,7 @@ Texture::Texture(QOpenGLFunctions& gl, const Bitmap<RGBColor>& bitmap, GLint par
             pixels[index + 2] = c.b;
             pixels[index + 2] = c.b;
         }
         }
     }*/
     }*/
-    gl.glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, int(bitmap.width), int(bitmap.height), 0, GL_RGB, GL_UNSIGNED_BYTE, reinterpret_cast<char*> (bitmap.pixels.get()));
+    gl.glTexImage2D(GL_TEXTURE_2D, 0, GL_R32F, int(bitmap.width), int(bitmap.height), 0, GL_RED, GL_FLOAT, copy.pixels.get());
     gl.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
     gl.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
     gl.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
     gl.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
     gl.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, param);
     gl.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, param);
@@ -55,10 +58,12 @@ Texture::Texture(Texture&& other) :
 
 
 void Texture::bind(void) const
 void Texture::bind(void) const
 {
 {
+    gl.glActiveTexture(GL_TEXTURE0);
     gl.glBindTexture(GL_TEXTURE_2D, id);
     gl.glBindTexture(GL_TEXTURE_2D, id);
 }
 }
 
 
 
 
+static GLuint gradId;
 void Texture::drawRect(QOpenGLShaderProgram* program,
 void Texture::drawRect(QOpenGLShaderProgram* program,
                        float x, float y, float width, float height,
                        float x, float y, float width, float height,
                        float tx, float ty, float tw, float th)
                        float tx, float ty, float tw, float th)
@@ -84,21 +89,31 @@ void Texture::drawRect(QOpenGLShaderProgram* program,
     int texCoordsLoc = program->attributeLocation("texCoord");
     int texCoordsLoc = program->attributeLocation("texCoord");
     int colorLocation = program->uniformLocation("color");
     int colorLocation = program->uniformLocation("color");
     int texLoc = program->uniformLocation("tex");
     int texLoc = program->uniformLocation("tex");
-    program->enableAttributeArray(vertexLoc);
-    program->enableAttributeArray(texCoordsLoc);
+    int gradLoc = program->uniformLocation("gradient");
     program->setAttributeArray(vertexLoc, vertices, 3);
     program->setAttributeArray(vertexLoc, vertices, 3);
     program->setAttributeArray(texCoordsLoc, texCoords, 2);
     program->setAttributeArray(texCoordsLoc, texCoords, 2);
+    program->enableAttributeArray(vertexLoc);
+    program->enableAttributeArray(texCoordsLoc);
     program->setUniformValue(colorLocation, color);
     program->setUniformValue(colorLocation, color);
 
 
 
 
     auto& gl3 = *QOpenGLContext::currentContext()->functions();
     auto& gl3 = *QOpenGLContext::currentContext()->functions();
-    gl3.glUniform1i(texLoc, 0);
-    gl3.glActiveTexture(GL_TEXTURE0 + 0);
+    gl3.glEnable(GL_TEXTURE_2D);
+
+    gl3.glUniform1i(texLoc, GL_TEXTURE0);
+    gl3.glUniform1i(gradLoc, GL_TEXTURE1);
+
+    gl3.glActiveTexture(GL_TEXTURE0);
     gl3.glBindTexture(GL_TEXTURE_2D, id);
     gl3.glBindTexture(GL_TEXTURE_2D, id);
+
+    //gl3.glActiveTexture(GL_TEXTURE1);
+    //gl3.glBindTexture(GL_TEXTURE_2D, gradId);
+
     gl3.glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
     gl3.glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
 
 
     program->disableAttributeArray(vertexLoc);
     program->disableAttributeArray(vertexLoc);
     program->disableAttributeArray(texCoordsLoc);
     program->disableAttributeArray(texCoordsLoc);
+    gl3.glActiveTexture(GL_TEXTURE0);
 #else
 #else
     gl.glColor3ub(255, 255, 255);
     gl.glColor3ub(255, 255, 255);
     gl.glEnable(GL_TEXTURE_2D);
     gl.glEnable(GL_TEXTURE_2D);
@@ -265,18 +280,18 @@ void Job::run(void)
     auto [absX, absY] = grid->getPositions(i, j);
     auto [absX, absY] = grid->getPositions(i, j);
     mnd::Real gw = grid->dpp * MandelView::chunkSize;
     mnd::Real gw = grid->dpp * MandelView::chunkSize;
 
 
-    Bitmap<float> f(MandelView::chunkSize, MandelView::chunkSize);
+    Bitmap<float>* f = new Bitmap<float>(MandelView::chunkSize, MandelView::chunkSize);
     mnd::MandelInfo mi = owner.getMandelInfo();
     mnd::MandelInfo mi = owner.getMandelInfo();
     mi.view.x = absX;
     mi.view.x = absX;
     mi.view.y = absY;
     mi.view.y = absY;
     mi.view.width = mi.view.height = gw;
     mi.view.width = mi.view.height = gw;
     mi.bWidth = mi.bHeight = MandelView::chunkSize;
     mi.bWidth = mi.bHeight = MandelView::chunkSize;
     try {
     try {
-        generator->generate(mi, f.pixels.get());
-        auto* rgb = new Bitmap<RGBColor>(f.map<RGBColor>([&mi, this] (float i) {
+        generator->generate(mi, f->pixels.get());
+        /*auto* rgb = new Bitmap<RGBColor>(f.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 } : gradient.get(i);
-        }));
-        emit done(level, i, j, calcState, rgb);
+        }));*/
+        emit done(level, i, j, calcState, f);
     }
     }
     catch(std::exception& ex) {
     catch(std::exception& ex) {
         printf("wat: %s?!\n", ex.what()); fflush(stdout);
         printf("wat: %s?!\n", ex.what()); fflush(stdout);
@@ -350,7 +365,7 @@ void Calcer::notFinished(int level, GridIndex i, GridIndex j)
 }
 }
 
 
 
 
-void Calcer::redirect(int level, GridIndex i, GridIndex j, long calcState, Bitmap<RGBColor>* bmp)
+void Calcer::redirect(int level, GridIndex i, GridIndex j, long calcState, Bitmap<float>* bmp)
 {
 {
     jobsMutex.lock();
     jobsMutex.lock();
     jobs.erase({ level, i, j });
     jobs.erase({ level, i, j });
@@ -384,8 +399,8 @@ MandelView::MandelView(mnd::MandelGenerator* generator, MandelWidget& owner) :
             }
             }
         }
         }
     }*/
     }*/
-    Bitmap<RGBColor> emp(1, 1);
-    emp.get(0, 0) = RGBColor{ 0, 0, 0 };
+    Bitmap<float> emp(1, 1);
+    emp.get(0, 0) = 0.0f;
     auto& gl = *QOpenGLContext::currentContext()->functions();
     auto& gl = *QOpenGLContext::currentContext()->functions();
     empty = std::make_unique<Texture>(gl, emp, GL_NEAREST);
     empty = std::make_unique<Texture>(gl, emp, GL_NEAREST);
     connect(&calcer, &Calcer::done, this, &MandelView::cellReady);
     connect(&calcer, &Calcer::done, this, &MandelView::cellReady);
@@ -578,6 +593,10 @@ void MandelView::paint(const mnd::MandelViewport& mvp)
             }
             }
 
 
             if (t != nullptr) {
             if (t != nullptr) {
+
+                auto& gl3 = *QOpenGLContext::currentContext()->functions();
+                gl3.glActiveTexture(GL_TEXTURE1);
+                gl3.glBindTexture(GL_TEXTURE_2D, owner.gradientTexture);
                 t->img->drawRect(this->owner.program,float(x), float(y), float(w), float(w));
                 t->img->drawRect(this->owner.program,float(x), float(y), float(w), float(w));
                 /*glBegin(GL_LINE_LOOP);
                 /*glBegin(GL_LINE_LOOP);
                 glVertex2f(float(x), float(y));
                 glVertex2f(float(x), float(y));
@@ -599,7 +618,7 @@ void MandelView::paint(const mnd::MandelViewport& mvp)
     }
     }
 }
 }
 
 
-void MandelView::cellReady(int level, GridIndex i, GridIndex j, Bitmap<RGBColor>* bmp)
+void MandelView::cellReady(int level, GridIndex i, GridIndex j, Bitmap<float>* bmp)
 {
 {
     auto& gl = *QOpenGLContext::currentContext()->functions();
     auto& gl = *QOpenGLContext::currentContext()->functions();
     this->getGrid(level).setCell(i, j,
     this->getGrid(level).setCell(i, j,
@@ -630,12 +649,45 @@ MandelWidget::~MandelWidget()
 
 
 void MandelWidget::setGradient(Gradient g)
 void MandelWidget::setGradient(Gradient g)
 {
 {
-    this->gradient = std::move(g);
+    /*this->gradient = std::move(g);
     if (mandelView) {
     if (mandelView) {
         mandelView->clearCells();
         mandelView->clearCells();
         mandelView->calcer.changeState();
         mandelView->calcer.changeState();
     }
     }
-    emit update();
+    emit update();*/
+
+    auto& gl = *this->context()->functions();
+    this->gradient = std::move(g);
+    int width = 1024;
+
+    std::vector<unsigned char> pixels(size_t(width * 3));
+    for (int i = 0; i < width; i++) {
+        float pos = i * this->gradient.getMax() / width;
+        RGBColor c = gradient.get(pos);
+        pixels.push_back(c.r);
+        pixels.push_back(c.g);
+        pixels.push_back(c.b);
+    }
+
+    unsigned char pix[] = { 255, 0, 0, 0, 255, 0, 0, 0, 255 };
+
+    GLuint id;
+    gl.glEnable(GL_TEXTURE_2D);
+    gl.glActiveTexture(GL_TEXTURE1);
+    gl.glGenTextures(1, &id);
+    gl.glBindTexture(GL_TEXTURE_2D, id);
+
+    gl.glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, 3, 1, 0, GL_RGB, GL_UNSIGNED_BYTE, reinterpret_cast<char*> (pix));
+    gl.glUniform1i(this->program->uniformLocation("gradient"), GL_TEXTURE1);
+    gl.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+    gl.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+    gl.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+    gl.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+
+
+    gradientTexture = id;
+    gradId = id;
+    update();
 }
 }
 
 
 
 
@@ -726,12 +778,17 @@ void MandelWidget::initializeGL(void)
     "   texc = texCoord;\n"
     "   texc = texCoord;\n"
     "}");
     "}");
     bool frag = program->addShaderFromSourceCode(QOpenGLShader::Fragment,
     bool frag = program->addShaderFromSourceCode(QOpenGLShader::Fragment,
+    "uniform sampler2D gradient;\n"
+    "uniform sampler2D tex;\n"
     "uniform mediump vec4 color;\n"
     "uniform mediump vec4 color;\n"
     "varying highp vec2 texc;\n"
     "varying highp vec2 texc;\n"
-    "uniform sampler2D tex;\n"
     "void main(void)\n"
     "void main(void)\n"
     "{\n"
     "{\n"
-    "   gl_FragColor = color * texture2D(tex, texc);\n"
+    "   float v = texture2D(tex, texc).r;\n"
+    "   gl_FragColor = texture2D(gradient, vec2(v, 0.0));\n"
+//    "   gl_FragColor = texture2D(tex, texc);\n"
+//    "   float v = texture2D(tex, texc).r;\n"
+//    "   gl_FragColor = vec4(v, 1.0 - v, v*v, 1);\n"
 //    "   gl_FragColor.g = 0.3;\n"
 //    "   gl_FragColor.g = 0.3;\n"
     "}");
     "}");
     //program.link();
     //program.link();
@@ -740,6 +797,7 @@ void MandelWidget::initializeGL(void)
     //gl3.glBindSampler(0, id);
     //gl3.glBindSampler(0, id);
 
 
     mandelView = nullptr;
     mandelView = nullptr;
+    setGradient(gradient);
     requestRecalc();
     requestRecalc();
 }
 }
 
 
@@ -804,9 +862,8 @@ void MandelWidget::paintGL(void)
     //QPainter painter{ this };
     //QPainter painter{ this };
 
 
 
 
-    QPainter painter{ this };
-    painter.beginNativePainting();
     updateAnimations();
     updateAnimations();
+
     mandelView->paint(this->currentViewport);
     mandelView->paint(this->currentViewport);
 
 
     static GLfloat const triangleVertices[] = {
     static GLfloat const triangleVertices[] = {
@@ -833,13 +890,15 @@ void MandelWidget::paintGL(void)
 
 
     program->disableAttributeArray(vertexLocation);
     program->disableAttributeArray(vertexLocation);
 
 
-    painter.endNativePainting();
-    if (rubberbanding)
-        drawRubberband();
+    /*QPainter painter{ this };
+    painter.beginNativePainting();
+    painter.endNativePainting();*/
+    /*if (rubberbanding)
+        drawRubberband(painter);
     if (displayInfo)
     if (displayInfo)
-        drawInfo();
+        drawInfo(painter);
     if (selectingPoint)
     if (selectingPoint)
-        drawPoint();
+        drawPoint(painter);*/
 }
 }
 
 
 
 
@@ -868,9 +927,8 @@ void MandelWidget::updateAnimations(void)
 }
 }
 
 
 
 
-void MandelWidget::drawRubberband(void)
+void MandelWidget::drawRubberband(QPainter& rubberbandPainter)
 {
 {
-    QPainter rubberbandPainter{ this };
     rubberbandPainter.fillRect(rubberband, QColor{ 125, 140, 225, 120 });
     rubberbandPainter.fillRect(rubberband, QColor{ 125, 140, 225, 120 });
 
 
     QPen pen{ QColor{ 100, 115, 200 } };
     QPen pen{ QColor{ 100, 115, 200 } };
@@ -883,7 +941,7 @@ void MandelWidget::drawRubberband(void)
 }
 }
 
 
 
 
-void MandelWidget::drawInfo(void)
+void MandelWidget::drawInfo(QPainter& infoPainter)
 {
 {
     const float DIST_FROM_BORDER = 15;
     const float DIST_FROM_BORDER = 15;
     float maxWidth = this->width() - 2 * DIST_FROM_BORDER;
     float maxWidth = this->width() - 2 * DIST_FROM_BORDER;
@@ -916,7 +974,6 @@ void MandelWidget::drawInfo(void)
     float lineY = this->height() - DIST_FROM_BORDER;
     float lineY = this->height() - DIST_FROM_BORDER;
     float lineXEnd = DIST_FROM_BORDER + pixels;
     float lineXEnd = DIST_FROM_BORDER + pixels;
 
 
-    QPainter infoPainter{ this };
     infoPainter.setPen(Qt::white);
     infoPainter.setPen(Qt::white);
     infoPainter.setFont(QFont("Arial", 12));
     infoPainter.setFont(QFont("Arial", 12));
     infoPainter.drawLine(QPointF{ DIST_FROM_BORDER, lineY }, QPointF{ lineXEnd, lineY });
     infoPainter.drawLine(QPointF{ DIST_FROM_BORDER, lineY }, QPointF{ lineXEnd, lineY });
@@ -924,13 +981,11 @@ void MandelWidget::drawInfo(void)
     infoPainter.drawLine(QPointF{ lineXEnd, lineY }, QPointF{ lineXEnd, lineY - 5 });
     infoPainter.drawLine(QPointF{ lineXEnd, lineY }, QPointF{ lineXEnd, lineY - 5 });
     infoPainter.drawText(int(DIST_FROM_BORDER), int(lineY - 20), int(lineXEnd - DIST_FROM_BORDER), 20,
     infoPainter.drawText(int(DIST_FROM_BORDER), int(lineY - 20), int(lineXEnd - DIST_FROM_BORDER), 20,
                          Qt::AlignCenter, QString::fromStdString(dis.str()));
                          Qt::AlignCenter, QString::fromStdString(dis.str()));
-    infoPainter.end();
 }
 }
 
 
 
 
-void MandelWidget::drawPoint(void)
+void MandelWidget::drawPoint(QPainter& pointPainter)
 {
 {
-    QPainter pointPainter{ this };
     pointPainter.setPen(QColor{ 255, 255, 255 });
     pointPainter.setPen(QColor{ 255, 255, 255 });
     pointPainter.drawLine(0, pointY, width(), pointY);
     pointPainter.drawLine(0, pointY, width(), pointY);
     pointPainter.drawLine(pointX, 0, pointX, height());
     pointPainter.drawLine(pointX, 0, pointX, height());

+ 9 - 8
MandelWidget.h

@@ -41,7 +41,7 @@ protected:
     QOpenGLFunctions& gl;
     QOpenGLFunctions& gl;
     inline Texture(QOpenGLFunctions& gl) : gl{ gl } {}
     inline Texture(QOpenGLFunctions& gl) : gl{ gl } {}
 public:
 public:
-    Texture(QOpenGLFunctions& gl, const Bitmap<RGBColor>& pict, GLint param = GL_LINEAR);
+    Texture(QOpenGLFunctions& gl, const Bitmap<float>& pict, GLint param = GL_LINEAR);
     ~Texture(void);
     ~Texture(void);
 
 
     Texture(const Texture& other) = delete;
     Texture(const Texture& other) = delete;
@@ -241,7 +241,7 @@ public:
 
 
     void run() override;
     void run() override;
 signals:
 signals:
-    void done(int level, GridIndex i, GridIndex j, long calcState, Bitmap<RGBColor>* bmp);
+    void done(int level, GridIndex i, GridIndex j, long calcState, Bitmap<float>* bmp);
 };
 };
 
 
 
 
@@ -269,9 +269,9 @@ public slots:
     void calc(TexGrid& grid, int level, GridIndex i, GridIndex j, int priority);
     void calc(TexGrid& grid, int level, GridIndex i, GridIndex j, int priority);
     void setCurrentLevel(int level);
     void setCurrentLevel(int level);
     void notFinished(int level, GridIndex i, GridIndex j);
     void notFinished(int level, GridIndex i, GridIndex j);
-    void redirect(int level, GridIndex i, GridIndex j, long calcState, Bitmap<RGBColor>* bmp);
+    void redirect(int level, GridIndex i, GridIndex j, long calcState, Bitmap<float>* bmp);
 signals:
 signals:
-    void done(int level, GridIndex i, GridIndex j, Bitmap<RGBColor>* bmp);
+    void done(int level, GridIndex i, GridIndex j, Bitmap<float>* bmp);
 };
 };
 
 
 
 
@@ -306,7 +306,7 @@ public:
     GridElement* searchUnder(int level, GridIndex i, GridIndex j, int recursionLevel);
     GridElement* searchUnder(int level, GridIndex i, GridIndex j, int recursionLevel);
     void paint(const mnd::MandelViewport& mvp);
     void paint(const mnd::MandelViewport& mvp);
 public slots:
 public slots:
-    void cellReady(int level, GridIndex i, GridIndex j, Bitmap<RGBColor>* bmp);
+    void cellReady(int level, GridIndex i, GridIndex j, Bitmap<float>* bmp);
 signals:
 signals:
     void redrawRequested(void);
     void redrawRequested(void);
 };
 };
@@ -344,6 +344,7 @@ private:
     std::unique_ptr<MandelView> mandelView;
     std::unique_ptr<MandelView> mandelView;
 
 
     QOpenGLShaderProgram* program;
     QOpenGLShaderProgram* program;
+    GLuint gradientTexture;
 public:
 public:
     MandelWidget(mnd::MandelContext& ctxt, mnd::MandelGenerator* generator, QWidget* parent = nullptr);
     MandelWidget(mnd::MandelContext& ctxt, mnd::MandelGenerator* generator, QWidget* parent = nullptr);
     ~MandelWidget(void) override;
     ~MandelWidget(void) override;
@@ -378,9 +379,9 @@ public:
 private:
 private:
     void updateAnimations(void);
     void updateAnimations(void);
 
 
-    void drawRubberband(void);
-    void drawInfo(void);
-    void drawPoint(void);
+    void drawRubberband(QPainter& p);
+    void drawInfo(QPainter& p);
+    void drawPoint(QPainter& p);
 public:
 public:
 
 
     void zoom(float scale, float x = 0.5f, float y = 0.5f);
     void zoom(float scale, float x = 0.5f, float y = 0.5f);

+ 14 - 5
libalmond/include/Gradient.h

@@ -26,11 +26,20 @@ public:
 
 
     //static Gradient readXml(const std::string& xml);
     //static Gradient readXml(const std::string& xml);
 
 
-    /*!
-     * \brief get a color at a specific position in this gradient
-     * \param x the position
-     * \return the color in sRGB format
-     */
+    ///
+    /// \brief get the maximum value this gradient accepts
+    ///
+    /// If \link Gradient::get(float) is called with a value
+    /// greater than the one returned by this function, the
+    /// value will either get clamped or wrapped around.
+    ///
+    float getMax(void) const;
+
+    ///
+    /// \brief get a color at a specific position in this gradient
+    /// \param x the position
+    /// \return the color in sRGB format
+    ///
     RGBColor get(float x) const;
     RGBColor get(float x) const;
 private:
 private:
     static RGBColorf lerpColors(RGBColorf a, RGBColorf b, float val);
     static RGBColorf lerpColors(RGBColorf a, RGBColorf b, float val);

+ 6 - 0
libalmond/src/Gradient.cpp

@@ -89,6 +89,12 @@ Gradient Gradient::defaultGradient(void)
 }
 }
 
 
 
 
+float Gradient::getMax(void) const
+{
+    return this->max;
+}
+
+
 RGBColor Gradient::get(float x) const
 RGBColor Gradient::get(float x) const
 {
 {
     if (colors.empty() || std::isnan(x) || std::isinf(x))
     if (colors.empty() || std::isnan(x) || std::isinf(x))