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

来源:互联网 发布:魔豆宝宝小屋淘宝店 编辑:程序博客网 时间:2024/05/21 16:59

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;

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 公众号申请链接无效怎么办 指纹打卡机时间调错已打卡怎么办 智慧云平台先锋讲座打不开怎么办 下雨穿套裙工装好冷怎么办 国家债务违约不要国际融资怎么办 欠钱的确还不起怎么办 生完孩孑后手发账握不死手怎么办 工作调动没啥消息怎么办 裁剪刀老是推歪怎么办 衣服上粘胶水了怎么办 衣服钻掉了有胶怎么办 衣服上贴纸掉了怎么办 裤子沾上502胶水怎么办 衣服上沾泡沫胶怎么办 衣服上面滴上502怎么办 502胶水弄衣服上怎么办 裤子上粘了胶怎么办 胶水滴在衣服上怎么办 衣服上有502胶水怎么办 衣服上面粘了胶怎么办 衣服上的胶干了怎么办 凌晨4点到火车站怎么办 运管罚款没钱交怎么办 郑州地铁票没买怎么办 遇到吸毒者拦路威胁要钱怎么办 开车遇见拦路要钱的怎么办 高速上有人拦车怎么办 马路上有人拦车怎么办 苹果手机下截软件要钱怎么办 孩子在学校问同学要钱怎么办 在学校被同学要钱怎么办 把人家店砸了要怎么办 外汇出金不到账怎么办 把罚款单弄丢了怎么办 在12306买不到下铺怎么办有 地铁票买反了怎么办 香港买错特惠票怎么办 到达迪拜t3 后怎么办 海藻面膜调多了怎么办 被鸡爪子抓伤了怎么办 被鸡抓伤肿了怎么办