I been learning modern opengl for a while. I really want to use Qt with opengl. But the Qt4.7.x's opengl was broken at windows.(I don't know if they fix it at Qt4.8.x. But the python binding works, both PyQt and PySide). So I have to waiting for Qt5. Qt5's opengl was redesigned, all new opengl
class are in QtGui module now. It's quite different with Qt4. Here's example how to use OpenGL3.3 with Qt5.1. The new opengl in Qt5
has prefix QOpenGL*. I want to learn the pure opengl
functions. So I will use gl* most of the time.
myglwindow.h
#ifndef MyGLWindow_H
#define MyGLWindow_H
#include <QWindow>
// for loading shaders and compile shaderprogram
#include <QOpenGLShaderProgram>
// load opengl functions, if you use different version
// change the number to your version number
#include <QOpenGLFunctions_3_3_Core>
class MyGLWindow : public QWindow, protected QOpenGLFunctions_3_3_Core
{
Q_OBJECT
public:
MyGLWindow(QScreen *screen=0);
~MyGLWindow();
// render function
void render();
// do all the initialize before render
void initialize();
protected:
void exposeEvent(QExposeEvent *event);
void resizeEvent(QResizeEvent *event);
private:
// opengl contex obj
QOpenGLContext *m_context;
// shader program obj
QOpenGLShaderProgram *m_program;
GLuint VAO; // Vertex Array Object
GLuint VBO; // Vertex Buffer Object
};
#endif // MyGLWindow_H
myglwindow.cpp
#include “myglwindow.h"
MyGLWindow::MyGLWindow(QScreen *screen=0)
: QWindow(screen)
{
// Tell Qt this window is use for OpenGL
setSurfaceType(OpenGLSurface);
// setup opengl context's format
// like opengl's version and profile
QSurfaceFormat format;
format.setMajorVersion(3);
format.setMinorVersion(3);
format.setProfile(QSurfaceFormat::CoreProfile);
setFormat(format);
// make sure the format was use by the window
// you don't need to call it directly, as it
// will be implicitly called by show()
create();
// create opengl context
m_context = new QOpenGLContext;
m_context->setFormat(format);
m_context->create();
// tell the window to use it
m_context->makeCurrent(this);
// load opengl functions
initializeOpenGLFunctions();
//
initialize();
}
MyGLWindow::~MyGLWindow()
{
}
void MyGLWindow::render()
{
// we need to make sure the context is current
m_context->makeCurrent(this);
// clear screen color to black
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT);
// active shader program
glUseProgram(m_program->programId());
// bind Vertex Array Object
glBindVertexArray(VAO);
// draw triangle
glDrawArrays(GL_TRIANGLES, 0, 3);
// bind Vertex Array to 0
glBindVertexArray(0);
glUseProgram(0);
m_context->swapBuffers(this);
}
void MyGLWindow::initialize()
{
// create shader program
m_program = new QOpenGLShaderProgram(m_context);
// load vertex shader
m_program->addShaderFromSourceFile(QOpenGLShader::Vertex, "vertexColors.vert");
// load fragment shader
m_program->addShaderFromSourceFile(QOpenGLShader::Fragment, "vertexColors.frag");
m_program->link(); // compile and link shader program
const float vertexData[] = {
// x y z w
0.0f, 0.5f, 0.0f, 1.0f,
0.5f, -0.366f, 0.0f, 1.0f,
-0.5f, -0.366f, 0.0f, 1.0f,
// R G B A
1.0f, 0.0f, 0.0f, 1.0f,
0.0f, 1.0f, 0.0f, 1.0f,
0.0f, 0.0f, 1.0f, 1.0f,
};
// create Vertex Buffer Object
glGenBuffers(1, &VBO);
// bind it to the GL_ARRAY_BUFFER
glBindBuffer(GL_ARRAY_BUFFER, VBO);
// copy data to GPU
glBufferData(GL_ARRAY_BUFFER, sizeof(vertexData), vertexData, GL_STATIC_DRAW);
// bind the GL_ARRAY_BUFFER to 0
glBindBuffer(GL_ARRAY_BUFFER, 0);
// create Vertex Array Object
glGenVertexArrays(1, &VAO);
// bind it
glBindVertexArray(VAO);
// bind VBO to GL_ARRAY_BUFFER
glBindBuffer(GL_ARRAY_BUFFER, VBO);
// enable vertex array
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
// setup the data format
// this will tell VAO that the vertex array 0 is something like
// [[0.0f, 0.5f, 0.0f, 1.0f], [0.5f, -0.366f, 0.0f, 1.0f,], [-0.5f, -0.366f, 0.0f, 1.0f]]
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, 0);
// the last parameter is a pointer
// specifies the offset of the first component of the vertexData[]
glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, (void*)48);
glBindVertexArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
void MyGLWindow::exposeEvent(QExposeEvent *event)
{
if(isExpose())
render();
}
void MyGLWindow::resizeEvent(QResizeEvent *event)
{
// tell opengl to resize
glViewport(0, 0, width(), height());
if(isExpose())
render();
}
main.cpp
#include <QApplication>
#include "myglwindow.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MyGLWindow w;
w.resize(640, 480);
w.show();
return a.exec();
}
vertex shader
vertexColors.vert
#version 330
layout(location=0) in vec4 position;
layout(location=1) int vec4 color;
out vec4 theColor;
void main()
{
gl_Position = position;
theColor = color;
}
Fragment shader
vertexColors.frag
#version 330
in vec4 theColor;
out vec4 outColor;
void main()
{
outColor = theColor;
}