高级GLSL
内建变量
顶点着色器
gl_PointSoze : float 输出变量,用于控制渲染 GL_POINTS 型图元时,点的大小。可用于粒子系统。将其设置为 gl_Position.z 时,可以使点的距离越远,大小越大。创建出类似近视眼看远处灯光的效果
glEnable(GL_PROGRAM_POINT_SIZE); //也是需要开启
void main()
{gl_Position = projection * view * model * vec4(aPos, 1.0); gl_PointSize = gl_Position.z;
}
gl_vertexID: int 型输入变量(只读),存储了正在绘制顶点的ID(当(使用glDrawElements)进行索引渲染的时候,这个变量会存储正在绘制顶点的当前索引。当(使用glDrawArrays)不使用索引进行绘制的时候,这个变量会储存从渲染调用开始的已处理顶点数量。)
片段着色器
gl_FragCoord: vec4型输出变量。存储了屏幕空间坐标(x,y ,以窗口左下角为原点)和图元深度值(z,0 - 1).常用来获取深度值。
我们已经使用glViewport设定了一个800x600的窗口了,所以片段窗口空间坐标的x分量将在0到800之间,y分量在0到600之间。
void main()
{ if(gl_FragCoord.x < 400)FragColor = vec4(1.0, 0.0, 0.0, 1.0);elseFragColor = vec4(0.0, 1.0, 0.0, 1.0);
}
gl_FrontFacing: bool 型输入变量。标记了当前图元是否为正面
#version 330 core
out vec4 FragColor;in vec2 TexCoords;uniform sampler2D frontTexture;
uniform sampler2D backTexture;void main()
{ if(gl_FrontFacing)FragColor = texture(frontTexture, TexCoords);elseFragColor = texture(backTexture, TexCoords);
}
给立方体里外使用不同的纹理:
gl_FragDepth :float 型输出变量。用于手动设置片段的深度值。在片段着色器中出现后,Early-Z 将被禁用
gl_FragDepth = 0.0; // 这个片段现在的深度值为 0.0
//如果着色器没有写入值到gl_FragDepth,它会自动取用gl_FragCoord.z的值。
从OpenGL 4.2起,我们仍可以对两者进行一定的调和,在片段着色器的顶部使用深度条件(Depth Condition)重新声明gl_FragDepth变量:
layout (depth_<condition>) out float gl_FragDepth;
这样子的话,当深度值比片段的深度值要小的时候,OpenGL仍是能够进行提前深度测试的。
接口块
但当程序变得更大时,你希望发送的可能就不只是几个变量了,它还可能包括数组和结构体。
接口块的声明和struct的声明有点相像,不同的是,现在根据它是一个输入还是输出块(Block),使用in或out关键字来定义的。
#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec2 aTexCoords;uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;out VS_OUT
{vec2 TexCoords;
} vs_out;void main()
{gl_Position = projection * view * model * vec4(aPos, 1.0); vs_out.TexCoords = aTexCoords;
}
这次我们声明了一个叫做vs_out的接口块,它打包了我们希望发送到下一个着色器中的所有输出变量
之后,我们还需要在下一个着色器,即片段着色器,中定义一个输入接口块。
#version 330 core
out vec4 FragColor;in VS_OUT
{vec2 TexCoords;
} fs_in;uniform sampler2D texture;void main()
{ FragColor = texture(texture, fs_in.TexCoords);
}
只要两个接口块的名字一样,它们对应的输入和输出将会匹配起来。这是帮助你管理代码的又一个有用特性,它在几何着色器这样穿插特定着色器阶段的场景下会很有用。
Uniform 缓冲对象
OpenGL为我们提供了一个叫做Uniform缓冲对象(Uniform Buffer Object)的工具,它允许我们定义一系列在多个着色器程序中相同的全局Uniform变量。当使用Uniform缓冲对象的时候,我们只需要设置相关的uniform一次。
参考:高级GLSL - LearnOpenGL CN
LearnOpenGL学习笔记(十) - 高级GLSL、几何着色器、实例化与抗锯齿 - Yoi's Home