• OpenGL ES着色器语言之操作数(官方文档第五章)


    OpenGL ES着色器语言之操作数(官方文档第五章)

    5.1操作数

    OpenGL ES着色器语言包含如下操作符.

    5.2数组下标

             数组元素通过数组下标操作符([ ])进行访问.这是操作数组的唯一操作符,举个访问数组元素的例子:

                       diffuseColor += lightIntensity[3] * NdotL;

    5.3函数调用

            如果一个函数有返回值,那么通常这个函数调用会用在表达式中.

    5.4构造器

            构造器使用函数调用语法,函数名是一个基本类型的关键字或者结构体名字,在初始化器或表达式中使用.参数被用来初始化要构造的值.构造器可以将一个数据标量类型转换为另一个标量类型,或者从较小的类型转换为较大的类型,或者从较大的类型转为较小的类型.

    5.4.1 转换和标量构造器

            标量之间转换:

    int (bool)         //将布尔型值转换成整数
    
    int (float)         //将浮点数值转换成整数
    
    float (bool)         //将布尔型值转换成浮点数
    
    float(int)         //将整型值转换成浮点数
    
    bool(int)         //将整数值转换成布尔型值
    
    bool(float)         //将浮点数值转换成布尔型值

           当构造器将一个float转换成int时,浮点数的小数部分将被自动舍弃掉.

           当int和float转换成bool时,0和0.0被转换成false,非0值将被转换成true.当构造器将bool值转换成int或float时,false被转换成0或0.0, true被转换成1或1.0.

           等价构造器,如float(float)也是合法的,但很少使用到.

           如果构造器的参数不是标量,如向量,那么构造器将取其第一个元素.如float (vec3)构造器将取vec3中的第一个值.

    5.4.2向量和矩阵构造器

            构造器也可以用来从标量集合,向量,矩阵中创建向量和矩阵.同时可以缩短向量长度.

            如果使用一个单一的标量来初始化向量,那么向量的所有值均使用该值进行初始化.如果使用一个单一的标量来初始化矩阵,那么矩阵的对角线的所有元素均会被初始化为该值,但其他元素将会被初始化为0.0

            如果一个向量通过多个标量,向量或矩阵或这几种的混合来构造,那么向量的元素将按照参数列表的顺序来初始化.构造器将从参数列表中按从左到右的顺序去取参数,如果参数有多个值,那么再依次从这个参数中将值取出.构造矩阵也是类似的.矩阵元素将按照列为主要顺序来构造.构造器将依次从参数列表中取出参数值来构造矩阵的元素.如果参数列表中的值的个数超过矩阵或向量的元素个数的话,将会引起错误.

            如果使用一个矩阵来构造矩阵的话,那么,参数矩阵中的元素值将放置到新矩阵的相应位置.

            如果基本类型(int , float, bool)作为参数传进构造器,但是要构造的元素类型和传进来的数据类型不同,那么将会使用类型转换.

    vec3(float) // initializes each component of with the float
    vec4(ivec4) // makes a vec4 with component-wise conversion
    vec2(float, float) // initializes a vec2 with 2 floats
    ivec3(int, int, int) // initializes an ivec3 with 3 ints
    bvec4(int, int, float, float) // uses 4 Boolean conversions
    vec2(vec3) // drops the third component of a vec3
    vec3(vec4) // drops the fourth component of a vec4
    vec3(vec2, float) // vec3.x = vec2.x, vec3.y = vec2.y, vec3.z = float
    vec3(float, vec2) // vec3.x = float, vec3.y = vec2.x, vec3.z = vec2.y
    vec4(vec3, float)
    vec4(float, vec3)
    vec4(vec2, vec2)
    
     
    
    vec4 color = vec4(0.0, 1.0, 0.0, 1.0);
    vec4 rgba = vec4(1.0); // sets each component to 1.0
    vec3 rgb = vec3(color); // drop the 4th component
    
     
    
    
    mat2(float)
    mat3(float)
    mat4(float)
    
    
    mat2(vec2, vec2);
    mat3(vec3, vec3, vec3);
    mat4(vec4, vec4, vec4, vec4);
    mat2(float, float,
    float, float);
    mat3(float, float, float,
    float, float, float,
    float, float, float);
    mat4(float, float, float, float,
    float, float, float, float,
    float, float, float, float,
    float, float, float, float);

    5.4.3结构体构造器

           一旦结构体被定义,并给了一个类型名,那么和其同名的构造器就可以使用了.

    struct light {
    float intensity;
    vec3 position;
    };
    light lightVar = light(3.0, vec3(1.0, 2.0, 3.0));

           传进构造器的参数必须和结构体里面声明的具有相同的顺序和类型.

           结构体构造器可以用于初始化器或者用在表达式中.

    5.5向量组件

           向量中每个组件的名称都使用一个单独的字符来表示.常用的位置,颜色,或者纹理坐标向量的组件直接和几个便利的数字相关联.访问向量中的组件可以使用向量名(.)组件名的方式.

           支持的组件名称如下:

           组件名称x,r,s在向量中是表示同一个组件的同义词.

           注意,为了不和颜色向量中的r(红色)混淆,纹理向量中的第三个组件名称使用了p.

           访问超出向量个数的组件会引起错误:

    vec2 pos;
    pos.x // is legal
    pos.z // is illegal

           组件选择语法可以一次选择多个组件:

    vec4 v4;
    v4.rgba; // is a vec4 and the same as just using v4,
    v4.rgb; // is a vec3,
    v4.b; // is a float,
    v4.xy; // is a vec2,
    v4.xgba; // is illegal - the component names do not come from
    // the same set.

            通过移动和替换组件可以产生不同的向量:

    vec4 pos = vec4(1.0, 2.0, 3.0, 4.0);
    vec4 swiz= pos.wzyx; // swiz = (4.0, 3.0, 2.0, 1.0)
    vec4 dup = pos.xxyy; // dup = (1.0, 1.0, 2.0, 2.0)

            组件组符号可以出现在左值中,也可以出现在右值中.

    vec4 pos = vec4(1.0, 2.0, 3.0, 4.0);
    pos.xw = vec2(5.0, 6.0); // pos = (5.0, 2.0, 3.0, 6.0)
    pos.wx = vec2(7.0, 8.0); // pos = (8.0, 2.0, 3.0, 7.0)
    pos.xx = vec2(3.0, 4.0); // illegal - 'x' used twice
    pos.xy = vec3(1.0, 2.0, 3.0); // illegal - mismatch between vec2 and vec3

            数组下标索引语法同样适用于向量.所以:

    vec4   pos;

    中pos[2]表示第三个元素,与使用pos.z是等价的。

    5.6  矩阵组件

            访问矩阵组件可以使用数组的下标索引语法。使用一维数组访问矩阵表示你要访问矩阵中对应的那一列组件,即返回相应列所有元素的向量。二位数组才是具体的访问某一个组件。由于矩阵是列优先的,因此,使用数组来索引矩阵元素的时候,数组的第一维表示列,第二维表示行。

    mat4 m;
    m[1] = vec4(2.0); // sets the second column to all 2.0
    m[0][0] = 1.0; // sets the upper left element to 1.0
    m[2][3] = 2.0; // sets the 4th element of the third column to 2.0

           如果下标越界,将引起编译时错误。 

    5.7结构体和字段

           结构体字段的访问也是要用到点操作符的(.)。

           可用于结构体的操作有如下几种:

           等于和赋值运算符只有两个操作数类型是同一个结构体时才有意义。即使两个结构体的名称和字段一模一样,他们也不是相等的。包含矩阵和采样器类型的结构体的赋值和等于操作是未定义的。

    Struct S {int x;};
    S a;
    {
    struct S {int x;};
    S b;
    a = b; // error: type mismatch
    }

    5.8  赋值

            赋值表达式结构如下:

                     lvalue-expression = expression;

            lvalue-expression 表示左值表达式,通过赋值运算符“=”将expression表达式的值赋给lvalue-expression;表达式和左值拥有相同的类型才会编译。所有的类型转换都必须显示地通过构造器来指定。左值必须是可写的。

            支持 += 、 -= 、 *= 、 /=等运算符。

            保留 %= 、<<= 、 >>=、 |=和^=等运算符以便后面修订用。

            读取一个未被写入或初始化的变量是合法的,但其值是未定义的。

    5.9  表达式

            在着色语言中表达式由以下方式创建:

    • bool. int, float型常量,所有向量类型,所有矩阵类型。
    • 所有类型的构造器
    • 所有类型的变量名,除了不跟下标的数组名外
    • 带下标的数组名
    • 不带下标的数组名。一般只用在函数参数传递中。
    • 带返回值的函数调用。
    • 组件字段选择器和数组下标返回值。
    • 括号表达式。任何表达式都可以是括号表达式。
    • 二进制运算符 + 、 - 、 * 、 /
    • %保留修订用
    • 一元负操作符(-),自加(++),自减(--)操作符。
    • 比较运算符。大于(>),小于(<),大于等于(>=),小于等于(<=)。如果想比较向量,使用内建函数lessThan,lessThanEqual,greaterThan,greaterThanEqual。
    • 等于(=)和不等于(!=)运算符。除了数组,包含数组的结构体,采样器,包含采样器的结构体外其他类型都可以使用。如果想让组件按位比较,使用内建的函数equal和notEqual。
    • 逻辑二进制运算符(&&, ||, ^)。
    • 逻辑一元运算符非(!)
    • 逗号运算符。逗号运算符返回表达式序列中最后一个的结果。
    • 三元选择运算符(?:)
    • 运算符(&,|,^,~,>>,<<)保留修订用。

    5.10  常量表达式

        常量表达式可以是以下几种:

    • 字符值(如5或true)
    • 全局或本地使用const修饰的变量,函数参数除外
    • 返回常量数组,常量矩阵的某个元素或常量结构体的某个字段
    • 参数都是常量表达式的结构体
    • 所有参数都是常量表达式的内建函数类型,除了纹理查找函数外。

       以下不能用在常量表达式:

    • 用户自定义的函数
    • uniform,attribute,varying变量        

       数组变量不能使常量表达式,因为常量必须在声明时进行初始化,但是数组没有初始化机制

    5.11  向量和矩阵操作

            对矩阵和向量操作就是对向量和矩阵的每一个单独组建进行操作。举个例子

    (1)向量和一个浮点数或整数相加,结果是向量的每一个元素都和该浮点数相加

    vec3 v, u;
    float f;
    v = u + f;
    等价于:
    v.x = u.x + f;
    v.y = u.y + f;
    v.z = u.z + f;

    (2)向量和向量相加,结果是两个向量的对应位置的组件分别相加

    vec3 v, u, w;
    w = v + u;

    等价于:

    w.x = v.x + u.x;
    w.y = v.y + u.y;
    w.z = v.z + u.z;

      这对于大部分操作符和所有的整数、浮点数向量和矩阵类型都是类似的操作。例外是矩阵和向量的乘法,矩阵和矩阵的乘法。如:

    (3)向量乘以矩阵,结果是

    vec3 v, u;
    mat3 m;
    u = v * m;
    等价于:
    u.x = dot(v, m[0]); // m[0] is the left column of m
    u.y = dot(v, m[1]); // dot(a,b) is the inner (dot) product of a and b
    u.z = dot(v, m[2]);

    (4)矩阵乘以向量,结果是矩阵的各行和向量相乘
    u = m * v;
    等价于:
    u.x = m[0].x * v.x + m[1].x * v.y + m[2].x * v.z;
    u.y = m[0].y * v.x + m[1].y * v.y + m[2].y * v.z;
    u.z = m[0].z * v.x + m[1].z * v.y + m[2].z * v.z;

    (5)矩阵乘以矩阵,前一个矩阵的行乘以后一个矩阵的列
    mat m, n, r;
    r = m * n;
    等价于:
    r[0].x = m[0].x * n[0].x + m[1].x * n[0].y + m[2].x * n[0].z;
    r[1].x = m[0].x * n[1].x + m[1].x * n[1].y + m[2].x * n[1].z;
    r[2].x = m[0].x * n[2].x + m[1].x * n[2].y + m[2].x * n[2].z;
    r[0].y = m[0].y * n[0].x + m[1].y * n[0].y + m[2].y * n[0].z;
    r[1].y = m[0].y * n[1].x + m[1].y * n[1].y + m[2].y * n[1].z;
    r[2].y = m[0].y * n[2].x + m[1].y * n[2].y + m[2].y * n[2].z;
    r[0].z = m[0].z * n[0].x + m[1].z * n[0].y + m[2].z * n[0].z;
    r[1].z = m[0].z * n[1].x + m[1].z * n[1].y + m[2].z * n[1].z;
    r[2].z = m[0].z * n[2].x + m[1].z * n[2].y + m[2].z * n[2].z;

  • 相关阅读:
    POJ3297+map字符串处理
    POJ3204+DInic+maxflow
    HDU4704+费马小定理
    FZU-1924+判断环/DFS/BFS
    FZU-1921+线段树
    FZU-1926+KMP
    CodeForce 339:A+B+C
    HDU2896+AC自动机
    POJ2527+多项式除法
    鼠标移入移出事件
  • 原文地址:https://www.cnblogs.com/Anita9002/p/4930869.html
Copyright © 2020-2023  润新知