在 Qt 5.4 中 类 使用最新的 OpenGL 函数
Using latest OpenGL functions across classes in Qt 5.4
我之前发布了一个关于如何让 OpenGL 在 Qt 上工作的问题,但现在我希望能够使用 OpenGL 的最新功能。在 Qt 之前,我使用的是 glew;但是 Qt 说 glew 与其 QtOpenGL 头文件冲突。我研究了 QGLWidget 和 QGLFunctions,但坦率地说,我很困惑我应该做什么才能简单地访问 OpenGL 的函数。
现在,我使用 Qt Creator 3.3.0 获得了 Qt 5.4,并且正在使用新的 QOpenGLWidget;然而,缺乏关于如何使用它的指导让我有点失望:Qt 文档在那里并且确实有帮助,但它只演示了如何实例化它,而不是在程序的其他位置使用它。我了解到这个QOpenGLWidget 的功能类似于QGLWidget。我应该从它继承的 Qt 详细信息;但是我没有在 class 中实例化 OpenGL 上下文,它想使用 OpenGL 函数;这发生在 class 'glWidget' 中,它继承自 QOpenGLWidget。
例如,摘自我的一个使用 OpenGL 代码的 classes:
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 是一个 class,它不继承任何东西。最初,它只是使用 glew 来获取 OpenGL 函数的声明;它不需要知道它们是否有效,因为那是 glew 的工作。然后在 mainApp class 中,我将实例化 glew。我也知道还有一个 QOpenGLFunctions class ,它的功能有点类似于 glew,但是对于所有这些 GL classes 来说,知道使用什么是非常混乱的。更重要的是,我尝试寻找 glGenVertexArrays(..) 但在 QOpenGLBuffer、QOpenGLFunctions 或 QOpenGLWidget 中找不到;据我所知,从 OpenGL 4.5 开始,它仍然是规范的一部分;但是我的图形驱动程序不使用 OpenGL 4.5,所以我改用 OpenGL 4.3。我只想说我愿意放弃 glew 以采用 Qt 自己的方法来调用 OpenGL 函数。
在各种 classes 使用 OpenGL 函数的程序中,我如何利用 Qt 调用它们而不使用 glew? Mesh 是其中一个 class 不实例化 OpenGL,但仅使用其功能。
让人们知道,我已经使用 Qt 一段时间了(虽然还不够!)并且非常喜欢 Qt;但我确实需要知道如何将 Qt 与 OpenGL 结合使用以继续开发。大多数教程仍然使用 5.4 之前的内容。
使用 OpenGL 的直接方法是创建一个包含函数指针的结构:
struct sLGLAPI
{
sLGLAPI() { memset( this, 0, sizeof( *this ) ); };
PFNGLACTIVETEXTUREPROC glActiveTexture;
PFNGLATTACHSHADERPROC glAttachShader;
PFNGLBEGINQUERYPROC glBeginQuery;
PFNGLBINDATTRIBLOCATIONPROC glBindAttribLocation;
...
用来自 OpenGL 共享库的指针 dlsym
填充它:
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 之间切换。
在 Qt 5.4 中,有带有版本特定 OpenGL 函数的头文件,因此:
#include <QOpenGLFunctions_3_3_Core>
或者您要使用的任何版本。然后在某个具有有效 OpenGL 上下文的地方,如 QOpenGLWidget::initializeGL() 创建并初始化一个 QOpenGLFunctions 对象:
QOpenGLFunctions_3_3_Core *fun = new QOpenGLFunctions_3_3_Core;
fun->initializeOpenGLFunctions();
然后在您的绘图代码中,只需使用该对象的 OpenGL 函数:
fun->glSomething(1,2,3)
#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.
};
使用QOpenGLFunctions_X_X_* 解决不了这个问题!
在使用 QOpenGLFunctions_X_X_* 之前,您需要设置 openGL 上下文的版本。
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);
干杯,
奈
我之前发布了一个关于如何让 OpenGL 在 Qt 上工作的问题,但现在我希望能够使用 OpenGL 的最新功能。在 Qt 之前,我使用的是 glew;但是 Qt 说 glew 与其 QtOpenGL 头文件冲突。我研究了 QGLWidget 和 QGLFunctions,但坦率地说,我很困惑我应该做什么才能简单地访问 OpenGL 的函数。
现在,我使用 Qt Creator 3.3.0 获得了 Qt 5.4,并且正在使用新的 QOpenGLWidget;然而,缺乏关于如何使用它的指导让我有点失望:Qt 文档在那里并且确实有帮助,但它只演示了如何实例化它,而不是在程序的其他位置使用它。我了解到这个QOpenGLWidget 的功能类似于QGLWidget。我应该从它继承的 Qt 详细信息;但是我没有在 class 中实例化 OpenGL 上下文,它想使用 OpenGL 函数;这发生在 class 'glWidget' 中,它继承自 QOpenGLWidget。
例如,摘自我的一个使用 OpenGL 代码的 classes:
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 是一个 class,它不继承任何东西。最初,它只是使用 glew 来获取 OpenGL 函数的声明;它不需要知道它们是否有效,因为那是 glew 的工作。然后在 mainApp class 中,我将实例化 glew。我也知道还有一个 QOpenGLFunctions class ,它的功能有点类似于 glew,但是对于所有这些 GL classes 来说,知道使用什么是非常混乱的。更重要的是,我尝试寻找 glGenVertexArrays(..) 但在 QOpenGLBuffer、QOpenGLFunctions 或 QOpenGLWidget 中找不到;据我所知,从 OpenGL 4.5 开始,它仍然是规范的一部分;但是我的图形驱动程序不使用 OpenGL 4.5,所以我改用 OpenGL 4.3。我只想说我愿意放弃 glew 以采用 Qt 自己的方法来调用 OpenGL 函数。
在各种 classes 使用 OpenGL 函数的程序中,我如何利用 Qt 调用它们而不使用 glew? Mesh 是其中一个 class 不实例化 OpenGL,但仅使用其功能。
让人们知道,我已经使用 Qt 一段时间了(虽然还不够!)并且非常喜欢 Qt;但我确实需要知道如何将 Qt 与 OpenGL 结合使用以继续开发。大多数教程仍然使用 5.4 之前的内容。
使用 OpenGL 的直接方法是创建一个包含函数指针的结构:
struct sLGLAPI
{
sLGLAPI() { memset( this, 0, sizeof( *this ) ); };
PFNGLACTIVETEXTUREPROC glActiveTexture;
PFNGLATTACHSHADERPROC glAttachShader;
PFNGLBEGINQUERYPROC glBeginQuery;
PFNGLBINDATTRIBLOCATIONPROC glBindAttribLocation;
...
用来自 OpenGL 共享库的指针 dlsym
填充它:
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 之间切换。
在 Qt 5.4 中,有带有版本特定 OpenGL 函数的头文件,因此:
#include <QOpenGLFunctions_3_3_Core>
或者您要使用的任何版本。然后在某个具有有效 OpenGL 上下文的地方,如 QOpenGLWidget::initializeGL() 创建并初始化一个 QOpenGLFunctions 对象:
QOpenGLFunctions_3_3_Core *fun = new QOpenGLFunctions_3_3_Core;
fun->initializeOpenGLFunctions();
然后在您的绘图代码中,只需使用该对象的 OpenGL 函数:
fun->glSomething(1,2,3)
#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.
};
使用QOpenGLFunctions_X_X_* 解决不了这个问题! 在使用 QOpenGLFunctions_X_X_* 之前,您需要设置 openGL 上下文的版本。 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);
干杯, 奈