QOpenGLShaderProgram

OpenGL默认设置着色器很繁琐,编译源码使用字符串硬编码的方式容易出错,如下面这种写法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
// 顶点着色器源码
auto vertexShaderSource =
"#version 330 core\n"
"layout (location = 0) in vec3 aPos;\n"
"void main() {\n"
" gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);\n"
"}\0";

// 片段着色器源码
auto fragmentShaderSource =
"#version 330 core\n"
"out vec4 FragColor;\n"
"void main() {\n"
" FragColor = vec4(0.0, 0.7, 1.0, 0.8);\n" // 淡蓝色
"}\0";


void OpenGLTest::initShader()
{
makeCurrent();

// 编译顶点着色器
const GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
glCompileShader(vertexShader);

// 检查顶点着色器编译错误
GLint success;
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
if (!success)
{
char infoLog[512];
glGetShaderInfoLog(vertexShader, 512, NULL, infoLog);
qDebug() << "顶点着色器编译失败:" << infoLog;
}

// 编译片段着色器
const GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
glCompileShader(fragmentShader);

// 检查片段着色器编译错误
glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);
if (!success)
{
char infoLog[512];
glGetShaderInfoLog(fragmentShader, 512, NULL, infoLog);
qDebug() << "片段着色器编译失败:" << infoLog;
}

// 链接着色器程序
m_shaderProgram = glCreateProgram();
glAttachShader(m_shaderProgram, vertexShader);
glAttachShader(m_shaderProgram, fragmentShader);
glLinkProgram(m_shaderProgram);

// 检查链接错误
glGetProgramiv(m_shaderProgram, GL_LINK_STATUS, &success);
if (!success)
{
char infoLog[512];
glGetProgramInfoLog(m_shaderProgram, 512, NULL, infoLog);
qDebug() << "着色器程序链接失败:" << infoLog;
}

// 删除临时着色器对象
if (success)
{
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
}

doneCurrent();
}

为了解决这个问题,可以使用Qt封装好的OpenGLShaderProgram和资源文件处理,相关代码如下

  • shape.vertex
1
2
3
4
5
#version 330 core
layout (location = 0) in vec3 aPos;
void main() {
gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);
}
  • shape.fragment
1
2
3
4
5
#version 330 core
out vec4 FragColor;
void main() {
FragColor = vec4(0.0, 0.7, 1.0, 0.8);
}

​ 示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
//声明
QOpenGLShaderProgram m_shaderProgram;

//创建着色器
void OpenGLShaderProgram::initShader()
{
makeCurrent();
// 链接着色器程序
m_shaderProgram.addShaderFromSourceFile(QOpenGLShader::Vertex, ":/shaders/shape.vertex");
m_shaderProgram.addShaderFromSourceFile(QOpenGLShader::Fragment, ":/shaders/shape.fragment");
if (!m_shaderProgram.link())
{
qDebug() << "Shader program linking failed:" << m_shaderProgram.log();
return;
}
doneCurrent();
}

//使用
m_shaderProgram.bind(); // 绑定着色器程序
  1. QOpenGLShader::Vertex:创建一个顶点着色器
  2. QOpenGLShader::Fragment:创建一个片段着色器
  3. addShaderFromSourceFile:创建着色器,编译代码分别在**:/shaders/shape.vertex:/shaders/shape.fragment**