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
Forum Updated to NodeBB v4.3 + New Features

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

Scheduled Pinned Locked Moved General and Desktop
6 Posts 2 Posters 5.7k 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
    • Z Offline
      Z Offline
      ZapB
      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.

      Nokia Certified Qt Specialist
      Interested in hearing about Qt related work

      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
          • Z Offline
            Z Offline
            ZapB
            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.

            Nokia Certified Qt Specialist
            Interested in hearing about Qt related work

            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