Qt Forum

    • Login
    • Search
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search
    • Unsolved

    Unsolved Error when use stencil buffer in FBO(QOpenGLFramebufferObject)

    General and Desktop
    1
    2
    50
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • MartinChan3
      MartinChan3 last edited by MartinChan3

      I try to draw concave polygon in a fbo like this(which is simply a triangle in a square), and I successfully draw it in QOpenGLWidget:
      test_openglwidget_render_m663gaaEPU.png
      However when I want to draw it in a FBO and convert it to an image to save, the result is always wrong( just a black image).I draw the concave polygon with stencil buffer enabled, here is all code(project package download):


      main.cpp:

      #include <QApplication>
      #include "renderwidget.h"
      
      int main(int argc, char *argv[])
      {
          QApplication a(argc, argv);
          RenderWidget pw;
          pw.show();
      
          return a.exec();
      }
      

      renderwidget.h:

      #ifndef RENDERWIDGET_H
      #define RENDERWIDGET_H
      
      #include <QOpenGLWidget>
      #include <QOpenGLFunctions_3_3_Compatibility>
      #include <QOpenGLShaderProgram>
      #include <QOpenGLFramebufferObject>
      
      class RenderWidget : public QOpenGLWidget, protected QOpenGLFunctions_3_3_Compatibility
      {
      public:
          RenderWidget(QWidget *parent = nullptr);
      
      protected:
          void initializeGL() override;
          void paintGL() override;
      
      private:
          QSharedPointer<QOpenGLShaderProgram> mProgram = nullptr;
          QSharedPointer<QOpenGLFramebufferObject> mFBO = nullptr;
          GLuint mPosAttr;
          GLuint mColAttr;
          GLuint mMatrixUniform;
      };
      
      #endif // RENDERWIDGET_H
      

      renderwidget.cpp:

      #include "renderwidget.h"
      #include <QDebug>
      
      RenderWidget::RenderWidget(QWidget *parent) : QOpenGLWidget(parent)
      {
          this->resize(800, 600);
      }
      
      void RenderWidget::initializeGL()
      {
          initializeOpenGLFunctions();
          glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
          glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
      
          if (mProgram.isNull())
          {
              mProgram.reset(new QOpenGLShaderProgram(this));
              mProgram->addShaderFromSourceFile(QOpenGLShader::Vertex, ":/vertex.vert");
              mProgram->addShaderFromSourceFile(QOpenGLShader::Fragment, ":/frag.frag");
              if (!mProgram->link())
              {
                  qDebug() << "Program was not linked right ";
              }
              else
              {
                  mPosAttr = mProgram->attributeLocation("posAttr");
                  mColAttr = mProgram->attributeLocation("colAttr");
                  mMatrixUniform = mProgram->uniformLocation("matrix");
              }
          }
      
          if (mFBO.isNull())
          {
              QOpenGLFramebufferObjectFormat format;
              format.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
              format.setSamples(0);
              mFBO.reset(new QOpenGLFramebufferObject(1920, 1080, format));
              qDebug() << QString("FBO attachment is %1, texture target is %2")
                          .arg(mFBO->format().attachment())
                          .arg(mFBO->format().textureTarget());
          }
      }
      
      void RenderWidget::paintGL()
      {
          mFBO->bind();   //If u want to see the effect without fbo, comment this line
      
          glViewport(0, 0, 1920, 1080);
          glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
          glClear(GL_COLOR_BUFFER_BIT);
      
          glFrontFace(GL_CW);
          glCullFace(GL_FRONT);
          glEnable(GL_CULL_FACE);
          glEnable(GL_DEPTH_TEST);
      
          mProgram->bind();
      
          QMatrix4x4 matrix;
          matrix.setToIdentity();
          matrix.ortho(0.0f, 1920.0f, 0.0f, 1080.0f, -1.0f, 1.0f);
          mProgram->setUniformValue(mMatrixUniform, matrix);
      
          QVector<float> pts;
          pts << 300 << 300
              << 900 << 300
              << 900 << 900
              << 300 << 900;
          pts << 750 << 750
              << 450 << 750
              << 450 << 450;
          QVector<int> startPosVec;
          startPosVec << 0
                      << 4
                         ;
          QVector<int> countVec;
          countVec << 4
                   << 3
                      ;
      
          QVector<float> colVec;
          for (const auto &c : countVec)
              for (int i = 0; i < c; i++)
                  colVec << float(1.0f) << float(1.0f) << float(1.0f);
      
          this->glVertexAttribPointer(mPosAttr, 2, GL_FLOAT, GL_FALSE, 0, pts.data());
          this->glVertexAttribPointer(mColAttr, 3, GL_FLOAT, GL_FALSE, 0, colVec.data());
          this->glEnableVertexAttribArray(mPosAttr);
          this->glEnableVertexAttribArray(mColAttr);
      
          this->glClear(GL_STENCIL_BUFFER_BIT);
          this->glClearStencil(0x0);
          this->glEnable(GL_STENCIL_TEST);
          this->glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
          this->glStencilFunc(GL_ALWAYS, 0x1, 0x1);
          this->glStencilOp(GL_KEEP, GL_KEEP, GL_INVERT);
          this->glDisable(GL_DEPTH_TEST);
      
          this->glMultiDrawArrays(GL_TRIANGLE_FAN, startPosVec.data() , countVec.data(), countVec.size());
      
          this->glEnable(GL_DEPTH_TEST);
          this->glStencilFunc(GL_NOTEQUAL, 0, 0x1);
          this->glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
          this->glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
      
          //this->glMultiDrawArrays(GL_TRIANGLE_FAN, startPosVec.data() , countVec.data(), countVec.size());
          GLfloat vertices[] = {
              100.0f, 100.0f,
              1900.0f, 100.0f,
              1900.0f, 1000.0f,
              100.0f, 1000.0f
          };
          GLfloat colors[] = {
              1.0f, 1.0f, 1.0f,
              1.0f, 1.0f, 1.0f,
              1.0f, 1.0f, 1.0f,
              1.0f, 1.0f, 1.0f
          };
          this->glDisableVertexAttribArray(mPosAttr);
          this->glDisableVertexAttribArray(mColAttr);
          this->glVertexAttribPointer(mPosAttr, 2, GL_FLOAT, GL_FALSE, 0, vertices);
          this->glVertexAttribPointer(mColAttr, 3, GL_FLOAT, GL_FALSE, 0, colors);
          this->glEnableVertexAttribArray(mPosAttr);
          this->glEnableVertexAttribArray(mColAttr);
          this->glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
      
          this->glDisable(GL_STENCIL_TEST);
          this->glDisableVertexAttribArray(mPosAttr);
          this->glDisableVertexAttribArray(mColAttr);
      
          mFBO->release();
          mProgram->release();
      
          glDisable(GL_CULL_FACE);
          glDisable(GL_DEPTH_TEST);
          this->glFlush();
      
          mFBO->toImage().save("./test.png");
      }
      

      vertex.vert:

      attribute highp vec4 posAttr;
      attribute lowp vec4 colAttr;
      varying lowp vec4 col;
      uniform highp mat4 matrix;
      void main() {
          col = colAttr;
          gl_Position = matrix * posAttr;
      }
      

      frag.frag:

      varying lowp vec4 col;
      void main() {
         gl_FragColor = col;
      }
      

      reference:
      Stackoverflow: Draw a concave polygon in OpenGL

      1 Reply Last reply Reply Quote 0
      • MartinChan3
        MartinChan3 last edited by

        So could anyone give some advice? :(

        1 Reply Last reply Reply Quote 0
        • First post
          Last post