GLSL
OpenGL着色器(shader)语言
典型结构:
典型结构基本数据类型:int, float, double, uint, bool
GLSL容器类型:vector, matrix
向量类型使用.操作符引用成员,如坐标(x, y, z, w),颜色(r, g, b, a),纹理坐标(s, t, p, q)
分量重组:
vec2 someVec;
vec4 differentVec = someVec.xyxx;
vec3 anotherVec = differentVec.zyw;
vec4 otherVec = someVec.xxxx + anotherVec.yxzy;
vec2 vect = vec2(0.5f,0.7f);
vec4 result = vec4(vect,0.0f,0.0f);
vec4 otherResult = vec4(result.xyz,1.0f);
顶点着色器:使用location这一元数据指定输入变量,这样我们才可以在CPU上配置顶点属性。顶点着色器需要为它的输入提供一个额外的layout标识,这样我们才能把它链接到顶点数据。
片段着色器:使用vec4颜色输出变量,若未定义输出颜色,则默认为黑色或白色
各着色器数据交流:从一个着色器向另一个着色器发送数据,必须在发送方着色器中声明一个输出,在接收方着色器中声明一个类似的输入。当类型和名字都一样的时候,OpenGL就会把两个变量链接到一起,它们之间就能发送数据了(这是在链接程序对象时完成的)。
着色器实例Uniform是一种从CPU中的应用向GPU中的着色器发送数据的方式,但uniform和顶点属性有些不同。首先,uniform是全局的(Global)。全局意味着uniform变量必须在每个着色器程序对象中都是独一无二的,而且它可以被着色器程序的任意着色器在任意阶段访问。第二,无论你把uniform值设置成什么,uniform会一直保存它们的数据,直到它们被重置或更新。
uniform变量定义 uniform变量在OpenGL代码中使用我们可以通过glUniform4f函数设置uniform值。注意,查询uniform地址不要求你之前使用过着色器程序,但是更新一个unform之前你必须先使用程序(调用glUseProgram),因为它是在当前激活的着色器程序中设置unform的。
uniform函数有许多,但命名方式遵循一定的规律:
glUniform函数添加后缀支持多属性:
顶点着色器 VBO存储 VAO使能多属性高级GLSL
GLSL的内建变量
gl_Position:顶点着色器裁剪空间输出的位置向量
gl_PointSize:用于基本图元GL_POINTS,设置点的大小,类型为float;使用前需开启
glEnable(GL_PROGRAM_POINT_SIZE);
gl_VertexID:整型变量,存储绘制的当前顶点的id。进行索引渲染是,它保存着当前绘制顶点的索引,其他时候保存的是从渲染开始起直到当前处理的这个顶点的编号。
片段着色器的变量
gl_FragCoord:它的z元素和特定的片段的深度相等;x,y是当前片段的窗口坐标
gl_FrontFacing:bool型,若当前片段是正面的一部分值为true,反之为false。可以根据其值为内外赋予不同的纹理
gl_FragDepth:设置当前片段的深度值,若不设置值则采用gl_FragCoord.z的值。可以使用深度条件重新声明这个变量
layout (depth_<condition>) out float gl_FragDepth;
condition可能取值:例如depth_greater
any 默认值. 前置深度测试是关闭的
greater 深度值只能比gl_FragCoord.z大
less 深度值只能设置得比gl_FragCoord.z小
unchanged 如果写入gl_FragDepth, 就会写gl_FragCoord.z
接口块
使用in, out关键字声明,如果接口块的名字一致,in块和out块的数据会联系起来
out VS_OUT{
vec2 TexCoords;
} vs_out;
in VS_OUT{
vec2 TexCoords;
} fs_in;
块的成员使用.运算符来引用;
Uniform缓冲对象
uniform缓冲对象比单独的uniform有很多好处。第一,一次设置多个uniform比一次设置一个速度快。第二,如果改变一个横跨多个着色器的uniform,在uniform缓冲中只需更改一次。第三,使用uniform缓冲对象可以在着色器中使用更多的uniform。OpenGL有一个对可使用uniform数据的数量的限制,可以用GL_MAX_VERTEX_UNIFORM_COMPONENTS来获取。当使用uniform缓冲对象中,这个限制的阈限会更高。所以无论何时,当达到了uniform的最大使用数量(比如做骨骼动画的时候),可以使用uniform缓冲对象。
uniform块布局GLSL 默认使用的uniform内存布局叫做共享布局(shared layout),叫共享是因为一旦偏移量被硬件定义,它们就会持续地被多个程序所共享。使用共享布局,GLSL可以为了优化而重新放置uniform变量,只要变量的顺序保持完整。
使用uniform缓冲
创建uniform缓冲之后往缓冲中更新或插入数据,可绑定到uboExampleBlock上,并使用glBufferSubData来更新它的内存。只需要更新这个uniform缓冲一次,所有的使用这个缓冲着色器就都会使用它更新的数据了。
在OpenGL环境(context)中,定义了若干绑定点(binding points),可以把一个uniform缓冲链接上去。当创建了一个uniform缓冲,把它链接到一个绑定点上,同时也把着色器中uniform块链接到同一个绑定点上,这样就把它们链接到一起了。下面的图标表示了这点:
绑定点 绑定着色器的uniform到绑定点必须为每个着色器共用的uniform设置绑定点。
之后将uniform缓冲对象绑定到同样的绑定点上,
绑定uniform缓冲到绑定点上从OpenGL4.2起,可以在着色器中通过添加另一个布局标识符来储存一个uniform块的绑定点,显式设置绑定点:
binding属性最后向uniform缓冲中添加数据,
添加数据到uniform缓冲中图片和一些文字来源于https://learnopengl-cn.github.io,本人收集作为笔记,如有侵权,望告知