第一章 入门
1.3 着色器
1.3.1 基本结构
利用着色器语言编写着色器,以顶点着色器和片段着色器为例,在着在顶点着色器中输出颜色变量vertexColor
,在片段着色器中输入变量vertexColor
作为图案的颜色。
#version 330 core
layout (location = 0) in vec3 aPos; // 位置变量的属性位置值为0
out vec4 vertexColor; // 为片段着色器指定一个颜色输出
void main()
{
gl_Position = vec4(aPos, 1.0); // 注意我们如何把一个vec3作为vec4的构造器的参数
vertexColor = vec4(0.5, 0.0, 0.0, 1.0); // 把输出变量设置为暗红色
}
#version 330 core
out vec4 FragColor;
in vec4 vertexColor; // 从顶点着色器传来的输入变量(名称相同、类型相同)
void main()
{
FragColor = vertexColor;
}
1、着色器开始要声明版本:#version 330 core
2、变量
-
变量声明形式为
in type in_variable_name
,输入和输出变量:in vec4 vertexColor
out vec4 vertexColor
,uniform变量:uniform vec4 ourColor
; -
数据类型
vecn
表示包含n个float值的向量(n=2,3,4),可以通过x,y,z,w取得分量值,同时也可以对变量进行重组;vec2 someVec; vec4 diffVec=someVec.xyxx; vec2 vect=vec2(0.5,0.7); vec4 result=(vect,0.0,0.0);
3、输入与输出
- 每个着色器都需要有输入和输出,利用关键字
in
和out
。 - 由于顶点着色器要从VAO中接受顶点数据,因此需要利用
layout(location=0)
来指定从哪个顶点属性编号中读取数据。并且顶点着色器有固定的输出gl_Position
,无需定义。 - 片段着色器中必须输出一个
vec4
颜色变量,定义渲染的颜色,名字自定义。 - 为实现从一个着色器向另一个着色器发送数据,可在一个着色器中声明一个输出,另一个着色器阶段声明一个名字相同的输入变量,变量就会传递下去。
1.3.2 uniform
1、uniform
关键字的变量是全局的,可以在任意的着色器中使用,该变量数据直接来源于CPU,与顶点数据不同,不经过VBO,VAO。
2、 在片段着色器中定义uniform型的颜色变量ourcolor
,利用CPU中的数据给它赋值。
3、为对变量赋值,首先需要找到着色器中uniform
属性变量的位置,然后让颜色值随着时间改变,就可得颜色渐变的图案。
#version 330 core
out vec4 FragColor;
uniform vec4 ourColor; // 在OpenGL程序代码中设定这个变量
void main()
{
FragColor = ourColor;
}
float timeValue = glfwGetTime();//获取时间数据
float greenValue = (sin(timeValue) / 2.0f) + 0.5f;//改变值的取值范围
int vertexColorLoaction = glGetUniformLocation(shaderProgram, "ourColor");//获取变量的位置
glUseProgram(shaderProgram);//为更新变量,首先需要启用着色器程序
glUniform4f(vertexColorLoaction, 0.0f, greenValue, 0.0f, 1.0f);//改变uniform变量的值
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
1.3.3 传递颜色数据
1、在上述中顶点数据只包含了位置信息,现增加顶点的颜色信息进行传递。
float vertices[] = {
-0.5f, -0.5f, 0.0f, 1.0f,0,0,
0.5f, -0.5f, 0.0f,0,1.0f,0,
0.0f, 0.5f, 0.0f,0,0,1.0f,
0.8f, 0.8f, 0.0f,1.0f,0,1.0f
};
2、数据变化后,VBO中的顶点数据变化为:
3、顶点数据属性指针也需发生变化,分别读取位置属性和颜色属性,另外步长变化为6 * sizeof(float)
,颜色数据的偏移量为3 * sizeof(float)
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0