高级GLSL
文章目录
一、GLSL的内建变量
内建变量均以"gl_"为前缀
1.顶点着色器的内建变量
(1)gl_PointSize
用来改变顶点,点的大小,通常用于粒子系统
# 记得开启
glEnable(GL_PROGRAM_POINT_SIZE);
void main()
{
gl_Position = projection * view * model * vec4(aPos, 1.0);
gl_PointSize = gl_Position.z;
}
(2)gl_VertexID
每个顶点的ID
如果使用glDrawElements绘制,则是当前顶点索引
如果使用glDrawArrays绘制,则是当前绘制顶点数的计数
2.片段着色器的内建变量
(1)gl_FragCoord
gl_FragCoord.xy代表每个片段的窗口坐标,原点在左下角
例如:gl_FragCoord的x和y分量是片段的窗口空间(Window-space)坐标,其原点为窗口的左下角。我们已经使用glViewport设定了一个800x600的窗口了,所以片段窗口空间坐标的x分量将在0到800之间,y分量在0到600之间。
gl_FragCoord.z代表了只可以读取的像素深度
(2)gl_FrontFacing
是一个bool变量,代表了面片的正反方向
(3)gl_FragDepth
代表了可以写的像素深度
从OpenGL 4.2起,我们仍可以对两者进行一定的调和,在片段着色器的顶部使用深度条件(Depth Condition)重新声明gl_FragDepth变量:
layout (depth_<condition>) out float gl_FragDepth;
二、接口块
用于着色器之间批量数据通信
形式为:块名(VS_OUT)要一样
顶点着色器:
out VS_OUT
{
vec2 TexCoords;
} vs_out;
片段着色器
in VS_OUT
{
vec2 TexCoords;
} fs_in;
三、Uniform缓冲对象
用于批量Uniform变量传递到着色器
1.在着色器形式为uniform块:
layout (std140) uniform Matrices
{
mat4 projection;
mat4 view;
};
2.Uniform块布局有三种:
共享布局(shared):默认的,内存布局在每个声明了这个Uniform块的程序中是不一致的,共享
std140布局:内存布局在每个声明了这个Uniform块的程序中是一致的,共享
紧凑布局(packed):省内存、但非共享
3.std140布局规则
layout (std140) uniform ExampleBlock
{
// 基准对齐量 // 对齐偏移量
float value; // 4 // 0
vec3 vector; // 16 // 16 (必须是16的倍数,所以 4->16)
mat4 matrix; // 16 // 32 (列 0)
// 16 // 48 (列 1)
// 16 // 64 (列 2)
// 16 // 80 (列 3)
float values[3]; // 16 // 96 (values[0])
// 16 // 112 (values[1])
// 16 // 128 (values[2])
bool boolean; // 4 // 144
int integer; // 4 // 148
};
4.使用Uniform缓冲(以绑定投影和观察矩阵为例)
(1)定义每个着色器的Uniform块
layout (std140) uniform Matrices
{
mat4 projection;
mat4 view;
};
(2)每个着色器的Uniform块绑定到绑定点0
unsigned int uniformBlockIndexRed = glGetUniformBlockIndex(shaderRed.ID, "Matrices");
unsigned int uniformBlockIndexGreen = glGetUniformBlockIndex(shaderGreen.ID, "Matrices");
unsigned int uniformBlockIndexBlue = glGetUniformBlockIndex(shaderBlue.ID, "Matrices");
unsigned int uniformBlockIndexYellow = glGetUniformBlockIndex(shaderYellow.ID, "Matrices");
glUniformBlockBinding(shaderRed.ID, uniformBlockIndexRed, 0);
glUniformBlockBinding(shaderGreen.ID, uniformBlockIndexGreen, 0);
glUniformBlockBinding(shaderBlue.ID, uniformBlockIndexBlue, 0);
glUniformBlockBinding(shaderYellow.ID, uniformBlockIndexYellow, 0);
(3)创建Uniform缓冲对象,并绑定到绑定点0
unsigned int uboMatrices
glGenBuffers(1, &uboMatrices);
glBindBuffer(GL_UNIFORM_BUFFER, uboMatrices);
glBufferData(GL_UNIFORM_BUFFER, 2 * sizeof(glm::mat4), NULL, GL_STATIC_DRAW);
glBindBuffer(GL_UNIFORM_BUFFER, 0);
glBindBufferRange(GL_UNIFORM_BUFFER, 0, uboMatrices, 0, 2 * sizeof(glm::mat4));
(4)在绑定点0创建内存空间,并生成数据
glm::mat4 projection = glm::perspective(glm::radians(45.0f), (float)width/(float)height, 0.1f, 100.0f);
glBindBuffer(GL_UNIFORM_BUFFER, uboMatrices);
glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(glm::mat4), glm::value_ptr(projection));
glBindBuffer(GL_UNIFORM_BUFFER, 0);
glm::mat4 view = camera.GetViewMatrix();
glBindBuffer(GL_UNIFORM_BUFFER, uboMatrices);
glBufferSubData(GL_UNIFORM_BUFFER, sizeof(glm::mat4), sizeof(glm::mat4), glm::value_ptr(view));
glBindBuffer(GL_UNIFORM_BUFFER, 0);