着色器
在OpenGL中,我们需要至少定义一个顶点着色器和一个片段着色器。
顶点着色器
下面是一个最基础的顶点着色器的写法:

每个着色器都起始于一个版本声明。
in关键字用来声明输入变量,即着色器接收从应用程序传递过来的数据,这些数据通常是顶点属性,例如顶点位置、法线、纹理坐标等。
layout关键字配合location限定符,用于指定变量在内存中的布局或者在着色器中的位置。
vec是GLSL中的向量数据类型,其中vec2表示包含两个分量的二维向量,vec3表示包含三个分量的三维向量,vec4表示包含四个分量的四维向量。
在上面的代码中,我们输入了一个vec3类型的变量position,它包含了顶点的坐标信息,之后我们在主函数中将其转换为GLSL内置的输出变量gl_Position。
gl_Position是一个四维向量(x,y,z,w),表示变换后的顶点位置,其中(x,y,z)表示变换后的顶点坐标,而w用于透视除法。透视除法是将齐次坐标(Homogeneous Coordinates)转换为三维坐标的过程。
——————————————————————————————————————
齐次坐标是一种将N维空间中的点表示为N+1维向量的方法。在三维空间中,齐次坐标通常用四维向量表示。一个点的三维坐标(x, y, z)可以表示为(x', y', z', w),其中:
x' = x * w,y' = y * w,z' = z * w
这里的w是齐次坐标的第四个分量,通常称为“权重”。通过引入权重,我们可以使用除法来实现透视效果。透视除法是将齐次坐标转换为三维坐标的过程,即(x/w, y/w, z/w)。
齐次坐标有一些有用的性质,例如平移、旋转和缩放变换可以统一地表示为矩阵乘法。这极大地方便了图形渲染中的变换操作。
——————————————————————————————————————
片段着色器
片段着色器所做的是计算像素最后的颜色输出。
颜色是一个四维向量,它的四个分量分别是红、绿、蓝和透明度,一般缩写为RGBA,其中每个分量的强度都设置在0.0到1.0之间。
下面是一个最基础的片段着色器的写法:

编译着色器
编译一个着色器需要三个步骤:创建着色器—绑定源码—编译着色器。
glCreateShader()用于创建一个着色器对象,并返回一个标识符。

glShaderSource()用于将着色器源代码与着色器对象进行关联。

shader是要关联源代码的着色器对象的标识符。
count是源代码字符串数组的大小,即源代码的行数。
string是指向源代码字符串数组的指针,可以是一个或多个源代码字符串。
length是指向一个整数数组的指针,用于指定每个源代码字符串的长度,如果为 NULL,则表示每个字符串都以 NULL 结尾。
glCompileShader()用于编译着色器。

着色器程序
着色器程序对象(Shader Program Object)是多个着色器合并之后并最终链接完成的版本。使用一个着色器程序有以下几个步骤:创建着色器程序—添加着色器—链接着色器—激活着色器程序。
glCreateProgram()用于创建着色器程序对象,并返回对象的标识符。

glAttachShader()用于把之前编译过的着色器附加到程序对象上。

glLinkProgram()把相关的着色器链接到程序对象,组合为一个可执行程序。

glUseProgram()用于激活着色器程序对象。

此外,在把着色器对象链接到程序对象以后,着色器对象就失去了用处。记得删除着色器对象,释放资源。
