I have trouble porting the hello triangle from I'm used to do outside of Qt with Glew and GLFW, into Qt 5.5 and the QOpenGlWidget, with the "new" way with things like QSurfaceFormat, QOpenGLfunctions, QOpenGLShaderProgram with Core profile and opengl >= 3.3.
Here is my QOpenGLWidget subclass "OGLWidget", which I adapted from this post. and this Qt tutorial
#include "oglwidget.h"
#include <QOpenGLWidget>
#include <QtGui/QWindow>
#include <QtGui/QOpenGLFunctions>
#include <QtGui/QOpenGLShaderProgram>
OGLWidget::OGLWidget(QWidget *parent)
:QOpenGLWidget(parent)
, m_program(0)
{
}
OGLWidget::~OGLWidget()
{
}
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";
void OGLWidget::initializeGL()
{
initializeOpenGLFunctions();
m_program = new QOpenGLShaderProgram(this);
m_program->addShaderFromSourceCode(QOpenGLShader::Vertex, vertexShaderSource);
m_program->addShaderFromSourceCode(QOpenGLShader::Fragment, fragmentShaderSource);
m_program->link();
m_posAttr = m_program->attributeLocation("posAttr");
m_colAttr = m_program->attributeLocation("colAttr");
m_matrixUniform = m_program->uniformLocation("matrix");
}
void OGLWidget::paintGL()
{
const qreal retinaScale = devicePixelRatio();
glViewport(0, 0, width() * retinaScale, height() * retinaScale);
glClear(GL_COLOR_BUFFER_BIT);
m_program->bind();
m_program->setUniformValue(m_matrixUniform, matrix);
GLfloat vertices[] = {
0.0f, 0.707f, 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,
0.0f, 0.0f, 1.0f
};
glVertexAttribPointer(m_posAttr, 3, GL_FLOAT, GL_FALSE, 0, vertices);
glVertexAttribPointer(m_colAttr, 3, GL_FLOAT, GL_FALSE, 0, colors);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glDrawArrays(GL_TRIANGLES, 0 , 3);
glDisableVertexAttribArray(1);
glDisableVertexAttribArray(0);
}
void OGLWidget::resizeGL(int w, int h)
{
matrix.setToIdentity();
matrix.perspective(60.0f, 4.0f/3.0f, 0.1f, 100.0f);
matrix.translate(0, 0, -2);
}
This works fine with this main.cpp:
#include <QApplication>
#include <QSurfaceFormat>
#include "oglwidget.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QSurfaceFormat format;
format.setDepthBufferSize(24);
format.setStencilBufferSize(8);
format.setVersion(3, 3);
QSurfaceFormat::setDefaultFormat(format);
OGLWidget myGLWidget;
myGLWidget.resize(640, 480);
myGLWidget.show();
return a.exec();
}
But then, when I add: format.setProfile(QSurfaceFormat::CoreProfile);
to the above block, and changing my shaders to what I have been learning recently with openGL tutorials that use Core profile and GLSL 3.3:
static const char *vertexShaderSource =
"#version 330 core;\n"
"layout (location = 0) in vec3 posAttr;\n"
"layout (location = 1) in vec3 colAttr;\n"
"out vec3 fragColor;\n"
"void main(){\n"
" gl_Position = matrix * vec4(posAttr, 1.0f);\n"
" fragColor = colAttr;\n"
"}\n";
static const char *fragmentShaderSource =
"#version 330 core;\n"
"in vec3 fragColor;\n"
"out vec4 color;\n"
"void main(){\n"
" color = vec4(fragColor, 1.0f);"
"}\n";
My code compiles, but I have a black screen. No triangle anymore.
I am using Qt 5.5, on a macbook pro retina, yosemite 10.10.5. GPU Intel Iris.
Any idea what I shall modify up there to say hello again to my colourful triangle?
Thanks
EDIT
Here is new version of the code which accounts for the comments, suggesting to add the VAO. I assumed the VBO was needed to but with no working example with these recent Qt classes I'm improvising. Nonetheless, my triangle still does not show up. I've simplified here as I use a single color directly coded in the shader.
OGLWidget::OGLWidget(QWidget *parent)
:QOpenGLWidget(parent)
, m_program(0)
{
}
OGLWidget::~OGLWidget()
{
}
static const char *vertexShaderSource =
"#version 330 core\n"
"layout (location = 0) in vec3 posAttr;\n"
"uniform mat4 matrix;\n"
"void main(){\n"
" gl_Position = matrix * vec4(posAttr, 1.0f);\n"
"}\n";
static const char *fragmentShaderSource =
"#version 330 core\n"
"out vec4 color;\n"
"void main(){\n"
" color = vec4(0.5f, 0.0f, 0.0f, 1.0f);\n"
"}\n";
void OGLWidget::initializeGL()
{
initializeOpenGLFunctions();
GLfloat vertices[] = {
0.0f, 0.707f, 0.0f,
-0.5f, -0.5f, 0.0f,
0.5f, -0.5f, 0.0f
};
m_program = new QOpenGLShaderProgram(this);
m_program->addShaderFromSourceCode(QOpenGLShader::Vertex, vertexShaderSource);
m_program->addShaderFromSourceCode(QOpenGLShader::Fragment, fragmentShaderSource);
m_program->link();
m_posAttr = m_program->attributeLocation("posAttr");
m_matrixUniform = m_program->uniformLocation("matrix");
const qreal retinaScale = devicePixelRatio();
glViewport(0, 0, width() * retinaScale, height() * retinaScale);
// Create Vertex Array Object
m_vao.create();
m_vao.bind();
// Create Vertex Buffer (Do not release until VAO is created)
m_vertexBuffer = QOpenGLBuffer(QOpenGLBuffer::VertexBuffer);
m_vertexBuffer.create();
m_vertexBuffer.bind();
m_vertexBuffer.setUsagePattern(QOpenGLBuffer::StaticDraw);
m_vertexBuffer.allocate(sizeof(vertices));
m_program->bind();
m_program->setAttributeBuffer(m_posAttr, GL_FLOAT, 0, 3*sizeof(GLfloat));
m_program->enableAttributeArray(m_posAttr);
m_program->setAttributeArray(m_posAttr, vertices, 3);
m_vao.release();
m_vertexBuffer.release();
m_program->release();
}
void OGLWidget::paintGL()
{
glClear(GL_COLOR_BUFFER_BIT);
m_program->bind();
m_program->setUniformValue(m_matrixUniform, matrix);
m_vao.bind();
glDrawArrays(GL_TRIANGLES, 0 , 3);
m_vao.release();
glDisableVertexAttribArray(1);
glDisableVertexAttribArray(0);
m_program->release();
}
void OGLWidget::resizeGL(int w, int h)
{
matrix.setToIdentity();
matrix.perspective(60.0f, 4.0f/3.0f, 0.1f, 100.0f);
matrix.translate(0, 0, -2);
}