Qt实现 QOpenGL绘制彩色三角形
1、QOpenGL介绍
QOpenGLWidget类封装了opengl,比起原生的opengl,使用起来很方便。只需要让子类继承QOpenGLWidget。
OpenGL(英语:Open Graphics Library,译名:开放图形库或者“开放式图形库”)是用于渲染2D、3D矢量图形的跨语言、跨平台的应用程序编程接口(API)。这个接口由近350个不同的函数调用组成,用来从简单的图形比特绘制复杂的三维景象。而另一种程序接口系统是仅用于Microsoft Windows上的Direct3D。OpenGL常用于CAD、虚拟现实、科学可视化程序和电子游戏开发。(摘自维基百科)
其实OpenGL是把图像数据和几何数据发送给电脑显卡,进行一系列处理后,把图形显示到屏幕上进行展示。
QOpenGLWidget允许在平台支持的情况下使用不同的OpenGL版本和配置文件,只需通过setFormat()设置请求的格式即可。
可以根据自己电脑所支持的opengl版本进行兼容性设置。
QSurfaceFormat format;format.setDepthBufferSize(24);format.setStencilBufferSize(8);format.setVersion(3, 2);format.setProfile(QSurfaceFormat::CoreProfile);this->setFormat(format);
QOpenGLWidget还提供了三个函数来方便我们处理业务。分别是
paintGL():绘制渲染opengl场景,update的时候会自动调用
resizeGL() :设置opengl的大小,resize的时候调用
initializeGL() :提供初始化opengl需要的环境的接口,在resizeGL或者paintGL之前会被调用一次。
2、效果

3、主要代码介绍:
1、着色器装载
void MyQOpengl::InitShader(){ //顶点着色器 QOpenGLShader *vShader = new QOpenGLShader(QOpenGLShader::Vertex, this); const char *vSrc = "in vec4 vPosition; \n" "in vec4 vColor; \n" "out vec4 color; \n" "void main() { \n" " color = vColor; \n" " gl_Position = vPosition; \n" "} \n"; vShader->compileSourceCode(vSrc); //片段着色器 QOpenGLShader *fShader = new QOpenGLShader(QOpenGLShader::Fragment, this); const char *fSrc = "in vec4 color; \n" "out vec4 fColor; \n" "void main() { \n" " fColor = color; \n" "} \n"; fShader->compileSourceCode(fSrc); //着色器程序 _pShaderProgram = new QOpenGLShaderProgram; _pShaderProgram->addShader(vShader); _pShaderProgram->addShader(fShader); _pShaderProgram->link(); _pShaderProgram->bind();}
这里我们需要创建一个顶点着色器和片段着色器,然后通过addShader装载它们,所谓着色器就是像素被渲染时执行的程序,在GPU中执行的程序。const char *vSrc字符串是opengl着色器语言(OpenGL Shading Language)即GLSL。通过这些语言来描述给GPU。
而顶点就是我们图形的几个顶角,片段就是几个顶点包围起来的全部像素点,通过对以上进行渲染,就能得到我们需要的图形和颜色。
2、顶点描述
下面描述的是三角形的三个顶点
//顶点位置GLfloat vertices[] = { -0.5f, -0.5f, //left 0.0f, 0.5f, //top 0.5f, -0.5f, //right};
如下图所示:

3、顶点颜色
对三个顶点进行颜色的描述,分别表示r、g、b,我们知道,通过r、g、b的组合可以组合出任何我们想要的颜色
GLfloat colors[] = { 1.0f, 0.5f, 0.2f, //r g b 1.0f, 0.5f, 0.2f, 1.0f, 0.5f, 0.2f,};
4、QOpenGLBuffer _vbo用于管理OpenGL的缓存对象,流程是create()创建缓存对象--bind()绑定对象关联的缓存到OpenGL环境--allocate()分配缓存空间--setAttributeBuffer()填充数据。
_vbo.create();_vbo.bind();_vbo.allocate(vertices, 18*sizeof(GLfloat)); GLuint vPosition = _pShaderProgram->attributeLocation("vPosition");_pShaderProgram->setAttributeBuffer(vPosition, GL_FLOAT, 0, 2, 0);glEnableVertexAttribArray(vPosition);
4、全部代码:
头文件:
#ifndef MYQOPENGL_H#define MYQOPENGL_H #include <QOpenGLWidget>#include <QOpenGLFunctions>#include <QOpenGLBuffer>#include <QOpenGLShaderProgram> class MyQOpengl : public QOpenGLWidget, protected QOpenGLFunctions{ Q_OBJECT public: explicit MyQOpengl(QWidget *parent = 0); void InitShader(); protected: void initializeGL() override; void paintGL() override; void resizeGL(int w, int h) override; private: QOpenGLShaderProgram *_pShaderProgram; QOpenGLBuffer _vbo;}; #endif // MYQOPENGL_H
cpp
#include "myqopengl.h"#include <QDebug> MyQOpengl::MyQOpengl(QWidget *parent) : QOpenGLWidget(parent){} void MyQOpengl::initializeGL(){ // 为当前环境初始化OpenGL函数 initializeOpenGLFunctions(); InitShader();} void MyQOpengl::InitShader(){ //顶点着色器 QOpenGLShader *vShader = new QOpenGLShader(QOpenGLShader::Vertex, this); const char *vSrc = "in vec4 vPosition; \n" "in vec4 vColor; \n" "out vec4 color; \n" "void main() { \n" " color = vColor; \n" " gl_Position = vPosition; \n" "} \n"; vShader->compileSourceCode(vSrc); //片段着色器 QOpenGLShader *fShader = new QOpenGLShader(QOpenGLShader::Fragment, this); const char *fSrc = "in vec4 color; \n" "out vec4 fColor; \n" "void main() { \n" " fColor = color; \n" "} \n"; fShader->compileSourceCode(fSrc); //着色器程序 _pShaderProgram = new QOpenGLShaderProgram; _pShaderProgram->addShader(vShader); _pShaderProgram->addShader(fShader); _pShaderProgram->link(); _pShaderProgram->bind();}void MyQOpengl::resizeGL(int w, int h){ glViewport(0,0,w,h);} void MyQOpengl::paintGL(){ glClear(GL_COLOR_BUFFER_BIT); glClearColor(0.2f, 0.3f, 0.3f,1.0f); //顶点位置 GLfloat vertices[] = { -0.5f, -0.5f, //left 0.0f, 0.5f, //top 0.5f, -0.5f, //right }; _vbo.create(); _vbo.bind(); _vbo.allocate(vertices, 18*sizeof(GLfloat)); GLuint vPosition = _pShaderProgram->attributeLocation("vPosition"); _pShaderProgram->setAttributeBuffer(vPosition, GL_FLOAT, 0, 2, 0); glEnableVertexAttribArray(vPosition); // 顶点颜色 GLfloat colors[] = { 1.0f, 0.5f, 0.2f, //r g b 1.0f, 0.5f, 0.2f, 1.0f, 0.5f, 0.2f, }; _vbo.write(6*sizeof(GLfloat), colors, 12*sizeof(GLfloat)); GLuint vColor = _pShaderProgram->attributeLocation("vColor"); _pShaderProgram->setAttributeBuffer(vColor, GL_FLOAT, 6*sizeof(GLfloat), 3, 0); glEnableVertexAttribArray(vColor); // 绘制 glDrawArrays(GL_TRIANGLES, 0, 3);}通过以上代码实现QOPenGL绘制了一个橘色的三角形[object Object]