OpenGL代码适用于GLFW,但不适用于Qt OpenGL

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了OpenGL代码适用于GLFW,但不适用于Qt OpenGL相关的知识,希望对你有一定的参考价值。

我正在尝试将OpenGL代码从GLFW传输到Qt,以便将其与更大的项目集成。但无论我尝试过什么,我都无法进行纹理显示,而我得到的只是黑屏。

在Qt中,程序编译时没有错误,我在尝试插入纹理之前设法绘制了一个多色三角形。

我已经尝试将Qt OpenGL对象用于着色器,着色器程序,纹理,并根据他们的示例重写代码,但仍然没有。

下面是一个简单的Qt实现,它试图显示一个纹理,导致黑屏。精确的GLFW等效工作正常:

CustomViewGL::CustomViewGL(QWidget *parent): QOpenGLWidget(parent)
{
    QSurfaceFormat format;

    format.setMajorVersion(3);
    format.setMinorVersion(3);
    format.setProfile(QSurfaceFormat::CoreProfile);
    setFormat(format);
}

void CustomViewGL::initializeGL()
{
    glewExperimental=true;

    if (glewInit() != GLEW_OK)
    {
        qDebug() << "Failed to initialize GLEW";
    }

    std::string vertexShaderSource =
            " #version 330 core
                                 "
            "                                                     "
            " layout (location = 0) in vec3 aPos;                 "
            " layout (location = 1) in vec2 aTexCoord;            "
            "                                                     "
            " out vec2 TexCoord;                                  "
            "                                                     "
            " void main()                                         "
            " {                                                   "
            "                                                     "
            "   TexCoord = aTexCoord;                             "
            "   gl_Position = vec4(aPos, 1.0);                    "
            "                                                     "
            " }                                                 ";

    std::string fragmentShaderSource =
            " #version 330 core
                                 "
            "                                                     "
            " in vec2 TexCoord;                                   "
            " out vec4 FragColor;                                 "
            " uniform sampler2D tex;                              "
            " void main()                                         "
            " {                                                   "
            "                                                     "
            " FragColor = texture(tex, TexCoord);                 "
            "                                                     "
            " }                                                 ";

    // Variables
    unsigned int shaderVertex, shaderFragment, shaderProgram;

    ....
    ....
    // Compile Shaders //
    ...
    ...

    glUseProgram(shaderProgram);

    // Vetrices
    float rectangle[] = {
        // positions          // texture coords
         1.0f,  1.0f, 0.0f,   1.0f, 1.0f,   // top right
         1.0f, -1.0f, 0.0f,   1.0f, 0.0f,   // bottom right
        -1.0f, -1.0f, 0.0f,   0.0f, 0.0f,   // bottom left
        -1.0f,  1.0f, 0.0f,   0.0f, 1.0f    // top left
    };

    unsigned int indices[] = {  // note that we start from 0!
        0, 1, 3,   // first triangle
        1, 2, 3    // second triangle
    };

    QImage texture = QImage("wall.jpg").convertToFormat(QImage::Format_RGB888);

    // Variables
    unsigned int VAO, VBO, EBO, tex;

    // VAO, VBO, Attributes Configuration
    glGenVertexArrays(1, &VAO);
    glBindVertexArray(VAO);

    glGenBuffers(1, &VBO);
    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    glBufferData(GL_ARRAY_BUFFER, sizeof(rectangle), rectangle, GL_STATIC_DRAW);


    glGenBuffers(1, &EBO);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);

    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0);
    glEnableVertexAttribArray(0);

    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float)));
    glEnableVertexAttribArray(1);

    // Texture

    glGenTextures(1, &tex);

    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, tex);

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);

    float borderColor[] = { 0.0f, 0.0f, 0.0f, 1.0f };
    glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor);

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_LINEAR);

    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, texture.width(), texture.height(), 0, GL_RGB, GL_UNSIGNED_BYTE, texture.bits());

    glGenerateMipmap(GL_TEXTURE_2D);
}

void CustomViewGL::paintGL()
{
    glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, (void*) 0);
}
答案

关于QOpenGLWidget,正如我在关于这个问题的评论中写的那样,我不喜欢的第一个行为就是没有缓冲交换功能。 Qt任意决定何时绘制东西,如question中所述,这是我绝对不想要的东西。其次,虽然我会绑定纹理并设置纹理数据,但它不会出现在屏幕上,除非a)每次在paintGL函数中绑定它或b)在绑定和设置TEXTURE0数据后调用glActiveTexture(GL_TEXTURE1),这是在最不奇怪的。

所以我决定切换到QGLWidget,the official Qt documentation recommends to avoid。 QGLWidget提供了禁用自动交换缓冲区的自由,具有交换缓冲区功能,并且正在使用问题中提到的代码(它本身是来自基于GLFW的实现的直接副本)。

为了禁用自动缓冲交换,选择OpenGL版本,设置反锯齿并设置共享上下文,下面的代码用作构造函数:

CustomViewGL::CustomViewGL(QWidget *parent, const QGLWidget *shareWidget):
    QGLWidget(parent, shareWidget) // QGLWidget accepts as a second
{                                  // constructor argument another QGLWidget
    QGLFormat format;              // thus context sharing between this and
                                   // the shareWidget is created

    format.setVersion(3,3); // Set OpenGL version, here 3.3
    format.setProfile(QGLFormat::CoreProfile); // Core Profile
    format.setSamples(16); // Anti Alliasing

    setFormat(format);

    setAutoBufferSwap(false); // Prevents Qt from drawing whenever it wants
}

构造函数的头文件声明是:

CustomViewGL(QWidget *parent = 0, const QGLWidget *shareWidget = 0);

然后实现protected function initializeGL()并输入初始化代码,您就可以开始了。

以上是关于OpenGL代码适用于GLFW,但不适用于Qt OpenGL的主要内容,如果未能解决你的问题,请参考以下文章

OpenGL 代码适用于 Windows 但不适用于 Mac

Opengl Array Texture,适用于原始数据,但不适用于图像数据

OpenGL - 在 NDC 中计算位置适用于着色器,但不适用于“常规”程序

OpenGL 4.1 不适用于 Mavericks

使用 Opengl CORE 函数和 Comptability profile - GLFW

QApplication::setWindowIcon 适用于 Windows XP,但不适用于 Windows 7