OpenGLES3.0笔记 (三) —— GLSL语法

[TOC]

OpenGL ES着色语言虽然是基于C/C++基本语法的语言,但是其与C/C++相比较还是有很大不同的。例如,该语言不支持双精度浮点型(double)、字节型(byte)、短整型(short)、长整型(long),并且取消了C中的联合体(union)及枚举类型(enum)等特性。

1. 数据类型概述

与C语言类似,着色语言中有许多内建的原生数据类型以及构建数据类型,如浮点型(float)、布尔型(bool)、有符号整型(int)、无符号整型(uint)、矩阵型(matrix)以及向量型(vec2、vec3等)等。总体来说,这些数据类型可以分为标量、向量、矩阵、采样器、结构体以及数组等几类

  • 标量

OpenGL ES3着色语言支持的标量类型有bool、int、uint与float

声明无符号整型(uint)字面常量时,需要在数字之后添加后缀u或U,否则该字面常量的类型为有符号整型

  • 向量

OpenGL ES着色语言中,向量可以看作是用同样类型的标量组成的,其基本类型也分为bool、int、uint及float 四种。每个向量可以由2个、3个或者4个相同的标量组成.

向 量 类 型 说  明
vec2 包含了2个浮点数的向量
bvec2 包含了2个布尔数的向量
vec3 包含了3个浮点数的向量
bvec3 包含了3个布尔数的向量
vec4 包含了4个浮点数的向量
bvec4 包含了4个布尔数的向量
ivec2 包含了2个整数的向量
uvec2 包含了2个无符号整数的向量
ivec3 包含了3个整数的向量
uvec3 包含了3个无符号整数的向量
ivec4 包含了4个整数的向量
uvec4 包含了4个无符号整数的向量

若向量是4维的,当看作颜色使用时,则可以使用的分量名为:r、g、b、a;
若向量是4维的,当看作位置使用时,则可以使用的分量名为:x、y、z、w;
若向量是4维的,当看作纹理坐标使用时,则可以使用的分量名为:s、t、p、q;
访问向量中的各个分量不但可以采用“.”加上不同的分量名,还可以将向量看作一个数组,用下标来进行访问

aColor.r=0.6;                            //给向量aColor的红色通道分量赋值
aColor.g=0.8;                            //给向量aColor的绿色通道分量赋值

aPosition.x=67.2;                        //给向量aPosition的X分量赋值
aPosition.z=48.3;                        //给向量aPosition的Z分量赋值

aTexCoor.s=0.65;                            //给向量aTexCoor的s分量赋值
aTexCoor.t=0.34;                            //给向量aTexCoor的t分量赋值

aColor[0]=0.6;                            //给向量aColor的红色通道分量赋值
aPosition[2]=48.3;                        //给向量aPosition的z轴分量赋值
aTexCoor[1]=0.34;                        //给向量aTexCoor的t分量赋值
  • 矩阵

矩阵按尺寸分为2×2矩阵、2×3矩阵和2×4矩阵、3×2矩阵、3×3矩阵和3×4矩阵以及4×2矩阵、4×3矩阵和4×4矩阵,其中矩阵类型的第一个数字表示矩阵的列数,第二个数字表示矩阵的行数,具体情况如表4-2所列。

矩 阵 类 型 说  明
mat2 2×2的浮点数矩阵
mat2×2 2×2的浮点数矩阵
mat3 3×3的浮点数矩阵
mat2×3 2×3的浮点数矩阵
mat4 4×4的浮点数矩阵
mat2×4 2×4的浮点数矩阵
mat3×2 3×2的浮点数矩阵
mat4×2 4×2的浮点数矩阵
mat3×3 3×3的浮点数矩阵
mat4×3 4×3的浮点数矩阵
mat3×4 3×4的浮点数矩阵
mat4×4 4×4的浮点数矩阵

OpenGL ES着色语言中,矩阵是按列顺序组织的,也就是一个矩阵可以看作由几个列向量组成。例如,mat3就可以看作由3个vec3组成。另外,mat2与mat2×2、mat3与mat3×3以及mat4与mat4×4是3组两两完全相同的类型,只是其类型的名称不同而已。

  • 采样器

采样器是着色语言中不同于C语言的一种特殊的基本数据类型,其专门用来进行纹理采样的相关操作。一般情况下,一个采样器变量代表一幅或一套纹理贴图。

采样器类型 说  明
sampler2D 用于访问浮点型的二维纹理
isampler3D 用于访问整型的三维纹理
sampler3D 用于访问浮点型的三维纹理
isamplerCube 用于访问整型的立方贴图纹理
samplerCube 用于访问浮点型的立方贴图纹理
isampler2DArray 用于访问整型的2D纹理数组
samplerCubeShadow 用于访问浮点型的立方阴影纹理
usampler2D 用于访问无符号整型的二维纹理
sampler2DShadow 用于访问浮点型的二维阴影纹理
usampler3D 用于访问无符号整型的三维纹理
sampler2DArray 用于访问浮点型的2D纹理数组
usamplerCube 用于访问无符号整型的立方贴图纹理
sampler2DArrayShadow 用于访问浮点型的2D阴影纹理数组
usampler2DArray 用于访问无符号整型的2D纹理数组
isampler2D 用于访问整型的二维纹理

需要注意的是,与前面介绍的几类变量不同,采样器变量不能在着色器中进行初始化。一般情况下采样器变量都用uniform限定符来修饰,从宿主语言(如C++、Java)接收传递进着色器的值。此外,采样器变量也可以用作函数的参数,但是作为函数参数时不可以使用out或inout修饰符来修饰。

  • 结构体

