zoukankan      html  css  js  c++  java
  • 【OPENGL】第三篇 着色器基础(二)


    在这一小节,主要学习GLSL的基本数据类型以及控制结构。GLSL具备了C++和Java的很多特性,我们会先了解所有着色阶段共有的特性,再了解各个着色器的专属特性。


    1、着色器的基本结构

    一个着色器程序和一个C程序类似,都是从main()函数开始执行的。同样支持单行注释//以及多行注释/**/

    #version 330 core
    void main(){
        // add test code
    }
    

     2、着色器的数据类型

    GLSL是一种强类型的语言,所有变量使用前的必须声明。可用字母、数字、以及下划线字符来组成变量名字。但是数字或者下划线字符不能作为变量名的第一个字符,也不能使用连续下划线。

    所有变量都必须在声明的同时进行初始化。

    类型透明:基本数据类型(float、double、int、uint、bool)以及聚合类型(所谓聚合类型就是基本类型的合并)

    类型不透明:采样器(sampler)、图像(Image)、原子计数器(atomic counter)。

    前面提到的聚合类型,每个基本类型都有对应的聚合类型,以int为例,有2D向量(vec2)、3D向量(vec3)、4D向量(vec4)以及矩阵(mat2、mat4)等类型。

    需要注意的是对于矩阵类型比如mat4×3,其中第一个值表示列数,第二个值表示行数。此外,矩阵的指定需要遵循主序的原则。也就是说,传入的数据将先填充列,然后填充行。

    向量与矩阵中的元素是可以单独访问和设置的。下面主要说三种比较特殊的分量

    (x,y,z,w) 与位置相关的分量

    (r,g,b,a)  与颜色相关的分量

    (s,t,p,q)  与纹理坐标相关的分量

    此外,还有数组类型,一个大小为n的数组的元素范围是0到n-1。

    float coeff[3];
    float[3] coeff;
    int indices[];
    

    类似其他语言比如C++/Java。  

    数组拥有构造函数 float coeff[3] = float[3](2.38, 3.14, 42.0)

    GLSL的数组可以获取数组的长度 length() 该函数返回元素的个数。因为长度值在编译时就是已知的,所以length()方法会返回一个编译时常量。

     3、着色器的存储限制符(Storage Qualifiers)

    数据类型可以通过一些修饰符来改变自己的行为。GLSL中一共定义了4种全局范围内的修饰符。

    1、const 将一个变量定义为只读形式,可以理解为常量的意思

    2、in 设置为着色器阶段的输入变量

    3、out 设置为着色器阶段的输出变量

    4、uniform 表示唯一,对所有几何图元的值都是一致的,除非应用程序对它执行了更新,否则着色器是并不会影响它的值的变化的。

    5、buffer 设置应用程序共享的愉快可读写的内存

    6、shared  只能用于用于计算着色器当中,它可以建立本地工作组内共享的内存。

    4、逻辑语句

    与其他语言类似GLSL提供了大量的操作符以及控制语句执行流程的逻辑操作

    包括算术运算符、操作符、ifels、while、for、break、continue、return等,

    这里有个特殊的关键字 discard 它只能用于片元着色器中,用于丢弃当前的片元、终止着色器的运行,不过这也得取决于具体的硬件实现。

    另外函数的声明以及定义和C/C++类似,并且使用函数之前必须先声明,否则会产生错误。但是,需要特别注意的是,GLSL中没有指针或者引用的概念,

    因此,GLSL提供了参数限制符,来表明其参数时候可以修改或者拷贝到函数等等,类型如下:

    1、in 将数据拷贝到函数中(默认)

    2、const in 将只读数据拷贝到函数中

    3、out 从函数中获取数值

    4、inout 将数据拷贝到函数中,并且返回函数中修改的数据


    以上大概了解了GLSL的数据类型以及语句,下面是一些零散的知识点,先看看,以后用到时再重新回顾。


    1、计算的不变性

    GLSL无法保证在不同的着色器中,两个完全相同的计算公式会得到完全一样的结果。因此GLSL提供了invariant和precise关键字来保持着色器之间的计算不变性。

    关于这个知识点,暂时无法理解,以后再回顾。

    ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------

    2、着色器的预处理器(跳过)

    3、数据块接口(Interface Blocks)

    着色器与应用程序之间,或者着色器阶段之间共享的变量可以组织为变量块的形式,并且有的时候必须采用这种形式

    例如 uniform块、in块、out块、buffer块等等。

    写法有点类型结构体的写法:

    下面以uniform为例
    uniform b{   vec4 v1;   bool v2; };
    一个uniform块中只可以包含透明类型的变量,而且uniform块必须在全局作用域内声明。

    注意:着色器中的数据类型有两种:不透明以及透明的。上文有提及。

    4、从应用程序中访问uniform块

    uniform变量是着色器与应用程序之间共享数据的桥梁,因此如果着色器中的uniform变量是定义在命名的uniform块中,那么就有必要找到不同变量的偏移值。

    5、Buffer块

    GLSL中的buffer块,或者对于应用程序而言,就是着色器的存储缓存对象(shader storage buffe object)

    与uniform块类似,但是buffer块更为强大。如果不需要写入缓存,那么可以直接使用uniform块,并且硬件设备本身可能也没有足够的资源空间来支持buffer块,

    但是uniform块通常是足够的。

    6、in/out块


    关于着色器的编译

     

    OpenGL着色器程序的编写与C语言等基于编译器的语言非常类似。

    我们使用编译器来解析程序,检查是否存在错误,然后将它翻译为目标代码obj。然后,在连接过程中将一系列目标文件合并,并产生最终的可执行程序。

    在程序中使用GLSL着色器的过程与之类似,只不过编译器和连接器都是OpenGL API的一部分而已。

     

    常规步骤:

    对于每一个着色器对象:

      1、创建一个着色器对象

      2、将着色器源代码编译为对象

      3、验证着色器的编译是否成功

    将后需要将多个着色器对象链接为一个着色器程序,包括:

      1、创建一个着色器程序

      2、将着色器对象关联到着色器程序

      3、连接着色器程序。

      4、判断着色器的连接过程是否成功完成

      5、使用着色器来处理顶点和片元

    相关OpenGL函数

      1、创建着色器对象  glCreateShader(GLenum type)

         type必须是  GL_VERTEX_SHADER、GL_FFRAGMENT_SHADER、

                  GL_TESS_CONTROL_SHADER、GL_TESS_EVALUATION_SHADER、GL_GEOMETRY_SHADER

         中的一个。

      2、将着色器的源代码关联到这个对象上。  glShaderSource(...)

      3、编译着色器对象的源代码       glCompileShader()

      4、将着色器对象shader关联到着色器程序program中    glAttachShader()

    and so on...


     

     

    不知不觉明天就是11月份了。一份小记拖了将近2个月,我也是醉了。

    最近发现了DOOM3源码,如获至宝。以后有时间会研究下约翰卡马克大神的这个引擎。

     

    10月31日

    广州

     

     

  • 相关阅读:
    【转+补充】在OpenCV for Android 2.4.5中使用SURF(nonfree module)
    Delphi StarOffice Framework Beta 1.0 发布
    Angular ngIf相关问题
    angularjs文档下载
    公众号微信支付开发
    公众号第三方平台开发 教程六 代公众号使用JS SDK说明
    公众号第三方平台开发 教程五 代公众号处理消息和事件
    公众号第三方平台开发 教程四 代公众号发起网页授权说明
    公众号第三方平台开发 教程三 微信公众号授权第三方平台
    公众号第三方平台开发 教程二 component_verify_ticket和accessToken的获取
  • 原文地址:https://www.cnblogs.com/MyGameAndYOU/p/4726029.html
Copyright © 2011-2022 走看看