Draw GL_LINE in QOpenGLWidget using array of coordinates

417 views Asked by At

I have working application done using QtCreator. My render class is

GLRendWindow::GLRendWindow(QWidget *parent): QOpenGLWidget(parent)

Now I would like to draw objects using arrays with coordinates of vertices.
I found some tutorial that draws triangle on this page: OpenGL Window Example

I tried to reused it to draw simple line

void GLRendWindow::drawLine()
{
    GLfloat line[] =
    {
        0.5f, 1.0f,
        0.5f, -1.0f
    };
    GLfloat line_colors[] =
    {
        1.0f, 0.0f, 0.0f, // red
        0.0f, 0.0f, 1.0f, // blue
    };
    shaderProgram->bind();
    glVertexAttribPointer(posAttr, 2, GL_FLOAT, GL_FALSE, 0, line);
    glVertexAttribPointer(colAttr, 3, GL_FLOAT, GL_FALSE, 0, line_colors);
    glEnableVertexAttribArray(colAttr);
    glEnableVertexAttribArray(posAttr);
    glDrawArrays(GL_LINE, 0, 2);
    glDisableVertexAttribArray(posAttr);
    glDisableVertexAttribArray(colAttr);
    shaderProgram->release();
}

Also my initialization method

void GLRendWindow::initializeGL()
{
    initializeOpenGLFunctions();
    glClearColor( 0.0f, 0.0f, 0.0f, 0.0f );
    glutInitDisplayMode( GLUT_DOUBLE | GLUT_RGB );

    shaderProgram = new QOpenGLShaderProgram(this);
    shaderProgram->addShaderFromSourceCode(QOpenGLShader::Vertex, vertexShaderSource);
    shaderProgram->addShaderFromSourceCode(QOpenGLShader::Fragment, fragmentShaderSource);
    shaderProgram->link();
    posAttr = shaderProgram->attributeLocation("posAttr");
    colAttr = shaderProgram->attributeLocation("colAttr");
}

and drawing method

void GLRendWindow::paintGL()
{
    glClear( GL_COLOR_BUFFER_BIT );
    glMatrixMode( GL_MODELVIEW );
    glLoadIdentity();
    drawLine();

    if (isUpdated)
    {
       //some other stuff

        isUpdated = false;
    }
    glFlush();
}

and resize method

void GLRendWindow::resizeGL(int w, int h)
{
    glViewport( 0, 0, w, h );
    glMatrixMode( GL_PROJECTION );
    glLoadIdentity();

    if ( w < h && w > 0 )
    {
        glFrustum( - 1.0, 1.0, - 1.0 * h / w, 1.0 * h / w, 1.0, 5.0 );
    }
    else
    {
        if ( w >= h && h > 0 )
        {
            glFrustum( - 0.3 * w / h, 0.3 * w / h, - 0.3, 0.3, 0.5, 5.0 );
        }
    }
}

But when I run app, nothing is drawed. No errors, no exceptions, nothing. In this tutorial I see

static const char *vertexShaderSource =
    "attribute highp vec4 posAttr;\n"
    "attribute lowp vec4 colAttr;\n"
    "varying lowp vec4 col;\n"
    "uniform highp mat4 matrix;\n"
    "void main() {\n"
    "   col = colAttr;\n"
    "   gl_Position = matrix * posAttr;\n"
    "}\n";

static const char *fragmentShaderSource =
    "varying lowp vec4 col;\n"
    "void main() {\n"
    "   gl_FragColor = col;\n"
    "}\n";

and it is possible solution is hidden here, but I completely don't understand what for it is and what is going on here. I am even not sure if this is necessary for drawing simple line.
What should I do to see stright line using array of coordinates?

2

There are 2 answers

3
Rabbid76 On BEST ANSWER

You missed to set specify the array of generic vertex attribute data for the color attribute (attribute lowp vec4 colAttr;). This is similar to specifying the vertex attributes.
For example, add the following code to GLRendWindow::drawLine:

GLfloat line_colors[] =
{
    1.0f, 0.0f, 0.0f, // red
    0.0f, 0.0f, 1.0f  // blue
};
glVertexAttribPointer(colAttr, 3, GL_FLOAT, GL_FALSE, 0, line_colors);
glEnableVertexAttribArray(colAttr);

You don't specify the color attribute array, so the value of colAttr is by default (0, 0, 0). Actually you draw a black line on a black background.


You are mixing different technologies. You have a shader program with a matrix Uniform:

uniform highp mat4 matrix;\n"
void main() {
   // [...]

   gl_Position = matrix * posAttr;
}

You don't set this uniform at all. Instead you try to set the legacy OpenGL fixed function matrix. The contents of the legacy current matrix do not magically appear in the unitary variable.

Use setUniformValue to set the value of the matrix uniform:

QMatrix4x4 matrix;
int matrix_location = shaderprogram->uniformLocation("matrix");

matrix.setToIdentity();
shaderprogram->setUniformValue(matrix_location, matrix);
4
rainbow On

Problem was also here

glDrawArrays(GL_LINE, 0, 2);

It should be

glDrawArrays(GL_LINES, 0, 2);

And I had to changed

static const char *vertexShaderSource =
    "attribute highp vec4 posAttr;\n"
    "attribute lowp vec4 colAttr;\n"
    "varying lowp vec4 col;\n"
    "uniform highp mat4 matrix;\n"
    "void main() {\n"
    "   col = colAttr;\n"
    "   gl_Position = matrix * posAttr;\n"
    "}\n";

to

static const char *vertexShaderSource =
    "attribute highp vec4 posAttr;\n"
    "attribute lowp vec4 colAttr;\n"
    "varying lowp vec4 col;\n"
    "void main() {\n"
    "   col = colAttr;\n"
    "   gl_Position = posAttr;\n"
    "}\n";