我尝试在这样的 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 中绘制凹多边形