【问题标题】:Error when use stencil buffer in FBO(QOpenGLFramebufferObject)在 FBO(QOpenGLFramebufferObject)中使用模板缓冲区时出错
【发布时间】:2020-12-19 07:42:57
【问题描述】:

我尝试在这样的 fbo 中绘制凹多边形(这只是正方形中的三角形),并且我在 QOpenGLWidget 中成功绘制了它:
example.png
但是,当我想在 FBO 中绘制它并将其转换为图像保存时,结果总是错误(只是一个黑色图像)。我在启用模板缓冲区的情况下绘制凹多边形,这里是所有代码(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");
}

顶点.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;
}

参考:
堆栈溢出:Draw a concave polygon in OpenGL

【问题讨论】:

    标签: c++ qt opengl qopenglfunctions


    【解决方案1】:

    帧缓冲区没有模板缓冲区。您必须将额外的模板缓冲区附件附加到帧缓冲区。更改QOpenGLFramebufferObjectFormat并设置附件QOpenGLFramebufferObject::CombinedDepthStencil

    QOpenGLFramebufferObjectFormat format;
    format.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
    

    【讨论】:

    • 其实这个方法我试过了,但是不行:(
    猜你喜欢
    • 2012-01-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-08
    • 2011-09-05
    相关资源
    最近更新 更多