Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

QT OpenGL unable to draw rectangle



  • I am learning QT and QT OpenGL. Based on example for drawing triangle it was implemented a following snippet of code. This code is invoked from class inherited from QOpenGLWindow, so all contexts are initialized. Snippet is tested against Qt 5.10 on MacOS X 10.13.3.

    The issue with that code is, that glDrawElements draws nothing, however if replace it to appropriate call of glDrawArrays I see something drawn on the screen (single triangle).

    I would appreciate it if somebody give me a clue what is wrong with that code, because I can't find a bug.

    #include <QOpenGLFunctions>
    
    #include <QtGui/QMatrix4x4>
    #include <QtGui/QScreen>
    
    float sg_vertices[] = {
         0.5f,  0.5f, 0.0f,  // top right
         0.5f, -0.5f, 0.0f,  // bottom right
        -0.5f, -0.5f, 0.0f,  // bottom left
        -0.5f,  0.5f, 0.0f   // top left
    };
    
    unsigned int sg_indices[] = { 
        0, 1, 3,   // first triangle
        1, 2, 3    // second triangle
    };
    
    void SquareRenderer::Initialize(QOpenGLContext* ctx)
    {
        m_program = std::make_unique<QOpenGLShaderProgram>(ctx);
        m_program->addShaderFromSourceFile(QOpenGLShader::Vertex, ":/shaders/shader.vert");
        m_program->addShaderFromSourceFile(QOpenGLShader::Fragment, ":/shaders/shader.frag");
        m_program->link();
    
        m_program->bind();
    
        // Create Buffer (Do not release until VAO is created)
        m_vertex = std::make_unique<QOpenGLBuffer>(QOpenGLBuffer::VertexBuffer);
        m_vertex->create();
        m_vertex->bind();
        m_vertex->setUsagePattern(QOpenGLBuffer::StaticDraw);
        m_vertex->allocate(sg_vertices, sizeof(sg_vertices));
    
        m_index = std::make_unique<QOpenGLBuffer>(QOpenGLBuffer::IndexBuffer);
        m_index->create();
        m_index->bind();
        m_index->setUsagePattern(QOpenGLBuffer::StaticDraw);
        m_index->allocate(sg_indices, sizeof(sg_indices));
    
        // Create Vertex Array Object
        m_object = std::make_unique<QOpenGLVertexArrayObject>();
        m_object->create();
        m_object->bind();
        m_program->enableAttributeArray(0);
        m_program->setAttributeBuffer(0, GL_FLOAT, 0, 3);
    
        // Release (unbind) all
        m_object->release();
        m_index->release();
        m_vertex->release();
        m_program->release();
    }
    
    void SquareRenderer::Draw(QOpenGLContext* ctx)
    {
        m_program->bind();
    
        {
            QMatrix4x4 matrix;
            matrix.perspective(120.0f, 2.0f, 0.1f, 100.0f);
            matrix.translate(0, 0, -2);
            matrix.rotate(100.0f * m_frame / ctx->screen()->refreshRate(), 0, 1, 0);
    
            m_program->setUniformValue("matrix", matrix);
        }
    
        {
          m_object->bind();
          ctx->functions()->glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
          m_object->release();
        }
    
        m_program->release();
    
        ++m_frame;
    }
    

    Shaders:

    Vertex:
    #version 330
    layout(location = 0) in vec3 position;
    uniform mat4 matrix;
    
    void main()
    {
      gl_Position = matrix * vec4(position, 1.0);
    }
    
    Fragment:
    #version 330
    out highp vec4 fColor;
    
    void main()
    {
        fColor = vec4(0.f, .8f, 0.f, 1.f);
    }
    
    


  • It seems QOpenGLBuffer assumes different sequence of calls, when used as elements buffer, because next modification (replacement QOpenGLBuffer to OpenGL functions) works as expected:

    void SquareRenderer::Initialize(QOpenGLContext* ctx)
    {
        m_program = std::make_unique<QOpenGLShaderProgram>(ctx);
        m_program->addShaderFromSourceFile(QOpenGLShader::Vertex, ":/shaders/shader.vert");
        m_program->addShaderFromSourceFile(QOpenGLShader::Fragment, ":/shaders/shader.frag");
        m_program->link();
    
        m_program->bind();
    
        ctx->functions()->glGenBuffers(1, &m_vbo);
        ctx->functions()->glGenBuffers(1, &m_ebo);
        m_object = std::make_unique<QOpenGLVertexArrayObject>();
        m_object->create();
    
        m_object->bind();
        ctx->functions()->glBindBuffer(GL_ARRAY_BUFFER, m_vbo);
        ctx->functions()->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_ebo);
    
        m_program->enableAttributeArray(0);
        m_program->setAttributeBuffer(0, GL_FLOAT, 0, 3);
    
        ctx->functions()->glBufferData(GL_ARRAY_BUFFER, sizeof(sg_vertices), sg_vertices, GL_STATIC_DRAW);
        ctx->functions()->glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(sg_indices), sg_indices, GL_STATIC_DRAW);
    
        m_object->release();
        ctx->functions()->glBindBuffer(GL_ARRAY_BUFFER, 0);
        ctx->functions()->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
    
        m_program->release();
    }
    


  • Well, it seems problem solved. Issue in sequence of buffers creation. Reimplementing the same sequence as in previous message, but using QOpenGLBuffer gave me rotating rectangle on the screen.


  • Lifetime Qt Champion

    Hi and welcome to the forums :)
    Its not often a poster both post and find the answer himself in such time span.
    Not with openGl at least.
    Good work.


Log in to reply