Error when use stencil buffer in FBO(QOpenGLFramebufferObject)
Unsolved
General and Desktop
-
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:
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 -
So could anyone give some advice? :(