OpenGLES 2.0中强制使用可编程的渲染管线的,使用的是glsl着色器语言,因为着色器语言是使用GPU,也就是图形处理器。而不是CPU,这样可以使CPU从繁重的几何计算和像素的处理中解脱出来。这就加大了处理的速度。
着色器语言基础
1. 标量
标量也被称为“无向量”其值只有大小,并没有方向。标量之间的运算遵循简单的运算法则。如质量、密度、体积、时间以及温度等都属于标量。OpenGL ES着色器语言支持的标量类型有布尔型(bool)、整形(int)和浮点型(float)。
2.向量
OpenGL ES 着色器语言中,向量可以看做是同样类型的标量组成,其基本类型也分为bool、int和float三种。每个向量可以有2个、3个、4个相同的标量组成,具体情况如下:
向量在着色器代码的开发有着十分重要的作用,可以很方便的存储以及存储颜色、位置、纹理坐标等不仅包含一组部分的量。开发中有时可能需要单独访问向量中的某个分量,基本的语法为“<向量名>.<分量名>”,根据目的地不同,主要有以下几种用法:
将一个向量看作颜色时,可以使用r,g,b,a四个分量名,分别代表红、绿、蓝、透明四个颜色通道。具体用法如下:
//给向量aColor的红色通道赋值
aColor.r=0.6;
将一个向量看作位置时,可以使用x,y,z,w等四个分量名,分别代表X轴,Y轴,Z轴和向量的模四个分量,具体用法和颜色类似。
将一个向量看作纹理坐标时,可以使用s,t,p,q四个分量名,其分别代表纹理坐标的不同分量。用法通颜色。
访问向量中的各个不同的分量不但可以采用“.”加上不同的分量名,还可以将向量看作一个数组,用下标来进行访问,具体用法如下:
//给向量aColor的红色通道复制
aColor[0]=0.6;
3.矩阵
在3D场景中的移位、旋转、缩放等变换都是由矩阵运算来实现的。因此3D场景的开发中会非常多的使用矩阵,常用的矩阵 2 * 2矩阵、3 * 3矩阵、4 * 4矩阵,具体情况如下表所示:
矩阵初始化的小知识点
1、mat3 m=mat3(4.0)左上角到右下角的对角线都为4.0,其它都是1
2、 把向量添加到矩阵中 :
vec3 f1=vec3(1.0,2.0,3.0)
vec3 f2=vec3(4.0,5.0,6.0)
vec3 f3=vec3(7.0,8.0,9.0)
mat3 m=mat3(f1,f2,f3)
3、 GLSL矩阵的创建先填充列再填充行
对于矩阵的访问,可以讲矩阵作为列向量的数组来访问。如matrix为一个mat4,可以使用matrix[2]取该矩阵的第三列,其为一个vec4;也可以使用matrix[2][2]取得第三列向量的第3个分量。
4.采样器
采样器是着色器语言中不同于C语言的一种特殊的基本数据类型,其专门用来进行纹理采样的相关操作。一般情况下,一个采样器变量代表一副或一套纹理贴图,其具体情况如下。
需要注意的是,与之前介绍的几种变量不同,采样器变量不能在着色器中初始化,一般情况下采样器变量都用uniform限定符来修饰,从宿主语言中(如java)接受传递进着色器的值。
5.结构体
OpenGL ES着色语言还提供了类似C语言中的用户自定义结构体,同样也是使用struct关键字进行声明,基本用法如下:
struct info{
vec3 color;
vec3 position;
vet textureCoor;
}
** 6.数组**
声明数组的方法主要有两种,在声明数组的同时,指定数组的大小:
4vec3 position[20];
在声明数组时,也可以不指定数组的大小,但必须符合下列两种情况之一。
//声明了一个大小不定的vec3数组
vec3 position[];
//再次声明该数组,并且指定大小
vec3 position[5];
在代码中访问数组的下表都是编译时常量,这是编译器会自动创建适当大小的数组,使得数组尺寸足够存储编译器看到的最大索引值对应的元素。
//声明了一个大小不定的vec3数组
vec3 position[];
//position 需要一个大小为4的数组
position[3]=vec3(3.0);
//position需要一个大小为21的数组
position[20]=vec3(6.0);
7.空类型使用void表示
仅仅用来声明不返回任何值得函数。例如在顶点着色器以及片元着色器中必须存在的main函数就是一个返回值为空的函数,代码如下:
void main(){
}
数据类型的基本使用
1. 声明、作用域及初始化
变量的声明以及作用域与java/C++语法类似,可以再任何需要的位置声明变量,同时期作用域也同样分为局部变量和全局变量:
//声明了全局变量a和b
int a,b;
//声明了全局变量aPosition并赋值
vec3 aPosition=vec3(1.0,2.2,3.3);
void myFunction(){
//声明了局部变量C并赋值
int c=14;
//给全局变量a赋值
a=4;
//给全局变量b赋值
b=a*c;
}
向量的初始化还有一些灵活的技巧
//声明浮点变量a并赋值
float a=12.3;
//声明浮点变量b并赋值
float b=11.4;
//声明二维向量va 并赋值
vec2 va=vec2(2.3,2,5);
//声明二维向量vb并赋值
vec2 vb=vec2(a,b);
//声明三维向量vc并赋值
vec3 vc=vec3(vb,12.5);
//声明四维向量vd并赋值
vec4 vd=vec4(va,vb);
//声明四维向量ve并赋值
vec4 ve=vec4(0.2);//相当于 vec4(0.2,0.2,0.2,0.2);
2.运算符
与大多数编程语言类似,常见的运算符都可以在该语言中使用,下面按照优先级列车OpenGL ES着色语言中可以使用的运算符。
3.限定符
与其他的编程语言一样,着色器中对变量也有很多可选的限定符,主要如下:
/*attribute 限定符只能用于顶点着色器中,不能在片元着色器中使用,而且at tribute限定符号只能用来修饰浮点数标量、浮点向量以及矩阵变量,不能用来修饰其他类型的变量*/
//顶点位置
attribute vec3 aPosition;
//顶点法向量
attribute vec3 aNormal;
uniform限定符为一致变量限定符,一致变量值的是对于同一组顶点组成的单个3D物体中所有顶点都相同的量。Uniform变量可以用来在顶点着色器或片元着色器中,其支持用来修饰所有的基本数据类型。与属性限定符类似,一致变量的值也是从宿主程序传入的。
//总变换矩阵
uniform mat4 uMVPMatrix;
//变换矩阵
uniform mat4 UMMatrix;
//光源位置
uniform vec3 uLightLocation;
//摄像机位置
uniform vec3 uCamera;
verying限定符 想要讲顶点着色器中的信息传入到片元着色器中,必须是用veering限定符,veering限定符修饰的全局变量又称为易变变量,易变变量可以看成是顶点着色器和片元着色器之间的动态接口,方便顶点着色器与片元着色器之间信息的传递。