赵工的个人空间


专业技术部分转网页计算转业余爱好部分


  网站建设

首页 > 专业技术 > 网站建设 > OpenGL ES着色器语言
OpenGL ES着色器语言

WebGL的图形绘制是基于着色器的,而着色器使用的是OpenGL ES着色器语言GLSL ES。GLSL ES语言是OpenGL的一个简化版本,目标平台是嵌入式系统或消费电子产品。

1. GLSL ES语言的基本规范:

GLSL ES语言与C语言很相似,而与JavaScript有很多不同。
1)大小写字母敏感:
GLSL ES语言程序是大小写敏感的,也就是使用text与Text是不同的。
2)语句分隔:
GLSL ES语言程序的每个语句都以分号(;)结束。
3)main()函数:
着色器程序的执行是从main()函数开始,有且只有一个main()函数,该函数不能接收任何参数,main()函数前的void表示函数没有返回值。
4)注释:
着色器程序的注释与C语言一致,有两种方式,单行注释使用“//”,多行注释使用“/*...*/”。
5)数据类型:
GLSL ES语言支持两种数据类型:
·数值类型:包括整型和浮点型,没有小数点的值被认为是整型,而有小数点的被认为是浮点型。
·布尔类型:包括true和false两个值。
GLSL ES语言不支持字符串类型。

2. GLSL ES语言的关键字和保留字:

GLSL ES语言的关键字包括:

attribute

bool

break

bvec2

bvec3

bvec4

const

continue

discard

do

else

false

float

for

highp

if

in

inout

Int

invariant

ivec2

ivec3

ivec4

lowp

mat2

mat3

mat4

medium

out

precision

return

sampler2D

samplerCube

struct

true

uniform

varying

vec2

vec3

vec4

void

while

GLSL ES语言保留字:供未来版本扩展使用

asm

cast

class

default

double

dvec2

dvec3

dvec4

enum

extern

external

fixed

flat

fvec2

fvec3

fvec4

goto

half

hvec2

hvec3

hvec4

inline

input

interface

long

namespace

noinline

output

packed

public

sampler1D

sampler1DShadow

sampler2DRect

sampler2DRectShadow

sampler2DShadow

sampler3D

sampler3DRect

short

sizeof

static

superp

switch

template

this

typedef

union

unsigned

using

volatile

 

3. GLSL ES语言的变量与运算符:

GLSL ES语言变量名可以使用大小写拉丁字母、数字及下划线组成,但首字母不能为数字,也不能以gl_、webgl_或_webgl_开头,也不能使用关键字及保留字。
GLSL ES语言是强类型语言,需要具体声明变量的数据类型,定义函数时也需要声明函数返回值类型,没有返回值需要声明为void。

1)变量的基本类型:
GLSL ES语言的基本类型包括:

类型

描述

float

单精度浮点数类型

int

整型数

bool

布尔值

2)类型转换:
GLSL ES语言在进行赋值操作时,等号两侧的数据类型必须一致,否则就会出错。如果给一个浮点数赋值为float f1=8;也会出错,因为对于数值类型,没有小数点的值被认为是整型,而有小数点的被认为是浮点型。
要将一个整型数赋值给浮点数变量,需要将整型数显式转换成浮点数,这个过程为类型转换。GLSL ES语言支持的类型转换内置函数有:

转换

函数

描述

转换为整型数

int(float)

将浮点数的小数部分删去,转化成整型数

int(bool)

true被转换为1,false被转换为0

转换为浮点数

float(int)

将整型数转换为浮点数

float(bool)

true被转换为1.0,false被转换为0.0

转换为布尔值

bool(int)

0被转换为false,其他非0值被转换为true

bool(float)

0.0被转换为false,其他非0值被转换为true

3)运算符及优先级:
GLSL ES语言支持的运算类型与JavaScript类似:

优先级

运算符

说明

1

圆括号 ()

 

2

函数调用 ()、数组索引 []、点操作符 .

 

3

自增 ++、自减 --、负 -、取反 !

 

4

乘 *、除 /、求余 %

 

5

加 +、减 -

 

6

按位左移 <<、按位右移 >>

 

7

小于 <、小于等于 <=、大于 >、大于等于 >=

 

8

判断相等 ==、判断不等 !=

 

9

按位与 &

 

10

按位异或 ^

 

11

按位或 |

 

12

逻辑与 &&

 

13

逻辑异或 ^^

 

14

逻辑或 ||

 

15

三元判断 condition ? expression1 : expression2

 

16

运算赋值+=、-=、*=、/=、%=、<<=、>>=、&=、^=、|=

 

17

顺序运算符,即逗号 ,

 

4. 矢量和矩阵:

GLSL ES语言支持矢量和矩阵运算。矢量和矩阵类型的变量都包含多个元素,每个元素是一个数值。矢量将这些元素排成一列,可以用来表示顶点坐标或颜色值等;而矩阵则将元素划分成行和列,可以用来表示变换矩阵。

1)GLSL ES语言支持的矢量和矩阵类型:

类别

GLSL ES数据类型

描述

 

矢量

vec2、vec3、vec4

具有2、3、4个浮点数元素的矢量

ivec2、ivec3、ivec4

具有2、3、4个整型数元素的矢量

bvec2、bvec3、bvec4

具有2、3、4个布尔值元素的矢量

矩阵

mat2、mat3、mat4

2x2、3x3、4x4的浮点数元素的矩阵

2)矢量构造函数:
矢量和矩阵通常使用与类型同名的内置构造函数来生成。比如对于vec4类型的矢量:
vec4  position=vec4(1.0, 2.0, 3.0, 4.0):
GLSL ES语言使用构造函数创建矢量很灵活:
vec3  v3=vec3(1.0, 1.0, 0.5);
vec2  v2=vec2(v3); //使用v3的前两个元素,将v2设为(1.0, 0.0)
vec4  v4=vec4(1.0); //将v4设为(1.0, 1.0, 1.0, 1.0)
也可以将多个矢量组合成一个矢量:
vec3  v4b=vec(v2, v4); //将v4b设为(1.0, 0.0, 1.0, 1.0)
这里先将v2的元素填充进来,如果还没有填满,就继续用v4中的元素填充,填满后后面的元素舍弃。

3)矩阵构造函数:
矩阵中的元素是按列主序排列的。
⑴向矩阵构造函数中传入矩阵中每一个元素的数值来构造矩阵:
mat4  m4=mat4(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0);
⑵向矩阵构造函数中传入一个或多个矢量:
vec2  v2_1=vec2(1.0, 3.0);
vec2  v2_2=vec2(2.0, 4.0);
mat2  m2_1=mat2(v2_1, v2_2);

vec4  v4=vec4(1.0, 3.0, 2.0, 4.0);
mat2  m2_2=mat2(v4);
⑶向矩阵构造函数中传入矢量和数值:
mat2  m2_3=mat2(1.0, 3.0, v2_2);
⑷向矩阵构造函数中传入单个数值,对角线上元素都是该数值,其他元素为0.0:
mat4  m4=mat4(1.0);
如果传入的数值的数量大于1,又没有达到矩阵元素的数量,就会出错。

4)访问矢量或矩阵中的元素:
访问矢量或矩阵中的元素,可以使用“.”或“[]”运算符。
⑴使用运算符“.”:
在矢量变量名后接点运算符,然后加上分量名,就可以访问矢量的元素了。矢量的分量名为:

类别

描述

x, y, z, w

用来获取顶点坐标的分量

r, g, b, a

用来获取颜色分量

s, t, p, q

用来获取纹理坐标分量,2D纹理使用s和t

实际上,任何矢量的x、r或s分量都会返回第1个分量,y、g、t分量都返回第2个分量。如果试图访问超过矢量长度的分量就会出错。
将同一个集合的多个分量名共同置于点运算符后,就可以从矢量中同时抽取出多个分量,这个过程称为混合swizzling。示例:
vec2  v2;
v2=v3.xy;
v2=v3.yz;
v2=v3.xx; //可以重复或跳过任意分量,也可以逆序
vec3  v3a;
v3a=v3.zyx;
聚合分量名也可以用作赋值表达式的左值:
vec4  position=vec4(1.0, 2.0, 3.0, 4.0);
position.xw=vec2(5.0, 6.0); //position=(5.0, 2.0, 3.0, 6.0);
⑵使用运算符“[]”:
可以使用“[]”并通过数组下标来访问矢量或矩阵的元素,下标从0开始。矩阵中的元素仍然是按列主序读取的。
mat4  m4=mat4(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0);
vec4  v4=m4[0]; //获取m4矩阵的第一列,即[1.0, 2.0, 3.0, 4.0]
连续使用两个“[]”运算符可以访问某列的某个元素:
float  m23=m4[1][2]; //将m23设置为m4的第2列中的第3个元素,即7.0
也可以使用同时使用“[]”运算符和分量名来访问矩阵中的元素:
float m32=m4[2].y; //将m32设为m4矩阵第3列中的第2个元素,即10.0
在“[]”中出现的索引值必须是常量索引值,包括整数字面量及用const修饰的全局变量或局部变量,或者是循环索引。上面三种组成的表达式也可以使用。

5)矢量和矩阵运算符:
对于矢量和矩阵,只可以使用比较运算符中的==和!=,不能使用<、<=、>、>=。如果想比较矢量和矩阵的大小,要使用内置函数,如lessThan()。

运算符

运算

适用数据类型

*

乘法

适用于vec[234]和mat[234]

/

除法

+

加法

运算结果的数据类型与参与运算的类型相一致

-

减法

++

自增

适用于vec[234]和mat[234],运算结果的数据类型与参与运算的类型相一致

--

自减

=

赋值

适用于vec[234]和mat[234]

+=, -=, *=,  /=

运算赋值

适用于vec[234]和mat[234]

==, !=

比较

适用于vec[234]和mat[234]

两个矢量或矩阵的相等比较==,如果每一个分量都相同就返回true;对于不等比较!=,如果有任何一个分量不同则返回true。如果要逐分量比较,可以使用内置函数equal()和notEqual()。

5. 结构体:

GLSL ES语言支持用户自定义类型,即结构体structures。

1)结构体声明:
使用关键字struct将已存在的类型聚合到一起,就可以定义为结构体。示例:
struct light{
vec4 color;
vec3 position;
}
light l1, l2;
上述代码定义了一种新的结构体light,其中包含color变量和position变量两个分量。定义之后,又声明了两个light类型的变量l1和l2。也可以在同一条语句中定义结构体并声明变量:
struct light{
vec4 color;
vec3 position;
} l1;

2)结构体赋值和构造:
结构体有标准的构造函数,名称与结构体一致。构造函数的参数顺序必须与结构体定义中的成员顺序一致。示例:
l1=light(vec4(0.0, 1.0, 0.0, 1.0), vec3(8.0, 3.0, 0.0));

3)访问成员:
在结构体变量名后紧跟点运算符“.”,然后加上成员名,就可以访问变量的成员。示例:
vec4  color=l1.color;
vec3  position=l1.position;

4)结构运算符:
结构体的成员可以参与其自身类型支持的任何运算,但结构体本身只支持赋值和比较运算:

运算符

运算

适用数据类型

=

赋值

赋值和比较运算符不适用于含有数组与纹理成员的结构体

==、!=

比较

当且仅当两个结构体变量所对应的所有成员都相等时,==运算符才返回true;如果任何某个成员不相等,那么!=运算符返回true。

6. 数组:

GLSL ES语言支持数组类型,但只支持一维数组,而且不支持pop()和push()等操作。
创建数组只需要在变量名后加上中括号和数组长度:
float  fliatArray[4]; //声明含有4个浮点数元素的数组
vec4  vec4Array[2]; //声明含有2个vec4对象的数组
数组的长度必须是大于0的整型表达式,包括整型字面量和用const限定字修饰的全局变量或局部变量,或者这两种组成的表达式,不包括函数参数。但const不能修饰数组本身。
数组不能在声明时被一次性地初始化,而必须显式地对每个元素进行初始化:
vec4Array[0]=vec4(4.0, 3.0, 6.0, 1.0):
vec4Array[1]=vec4(3.0, 2.0, 0.0, 1.0);
数组元素可以通过索引值来访问,索引值从0开始。只有整型表达式和uniform变量可以被用作数组的索引值。
数组本身只支持“[]”运算符,但数组元素能够参与其自身类型支持的任意运算:
float  f=floatArray[1]*3.14;
vec4  v4=vec4Array[0]*vec4(1.0, 2.0, 3.0, 4.0);

7. 取样器:

GLSL ES语言支持一种内置类型sampler,称为取样器,是通过该类型变量访问纹理。有两种基本类型的取样器,sampler2D和samplerCube。取样器变量只能使用uniform变量,或者需要访问纹理的函数,如texture2D()函数的参数。示例:
uniform sampler2D u_Sampler;
唯一能赋值给取样器变量的是纹理单元的编号,而且必须使用WebGL方法gl.uniformli()来赋值。比如:
gl.uniformli(u_Sampler, 0); //将纹理单元编号0传给着色器
取样器类型变量受到着色器支持的纹理单元的最大数量限制:

着色器

表示最大数量的内置常量

最小数量

顶点着色器

const mediump int gl_MaxVertextTextureImageUnits

0

片元着色器

const mediump int gl_MaxTextureImageUnits

8

8. 程序流程控制:

着色器中的分支与循环与JavaScript或C语言中的几乎一样。

1)if语句和if-else语句:
可以使用if语句或if-else语句进行分支判断,以控制程序流程。格式为:
if (条件表达式1) {
如果条件表达式1为true执行的语句
} else if (条件表达式2) {
如果条件表达式1为false而条件表达式2为true执行的语句
} else {
如果上述两个条件都为false执行的语句
}
if语句或if-else语句中都必须包含布尔值,或者产生布尔值的表达式,但不能使用布尔值类型的矢量。过多的if或if-else语句会降低着色器的执行速度。GLSL ES语言中没有switch语句。

2)for语句:
for语句的格式为:
for (初始表达式 ; 条件表达式 ; 循环步进表达式) {
反复执行的语句
}
循环变量只能在初始化表达式中定义,条件表达式可以为空,空的表达式返回true。
for语句的限制有:
·只允许有一个循环变量,循环变量只能是int或float类型
·循环表达式必须是以下形式:i++,i--,i+=常量表达式或i-=常量表达式
·条件表达式必须是循环变量与整型常量恶比较
·在循环体内,循环变量不可被赋值
这些限制是为了使编译器就能够对for循环进行内联展开

3)continue、break和discard语句:
只能在for语句中使用continue和break。通常将它们与if语句搭配使用。
·continue中止包含该语句的最内层循环和执行循环表达式(递增/递减循环变量),然后执行下一次循环。
·break中止包含该语句的最内层循环,并不再继续执行循环
discard只能在片元着色器中使用,表示放弃当前片元,直接处理下一个片元。

9. 函数:

1)函数的定义:
GLSL ES语言定义函数的方式更接近于C语言,格式为:
返回类型 函数名(type arg0, type1 arg1, ..., typen argn) {
函数计算
return 返回值;
}
如果函数不返回值,函数中就不需要有return语句,这时返回类型必须是void。也可以将自定义的结构体类型指定为返回类型,但是结构体的成员中不能有数组。
示例:将RGBA颜色值转化为亮度值
float  luma(vec4 color) {
float  r=color.r;
float  g=color.g;
float  b=color.b;
return 0.2126*r+0.7162*g+0.0722*b;
}
声明了函数后,就可以调用了:
attribute  vec4 a_Color;
void main() {
......
float brightness=luma(a_Color);
......
}
GLSL ES语言不能递归调用,也是为了便于编译器对函数进行内联展开。

2)函数声明:
如果函数定义是在其调用之后,就必须在调用前先声明该函数的规范,其中会先声明这个函数的参数、参数类型、返回值等等。而在JavaScript中是不需要提前声明函数的。

3)参数限定字:
GLSL ES语言中,可以为函数参数指定限定字,以控制参数的行为。可以将函数参数定义为:
·传递给函数的
·将要在函数中被赋值的
·既要传递给函数的,也是将要在函数中被赋值的
GLSL ES语言中的参数限定字有:

类别

规则

描述

in

向函数中传入值

参数传入函数,函数内可以使用参数的值,也可以修改其值,但内部的修改不会影响传入值

const in

向函数中传入值

参数传入函数,函数内可以使用但不能修改

out

在函数中被赋值,并被传出

传入变量的引用,若在内部被修改会影响外部传入的变量

inout

传入函数,同时在函数中被赋值,并被传出

传入变量的引用,函数会用到变量的初始值,然后修改变量的值。会影响到外部传入的量

无(默认)

将一个值传给函数

和in一样

限定字in是默认的,可以省略。限定字out和inout类似于C语言的指针,使用out限定字也可以向外部传递函数结果。

4)内置函数:
GLSL ES语言提供了很多常用的内置函数,常用的类别有:

类别

内置函数

角度函数

角度转弧度radians、弧度转角度degrees

三角函数

正弦sin、余弦cos、正切tan、反正弦asin、反余弦acos、反正切atan

指数函数

指数pow、自然指数exp、自然对数log、2的指数exp2、以2为底的对数log2、开平方sqrt、开平方的倒数inversesqrt

通用函数

绝对值abs、最小值min、最大值max、取余数mod、取正负号sign、向下取整floor、向上取整ceil、限定范围clamp、线性内插mix、步进函数step、艾米内插步进smoothstep、获取小数部分fract

几何函数

矢量长度length、两点间距离distance、内积dot、外积cross、归一化normalize、矢量反射reflect、使矢量朝前faceforward

矩阵函数

逐元素乘法matrixCmpMult

矢量函数

逐元素小于lessThan、逐元素小于等于lessThanEqual、逐元素大于greaterThan、逐元素大于等于greaterThanEqual、逐元素相等equal、逐元素不等notEqual、任一元素为true则为true函数any、所有元素为true则为true函数all、逐元素取补not

纹理函数

在二维纹理中获取纹理像素texture2D、在立方体纹理中获取纹理像素textureCube、texture2D的投影版本texture2DProj、texture2D的金字塔版本texture2DLod、textureCube的金字塔版本textureCubeLod、texture2DLod的投影版本texture2DProjLod

5)全局变量和局部变量:
GLSL ES语言也有全局变量和局部变量,全局变量可以在程序中的任意位置使用,而局部变量只能在有限的某一部分代码中使用。
GLSL ES语言中,如果变量声明在函数的外面,那么就是全局变量;如果声明在函数内部,那就是局部变量。局部变量只能在函数内部使用。

10. 存储限定字:

GLSL ES语言中,经常使用attribute、varying和uniform限定字来修饰变量,有时也会使用const限定字。

1)const变量:
GLSL ES语言用const限定字表示变量的值不能被改变。声明const变量时,需要将const写在类型之前,声明同时必须对它进行初始化,声明之后就不能再改变其值。示例:
const int lightspeed=299792458; //光速
const vec4 red=vec4(1.0, 0.0, 0.0, 1.0); //红色
const mat4 identity=mat4(1.0); //单位矩阵

2)Attribute变量:
attribute变量只能出现在顶点着色器中,只能被声明为全局变量,被用来表示逐点的信息。attribute变量的类型只能是float、vec2、vec3、vec4、mat2、mat3、mat4。
顶点着色器中能够容纳的attribute变量的最大数目与设备有关,可以通过访问内置的全局变量来获取该值,但支持WebGL的环境都支持至少8个attribute变量。

变量类型

内置全局变量(表示最大数量)

最小值

attribute变量

const mediump int gl_MaxVertexAttribs

8

顶点着色器uniform变量

const mediump int gl_MaxVertexUniformVectors

128

片元着色器uniform变量

const mediump int gl_MaxFragmentUniformVectors

16

varying变量

const mediump int gl_MaxVaryingVectors

8

3)uniform变量:
uniform变量可以用在顶点着色器和片元着色器中,且必须是全局变量。uniform变量是只读的,可以是除了数组或结构体之外的任意类型。如果顶点着色器和片元着色器中声明了同名的uniform变量,那么它就会被两种着色器共享。
uniform变量中包含了各顶点或各片元共用的数据,使用JavaScript向其传递数据。比如变换矩阵就是所有顶点共用的,所以在着色器中是uniform变量。

4)varying变量:
varying变量必须是全局变量,必须在两种着色器中声明同名、同类型变量,用来从顶点着色器向片元着色器传输数据。varying变量只能是float、vec2、vec3、vec4、mat2、mat3、mat4类型。varying变量的数量限制也与设备有关,至少支持8个。
顶点着色器中赋给varying变量的值并不是直接传给片元着色器的varying变量,而是经过了光栅化过程,光栅化时根据绘制的图形对顶点着色器varying变量进行内插,然后再传递给片元着色器的varying变量。

11. 精度限定字:

GLSL ES语言引入了精度限定字,目的是提高着色器的运行效率,消减内存使用。精度限定字用来表示每种数据具有的精度,高精度的程序需要更大的内存并需要更久的计算时间,低精度的程序需要的开销则小得多。使用精度限定字,就能精细地控制程序在效果和性能之间的平衡。在低精度下,WebGL程序的运行结果会比较粗糙或不准确。

1)WebGL程序支持的精度:
WebGL程序支持三种精度,其限定字分别为高精度highp、中精度mediump、低精度lowp:

精度限定字

描述

默认数值范围和精度(Float|int)

highp

高精度,顶点着色器的最低精度

OpenGL 精度OpenGL

OpenGL

mediump

中精度,片元着色器的最低精度

OpenGL 精度OpenGL

OpenGL

lowp

低精度,可以表示所有颜色

OpenGL 精度OpenGL

OpenGL

上述数值范围和精度与系统环境有关,可以使用gl.getShaderPrecisionFormat()来检查。

2)精度声明:
声明精度示例:
mediump float size;
highp vec4 position;
lowp vec4 color;
为每个变量都声明精度很繁琐,可以使用关键字precision来声明着色器的默认精度,这行代码必须在顶点着色器或片元着色器的顶部,格式为:
precision 精度限定字 类型名称;
声明后,这种类型的变量的默认精度由精度限定字指定,接下来所有不以精度限定字修饰的该类型变量,其精度就是默认精度。示例:
precision mediump float; //所有浮点数默认为中精度
precision highp int; //所有整型数默认为高精度

3)着色器默认精度:
一般情况下,除了在片元着色器中对float类型做出限定,并不显式限定类型的精度,因为着色器已经设了默认精度。

着色器类型

数据类型

默认精度

顶点着色器

int

highp

float

highp

sampler2D

lowp

samplerCube

lowp

片元着色器

int

mediump

float

sampler2D

lowp

samplerCube

lowp

片元着色器中的float类型并没有默认精度,需要显式设置,如果不设置就会导致编译错误。一般情况下,会将片元着色器的float类型设置为中精度:
precision mediump float;
WebGL是否在片元着色器支持highp精度,取决于具体的设备,如果支持,那么着色器就会定义内置宏GL_FRAGMENT_PRECISION_HIGH。
如果不确定,也可以使用这种适中的默认值:
#ifdef  GL_ES
precision mediump float;
#endif

12. 预处理指令:

GLSL ES语言支持预处理指令。预处理指令用来在编译前对代码进行预处理。前面的代码就使用了预处理指令,代码中检查是否已经定义了GL_ES宏,如果是就执行#ifdef和#endif之间的代码。

1)三种预处理指令
GLSL ES语言中可能用到三种预处理指令:
⑴表达式条件:
#ifdef  表达式
如果条件表达式为真执行的代码
#endif
⑵定义宏条件:
#ifdef  宏名
定义了此宏执行的代码
#endif
⑶未定义宏条件:
#ifndef  宏名
没有定义此宏执行的代码
#endif

2)宏定义及解除:
可以使用#define指令进行宏定义,格式为:
#define 宏名 宏内容
也可以使用#undef指令解除宏定义:
#undef 宏名

3)使用#else的预处理指令:
可以使用#else指令配合#ifdef定义预处理指令。示例:
#define NUM 100
#if NUM==100
当宏NUM为100执行的代码
#else
否则执行的代码
#endif

4)宏名与内置宏:
宏的名称可以任意取,但不能与内置的宏名相同。内置宏名有:

GL_ES

在OpenGL ES 2.0中定义为1

GL_FRAGMENT_PRECISION_HIGH

片元着色器支持highp精度

5)使用宏的片元着色器精度设置:
可以使用下述的片元着色器精度设置:
#ifdef  GL_ES
#ifdef  GL_FRAGMENT_PRECISION_HIGH
precision highp float;
#else
precision mediump float;
#endif
#endif

6)指定着色器使用的GLSL ES版本:
使用#version来指定着色器使用的GLSL ES:
#version  number;
可以接受的版本包括100(GLSL ES 1.00)和101(GLSL ES 1.01)。如果不使用#version指令,着色器将默认GLSL ES的版本是1.00。指定1.01版本的代码为:
#version 101
#version指令必须在着色器顶部,在它之前只能有注释和空白。

附:GLSL ES语言的内置函数:

1. 角度和三角函数:
此类函数中,如果参数为矢量,就是对矢量的每个分量进行运算。
1)radians(degree):将角度值转化为弧度值
参数可以使用float、vec2、vec3、vec4类型数据,函数返回值与参数数据类型相一致。
2)degrees(radian);将弧度值转化为角度值
参数可以使用float、vec2、vec3、vec4类型数据,函数返回值与参数数据类型相一致。
3)sin(angle):正弦三角函数,参数使用弧度
参数可以为float、vec2、vec3、vec4类型数据,函数返回值与参数数据类型相一致。
4)cos(angle):余弦三角函数,参数使用弧度
参数可以为float、vec2、vec3、vec4类型数据,函数返回值与参数数据类型相一致。
5)tan(angle):正切三角函数,参数使用弧度
参数可以为float、vec2、vec3、vec4类型数据,函数返回值与参数数据类型相一致。
6)asin(x):反正弦三角函数,返回值为弧度,在[-π/2, π/2]区间
参数可以为float、vec2、vec3、vec4类型数据,函数返回值与参数数据类型相一致。
7)acos(x):反余弦三角函数,返回值为弧度,在[-π/2, π/2]区间
参数可以为float、vec2、vec3、vec4类型数据,函数返回值与参数数据类型相一致。
8)atan(y, x):反正切三角函数,返回值为弧度,正切值为y/x,x和y的符号决定处于哪个象限中,返回值在[-π, π]区间。参数可以为float、vec2、vec3、vec4类型数据,函数返回值与参数数据类型相一致。
9)atan(x):反正切三角函数,返回值为弧度,在[-π, π]区间
参数可以为float、vec2、vec3、vec4类型数据,函数返回值与参数数据类型相一致。

2. 指数对数函数:

此类函数中,如果参数为矢量,就是对矢量的每个分量进行运算。
1)pow(x, y):返回x的y次幂。如果x<0,返回未定义值;如果x=0而y<0,返回未定义值
参数可以使用float、vec2、vec3、vec4类型数据,函数返回值与参数数据类型相一致。
2)exp(x):返回x的自然指数幂
参数可以为float、vec2、vec3、vec4类型数据,函数返回值与参数数据类型相一致。
3)log(x):返回x的自然对数,如果x<0,返回未定义值
参数可以为float、vec2、vec3、vec4类型数据,函数返回值与参数数据类型相一致。
4)exp2(x):返回2的x幂
参数可以为float、vec2、vec3、vec4类型数据,函数返回值与参数数据类型相一致。
5)log2(x):返回以2为底的x的对数,如果x<=0,返回未定义值
参数可以为float、vec2、vec3、vec4类型数据,函数返回值与参数数据类型相一致。
6)sqrt(x):返回x的平方根,如果x<0,返回未定义值
参数可以为float、vec2、vec3、vec4类型数据,函数返回值与参数数据类型相一致。
7)inversesqrt(x):返回x的平方根的倒数,如果x<0,返回未定义值
参数可以为float、vec2、vec3、vec4类型数据,函数返回值与参数数据类型相一致。

3. 通用函数:

此类函数中,如果参数为矢量,就是对矢量的每个分量进行运算。
1)abs(x):返回x的无符号绝对值
参数可以使用float、vec2、vec3、vec4类型数据,函数返回值与参数数据类型相一致。
2)sign(x):返回x的符号,即如果x>0返回1.0,如果x=0返回0.0,否则返回-1.0
参数可以使用float、vec2、vec3、vec4类型数据,函数返回值与参数数据类型相一致。
3)floor(x):返回小于等于x且最接近x的整数
参数可以使用float、vec2、vec3、vec4类型数据,函数返回值与参数数据类型相一致。
4)ceil(x):返回大于等于x且最接近x的整数
参数可以使用float、vec2、vec3、vec4类型数据,函数返回值与参数数据类型相一致。
5)fract(x):返回x的小数部分,即返回x-floor(x)
参数可以使用float、vec2、vec3、vec4类型数据,函数返回值与参数数据类型相一致。
6)mod(x, y):返回x除以y的余数,即(x-y*floor(x/y))
参数可以都使用float、vec2、vec3、vec4类型数据,函数返回值与x的数据类型相一致。
当x的数据类型为vec2、vec3、vec4时,y的数据类型可以为float。
7)min(x, y):返回x和y的最小值,即y<x则返回y,否则返回x
参数可以都使用float、vec2、vec3、vec4类型数据,函数返回值与x的数据类型相一致。
当x的数据类型为vec2、vec3、vec4时,y的数据类型可以为float。
8)max(x, y):返回x和y的最大值,即x<y则返回y,否则返回x
参数可以都使用float、vec2、vec3、vec4类型数据,函数返回值与x的数据类型相一致。
当x的数据类型为vec2、vec3、vec4时,y的数据类型可以为float。
9)clamp(x, minVal, maxVal):将x限制在min和max之间,即min(max(x, minVal), maxVal)
参数可以都使用float、vec2、vec3、vec4类型数据,函数返回值与x的数据类型相一致。
当x的数据类型为vec2、vec3、vec4时,minVal和maxVal的数据类型可以都为float。
10)mix(x, y, a):返回x和y的线性混合,即x*(1-a)+y*a
参数可以都使用float、vec2、vec3、vec4类型数据,函数返回值与参数x的数据类型相一致。
当x的数据类型为vec2、vec3、vec4时,y的数据类型或a的数据类型可以有一种为float。
11)step(edge, x):根据两个数值生成阶梯函数,即如果x<edge则返回0.0,否则返回1.0
参数可以都使用float、vec2、vec3、vec4类型数据,函数返回值与x的数据类型相一致。
当x的数据类型为vec2、vec3、vec4时,edge的数据类型可以为float。
12)smoothstep(edge0, edge1, x):经过Hermite插值的阶梯函数。如果x<=edge0则返回0.0,如果x>=edge1则返回1,否则按如下方法插值出一个值
t=clamp((x-edge0)/(edge1-edge0), 0, 1);
return  t*t*(3-2*t);
参数可以都使用float、vec2、vec3、vec4类型数据,函数返回值与参数的数据类型相一致。

4. 几何函数:

1)length(x):返回矢量x的长度
参数可以使用float、vec2、vec3、vec4类型数据,函数返回值为float类型。
2)distance(p0, p1):返回p0和p1之间的距离,即length(p0-p1)
参数可以使用float、vec2、vec3、vec4类型数据,函数返回值为float。
3)dot(x, y):返回x和y的点积,对vec3:x[0]*y[0]+x[1]*y[1]+x[2]*y[2]
参数可以使用float、vec2、vec3、vec4类型数据,函数返回值为float。
4)cross(x, y):返回x和y的叉积
参数和返回值都为vec3数据类型。
5)normalize(x):对x进行归一化,保持矢量方向不变但长度为1,即x/length(x)
参数可以使用float、vec2、vec3、vec4类型数据,函数返回值与参数的数据类型相一致。
6)faceforward(N, I, Nref):法向矢量反方向,根据入射矢量I和参考矢量Nref来调整法向矢量。如果dot(Nref, I)<0则返回N,否则返回-N
参数可以都使用float、vec2、vec3、vec4类型数据,函数返回值与参数的数据类型相一致。
7)reflect(I, N):计算反射矢量,入射矢量I,表面法向矢量N,返回I-2*dot(N, I)*N,其中的N必须已归一化
参数可以都使用float、vec2、vec3、vec4类型数据,函数返回值与参数的数据类型相一致。
8)refract(I, N, eta):根据入射光和介质特性计算折射现象。入射光方向为I,表面方向矢量为N,介质的折射率为eta,返回被折射后的光线方向:
k=1.0-eta*eta*(1.0-dot(N, I)*dot(N, I))
if(k<0.0) 返回0.0或由0.0组成的对应矢量
入射光矢量I和表面法向矢量N必须已经归一化
参数I和N可以都使用float、vec2、vec3、vec4类型数据,函数返回值与这两个参数的数据类型相一致,eta则为float。

5. 矩阵函数:

matrixCompMult(x, y):将矩阵x和矩阵y相乘,即result[i][j]=x[i][j]*y[i][j]
参数可以都使用fvec2、vec3、vec4类型数据,函数返回值与参数的数据类型相一致。

6. 矢量函数:

