GLSL

GLSL

2017-01-04  本文已影响0人  龙遁流

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,本人收集作为笔记,如有侵权,望告知


上一篇下一篇

猜你喜欢

热点阅读