簡體   English   中英

OpenGL代碼適用於GLFW,但不適用於Qt OpenGL

[英]OpenGL Code works on GLFW but not on 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\n                                 "
            "                                                     "
            " 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);                    "
            "                                                     "
            " }\0                                                 ";

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

    // 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可以隨意決定何時繪制內容,這是我絕對不希望的。 其次,盡管我將綁定紋理並設置紋理數據,但除非a)每次在paintGL函數中進行綁定或b)在綁定並設置TEXTURE0數據后調用glActiveTexture(GL_TEXTURE1),否則它將不會出現在屏幕上,最不奇怪。

因此,我決定切換到QGLWidget,這是Qt官方文檔建議避免的 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);

然后實現受保護的函數initializeGL()並輸入初始化代碼,您就可以開始了。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM