高级GLSL
顶点着色器变量
- gl_Position是顶点着色器裁剪空间的输出位置向量.
- gl_PointSize是输出向量,float,设置点的宽高(像素),如果设置为z值,则点会随着距离变远而变大。
- gl_VertexID是输入变量,当前正在绘制顶点的ID.
片段着色器变量
- gl_FragCoord,z对应的是片段的深度值,输入变量,x,y是片段窗口空间坐标(以左下角为原点)
- gl_FrontFacing是输入变量,用来决定一个面是正面还是背面,在内部和外部可以使用不同纹理。
- gl_FragDepth是输出变量,可以修改深度值
接口块
//使用复杂结构进行输入输出
#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;
}
Uniform缓冲对象
#version 330 core
layout (location = 0) in vec3 aPos;
layout (std140) uniform Matrices
{
mat4 projection;
mat4 view;
};
uniform mat4 model;
void main()
{
gl_Position = projection * view * model * vec4(aPos, 1.0);
}
Uniform块布局
Uniform块的内容存在一个缓冲对象上,只是一块预留内存,如下面这个布局:
layout (std140) uniform ExampleBlock
{
float value;
vec3 vector;
mat4 matrix;
float values[3];
bool boolean;
int integer;
};
但是变量间间距难以处理,使用共享布局可以在多个程序之间使用,但难以知道偏移量(由程序自行处理得到),可以使用std140布局,显式声明变量布局.
使用Uniform缓冲:
几何着色器
输入是一个图元(如点或三角形)的一组顶点,几何着色器可以把这组顶点变换为不同的图元,并且能生成更多的顶点。
几何着色器例子:
#version 330 core
layout (points) in;//输入布局,设置输入的形状
layout (line_strip, max_vertices = 2) out;
//输出布局,设置输出的形状
void main() {
gl_Position = gl_in[0].gl_Position + vec4(-0.1, 0.0, 0.0, 0.0);
EmitVertex();
gl_Position = gl_in[0].gl_Position + vec4( 0.1, 0.0, 0.0, 0.0);
EmitVertex();
EndPrimitive();
}
比如可以输入为点,而输出为多边形,只要使用EmitVertex()就可以提交多个点。
实现一个爆炸效果:使用几何着色器将每个贴图的三角形面元点按照三角形的法线随时间移动。
法向量可视化:
//几何着色器
void GenerateLine(int index)
{
gl_Position = projection * gl_in[index].gl_Position;
EmitVertex();
gl_Position = projection * (gl_in[index].gl_Position +
vec4(gs_in[index].normal, 0.0) * MAGNITUDE);
EmitVertex();
EndPrimitive();
}
实例化
将大量数据一次性发送给GPU,然后使用一个绘制函数让OpenGL使用这些数据绘制多个物体。
- 一种方法是将大量数据定义在同一个数组中,并进行标号,然后通过Uniform直接一次性传入到着色器。
- 实例化数组,使用顶点属性指针,首先创建顶点缓冲对象,配置属性指针:
unsigned int instanceVBO;
glGenBuffers(1, &instanceVBO);
glBindBuffer(GL_ARRAY_BUFFER, instanceVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(glm::vec2) * 100, &translations[0], GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
//配置属性指针:
glEnableVertexAttribArray(2);
glBindBuffer(GL_ARRAY_BUFFER, instanceVBO);
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), (void*)0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glVertexAttribDivisor(2, 1);//告诉OpenGL什么时候更新顶点属性的内容到新一组数据。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)