GLSL-变量和类型

基础类型

GLSL支持下面几种基本类型。

类型 解释
void void,函数不需要返回值时用这个
bool 布尔类型,true或者false
int 有符号整数
float 有符号浮点数
vec2 包含2个float的向量
vec3 包含3个float的向量
vec4 包含4个float的向量
bvec2 包含2个bool的向量
bvec3 包含3个bool的向量
bvec4 包含4个bool的向量
ivec2 包含2个int的向量
ivec3 包含3个int的向量
ivec4 包含4个int的向量
mat2 2*2的float的矩阵
mat3 3*3的float的矩阵
mat4 4*4的float的矩阵
sampler2D 操作2D的Texture的句柄
samplerCube 操作cube的Texture的句柄

另外,GLSL不支持指针类型。

Structures 结构体

GLSL支持结构体,把一些系统定义的类型聚到一起,组成自定义的类型。例如:

struct light {
    float intensity;
    vec3 position;
} lightVar;

然后,可以通过下面的方式声明一个结构体:

light lightVar2;

和C++中的结构体差不多。结构体里最少有一个成员,而且不支持结构体的嵌套。

Arrays 数组

GLSL中的数组和C++的数组很类似,支持最基本类型,也支持结构体。例如:

float frequencies[3];
uniform vec4 lightPosition[4];
const int numLights = 2;
light lights[numLights];

GLSL的数组无法在声明的时候初始化。

存储限定符

限定符 含义
本地可读可写,或者是函数的参数
const 常量,或者是函数的只读参数
attribute 连接Vertex Shader和OpenGL ES
uniform 不会改变的常量
varying 连接Vertex Shader和Fragment Shader,提供差值

成员变量、局部变量以及函数参数只能使用const
函数返回值和结构体内的变量不适用限定符。
成员变量没有标明限定符,或者标了const的,必须在声明的时候初始化。uniform、attribute、varying这三个不受此限制。

const 限定符

const限定符标识一个只读常量,在声明的时候就必须初始化。例如:

const vec3 zAxis = vec3 (0.0, 0.0, 1.0);

但是,结构体里的变量不能设成const,数组以及包含数组的结构体也不能设成const,因为数组无法在声明的时候初始化。

attribute 限定符

attribute是用来给Vertex Shader传递顶点数据的,只能用在Vertex Shader中。一般通过OpenGL API来初始化。

attribute 无法修饰数组和结构体。

具体:

attribute vec4 position;
attribute vec3 normal;
attribute vec2 texCoord;

Uniform 限定符

uniform是只读的,只能通过OpenGL API进行初始化。举例:

uniform vec4 lightPosition;

Varying 限定符

Varying变量是连接Vertex Shader和Fragment Shader的桥梁,Vertex Shader会为每个Vertex计算颜色、坐标等信息,写入Varying变量。然后Fragment Shader会读取这些数据进行进一步的操作。

这里比较难理解的就是差值,还是要通过实例来理解。举个例子,比如一张图片要绘制一千个Fragment(可以理解成需要绘制一千个像素点),我们不可能挨个去赋值,只能通过系统自动差值的方式实现。

Vertex Shader可以写Varying变量,也可以读,Fragment Shader只能读Varying变量,不能写。Vertex Shader中定义的Varying变量必须和Fragment Shader中的定义完全匹配。不能多定义Varying变量,也不能少定义。Fragment Shader中定义的Varying变量必须在Vertex Shader中有完全一样的定义。

关于Vertex Shader和Fragment Shader中Varying变量的定义关系,有个图:

上图中的static use是指在Shader中有明确的使用,比如读写等操作。

Varying变量声明举例:

varying vec3 normal;

Varying变量不可应用于结构体。

参数限定符

函数的参数可以使用下面的三个参数限定符。

限定符 作用
< none: default > 和 in 完全一样
in 传给函数,在函数中读取值
out 传给函数,在函数中写入值;传给函数的时候没有初始化
inout in 和 out 作用的结合