NoodleCollie
NoodleCollie

Reputation: 1087

OpenGL translations do not take effect

These questions may well be very basic, so bear with me.

I've built a very small Qt program to mess around with OpenGL and try to learn about the rendering method and have got a coloured triangle working (extending this tutorial http://qt-project.org/wiki/How_to_use_OpenGL_Core_Profile_with_Qt). My problem now is that any transformations I try to apply to the triangle do nothing. On top of this, changing the params to glOrtho doesn't appear to do anything to the display, and I have no idea how the params to glViewport are supposed to work: making them smaller seems to make the rendered area of the 3D world larger.

Code:

This is my vertex/index array (vec3 position, vec3 colour)

static GLfloat tri[] = { -0.5f, -0.5f, 0.0f,  0.0f, 0.0f, 1.0f,
                        0.5f, -0.5f, 0.0f,  0.0f, 1.0f, 0.0f,
                        0.0f,  0.5f, 0.0f,  1.0f, 0.0f, 0.0f };

static GLuint tri_ind[] = { 0, 1, 2 };

static int SIZEOF_TRI = 2 * 3 * 3 * sizeof(GLfloat);
static int SIZEOF_TRI_IND = 3 * sizeof(GLuint);
static int NUM_TRI_VERTS = 3;

My OpenGL widget uses Qt's buffer object for vertex and index buffers:

class GLWidget : public QGLWidget
{
    Q_OBJECT
public:
    GLWidget( const QGLFormat& format, QWidget* parent = 0 );

protected:
    virtual void initializeGL();
    virtual void resizeGL( int w, int h );
    virtual void paintGL();

    virtual void keyPressEvent( QKeyEvent* e );

private:
    bool prepareShaderProgram( const QString& vertexShaderPath,
                               const QString& fragmentShaderPath );

    QGLShaderProgram m_shader;
    QGLBuffer m_vertexBuffer;
    QGLBuffer m_indexBuffer;
};

The constructor initialises the buffers:

GLWidget::GLWidget( const QGLFormat& format, QWidget* parent )
    : QGLWidget( format, parent ),
      m_vertexBuffer( QGLBuffer::VertexBuffer ),
      m_indexBuffer( QGLBuffer::IndexBuffer )
{
}

initialiseGL initialises the rest:

void GLWidget::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 );

    glClearDepth(1.0);
    glEnable(GL_DEPTH_TEST);
    glDepthFunc(GL_LEQUAL);

    // Prepare a complete shader program...
    QString vert = QCoreApplication::applicationDirPath() + "/simple.vert";
    QString frag = QCoreApplication::applicationDirPath() + "/simple.frag";
    if ( !prepareShaderProgram( vert, frag ) )
        return;

    // 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;
    }

    // We need us some vertex data. Start simple with a triangle ;-)
    GLfloat* points = tri;
    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( points, SIZEOF_TRI );

    // Indices
    GLuint* indices = tri_ind;
    m_indexBuffer.create();
    m_indexBuffer.setUsagePattern( QGLBuffer::StaticDraw );
    if ( !m_indexBuffer.bind() )
    {
        qWarning() << "Could not bind vertex buffer to the context";
        return;
    }
    m_indexBuffer.allocate( indices, SIZEOF_TRI_IND );


    // Enable the "vertex" attribute to bind it to our currently bound
    // vertex buffer.
    m_shader.setAttributeBuffer( "vertex", GL_FLOAT, 0, 3, 6 * sizeof(GLfloat) );
    m_shader.enableAttributeArray( "vertex" );
    m_shader.setAttributeBuffer( "color", GL_FLOAT, 3 * sizeof(GLfloat), 3, 6 * sizeof(GLfloat) );
    m_shader.enableAttributeArray( "color" );
}

And paintGL does a translation and draws the vertices:

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

    // Draw stuff
    glLoadIdentity();
    glTranslatef(10.0, 10.0, 0.0);
    glDrawArrays( GL_TRIANGLES, 0, NUM_TRI_VERTS );
}

The triangle looks exactly the same as before I added the translation.

Furthermore, in resizeGL (when the widget is resized), changing the params to glOrtho has no effect on the display. There was no difference between +-5 and +-10. If I set the width and height of glViewport to 100 each, and then to 200 each, the triangle appears larger (in the bottom left corner) when the values are 200 than when they are 100. I would have thought having a larger viewport size would mean the objects inside appear smaller, but maybe I'm missing something.

void GLWidget::resizeGL( int w, int h )
{
    // Set the viewport to window dimensions
    glViewport( 0, 0, w, qMax( h, 1 ) );

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrtho(-10.0, 10.0, -10.0, 10.0, -5.0, 100.0);
    glMatrixMode(GL_MODELVIEW);
}

Can anyone give me any pointers in the right direction?

Thanks.

EDIT: Vertex shader:

#version 330

in vec3 vertex;
in vec3 color;
out vec3 Color;

void main( void )
{
    Color = color;
    gl_Position = vec4(vertex, 1.0);
}

Fragment shader:

#version 330
 
layout(location = 0, index = 0) out vec4 fragColor;
in vec3 Color;
 
void main( void )
{
    fragColor = vec4(Color, 1.0);
}

Upvotes: 1

Views: 290

Answers (1)

datenwolf
datenwolf

Reputation: 162164

Your shaders are written to work in a OpenGL-3.3 or later core profile. You're using deprecated fixed function pipeline methods (glMatrixMode, glLoadIdentity, glTranslate, etc.) that don't work in a core profile. Use a real matrix math library like GLM, Eigen, or linmath.h to calculate the matrices, then pass them to shader uniforms.

Upvotes: 3

Related Questions