Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Error when use stencil buffer in FBO(QOpenGLFramebufferObject)
QtWS25 Last Chance

Error when use stencil buffer in FBO(QOpenGLFramebufferObject)

Scheduled Pinned Locked Moved Unsolved General and Desktop
2 Posts 1 Posters 153 Views
  • 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.
  • MartinChan3M Offline
    MartinChan3M Offline
    MartinChan3
    wrote on last edited by MartinChan3
    #1

    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
    0
    • MartinChan3M Offline
      MartinChan3M Offline
      MartinChan3
      wrote on last edited by
      #2

      So could anyone give some advice? :(

      1 Reply Last reply
      0

      • Login

      • Login or register to search.
      • First post
        Last post
      0
      • Categories
      • Recent
      • Tags
      • Popular
      • Users
      • Groups
      • Search
      • Get Qt Extensions
      • Unsolved