c++ - 调用 QGLWidget::setFormat = 无绘图

标签 c++ qt opengl

我需要向现有的 Qt 应用程序添加一些 3D 图形。我使用的是 Qt 5.2,但我使用的是旧的 QGL* 类,至少目前是这样。首先,我只想画一个三角形。

我本来可以正常工作,但后来我尝试通过调用 QGLWidget::setFormat 显式设置 OpenGL 版本,突然间我的三角形不再绘制了。我注释掉了我实际设置版本的那一行,它没有任何区别:用 QGLWidget::format 返回的值调用 QGLWidget::setFormat 突然使绘图不发生。发生了什么事?

测试GL.cpp:

#include <QApplication>
#include <QDialog>
#include <QVBoxLayout>

#include "GLWidget.h"

class GLDialog : public QDialog
{
public:
  GLDialog()
  {
    QVBoxLayout *layout = new QVBoxLayout(this);
    layout->addWidget(new GLWidget);
  }
};

int main(int argc, char **argv)
{
  QApplication app(argc, argv);

  GLDialog dlg;
  dlg.resize(200,200);
  dlg.show();

  return app.exec();

}

GLWidget.h:

#ifndef GLWIDGET_H
#define GLWIDGET_H

#include <QColor>
#include <QGLWidget>
#include <QVector>
#include <QVector3D>

class GLWidget : public QGLWidget
{
  Q_OBJECT
public:
  GLWidget(QWidget * = 0, const QGLWidget * = 0, Qt::WindowFlags = 0);

protected:
  virtual void initializeGL();
  virtual void paintGL();
  virtual void resizeGL(int, int);
  //virtual void mousePressEvent(QMouseEvent *);
  //virtual void mouseMoveEvent(QMouseEvent *);

private:
  QVector<QVector3D> _triangle;
  QColor _backgroundColour;
  QColor _triangleColour;
};

#endif

GLWidget.cpp:

#include <QtOpenGL>
#include <QGLContext>
#include <QGLFormat>
#include <QGLShader>
#include <QGLShaderProgram>

#include <QDebug>

#include "GLWidget.h"


GLWidget::GLWidget(QWidget *parent, const QGLWidget *shareWidget, Qt::WindowFlags f)
: QGLWidget(parent, shareWidget, f)
{ 
  QGLFormat newFormat(format());
  //newFormat.setVersion(3,3);
  /* Comment out the following line and a triangle appears */
  setFormat(newFormat);
}

void GLWidget::initializeGL()
{
  _backgroundColour = Qt::black;
  _triangleColour = Qt::white;
  _triangle.push_back(QVector3D(-0.75, 0.75, 0));
  _triangle.push_back(QVector3D(-0.75, -0.75, 0));
  _triangle.push_back(QVector3D(0.75, -0.75, 0));


}

void GLWidget::paintGL()
{
  qglClearColor(_backgroundColour);
  glClear(GL_COLOR_BUFFER_BIT);

  glEnableClientState(GL_VERTEX_ARRAY);
  glVertexPointer(3, GL_FLOAT, 0, _triangle.constData());
  glDrawArrays(GL_TRIANGLES, 0, 3);


}

void GLWidget::resizeGL(int width, int height)
{
  int side = qMin(width, height);

  int hoffset = (int)((width - side) / 2.0 + 0.5);
  int voffset = (int)((height - side) / 2.0 + 0.5);

  glViewport(hoffset, voffset, side, side);
}

testGL.pro:

######################################################################
# Automatically generated by qmake (3.0) Fri Apr 18 16:09:15 2014
######################################################################

TEMPLATE = app
TARGET = testGL
INCLUDEPATH += .
CONFIG += qt warn_on debug

QT += opengl

# Input
HEADERS += GLWidget.h
SOURCES += GLWidget.cpp testGL.cpp

我是 OpenGL 的初学者,所以请原谅我的代码愚蠢。请注意,我没有明确设置着色器。那将是我的下一步。

更新:

我关注了this advice并使用带有 QGLFormat 对象的备用 QGLWidget 构造函数。我得到了一些有趣的行为。

  1. 如果我只创建一个 QGLFormat,但不设置它的版本,我会得到一个三角形。请求的版本是 2.0,但检查我的 GLWidget 构造函数中的版本显示它是 3.0。
  2. 如果我显式调用 QGLFormat::setVersion(3,0),我会得到版本 3.3,但不会得到三角形。
  3. 如果我显式调用 QGLFormat::setVersion(2,0),我会得到一个三角形,并且设置的版本是 3.0。

新的 GLDialog 代码:

class GLDialog : public QDialog
{
public:
  GLDialog()
  {
    QVBoxLayout *layout = new QVBoxLayout(this);
    QGLFormat format;

    /* Comment this line out or change to 2,0 to get a triangle */
    format.setVersion(3,0); 

    layout->addWidget(new GLWidget(format,this));
  }
};

在 GLWidget 构造函数中输出此格式字符串:

QGLFormat(options QFlags(0x1|0x2|0x4|0x8|0x20|0x80|0x400) , plane  0 , depthBufferSize  24 , accumBufferSize  -1 , stencilBufferSize  8 , redBufferSize  8 , greenBufferSize  8 , blueBufferSize  8 , alphaBufferSize  8 , samples  -1 , swapInterval  -1 , majorVersion  3 , minorVersion  3 , profile  1 )

如果我注释掉指示的行:

