QOpenGLWidget类中的QPainter和OpenGL本机代码

dun*_*naj 3 c++ opengl qt qt5 visual-studio-2013

我正在准备一个桌面应用程序来绘制一些2D图.我正在使用C++:Qt 5和visual studio 2013.我创建了一个简单的GUI并将myQOpenGLWidget放入其中.我已经使用自己的openGl着色器绘制了图形,轴和刻度.一切正常,现在我想将描述添加到我的轴和刻度线,以使图形可以分析.就像在OpenGL中一样,没有用于渲染文本的专用函数,我想出了使用QPainter对象只是为了已经创建的绘图添加了所需的描述.以下是开始的问题......

这是我的QopenGLWidget实现的功能:

void GLWidget::initializeGL() {
initializeOpenGLFunctions();
glEnable(GL_POINT_SPRITE);
glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

vertexShad = new QOpenGLShader(QOpenGLShader::Vertex);
fragmentShad = new QOpenGLShader(QOpenGLShader::Fragment);

bool flag = vertexShad->compileSourceFile(QString("vs.glsl"));
if (flag) printf("compiled vertex Shader\n");
flag = fragmentShad->compileSourceFile(QString("fs.glsl"));
if (flag) printf("compiled fragment Shader\n");
flag = program.addShader(vertexShad);
if (flag) printf("linked vertex Shader\n");
flag = false;
flag =program.addShader(fragmentShad);
if (flag) printf("linked fragment Shader\n");

program.link();
program.bind();
}
Run Code Online (Sandbox Code Playgroud)

paintGL:

void GLWidget::paintGL() {
painter = new QPainter(this);

painter->beginNativePainting();
glViewport(0, 0, this->width(), this->height());
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
drawAxes();
glViewport(MARGIN, MARGIN, this->width() - MARGIN * 2, this->height() - MARGIN * 2);
glScissor(MARGIN, MARGIN, this->width() - MARGIN * 2, this->height() - MARGIN * 2);
glEnable(GL_SCISSOR_TEST);
  // here are the functions which use native openGL code
  // ...
  // disabling openGL settings
glDisable(GL_SCISSOR_TEST);
glDisable(GL_POINT_SPRITE);
glDisable(GL_VERTEX_PROGRAM_POINT_SIZE);
glDisable(GL_BLEND);
painter->endNativePainting();

drawTicksValues(); // function that uses QPainter
painter->end();
 }
Run Code Online (Sandbox Code Playgroud)

drawTicksValues:

void GLWidget::drawTicksValues() {
char * maxText = new char[4];
sprintf(maxText, "%d", maxY);
char * minText = new char[4];
sprintf(minText, "%d", minY);
painter->drawText(0, MARGIN, QString(maxText));
painter->drawText(0, height() - MARGIN, QString(minText));
painter->drawText(MARGIN, height() - MARGIN + 20, QString("0"));
painter->drawText(width() - MARGIN, height() - MARGIN + 20, QString(100));
}
Run Code Online (Sandbox Code Playgroud)

主要:

int main(int argc, char *argv[])
{
 QApplication a(argc, argv);
 QSurfaceFormat  format;
 format.setSamples(4);
 format.setDepthBufferSize(24);
 format.setStencilBufferSize(8);

 QSurfaceFormat::setDefaultFormat(format);
 SymmGaitModels w;
 w.show();
 return a.exec();
}
Run Code Online (Sandbox Code Playgroud)

不幸的是,当我运行代码时,使用未注释的QPainter部分,轴和图被清除,只显示我用QPainter绘制的数字.但是如果我评论QPainter部分,那么绘图和轴都会正常绘制.有什么建议我如何将QPainter文本添加到我的情节而不是清除它?

dun*_*naj 5

我终于成功了.

首先,我必须更改并设置格式(您必须在显示小部件之前更改它),例如在main函数中,在我的应用程序显示之前

主要:

int main(int argc, char *argv[])
{
 QApplication a(argc, argv);

 SymmGaitModels w;
   // GLWidget is my implemantation of QOpenGLWidget
 GLWidget* gl = w.findChild<GLWidget*>("OpenGLWidget");
 QSurfaceFormat  format;
 //format.setSamples(4);
 //format.setDepthBufferSize(24);
 //format.setStencilBufferSize(8);
   format.setProfile(QSurfaceFormat::OpenGLContextProfile::CompatibilityProfile);
 QSurfaceFormat::setDefaultFormat(format);

 gl->setFormat(format);
 w.show();
 return a.exec();
}
Run Code Online (Sandbox Code Playgroud)

而且,我不得不在我的openGL函数之间移动所有(甚至启用和禁用诸如blend,point_sprite等之类的东西,这会导致我的问题)

QPainter-> beginNativePainting()
 ...
QPainter->endNativePainting();
Run Code Online (Sandbox Code Playgroud)

我不得不实现paintEvent函数.我只是把paintGL()表达式放在那里.现在我的函数看起来像这样:

void GLWidget::initializeGL() {
 printf("autoFILL: %d\n",this->autoFillBackground());
 initializeOpenGLFunctions(); // this function has to stay in initializeGL
 // commented functions below has to be removed and put after beginNativePainting
     //glEnable(GL_POINT_SPRITE);
 //glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
 //glEnable(GL_BLEND);
 //glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

   // shaders may be compiled and added here, but program has to be linked and built after beginNativePainting()
 vertexShad = new QOpenGLShader(QOpenGLShader::Vertex);
 fragmentShad = new QOpenGLShader(QOpenGLShader::Fragment);

 bool flag = vertexShad->compileSourceFile(QString("vs.glsl"));
 //bool flag = vertexShad->compileSourceCode(vertexShadSrc);
 if (flag) printf("compiled vertex Shader\n");
 flag = fragmentShad->compileSourceFile(QString("fs.glsl"));
 //flag = fragmentShad->compileSourceCode(fragmentShadSrc);
 if (flag) printf("compiled fragment Shader\n");
 flag = program.addShader(vertexShad);
 if (flag) printf("linked vertex Shader\n");
 flag = false;
 flag =program.addShader(fragmentShad);
 if (flag) printf("linked fragment Shader\n");
}

void GLWidget::paintEvent(QPaintEvent *e) {
 paintGL(); // still this, widget has to be now refreshed by widget->update()
 }

void GLWidget::paintGL() {
 painter = new QPainter(this);
 painter->beginNativePainting();
 //
 glEnable(GL_POINT_SPRITE);
 glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
 glEnable(GL_BLEND);
 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

 program.link();
 program.bind();
 //
 glViewport(0, 0, this->width(), this->height());
 glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
 glClear(GL_COLOR_BUFFER_BIT);
 drawAxes();
 glViewport(MARGIN, MARGIN, this->width() - MARGIN * 2, this->height() - MARGIN * 2);
 glScissor(MARGIN, MARGIN, this->width() - MARGIN * 2, this->height() - MARGIN * 2);
 glEnable(GL_SCISSOR_TEST);
 // methods using native openGL functions here
 glDisable(GL_SCISSOR_TEST);
 glDisable(GL_POINT_SPRITE);
 glDisable(GL_VERTEX_PROGRAM_POINT_SIZE);
 glDisable(GL_BLEND);
 program.disconnect();
 painter->endNativePainting();
 drawTicksValues();
 painter->end();
}
Run Code Online (Sandbox Code Playgroud)

添加paintEvent实现后,必须使用widget-> update()刷新openGL小部件.

希望它对那些努力使用QPainter和原生openGL函数的人有所帮助,因为Qt doc在这个主题上似乎有点浅薄.

谢谢!亚当