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;

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

  1. OpenGL ES着色器语言之变量和数据类型(二)(官方文档第四章)

    OpenGL ES着色器语言之变量和数据类型(二)(官方文档第四章) 4.5精度和精度修饰符 4.5.1范围和精度 用于存储和展示浮点数.整数变量的范围和精度依赖于数值的源(varying,unifo ...

  2. OpenGL ES着色器语言之着色概览(官方文档)

    OpenGL ES着色器语言之着色概览(官方文档第二章) 事实上,OpenGL ES着色语言是两种紧密关联的语言.这些语言用来在OpenGL ES处理管线的可编程处理器创建着色器. 在本文档中,除非另 ...

  3. OpenGL ES着色器语言之语句和结构体(官方文档第六章)内建变量(官方文档第七、八章)

    OpenGL ES着色器语言之语句和结构体(官方文档第六章) OpenGL ES着色器语言的程序块基本构成如下: 语句和声明 函数定义 选择(if-else) 迭代(for, while, do-wh ...

  4. OpenGL ES着色器语言之变量和数据类型(一)(官方文档第四章)和varying,uniform,attribute修饰范围

    OpenGL ES着色器语言之变量和数据类型(一)(官方文档第四章)   所有变量和函数在使用前必须声明.变量和函数名是标识符. 没有默认类型,所有变量和函数声明必须包含一个声明类型以及可选的修饰符. ...

  5. OpenGL ES着色器语言之静态使用(static use)和预处理

    OpenGL ES着色器语言之静态使用(static use) 在OpenGL ES中有一个术语叫静态使用(static use),什么叫静态使用呢? 在写代码中,对于一个变量可能具有以下三种情况: ...

  6. Android OpenGL ES 开发(八): OpenGL ES 着色器语言GLSL

    前面的文章主要是整理的Android 官方文档对OpenGL ES支持的介绍.通过之前的文章,我们基本上可以完成的基本的形状的绘制. 这是本人做的整理笔记: https://github.com/re ...

  7. Tensorflow官方文档中文版——第二章(瞎奖杯写)

    包含如下几个部分: 1.面向机器学习初学者的 MNIST 初级教程 2.面向机器学习专家的 MNIST 高级教程 3.TensorFlow 使用指南 4.卷积神经网络 5.单词的向量表示(word e ...

  8. Tensorflow官方文档中文版——第一章

    第一示例: import tensorflow as tf import numpy as np x_data=np.float32(np.random.rand(,))#随机输入 y_data=np ...

  9. 【cocos2d-js官方文档】五、Cocos2d-JS v3.0的新Action API

    新增action中的方法 曾经,当我们须要反复一个action的时候,我们须要: sprite.runAction(cc.Repeat.create(action, 2)); 上面代码中创建了一个新的 ...

随机推荐

  1. jquery操作属性 attr()和 prop()兼容性问题

    jquery1.6中新加了一个方法prop(),一直没用过它,官方解释只有一句话:获取在匹配的元素集中的第一个元素的属性值. 大家都知道有的浏览器只要写disabled,checked就可以了,而有的 ...

  2. CF 602C The Two Routes(dij+邻接矩阵)

    ( ̄▽ ̄)" #include<iostream> #include<cstdio> #include<cmath> #include<algori ...

  3. bzoj4318: OSU!&&CF235BLet's Play Osu!

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=4318 4318: OSU! Time Limit: 2 Sec  Memory Limit ...

  4. hdu_5314_Happy King(树的点分治)

    题目链接:hdu_5314_Happy King 题意: 给出一颗n个结点的树,点上有权值: 求点对(x,y)满足x!=y且x到y的路径上最大值与最小值的差<=D: 题解: 还是树的点分治,在统 ...

  5. 一、ASP.NET Routing路由(深入解析路由系统架构原理)

    阅读目录: 1.开篇介绍 2.ASP.NET Routing 路由对象模型的位置 3.ASP.NET Routing 路由对象模型的入口 4.ASP.NET Routing 路由对象模型的内部结构 4 ...

  6. OpenCV2.x自学笔记——固定阈值

    threshold( const CvArr* src,  CvArr* dst,  double threshold,  double max_value,  int threshold_type) ...

  7. C/C++ - <string> 与<string.h>、<cstring>的区别

    <string.h><string.h>是C版本的头文件,包含比如strcpy.strcat之类的字符串处理函数. <string><string>是C ...

  8. VC中获取窗口控件相对客户区的坐标

    1: RECT rect; 2: GetDlgItem(item_id).GetWindowRect(&rect); 3: ScreenToClient(&rect);

  9. UI线程

    Application.Current.Dispatcher.Invoke(new Action(() =>))

  10. 安装jar包到本地maven仓库

    1.打开cmd 直接输入一下命令 自己下载的jar包放在d盘根目录下,jar名字叫spring-context-support-3.1.0.RELEASE.jar DgroupId后面写的是group ...