目录
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绘制了一个橘色的三角形,具体的API这里不进行过多讨论,主要是熟悉opengl的绘图流程,后面再专门对相关的接口进行探讨,以上。