在Qt 5.4中跨类使用最新的OpenGL函数

时间:2015-01-30 12:10:12

标签: c++ qt opengl opengl-es qt5

我之前发布了一个关于如何让OpenGL在Qt上工作的问题,但现在我希望能够使用OpenGL的最新功能。在Qt之前,我正在使用glew;但Qt说glew与其QtOpenGL头文件冲突。我查看了QGLWidget和QGLFunctions,但坦率地说,我对于为了简单地访问OpenGL的功能而应该做些什么感到困惑。

现在,我使用Qt Creator 3.3.0获得了Qt 5.4并使用了新的QOpenGLWidget;然而,如何使用它缺乏指导会让我失望:Qt文档存在并且确实有帮助,但它只演示了如何实例化它,而不是在程序的其他位置使用它。据我所知,这个QOpenGLWidget函数类似于QGLWidget。 Qt详细说明我应该继承它;但是我没有在它想要使用OpenGL函数的类中实例化OpenGL上下文;发生在类'glWidget'中,它继承自QOpenGLWidget。

例如,从我的一个使用OpenGL代码的类中摘录:

void Mesh::init()
{
    pNumIndices = pIndices.size();

    glGenVertexArrays(1, &pVAO);
    glGenBuffers(1, &pVertexBuffer);
    glGenBuffers(1, &pIndexBuffer);
    glBindVertexArray(pVAO);

    glBindBuffer(GL_ARRAY_BUFFER, pVertexBuffer);
    glBufferData(GL_ARRAY_BUFFER, pVertices.size() * sizeof(Vertex),
                 &pVertices[0], GL_STATIC_DRAW);

    // etc..
}

Mesh是一个不从任何东西继承的类。最初,它只使用了glew,因此它可以获得OpenGL函数的声明;它不需要知道它们是否有效,因为那是glew的工作。然后在mainApp类中,我将实例化glew。我也明白,还有一个QOpenGLFunctions类,它的功能与glew的功能类似,但是对于所有这些GL类而言,知道要使用的内容显然令人困惑。更重要的是,我尝试寻找glGenVertexArrays(..),但在QOpenGLBuffer,QOpenGLFunctions或QOpenGLWidget中找不到它;到目前为止,我知道,从OpenGL 4.5开始,它仍然是规范的一部分;但我的图形驱动程序不使用OpenGL 4.5,所以我改用OpenGL 4.3。我只想说我愿意放弃采用Qt自己的方法来调用OpenGL函数。

在各种类使用OpenGL函数的程序中,如何在不使用glew的情况下使用Qt来调用它们? Mesh是那些不实例化OpenGL的类之一,但仅仅使用其功能。

正如人们所知,我已经使用Qt一段时间了(虽然不够!)并且确实喜欢Qt;但我确实需要知道如何将Qt与OpenGL结合使用以继续开发。大多数教程仍然使用5.4之前的东西。

4 个答案:

答案 0 :(得分:4)

在Qt 5.4中,有标题版本特定的OpenGL函数,所以:

#include <QOpenGLFunctions_3_3_Core>

或者您想要使用的任何版本。然后使用像QOpenGLWidget :: initializeGL()这样的有效OpenGL上下文创建并初始化QOpenGLFunctions对象:

QOpenGLFunctions_3_3_Core *fun = new QOpenGLFunctions_3_3_Core;
fun->initializeOpenGLFunctions();

然后在你的绘图代码中,只使用该对象的OpenGL函数:

fun->glSomething(1,2,3)

答案 1 :(得分:2)

使用QOpenGLFunctions_X_X_ *无法解决此问题! 您需要先设置openGL上下文的版本,然后才能使用QOpenGLFunctions_X_X_ *。 Qt使用默认版本(我认为1.X),因此您需要将此代码添加到main.cpp文件中

        QSurfaceFormat format;
//        format.setDepthBufferSize(24);
    //    format.setStencilBufferSize(8);

        format.setMajorVersion( 3 ); //whatever version
        format.setMinorVersion( 3 ); //
        format.setProfile(QSurfaceFormat::CoreProfile);
        QSurfaceFormat::setDefaultFormat(format);

干杯, 奈

答案 2 :(得分:1)

使用OpenGL的简单方法是创建一个包含函数指针的结构:

struct sLGLAPI
{
    sLGLAPI() { memset( this, 0, sizeof( *this ) ); };
    PFNGLACTIVETEXTUREPROC      glActiveTexture;
    PFNGLATTACHSHADERPROC       glAttachShader;
    PFNGLBEGINQUERYPROC         glBeginQuery;
    PFNGLBINDATTRIBLOCATIONPROC glBindAttribLocation;
    ...

使用指针dlsym填充 - 来自OpenGL共享库:

API->glActiveTexture = ( PFNGLACTIVETEXTUREPROC )GetGLProc( "glActiveTexture" );
API->glAttachShader = ( PFNGLATTACHSHADERPROC )GetGLProc( "glAttachShader" );
API->glBeginQuery = ( PFNGLBEGINQUERYPROC )GetGLProc( "glBeginQuery" );
API->glBindAttribLocation = ( PFNGLBINDATTRIBLOCATIONPROC )GetGLProc( "glBindAttribLocation" );

仅通过此结构访问代码中的OpenGL。例如:

API->glShaderSource( Shader, 1, &Code, nullptr );
API->glCompileShader( Shader );

这样您就可以隐藏完整的OpenGL API,甚至可以在必要时使用存根函数,例如,记录参数或在OpenGL和OpenGL ES之间切换。

答案 3 :(得分:1)

#include <QOpenGLFunctions_3_3_Core>

class Mesh : public QOpenGLFunctions_3_3_Core
{
public:
    Mesh();//initializeOpenGLFunctions()
    ~Mesh();      

    void func();//glxxx in it. when using it ,you need an opengl context.
                //for example, use makeCurrent() in QOpenGLWidget subclass.
};