Question

I'm trying to port my old Qt/OpenGL game from Linux to Windows. I'm using Qt Creator. It compiled fine right away but gave a lot of errors like undefined reference to 'glUniform4fv@12' at linking stage.

I've tried to link more libs -lopengl32 -lglaux -lGLU32 -lglut -lglew32 but it gave the same result.

Qt also uses -lQt5OpenGLd by default.

I'm including QGLWIdget with :

#define GL_GLEXT_PROTOTYPES
#include <QGLWidget>

I've also tried using GLEW but it confilcts with Qt (or QOpenGL?).

How can I get rid of those undefined references? Is there any other library that i have to link to?

Thanks in advance.

Tomxey

Was it helpful?

Solution

Windows doesn't provide the prototypes of any OpenGL function introduced after OpenGL 1.1. You must resolve the pointers to those functions at runtime (via GetProcAddress -- or better QOpenGLContext::getProcAddress, see below).


Qt offers excellent enablers to ease this job:

  • QOpenGLShader and QOpenGLShaderProgram allow you manage your shaders, shader programs, and their uniforms. QOpenGLShaderProgram provides nice overloads allowing you to seamlessly pass QVector<N>D or QMatrix<N>x<N> classes:

    QMatrix4x4 modelMatrix = model->transform();
    QMatrix4x4 modelViewMatrix = camera->viewMatrix() * modelMatrix;
    QMatrix4x4 modelViewProjMatrix = camera->projMatrix() * modelViewMatrix;
    ...
    program->setUniform("mv", modelViewmatrix);
    program->setUniform("mvp", modelViewProjMatrix);
    
  • QOpenGLContext::getProcAddress() is a platform-independent function resolver (useful in combination with QOpenGLContext::hasExtension() to load extension-specific functions)

  • QOpenGLContext::functions() returns a QOpenGLFunctions object (owned by the context), which offers as public API the common subset between OpenGL 2 (+FBO) / OpenGL ES 2.¹ It will resolve the pointers behind the scenes for you, so all you have to do is calling

    functions->glUniform4f(...);
    
  • QOpenGLContext::versionFunctions<VERSION>() will return a QAbstractOpenGLFunctions subclass, namely, the one matching the VERSION template parameter (or NULL if the request can't be satisfied):

    QOpenGLFunctions_3_3_Core *functions = 0;
    functions = context->versionFunctions<QOpenGLFunctions_3_3_Core>();
    if (!functions) 
         error(); // context doesn't support the requested version+profile
    functions->initializeOpenGLFunctions(context);
    
    functions->glSamplerParameterf(...); // OpenGL 3.3 API
    functions->glPatchParameteri(...); // COMPILE TIME ERROR, this is OpenGL 4.0 API
    
  • As an alternative way, you can make your "drawing" classes /inherit/ from QOpenGLFunctionsX. You can initalize them as usual, but this way you can keep your code like:

    class DrawThings : public QObject, protected QOpenGLFunctions_2_1
    {
        explicit DrawThings(QObject *parent = 0) { ... }
        bool initialize(QOpenGLContext *context)
        {
            return initializeOpenGLFunctions(context);
        }
        void draw()
        {
            Q_ASSERT(isInitialized());
            // works, it's calling the one in the QOpenGLFunctions_2_1 scope...
            glUniform4f(...); 
        }
    }
    

¹ There are also "matching" classes in the QtOpenGL module, i.e. QGLContext and QGLFunctions. If possible, avoid using QtOpenGL in new code, as it's going to be deprecated in a couple of releases in favour of the QOpenGL* classes.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top