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 Post 提交内容中有标签报错

    Post编辑一点内容要传后台数据库: var html = editor2.html() console.log(encodeURIComponent(html)); //console.log(&q ...

  2. hdu 1072 广搜

    路径是可以重复走的,但是如果再一次走过时间重置点是没有意义的 #include <iostream> #include <cstdio> #include <cstrin ...

  3. Openjudge-计算概论(A)-求满足条件的3位数

    描述: 编写程序,按从小到大的顺序寻找同时符合条件1和2的所有3位数,条件为: 1.该数为完全平方数 2.该数至少有2位数字相同 例如,100同时满足上面两个条件. 输入输入一个数n,n的大小不超过实 ...

  4. matlab显示图像的横纵坐标

    imshow(I);title('公路');axis on;  %如果不需要,on改为off

  5. COM与.NET程序集导出和部署COM组件

    为了分布式和多客户端调用我们还需要将写好的COM组件发布到一台服务器上.这里我们将组件部署到操作系统的COM+应用程序中去.如果没此需要就可以导出后,在C++环境中调用COM了. 第一步:导出COM组 ...

  6. 基于QTcpSocket和QTcpServer的Tcp通讯以及QDataStream序列化数据

    最近要在QT下开发Tcp通讯,发送序列化数据以便于接收. 这里涉及到几个问题: 1.QTcpSocket.QTcpServer的通讯 2.QDataStream序列化数据 多的不说,直接上干货!!! ...

  7. docker network

    前言:前面的部分一直都是单机跑docker,但实际生产环境不可能只用一台来跑.肯定会用到多台,因为他们都是内部私有ip,那么多台主机之间的容器如何通信?这个是个很头疼的问题!目前主流几种方法如下: 1 ...

  8. placeholder改变颜色

    ::-webkit-input-placeholder { /* WebKit browsers */ color: #cfcfcf; } :-moz-placeholder { /* Mozilla ...

  9. Flask -- 内容管理系统

    例子: # content_manager.py # 把TOPIC存在一个字典里,key为关键字,value为二维数组# TOPIC_DICT['Django'][0]为Title,TOPIC_DIC ...

  10. html5学习(三)

    html5特点: 1 微数据与微格式等方面的支持. 2 本地存储,离线应用. 3 API调用,地图,位置,LBS等. 4 连接通讯,后台线程. 5 多媒体. 7 css3.