此类函数中,如果参数为矢量,就是对矢量的每个分量进行运算。
1)lessThan(x, y):逐分量比较x<y是否成立
参数可以都使用vec2、vec3、vec4、ivec2、ivec3、ivec4类型数据,函数返回值为与参数矢量长度相同的bvec矢量,即bvec2、bvec3或bvec4。
2)lessThanEqual(x, y):逐分量比较x<=y是否成立
参数可以都使用vec2、vec3、vec4、ivec2、ivec3、ivec4类型数据,函数返回值为与参数矢量长度相同的bvec矢量,即bvec2、bvec3或bvec4。
3)greaterThan(x, y):逐分量比较x>y是否成立
参数可以都使用vec2、vec3、vec4、ivec2、ivec3、ivec4类型数据,函数返回值为与参数矢量长度相同的bvec矢量,即bvec2、bvec3或bvec4。
4)greaterThanEqual(x, y):逐分量比较x>=y是否成立
参数可以都使用vec2、vec3、vec4、ivec2、ivec3、ivec4类型数据,函数返回值为与参数矢量长度相同的bvec矢量,即bvec2、bvec3或bvec4。
5)equal(x, y):逐分量比较==是否成立
参数可以都使用vec2、vec3、vec4、ivec2、ivec3、ivec4类型数据,函数返回值为与参数矢量长度相同的bvec矢量,即bvec2、bvec3或bvec4。
6)notEqual(x, y):逐分量比较!=是否成立
参数可以都使用vec2、vec3、vec4、ivec2、ivec3、ivec4类型数据,函数返回值为与参数矢量长度相同的bvec矢量,即bvec2、bvec3或bvec4。
7)not(x):矢量逐分量的逻辑反运算
参数可以使用bvec2、bvec3、bvec4类型数据,函数返回值与参数的数据类型一致。
8)any(x):矢量的任一分量为true则返回true
参数可以使用bvec2、bvec3、bvec4类型数据,函数返回值为bool数据类型。
9)all(x):矢量的所有分量为true则返回true
参数可以使用bvec2、bvec3、bvec4类型数据,函数返回值为bool数据类型。

7. 纹理查询函数:

1)vec4  texture2D(sampler2D sampler, vec2 coord):使用纹理坐标coord,从当前绑定到sampler的二维纹理中读取相应的纹理像素。
2)vec4  texture2D(sampler2D sampler, vec2 coord, float bias):使用纹理坐标coord和偏移bias,从当前绑定到sampler的二维纹理中读取相应的纹理像素,bias只能在片元着色器中使用表示使用Mip纹理时加在当前lod上的值。
3)vec4  texture2DProj(sampler2D sampler, vec3 coord):使用纹理坐标coord,从当前绑定到sampler的投影纹理中读取相应的纹理像素。
4)vec4  texture2DProj(sampler2D sampler, vec3 coord, float bias):使用纹理坐标coord和偏移bias,从当前绑定到sampler的投影纹理中读取相应的纹理像素,bias只能在片元着色器中使用表示使用Mip纹理时加在当前lod上的值。
5)vec4  texture2DProj(sampler2D sampler, vec4 coord):使用纹理坐标coord,从当前绑定到sampler的投影纹理中读取相应的纹理像素,coord的最后1个分量被忽略。
6)vec4  texture2DProj(sampler2D sampler, vec4 coord, float bias):使用纹理坐标coord和偏移bias,从当前绑定到sampler的投影纹理中读取相应的纹理像素,coord的最后1个分量被忽略,bias只能在片元着色器中使用表示使用Mip纹理时加在当前lod上的值。
7)vec4  texture2DLod(sampler2D sampler, vec2 coord, float load):使用纹理坐标coord和lod,从当前绑定到sampler的二维纹理中读取相应的纹理像素,lod为使用Mip纹理时的序号。
8)vec4  texture2DProjLod(sampler2D sampler, vec3 coord, float lod):使用纹理坐标coord和lod,从当前绑定到sampler的投影纹理中读取相应的纹理像素,lod为使用Mip纹理时的序号。
9)vec4  texture2DProjLod(sampler2D sampler, vec4 coord, float lod):使用纹理坐标coord和lod,从当前绑定到sampler的投影纹理中读取相应的纹理像素,coord的最后1个分量被忽略,lod为使用Mip纹理时的序号。
10)vec4  textureCube(samplerCube sampler, vec3 coord):使用纹理坐标coord,从当前绑定到sampler的立方体纹理中读取相应的纹理像素。coord的方向可用来指定立方体纹理的表面。
11)vec4  textureCube(samplerCube sampler, vec3 coord, float bias):使用纹理坐标coord和偏移bias,从当前绑定到sampler的立方体纹理中读取相应的纹理像素。coord的方向可用来指定立方体纹理的表面,bias只能在片元着色器中使用表示使用Mip纹理时加在当前lod上的值。
12)vec4  textureCubeLod(samplerCube sampler, vec3 coord, float lod):使用纹理坐标coord和lod,从当前绑定到sampler的立方体纹理中读取相应的纹理像素。coord的方向可用来指定立方体纹理的表面,lod表示使用Mip纹理的序号。

Copyright@dwenzhao.cn All Rights Reserved   备案号:粤ICP备15026949号
联系邮箱:dwenzhao@163.com  QQ:1608288659