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?
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);