0

我尝试在这样的 fbo 中绘制凹多边形(这只是正方形中的三角形),并且我在 QOpenGLWidget 中成功绘制了它:
example.png
但是当我想在 FBO 中绘制它并将其转换为图像时保存,结果总是错误(只是一个黑色的图像)。我在启用模板缓冲区的情况下绘制凹多边形,这里是所有代码(<a href="https://www.wenshushu.cn/f/3dyxccyxn6w" rel= "nofollow noreferrer">项目包下载):


主.cpp:

#include <QApplication>
#include "renderwidget.h"

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    RenderWidget pw;
    pw.show();

    return a.exec();
}

渲染小部件.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

渲染小部件.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;
}

碎片片段:

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

参考:
Stackoverflow:在 OpenGL 中绘制凹多边形

4

1 回答 1

0

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

QOpenGLFramebufferObjectFormat format;
format.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
于 2020-08-31T07:47:00.037 回答