QT中Shader类与多VAO、VBO的使用
1. QOpenGLShaderProgram
在不使用QOpenGLShaderProgram
类时,OpenGL
加载一个shader
大概需要以下步骤:
- 创建着色器
glCreateShader
- 绑定着色器
glShaderSource
- 编译着色器
glCompileShader
- 创建
shader
程序glCreateProgram
- 将着色器添加到
shader
程序glAttachShader
- 连接
shader
程序 - 使用
shader
程序glUseProgram
- 使用完后进行解绑
示例如下:
// 创建顶点着色器
GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
// 绑定着色器
glShaderSource(vertexShader,1,&vertexShaderSource,NULL);
// 编译顶点着色器
glCompileShader(vertexShader);
// 创建片段着色器
GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader,1,&fragmentShaderSource,NULL);
// 编译片段着色器
glCompileShader(fragmentShader);
// 链接 shaders
m_shaderProgram = glCreateProgram();
glAttachShader(m_shaderProgram,vertexShader);
glAttachShader(m_shaderProgram,fragmentShader);
glLinkProgram(m_shaderProgram);
// 使用shader program
glUseProgram(m_shaderProgram);
// 使用完后进行解绑
glUseProgram(0);
使用QOpenGLShaderProgram
后代码会相对简便非常多,步骤如下:
- 给
QOpenGLShaderProgram
设置shader
源码 - 进行链接
- 进行绑定使用
- 使用完后进行解绑
示例如下:
// 添加顶点 shader
m_shaderProgram.addShaderFromSourceFile(QOpenGLShader::Vertex, ":/shaders/vertex_shader.vert");
// 添加片段 shader
m_shaderProgram.addShaderFromSourceFile(QOpenGLShader::Fragment, ":/shaders/fragment_shader.frag");
// 链接
m_shaderProgram.link();
// 绑定,只有在绑定完后才可以对这个shader的变量进行设置
m_shaderProgram.bind();
// 使用完后进行解绑
m_shaderProgram.release();
2. 多VAO、VBO使用
多VAO
、VBO
在创建上与单VAO
、VBO
的区别是通过数组形式创建,示例如下:
// 创建VAO
glGenVertexArrays(2, m_VAO);
// 创建VBO
glGenBuffers(2, m_VBO);
// 解除VBO
glDeleteBuffers(2,m_VBO);
// 解除VAO
glDeleteVertexArrays(2,m_VAO);
2.1 用多VAO、VBO绘制两个不同的三角形
VAO
、VBO
的数据关联绑定,代码如下:// 绑定VAO和VBO对象 glBindVertexArray(m_VAO[0]); glBindBuffer(GL_ARRAY_BUFFER, m_VBO[0]); // 为缓冲对象创建一个新的数据存储 glBufferData(GL_ARRAY_BUFFER, sizeof(firstTriangle), firstTriangle, GL_STATIC_DRAW); /* * 定义一个通用顶点属性数据数组:告诉显卡如何解析缓冲里的属性值 * index:指定要修改的通用顶点属性的索引值 * size:指定通用顶点属性的分量,必须为1、2、3或4,初始值为4 * type:指定数组中每个元素得到类型,初始值为GL_FLOAT * normalized:指定在访问定点数据值时是否应将其归一化 (GL_TRUE) 或直接转换为定点值 (GL_FALSE) * stride:指定数组中每个通用顶点属性的步长 * pointer:指定通用顶点属性的属性的起始位置 */ glVertexAttribPointer(0, 3, GL_FLOAT, GL_TRUE, 3 * sizeof(GLfloat), (void*)0); // 开启VAO管理的第一个属性值 VAO[0] 的第一个属性 glEnableVertexAttribArray(0); // 解绑 glBindBuffer(GL_ARRAY_BUFFER, 0); glBindVertexArray(0); // 绑定VAO和VBO对象 glBindVertexArray(m_VAO[1]); glBindBuffer(GL_ARRAY_BUFFER, m_VBO[1]); // 为缓冲对象创建一个新的数据存储 glBufferData(GL_ARRAY_BUFFER, sizeof(secondTriangle), secondTriangle, GL_STATIC_DRAW); /* * 定义一个通用顶点属性数据数组:告诉显卡如何解析缓冲里的属性值 */ glVertexAttribPointer(0, 3, GL_FLOAT, GL_TRUE, 3 * sizeof(GLfloat), (void*)0); // 开启VAO管理的第一个属性值 VAO[1] 的第一个属性 glEnableVertexAttribArray(0); // 解绑 glBindBuffer(GL_ARRAY_BUFFER, 0); glBindVertexArray(0);
- 绘制三角形
绘制代码里主要是,不同VAO
的切换,如下:glBindVertexArray(m_VAO[0]); glDrawArrays(GL_TRIANGLES, 0, 3); glBindVertexArray(0); glBindVertexArray(m_VAO[1]); glDrawArrays(GL_TRIANGLES, 0, 3); glBindVertexArray(0);