天天看点

OpenGL ES Shader相关API 总结【4】—— GLSL 语法小结【持续更新】

基本类型:

1.数值类型

2.布尔类型

注意:不能自动转型;矢量也不能自动补齐

变量:

1.a-z, A-Z, 0-9, _

2.首字母不能为数字

3.不能用关键字和保留字作变量名

4.不能以gl_,_webgl_开头

复杂变量

结构体

和C类似

数组

1.只支持一维数组

2.长度必须大于0的整型常量表达式

3.不可用const修饰

注:ES 2.0有以下限制:

4.Vertex Shader中的Sampler和Fragment Shader中的uniform数组只能被常整数表达式索引。(常整数表达式:常整数或常整数的运算)

采样器

1.通过采样器访问纹理

2.sampler2D

3.只能是uniform变量

4.纹理单元编号(至少支持8个)

流程控制

1.if / else if / else

①条件只能是bool类型;

②条件最好是uniform类型。

2.for(和C类似)

①循环条件中的loop_index必须是和常量表达式比较;

②循环条件中的loop_index只能和常量表达式进行增减;

③循环主体中的loop_index相当于常量,不能被修改;

④不支持while和do-while循环。

内置函数

三角函数

指数函数

通用函数

几何函数

矩阵函数

矢量函数

纹理查询函数

限定字

存储限定字:

const

编译时的常量,或者对函数来说为只读的参数,必须在声明时初始化。

attribute

修饰的变量只能用于顶点着色器,片元着色器中无法使用,数量限制至少是8,不能修饰array和struct。

uniform

客户端传递进来的变量,修饰的变量相对于所有顶点之间(或所有片元之间)在某一次渲染中是不变(相同)的,在着色器中为只读。

顶点着色器中uniform的个数有限制, ES 2.0是128个vec4条目, ES 3.0是256个vec4条目

片元着色器中uniform的个数限制, ES 2.0是16个vec4条目。

一共有四种类型的变量会占用uniform存储空间:

①uniform修饰符声明的变量

②const常量

③字面量(直接使用数字):相同值的实例会重复占用空间,所以最好使用const变量进行声明

④特定实现的常数

varying( ES 2.0才有这个类型, ES 3.0直接in/out)

修饰的数据从顶点着色器传输(插值)到片元着色器中

in

上一个阶段传递过来的变量,只读

in centroid

上一个阶段传递过来的变量,使用质心插值(针对多重采样缓冲区才有效)

out

传递到下一个阶段或者在函数中指定的返回值

out centroid

传递到下一个阶段,使用质心插值(针对多重采样缓冲区才有效)

inout

一个读/写变量,仅用于声明一个函数的一个参数;因为GLSL不支持指针和引用,所以这是一个值传递到一个函数并且允许这个函数修改并返回同一个变量值的唯一方法。

ES 3.0 支持smooth/flat插值修饰符,默认是smooth。

ES 3.0 支持uniform blocks。

精度限定字:

highp:

通常顶点着色器中的float是highp

适用于通过矩阵进行顶点位置变换、法线变换、纹理坐标的生成以及变换等操作。

mediump:

通常顶点着色器中的int是mediump

适用于颜色与光照的计算。

lowp:

通常片元着色器中的float是lowp

手动定义精度的方式:

precision lowp float      

为变量指定合适的精度能够显著提高shader的性能

精度限定字表:

精度限定字表

OpenGL ES Shader相关API 总结【4】—— GLSL 语法小结【持续更新】

在顶点着色器中,如果没有指定默认精度,则int和float的默认精度都是highp。对于片元着色器,float类型的默认精度没有默认值,必须显示的声明。并且在fs中,不一定支持highp,可查询得知是否支持(GL_FRAGMENT_PRECISION_HIGH定义,或者查询OES_fragment_precision_high扩展)。

不变量限定字:

Invariance:

invariant关键字可以作用于vs输出的任意varying变量上。

shader在编译时,编译器可能进行优化,导致指令被重排。这意味着两个shader间相同的计算,不一定产生精确相等的结果。这对于multipass渲染来说是个问题,一个物体被渲染多次,如果计算出来的位置有差别,就会有瑕疵。比如产生z-fighting。

使用invariant可以在写shader时指定如果使用了相同的计算,输出的结果必须精确一致。

1.invariant关键字可以使用在varying声明上或者已经声明的varying上。

invariant gl_Position; //内置的已经声明的varying,使用invariant
invariant varying texCoord; //声明时使用invariant      

2.可以使用#pragma指令器然所有的变量invariant: 

#pragmaSTDGL invariant(all)      

注意,为了实现invariant,编译器限制了优化,所有仅当需要时才使用invariant。 

继续阅读