OpenGL ES着色语言还提供了类似于C语言中的用户自定义结构体,同样也是使用struct关键字进行声明,基本用法与C语言基本类似,不在此赘述了。

  • 数组

在着色语言中,开发人员可以声明任何类型的数组。声明数组的方式主要有两种,具体如下所列。
(1). 在声明数组的同时,指定数组的大小:
vec3 position[20]; //声明了一个包含20个vec3的数组,索引从0开始
(2). 在声明数组并初始化的同时,可以不指定数组的大小,不支持动态长度数组

float x[]=float[2](1.0,2.0);                //数组的长度为2
float y[]=float[](1.0,2.0,3.0);            //数组的长度为3

OpenGL ES 3.0的着色语言只支持一维数组的使用,不支持二维以及更多维数组的使用。

2. 运算符

运 算 符 说  明
() 括号分组
[ ] 数组下标
() 函数调用和构造函数结构
. 用于成员选择与混合
++ -- 自加1与自减1后缀
++ -- 自加1与自减1 前缀
+ - ~ ! 一元运算符
* / % 乘法、除法和取余
+ - 加法与减法
<< >> 逐位左移和右移
< > <= >= 关系运算符
== != 等于以及不等于
& 逐位与
^ 逐位异或
逐位或
&& 逻辑与
^^ 逻辑异或
|| 逻辑或
?: 选择
= += -= *= /= 赋值运算符
%= <<= >>= &= ^= |= 赋值运算符
, 按顺序排列
  • OpenGLES运算符的特殊操作

某些OpenGLES的运算符有不同于c语言的操作,下面简单介绍下。

  • 通过运算符“.”进行混合选择操作
    在运算符“.”之后列出一个向量中需要的各个分量的名称,就可以选择并重新排列这些分量。下面的代码片段说明了这个问题。
vec4 color= vec4(0.7,0.1,0.5,1.0);    //声明一个vec4类型的向量color
vec3 temp=color.agb;            //相当于获取到一个向量(1.0,0.1,0.5)赋值给temp
vec4 tempL=color.aabb;        //相当于获取到一个向量(1.0,1.0,0.5,0.5)赋值给tempL
vec3 tempLL;                //声明了一个3维向量tempLL
tempLL.grb=color.aab;        //对向量tempLL的3个分量赋值

一次出现的各部分的分量名称必须是来自同一名称组。3个名称组分别为:xyzw、rgba、stpq

3. 构造函数

  • 矩阵的构造函数

矩阵的构造函数共有3种基本形式。

  • 如果矩阵的构造函数内只有一个标量值,那么矩阵的对角线上的分量都等于该值,其余值为0。
  • 矩阵可以由许多向量构造而成。比如说,一个mat2矩阵可以由两个vec2构成。
  • 矩阵还可以由大量的标量值构成,矩阵的分量由左向右依次被赋值。
vec2 d=vec2(1.0,2.0);                //d的分量值分别为1.0、2.0 
mat2 e=mat2(d,d);                    //e的第一列和第二列均为1.0、2.0
mat3 f=mat3(e);        //将矩阵e放到矩阵f的左上角,右下角剩余对角线元素的值为1,其余为0
mat4x2 g=mat4x2(d,d,d,d);                //声明一个mat4*2矩阵
mat2x3 h=mat2x3(g); //将矩阵g左上角的2*2个元素值赋值给h中的对应元素,h矩阵的最后一行为0,0
mat3 myMat3 = mat3(1.0, 0.0, 0.0,          //矩阵myMat3第一列的值
                0.0, 1.0, 0.0,        //矩阵myMat3第二列的值
                0.0, 1.0, 1.0);     //矩阵myMat3第三列的值

OpenGL ES中矩阵元素的存储顺序以列为主,即矩阵由列向量组成。因此,当使用矩阵的构造函数时,矩阵的元素将会按照矩阵的列的顺序依次被参数赋值。这一点从上述代码片段的第5行有所体现

其他数据类型的构造函数和C语言一样,不再赘述。

类型转换

OpenGL ES着色语言没有提供类型的自动提升功能,并且对类型匹配的要求十分严格。赋值表达式中的两个操作数类型必须完全相同,另外调用函数时的形参以及实参的类型也必须完全相同
同时OpenGL ES着色语言也没有提供数据类型的强制转换功能,只能使用构造函数来完成类型转换

float f=1.0;        //声明一个浮点数f并赋值
bool b=bool(f);        //将浮点数转换成布尔类型,该构造函数将非0的数字转为true,0转为false
float f1=float(b);    //将布尔值转变为浮点数,true转换为1.0,false转换为0.0
int c=int(f1);        //将浮点数转换成有符号或者无符号整型,直接去掉小数部分

存储限定符

这些限定符中大部分只能用来修饰全局变量,主要的如下所列。

限 定 符 说  明
const 用于声明常量
in/centroid in 一般用于声明着色器的输入变量,如顶点着色器中用来接收顶点位置、颜色等数据的变量,centroid in变量与插值类型有关
out/centroid out 一般用来声明着色器的输出变量,如从顶点着色器向片元着色器传递的顶点位置等数据的变量,centroid out变量与插值类型有关
uniform 一般用于对同一组顶点组成的单个3D物体中所有顶点都相同的量,如当前的光源位置

限定符在使用时应该放在变量类型之前,且使用in、uniform以及out限定符修饰的变量必须为全局变量。同时要注意的是,着色语言中没有默认限定符的概念,因此如果有需要,必须为全局变量明确指定需要的限定符。

插值限定符

一致块

layout限定符

流程控制

函数声明和使用

你可能感兴趣的:(OpenGLES3.0笔记 (三) —— GLSL语法)