QGLFormat(options QFlags(0x1|0x2|0x4|0x8|0x20|0x80|0x400) , plane  0 , depthBufferSize  24 , accumBufferSize  -1 , stencilBufferSize  8 , redBufferSize  8 , greenBufferSize  8 , blueBufferSize  8 , alphaBufferSize  8 , samples  -1 , swapInterval  -1 , majorVersion  3 , minorVersion  0 , profile  0 )

如果我将请求的版本更改为 2.0:

QGLFormat(options QFlags(0x1|0x2|0x4|0x8|0x20|0x80|0x400) , plane  0 , depthBufferSize  24 , accumBufferSize  -1 , stencilBufferSize  8 , redBufferSize  8 , greenBufferSize  8 , blueBufferSize  8 , alphaBufferSize  8 , samples  -1 , swapInterval  -1 , majorVersion  3 , minorVersion  0 , profile  0 )

最佳答案

在我调用 setFormat() 之后,在我的 GLWidget 构造函数中调用 makeCurrent() 就可以了。使用 Qt 5.2,设置格式实际上并没有给我请求的格式(即,请求 OpenGL 2.1 实际上设置了 OpenGL 3.0,而请求 3.0 实际上设置了 3.3)。虽然我的系统支持 OpenGL 3.3,但除非使用的版本是 3.0 或更低版本,否则我不会得到三角形。但是设置版本有效。

对采用 QGLFormat 对象的备用构造函数的调用也有效(直到 3.0 版...同样,请求 3.0 给我 3.3,请求 2.1 给我 3.0)。

使用Qt 4.8,同样的代码可以工作,并且可以请求到3.3版本,我请求的版本就是我得到的版本。

一个工作示例:

测试GL.cpp:

#include <QApplication>
#include <QDialog>
#include <QGLFormat>
#include <QVBoxLayout>

#include <QDebug>
#include "GLWidget.h"

class GLDialog : public QDialog
{
public:
  GLDialog()
  {
    QVBoxLayout *layout = new QVBoxLayout(this);
    layout->addWidget(new GLWidget(this));//format,this));
  }
};

int main(int argc, char **argv)
{
  QApplication app(argc, argv);

  GLDialog dlg;
  dlg.resize(200,200);
  dlg.show();

  return app.exec();

}

GLWidget.h:

#ifndef GLWIDGET_H
#define GLWIDGET_H

#include <QColor>
#include <QGLWidget>
#include <QGLFormat>
#include <QGLFunctions>
#include <QGLShader>
#include <QGLShaderProgram>

#include <QVector>
#include <QVector3D>

class GLWidget : public QGLWidget, protected QGLFunctions
{
  Q_OBJECT
public:
  GLWidget(QWidget * = 0, const QGLWidget * = 0, Qt::WindowFlags = 0);

protected:
  virtual void initializeGL();
  virtual void paintGL();
  virtual void resizeGL(int, int);

private: 
  QVector<QVector3D> _triangle;
  QColor _backgroundColour;
};

#endif

GLWidget.cpp:

#include <QtOpenGL>
#include <QGLContext>
#include <QGLFormat>

#include <QDebug>

#include <string>
#include <cstring>
#include "GLWidget.h"

GLWidget::GLWidget(QWidget *parent, const QGLWidget *shareWidget, Qt::WindowFlags f)
: QGLWidget(parent, shareWidget, f)
{ 
  QGLFormat newFormat(format());
  newFormat.setVersion(2,1);
  setFormat(newFormat);

  makeCurrent();
  resizeGL(width(), height());
}

void GLWidget::initializeGL()
{  
  _backgroundColour = Qt::black;

  _triangle.push_back(QVector3D(-0.75, 0.75, 0));
  _triangle.push_back(QVector3D(-0.75, -0.75, 0));
  _triangle.push_back(QVector3D(0.75, -0.75, 0));
}

void GLWidget::paintGL()
{
  qglClearColor(_backgroundColour);
  glClear(GL_COLOR_BUFFER_BIT);

  glEnableClientState(GL_VERTEX_ARRAY);
  glVertexPointer(3, GL_FLOAT, 0, _triangle.constData());
  glDrawArrays(GL_TRIANGLES, 0, 3);

}

void GLWidget::resizeGL(int width, int height)
{
  int side = qMin(width, height);

  int hoffset = (int)((width - side) / 2.0 + 0.5);
  int voffset = (int)((height - side) / 2.0 + 0.5);

  glViewport(hoffset, voffset, side, side);
}

testGL.pro:

######################################################################
# Automatically generated by qmake (3.0) Fri Apr 18 16:09:15 2014
######################################################################

TEMPLATE = app
TARGET = testGL
INCLUDEPATH += .
CONFIG += qt warn_on debug

QT += opengl

# Input
HEADERS += GLWidget.h
SOURCES += GLWidget.cpp testGL.cpp

关于c++ - 调用 QGLWidget::setFormat = 无绘图,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23379995/

相关文章:

c++ - 在Qt中模拟全局按键

windows - 在 Qt5 中 QWidget::winEvent 不存在

c++ - 在顶点着色器中将纹理数据解释为顶点数据

c++ - 如何分析 Linux 可执行文件的静态内存使用情况?

c++ - 如何处理 “signed/unsigned mismatch” 警告(C4018,无循环)?

c++ - C++ 和 QML 中的 QT QML 项

qt - 配置 qtbase 失败,错误为 : "Could not find qmake spec ' '.”

algorithm - 不变尺度几何

performance - 2d 绘图基元和图像 : OpenGL, Cairo 或 Agg

android - 来自 glUniform1i 的无法解释的 GL_INVALID_OPERATION(OpenGL 认为 int 是 float?)