调用QGLWidget :: setFormat =没有绘图

时间:2014-04-30 05:00:01

标签: c++ qt opengl

我需要在现有的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。
  4. 新的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 )
    

1 个答案:

答案 0 :(得分: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,而我要求的版本是我得到的版本。

一个工作示例:

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