使用glew在QT中解决OpenGL函数问题

8

已经过去了17天,我正在努力使用QT编写OpenGL的简单程序,但是在谷歌上搜索到的所有教程都失败了。

我已经使用msvc2010编译了QT 5.0.1,并使用-opengl desktop选项使桌面OpenGL成为默认选项。

我阅读了Sean Harmer的教程,但它依赖于QT来解决OpenGL函数。

根据一些人的说法,不可能在QT中使用glew,因为QT内置库会阻止glew包含其头文件,但根据Sean Harmer 这里 的说法,这是可能的(但没有说明如何实现)。

即使使用QGLWidget,我也无法使用OpenGL扩展。

现在我想要使用所有OpenGL函数和所有QT窗口函数分开,即QT不对OpenGL产生干扰。

如果有人能用简单的三角形示例和任何扩展向我解释该过程,我将不胜感激。

我在项目中使用了glew库,并在程序的起始位置#include了glew.h,但编译时出现错误:

glwidget.obj:-1: error: LNK2001: unresolved external symbol imp_ _glewGenVertexArrays

我的.pro文件:

QT       += core gui opengl

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

TARGET = Trial
TEMPLATE = app

SOURCES += main.cpp\
        mainwindow.cpp \
    glwidget.cpp

HEADERS  += mainwindow.h \
    glwidget.h

FORMS    += mainwindow.ui

RESOURCES += \
    resources.qrc
win32: LIBS += -L$$PWD/../../../../../OpenGL/glew-1.9.0/lib/ -lglew32s

INCLUDEPATH += $$PWD/../../../../../OpenGL/glew-1.9.0/include
DEPENDPATH += $$PWD/../../../../../OpenGL/glew-1.9.0/include

win32: PRE_TARGETDEPS += $$PWD/../../../../../OpenGL/glew-1.9.0/lib/glew32s.lib

通过glewInfo输出: GLEW版本1.9.0 报告像素格式1的能力 运行于来自NVIDIA Corporation的GeForce GT 540M/PCIe/SSE2 支持OpenGL版本4.3.0

void GLWidget::initializeGL()
{
    GLenum err = glewInit();
    if(err != GLEW_OK)
    {
        printf("%s",glewGetErrorString(err));
    }

    glEnable(GL_DEPTH_TEST);
    qglClearColor(QColor(Qt::red));

    shaderProgram.addShaderFromSourceFile(QGLShader::Vertex, ":/vertexShader.vsh");
    shaderProgram.addShaderFromSourceFile(QGLShader::Fragment, ":/fragmentShader.fsh");
    shaderProgram.link();
    shaderProgram.bind();

    const GLubyte *oglVersion = glGetString(GL_VERSION);
    printf( "%s\n",oglVersion );

    GLfloat vertices[3][3] ={{ -0.5, -0.5, -1 },
                { 0,    0.5,    -1},
                    { 0.5,  -0.5,   -1}};
    vertexArray.create();
    vertexArray.setUsagePattern(QOpenGLBuffer::StaticDraw);
    vertexArray.allocate( vertices, 3 * 3 * sizeof( GLfloat ) );
    vertexArray.bind();
    shaderProgram.setAttributeBuffer( "vVertex", GL_FLOAT, 0, 3 );
    shaderProgram.enableAttributeArray( "vVertex" );

    GLuint arr[5];
    glGenBuffers(5,arr);
}

当使用静态标记添加glew32s.lib时,会出现“unresolved external symbol imp__glew”错误,但是当使用动态标记添加glew32.lib时,这些错误会消失。 尽管我的程序在调试模式下意外终止,但问题出在glDrawArrays... - avg598
如果您正在尝试在Windows上进行静态链接,您需要定义GLEW_STATIC标记。假定您在拥有有效上下文后调用了glewInit() - cmannett85
是的,我在 initializeGL() 中使用了 glewInit()。 正如您所说,我添加了 GLEW_STATIC 在 #include glew.h 的前面,但它会出现警告: :-1: warning: LNK4098: defaultlib 'LIBCMT' conflicts with use of other libs; use /NODEFAULTLIB:library glew32s.lib(glew.obj):-1: warning: LNK4099: PDB 'vc100.pdb' was not found with 'glew32s.lib(glew.obj)' or at 'D:\Dexter\Softwares\Programming stuff\QT Projects\Trial-build-Desktop_Qt_5_0_1_MSVC2010_32bit-Debug\debug\vc100.pdb'; linking object as if no debug info. - avg598
我对MSVC不是很了解,但它似乎在告诉你“使用 /NODEFAULTLIB:library glew32s.lib”。 - cmannett85
我从未使用过GLUT,所以不清楚。如果您正在静态链接到GLEW,则建议您首先从源代码构建它。 - cmannett85
显示剩余7条评论
3个回答

