GLSL

作者: 龙遁流 | 来源:发表于2017-01-04 14:44 被阅读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,本人收集作为笔记,如有侵权,望告知


    相关文章

      网友评论

        本文标题:GLSL

        本文链接:https://www.haomeiwen.com/subject/txfuvttx.html