【问题标题】:Calling QGLWidget::setFormat = no drawing调用 QGLWidget::setFormat = 不绘图
【发布时间】:2014-05-03 01:00:12
【问题描述】:

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

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

testGL.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 )

【问题讨论】:

  • 您使用的 Qt 版本是什么,什么平台?请注意,setFormat 已过时。不要使用它。直接处理上下文。
  • Arch Linux 上的 Qt 5.2。 QGLContext 似乎不允许我设置 OpenGL 版本...除非您的意思是调用 QGLWidget::context()->setFormat(...)。当我这样做时,背景甚至都没有被清除。

标签: c++ qt opengl


【解决方案1】:

在我调用 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版本,我请求的版本就是我得到的版本。

一个工作示例:

testGL.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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-03-16
    • 1970-01-01
    • 1970-01-01
    • 2016-04-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多