17

所有问题现已解决。

第一个问题是:QT 5.0.1默认不支持OpenGL,需要使用 -opengl desktop 编译。 这里是有关如何使用VS2010编译QT的教程, 或者您可以从QT下载新的OpenGL版本。

第二个问题是将glew库添加到项目中。 如果您添加 glew32s.lib(静态库),则必须在“#include ”之前添加“#define GLEW_STATIC”。 建议使用 glew32.lib(动态库)。

第三个问题是,即使您的GPU支持版本4.3,某些OpenGL函数仍会出现段错误。 GLEW从图形驱动程序中获取有关支持的扩展信息。然而,实验性或预发布驱动程序可能不会通过标准机制报告每个可用的扩展名,在这种情况下,GLEW将报告不支持。为了解决这种情况,可以在调用glewInit()之前将glewExperimental全局开关设置为GL_TRUE,这样可以确保公开所有具有有效入口点的扩展名。

花了18天时间解决这些问题,现在很高兴能开始实际编程。


4

以下代码可以在 MSVC2008 express、qt 4.8.1 和 glew 版本 1.7.0 上编译通过:

main.cpp:

#include <GL/glew.h>
#include <QApplication>
#include <QGLWidget>

int main(int argc, char** argv){
    glewInit();//<<-- glew function
    QApplication app(argc, argv);
    QGLWidget widget;

    GLuint arr;
    glGenVertexArrays(1, &arr);//<--no linker error (added just for testing, most likely won't gen arrays)

    widget.show();
    return app.exec();
}

gltest.pro:

TEMPLATE = app
TARGET = 
DEPENDPATH += .
INCLUDEPATH += . d:/c++/libs/include
LIBS += -L"d:/c++/libs/lib" -lglew32

CONFIG += console
QT += opengl

# Input
SOURCES += main.cpp

我认为在Qt 5中情况不会有任何不同。

可以自由地覆盖QGLWidget的paintGL,并使用扩展绘制任何内容。对于这个,我身边没有代码片段。

建议:
1. 使用预编译的二进制文件。
2. 使用动态链接版本的GLEW可能是有意义的。
3. 注意头文件包含顺序。

据一些人说

人们说很多事情,您不需要相信它们的全部。


0

我想分享一下我的最新发现,关于如何让Qt和glew在(目前)最新的Windows环境下(Qt 5.15.1 + QMake + MSVC 2019 + glew 2.1.0)共同工作。希望其他人可以避免像我一样花费无数小时来解决这个问题。以下是我所做的:

  1. 将glew32.dll和glew32.lib复制到项目目录中的某个位置。确保glew的位数与您告诉Qt要构建的可执行文件的位数匹配。我没有使用库的静态版本,因为我无法使其正常工作。
  2. 在您的.pro(QMake)文件中,编写类似于以下内容的代码:
GLEW_INCLUDE_PATH = "$$PWD/ext/glew/include" # put glew headers here
GLEW_LIB_PATH = "$$PWD/ext/glew/x64"         # put glew32.dll and glew32.lib here

LIBS += -L$$GLEW_LIB_PATH -lglew32 -lglu32 -lopengl32

DEPENDPATH += .
INCLUDEPATH += $$GLEW_INCLUDE_PATH

与之前的答案相比,我唯一做出的改变是将-lglu32-lopengl32添加到链接参数中。在Windows上似乎它们是必需的,否则MSVC会抱怨OpenGL API函数的某些链接错误。

  1. 此外,尝试使用QOpenGLWidget代替QGLWidget。当我的程序退出并尝试在析构函数中销毁OpenGL句柄(如缓冲区和纹理句柄)时,QGLWidget会导致一些奇怪的OpenGL“无效操作”错误。 glIntercept向我展示了这是因为wgl上下文在句柄被释放之前被销毁。切换到QOpenGLWidget完全解决了这个问题。

希望你现在可以享受使用glew和Qt了!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接