QOpenGLWidget类中的QPainter和OpenGL本机代码 [英] QPainter and OpenGL native code in QOpenGLWidget class

查看:146
本文介绍了QOpenGLWidget类中的QPainter和OpenGL本机代码的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在准备一个桌面应用程序来绘制一些2D图.我正在使用C ++:Qt 5和Visual Studio2013.我创建了一个简单的GUI,并将myQOpenGLWidget放入其中.我已经在使用自己的openGl着色器绘制绘图,坐标轴和刻度线了.一切正常,现在我想将说明添加到我的坐标轴和刻度中,以使图形可以分析.由于在OpenGL本身中没有专门的功能来渲染文本,因此我想出了使用QPainter对象只是为了将所需的描述添加到已创建的绘图中.这是开始出现的问题...

I am preparing a desktop application to draw some 2D plots. I am using C++: Qt 5 and visual studio 2013. I created a simple GUI and put myQOpenGLWidget in it. I am already drawing the plots, axes and ticks using my own openGl shaders. Everything works fine and now I want to add the description to my axes and ticks to make the graph possible to analysis. As in OpenGL itself there is no dedicated functions to render text, I came up with using QPainter object just to add the desired description to already created plot. And here are problems starting...

这是我QopenGLWidget实现的功能:

Here is my functions of my QopenGLWidget implementation:

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();
}

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();
 }

drawTicksValues:

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));
}

主要:

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();
}

不幸的是,当我运行代码时,如果未注释QPainter部分,则清除了轴和图,仅显示了我用QPainter绘制的数字.但是,如果我评论QPainter部分,则将正常绘制图和轴.有什么建议可以将带有QPainter的文本添加到绘图中而不是将其清除?

Unfortunately, when I run the code, with uncommented QPainter part, the axis and plots are cleared, only the numbers I paint with QPainter are shown. But if I comment the QPainter part, the plots and axes are drawed normally. Any suggestions how I can add the text with QPainter to my plot instead of clearing it?

推荐答案

我终于设法使事情起作用.

I finally managed to get things work.

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

First of all, I had to change and set the format (you have to change it before widget is shown), for example in main function , before my app was shown

主要:

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();
}

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

Moreover, I had to move all (even enabling and disabling things like blend, point_sprite etc, which caused my problems) of my openGL functions between

QPainter-> beginNativePainting()
 ...
QPainter->endNativePainting();

我必须实现paintEvent函数.我只是在这里放了paintGL()表达式. 现在我的函数看起来像这样:

And I had to implement paintEvent function. I just put paintGL() expression there. Now my functions look like that:

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();
}

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

After adding paintEvent implementation, the openGL widget has to be now refreshed using widget->update().

希望这对那些同时使用QPainter和本机openGL函数而苦苦挣扎的人有所帮助,因为Qt doc在这个话题上似乎有些肤浅.

Hope it will be helpful for other people who are struggling with using both QPainter and native openGL functions, as Qt doc seems to be a little shallow on this topic.

谢谢! 亚当

这篇关于QOpenGLWidget类中的QPainter和OpenGL本机代码的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