Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. [Solved] QGLShaderProgram problem getting object to show with OpenGL 3.0
Qt 6.11 is out! See what's new in the release blog

[Solved] QGLShaderProgram problem getting object to show with OpenGL 3.0

Scheduled Pinned Locked Moved General and Desktop
6 Posts 2 Posters 7.4k Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • B Offline
    B Offline
    Bobby B
    wrote on last edited by
    #1

    Hi,

    I wanted to try OpenGL programming using Qt. However, I have problems getting an image to show up. I took some pieces of code that I found in the documentation but I don't know where the problem is. My only guess is that I'm not sending the attribute data correctly.

    What I'm attempting to do is to draw a triangle with a different colour near each vertex.

    The code that I have for it is shown below (Note that m_shader is the QGLShaderProgram object).
    @
    GLRenderer::GLRenderer( const QGLFormat& format, QWidget* parent )
    : QGLWidget( format, parent )
    {
    }

    void GLRenderer::initializeGL()
    {
    QGLFormat glFormat = QGLWidget::format();
    if ( !glFormat.sampleBuffers() )
    qWarning() << "Could not enable sample buffers";

    glClearColor( 0.0f, 0.0f, 0.0f, 1.0f );
    
    m_shader.addShaderFromSourceFile&#40; QGLShader::Vertex, ":/test.vert" &#41;;
    m_shader.addShaderFromSourceFile( QGLShader::Fragment, ":/test.frag" &#41;;
    m_shader.link(&#41;;
    
    if ( !m_shader.bind(&#41; )
    {
        qWarning() << "Could not bind shader program";
        return;
    }
    
    GLfloat points[] = { -0.5f, -0.5f, 0.0f,
                         -0.5f,  0.5f, 0.0f,
                          0.5f,  0.5f, 0.0f };
    GLfloat colors[] = { 1.0f, 0.0f, 0.0f,
                         0.0f, 1.0f, 0.0f,
                         1.0f, 1.0f, 1.0f };
    
    int vertexLocation = m_shader.attributeLocation("vertex");
    int colourLocation = m_shader.attributeLocation("color_in");
    
    m_shader.setAttributeArray(vertexLocation, points, 3);
    m_shader.setAttributeArray(colourLocation, colors, 3);
    m_shader.enableAttributeArray(vertexLocation);
    m_shader.enableAttributeArray(colourLocation);
    

    }

    void GLRenderer::resizeGL( int w, int h )
    {
    glViewport( 0, 0, w, h );
    }

    void GLRenderer::paintGL()
    {
    // Clear the buffer with the current clearing color
    glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

    // Draw stuff
    glDrawArrays( GL_TRIANGLES, 0, 3 );
    

    }
    @

    The vertex shader I wrote is
    @
    #version 130

    in vec3 vertex;
    in vec3 color_in;
    out vec3 color;

    void main( void )
    {
    gl_Position = vec4(vertex, 1.0);
    color = vec3(color_in);
    }
    @

    The fragment shader I wrote is
    @
    #version 130

    in vec3 color;
    out vec4 fragColor;

    void main( void )
    {
    fragColor = vec4(color, 1.0);
    }
    @

    And in case any of you were wondering where I used the GLRenderer object I wrote this piece of code in the main file
    @
    QGLFormat glFormat;
    glFormat.setVersion( 3, 0 );
    glFormat.setProfile( QGLFormat::CoreProfile );
    glFormat.setSampleBuffers( true );

    GLRenderer w( glFormat );
    w.show();
    

    @

    I'm fairly new to this graphics stuff but I am really interested in using OpenGL with Qt so if any of you can offer any help or tips on fixing my program or making it better I would very much appreciate it.

    Thank you in advance.

    Sincerely,
    Bobby

    1 Reply Last reply
    0
    • ? Offline
      ? Offline
      A Former User
      wrote on last edited by
      #2

      This "article":http://developer.qt.nokia.com/wiki/How_to_use_OpenGL_Core_Profile_with_Qt should get you up and running with a basic OpenGL 3.3 context.

      1 Reply Last reply
      0
      • B Offline
        B Offline
        Bobby B
        wrote on last edited by
        #3

        Thanks for the reply,

        I have used some parts of the code to help me understand and I believe that I have found a solution. However I am unsure if my solution is the best way to go about it.

        Most of what I changed is in the initializeGL() method:
        @
        void GLRenderer::initializeGL()
        {
        QGLFormat glFormat = QGLWidget::format();
        if ( !glFormat.sampleBuffers() )
        qWarning() << "Could not enable sample buffers";

        // Set the clear color to black
        glClearColor( 0.0f, 0.0f, 0.0f, 1.0f );
        
        // Prepare a complete shader program...
        if ( !prepareShaderProgram( ":/test.vert", ":/test.frag" ) )
            return;
        
        // Data contains the vertex positions and the corresponding
        // colours.
        GLfloat vertexData[] = { -0.5f, -0.5f, 0.0f, 1.0f,
                                 -0.5f,  0.5f, 0.0f, 1.0f,
                                  0.5f,  0.5f, 0.0f, 1.0f,
                                  1.0f,  0.0f, 0.0f, 1.0f,
                                  0.0f,  1.0f, 0.0f, 1.0f,
                                  0.0f,  0.0f, 1.0f, 1.0f, };
        
        m_vertexBuffer.create();
        m_vertexBuffer.setUsagePattern( QGLBuffer::StaticDraw );
        if ( !m_vertexBuffer.bind() )
        {
           qWarning() << "Could not bind vertex buffer to the context";
           return;
        }
        m_vertexBuffer.allocate( vertexData, sizeof(vertexData) );
        
        // Bind the shader program so that we can associate variables from
        // our application to the shaders
        if ( !m_shader.bind() )
        {
           qWarning() << "Could not bind shader program to context";
           return;
        }
        
        // Enable the "vertex" and "colour" attribute to bind it to our currently bound
        // vertex buffer.
        m_shader.setAttributeBuffer( "vertex", GL_FLOAT, 0, 4 );
        m_shader.setAttributeBuffer("colour", GL_FLOAT, 3 * 4*sizeof(float), 4);
        m_shader.enableAttributeArray( "vertex" );
        m_shader.enableAttributeArray("colour");
        

        }
        @

        As you can probably see I have combined the vertex position and colours into one array. I have also added a bit of code
        @
        //Set offset to start at the fourth 4-component vector (1.0f, 0.0f, 0.0f, 1.0f)
        m_shader.setAttributeBuffer("colour", GL_FLOAT, 3 * 4*sizeof(float), 4);
        m_shader.enableAttributeArray("colour");
        @

        I made some minor changes to the vertex and fragment shaders because I used 4-component vectors instead of the 3-component vectors I used before.
        Vertex Shader:
        @
        #version 130

        in vec4 vertex;
        in vec4 colour;
        out vec4 colourOut;

        void main( void )
        {
        gl_Position = vertex;
        colourOut = colour;
        }
        @
        Fragment Shader:
        @
        #version 130

        in vec4 colourOut;
        out vec4 fragColor;

        void main( void )
        {
        fragColor = colourOut;
        }
        @
        That is what I did to get the colours in. However, I am not sure if joining the position and colour arrays into one array was the best solution. I would prefer if I could keep the two separate but I do not know how do it.

        1 Reply Last reply
        0
        • B Offline
          B Offline
          Bobby B
          wrote on last edited by
          #4

          Wait, I think I found a way to keep the position data and colour data separate.

          Just split the vertexData array
          @
          GLfloat position[] = { -0.5f, -0.5f, 0.0f, 1.0f,
          -0.5f, 0.5f, 0.0f, 1.0f,
          0.5f, 0.5f, 0.0f, 1.0f, };
          GLfloat colour[] = { 1.0f, 0.0f, 0.0f, 1.0f,
          0.0f, 1.0f, 0.0f, 1.0f,
          0.0f, 0.0f, 1.0f, 1.0f };
          @

          Then replace the line
          @
          m_vertexBuffer.allocate( vertexData, sizeof(vertexData) );
          @
          with several lines shown below
          @
          m_vertexBuffer.allocate( sizeof(position) + sizeof(colour) );

          m_vertexBuffer.write(0, position, sizeof(position));
          m_vertexBuffer.write(sizeof(position), colour, sizeof(colour));
          

          @

          I think this is a better method than before, but if anyone knows how to do it better I would be glad to hear from you.

          1 Reply Last reply
          0
          • ? Offline
            ? Offline
            A Former User
            wrote on last edited by
            #5

            Just use two vertex buffer objects. Here is a similar example from another demo I have where I have used separate VBOs for the vertices and the colors. I call these functions from initialiseGL().

            @
            bool GLWidget::prepareVertexBuffer()
            {
            float vertices[] = { -600.0f, -337.0f, 0.0f, 1.0f,
            -600.0f, 337.0f, 0.0f, 1.0f,
            600.0f, 337.0f, 0.0f, 1.0f,
            600.0f, -337.0f, 0.0f, 1.0f };
            m_vertexBuffer.create();
            m_vertexBuffer.setUsagePattern( QGLBuffer::StaticDraw );
            if ( !m_vertexBuffer.bind() )
            {
            qDebug() << "Could not bind vertex buffer to the context";
            return false;
            }
            m_vertexBuffer.allocate( vertices, 4 * 4 * sizeof( float ) );
            return true;
            }

            bool GLWidget::prepareColorsBuffer()
            {
            float colors[] = { 1.0f, 0.0f, 0.0f, 1.0f
            0.0f, 1.0f, 0.0f, 1.0f
            0.0f, 0.0f, 1.0f, 1.0f
            1.0f, 1.0f, 1.0f, 1.0f };
            m_colorBuffer.create();
            m_colorBuffer.setUsagePattern( QGLBuffer::StaticDraw );
            if ( !m_colorBuffer.bind() )
            {
            qDebug() << "Could not bind colors buffer to the context";
            return false;
            }
            m_colorBuffer.allocate( colors, 4 * 4 * sizeof( float ) );
            return true;
            }
            @

            Then later on in initialiseGL() you can do something like this:

            @
            // Enable the "vertex" attribute to bind it to our vertex buffer
            m_vertexBuffer.bind();
            m_shader.setAttributeBuffer( "vertex", GL_FLOAT, 0, 4 );
            m_shader.enableAttributeArray( "vertex" );

            // Enable the "color" attribute to bind it to our colors buffer
            m_colorBuffer.bind();
            m_shader.setAttributeBuffer( "color", GL_FLOAT, 0, 4 );
            m_shader.enableAttributeArray( "color" );
            

            @

            That way when you call glDrawArrays() your shaders will get passed in all the enabled attribute arrays (vertex and color here) in one go.

            1 Reply Last reply
            0
            • B Offline
              B Offline
              Bobby B
              wrote on last edited by
              #6

              I see, that does seem better than my idea. Thank you very much. Your help is very much appreciated.

              1 Reply Last reply
              0

              • Login

              • Login or register to search.
              • First post
                Last post
              0
              • Categories
              • Recent
              • Tags
              • Popular
              • Users
              • Groups
              • Search
              • Get Qt Extensions
              • Unsolved