0、写在前面的话
这里只是学习的时候做的笔记记录方便日后的查看,如果有大神看到觉得有问题的地方希望能给予指出,方便日后的学习,谢谢!
我是用的Qt版本为Qt5.6,开发环境为Qt Creator
1、QOpenGLWidget
在Qt开发环境下,使用OpenGL的可编程管线绘制一个三角形
效果如下图所示:
这里使用QOpenGLWidget进行绘制的,在QOpenGLWidget中需要重写
void initializeGL(void);
void resizeGL(int w, int h);
void paintGL(void);
这三个函数,initializeGL()函数为初始化窗口调用的函数,resizeGL()函数改变窗口大小时调用,paintGL()是每一帧绘制的函数。
2、创建Program,加载Shader
使用OpenGL的shader绘制三角形,就要创建一个shader的程序,Qt中实现了QOpenGLShader、QOpenGLShaderProgram类,方便程序的创建和添加Shader。使用代码如下,本例中程序加载两个shader(vertex shader 和fragment shader):
// 创建一个GPU程序
GLuint createGPUProgram(QString nVertexShaderFile, QString nFragmentShaderFile);
QOpenGLShader *m_VertexShader;
QOpenGLShader *m_FragmentShader;
QOpenGLShaderProgram *m_Program;
GLuint OpenGLWidget::createGPUProgram(QString nVertexShaderFile, QString nFragmentShaderFile)
{
m_VertexShader = new QOpenGLShader(QOpenGLShader::Vertex);
bool isOK = m_VertexShader->compileSourceFile(nVertexShaderFile);
if (!isOK)
{
delete m_VertexShader;
m_VertexShader = nullptr;
return 0;
}
m_FragmentShader = new QOpenGLShader(QOpenGLShader::Fragment);
if (!m_FragmentShader->compileSourceFile(nFragmentShaderFile))
{
delete m_VertexShader;
delete m_FragmentShader;
m_FragmentShader = nullptr;
return 0;
}
m_Program = new QOpenGLShaderProgram(this);
m_Program->addShader(m_VertexShader);
m_Program->addShader(m_FragmentShader);
m_Program->link();
return m_Program->programId();
}
其中Vertex shader和fragment shader的内容如下:
3、shader内容
在OpenGL的Shader使用,GLSL语言,与C语言很类似。下面是关于GLSL的一些简单的介绍:
attribute CPU与Shader传递数据,只能在CPU与Vertex Shader之间使用。
uniform 可用于CPU与任意Shader传递数据,一般用于传递矩阵等较大的数据。
varying 可用于Shader间传递数据。
本例子中,数据是CPU->Vertex Shader->Fragmen Shader顺序传递,Vertex shader是处理数据,Fragment shader会终的转换为像素的处理。最后通过OpenGL渲染到屏幕输出。
Vertex Shader:
attribute vec3 pos;
attribute vec4 color;
uniform mat4 M;
uniform mat4 V;
uniform mat4 P;
varying vec4 M_Color;
void main()
{
M_Color = color;
gl_Position = P * V * M * vec4(pos, 1.0);
}由于OpenGL中为列向量和矩阵,这里需要使用矩阵左乘的形式。Vertex shader对应一个点的调用。
其中,M为传递的模型矩阵、V为视图矩阵、P为投影矩阵。
Fragment Shader:
varying vec4 M_Color;
void main()
{
gl_FragColor = M_Color;
}
4、为Shader中传入数据
为attribute中和uniform中的数据赋值,需要获取Shader中的Location
// 获取Uniform ID & Attribute ID
m_MLocationMat = OpenGLCore->glGetUniformLocation(programId, "M");
m_VLocationMat = OpenGLCore->glGetUniformLocation(programId, "V");
m_PLocationMat = OpenGLCore->glGetUniformLocation(programId, "P");
m_PosVector = OpenGLCore->glGetAttribLocation(programId, "pos");
m_ColorVector = OpenGLCore->glGetAttribLocation(programId, "color");
其中OpenGLCore为
OpenGLCore = QOpenGLContext::currentContext()->versionFunctions<QOpenGLFunctions_3_2_Core>();使用OpenGL3.2的核心,programId为QOpenGLShaderProgram的programId。
顶点数据如下:
struct VertexInfo
{
float pos[3];
float color[4];
};
VertexInfo nVertexInfo[3];
nVertexInfo[0].pos[0] =