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;

原文地址:https://www.cnblogs.com/Anita9002/p/4930869.html