GLSL-内置函数

GLSL内置了若干类内置的便利函数,用于标量和向量的计算。其中很多内置函数可以用于多个类型的Shader,也有一些是提供了直接操作硬件的方法,这种一般只适用于特定的Shader

内置函数大致分为三类:

  • 提供方便的函数来操作硬件,比如提供操作texture map的函数。在GLSL中没有其他的方式可以模仿这些函数实现对应的功能。
  • 提供很多小的工具函数,比如clamp、mix等等,可以供开发者很方便的调用,都是非常常用的,有一些是直接操作硬件的。编译器把这些函数映射到复杂的编译指令集是一件困难的事情。
  • 提供一些操作,这些操作在特定的场景下会被图形硬件加速。三角函数就属于这一类。

很多函数的命名和常见的C语言库类似,但是参数支持向量和更多的标量。

开发者在编写程序时应该直接使用这些内置函数,不要造轮子,因为这些内置函数是最理想的实现方式(比如有可能是直接硬件支持的)。

开发者的代码可以重载这些函数,但是不能重新定义它。

在使用内置函数时,所有的输入参数和返回值必须类型匹配。

参数和返回值没有指定精度修饰符。对于生成texture的函数来说,返回值的精度类型和参数sampler的精度类型一致。

uniform lowp sampler2D sampler;
highp vec2 coord;
...
lowp vec4 col = texture2D (sampler, coord); // 函数返回的texture2D的精度和参数sampler一样,也是lowp

其他内置函数的形参的精修饰符是无关紧要的,这些内置函数的返回值的精度类型和参数的实参的最高精度保持一致。参考章节4.5.2“精度修饰符”获取更多细节。

角和三角函数

以下这些函数的参数中的angle默认都是指的弧度(radian)。所有的函数都不会出现报除数为0的错误,当除数为0的时候,返回值是undefined

语法 说明
genType radians (genType degrees) 角度转弧度(degrees to radians)
genType degrees (genType radians) 弧度转角度(radians to degrees)
genType sin (genType angle) 三角函数-正弦sine
genType cos (genType angle) 三角函数-余弦cosine
genType tan (genType angle) 三角函数-正切tangent
genType asin (genType x) 反三角函数-反正弦arc sine
genType atan (genType y, genType x) 反三角函数-反余弦arc cosine
genType atan (genType y_over_x) 反三角函数-反正切arc tangent

三角函数与反三角函数基础可参考三角函数与反三角函数(图像)

指数函数

语法 说明
genType pow (genType x, genType y) x的y次方,\(x^y\)。如果x<0,则结果是undefined;如果x=0并且y<=0,则结果是undefined
genType exp (genType x) x的自然指数,\(e^x\)
genType log (genType x) x的自然对数,\(\log_ex\),即\(\ln{x}\)x<=0时结果是undefined
genType exp2 (genType x) 2的x次方,\(2^x\)
genType log2 (genType x) 以2为底,x的自然对数,\(log_2x\),x<=0时结果是undefined
genType sqrt (genType x) 对x进行开根号,\(\sqrt{x}\),x<0时结果是undefined
genType inversesqrt (genType x) sqrt的倒数,\(\frac{1}{\sqrt x}\),x<=0时结果是undefined

常用函数

语法 说明
genType abs (genType x) x的绝对值
genType sign (genType x) 判断x是正数、负数,还是零
genType floor (genType x) 返回不大于x的最大整数
genType ceil (genType x) 返回不小于x的最小整数
genType fract (genType x) 返回x的小数部分,即x-floor(x)
genType mod (genType x, genType y) 返回x – y * floor (x/y)
genType min (genType x, genType y) 返回x和y的较小值
genType max (genType x, genType y) 返回x和y的较大值
genType clamp (genType x, genType minVal, genType maxVal) min (max (x, minVal), maxVal),如果minVal > maxVal,则返回undefined
genType mix (genType x, genType y, genType a) 返回x * (1−a) + y * a

几何函数

这些函数都是一些向量相关的操作。

语法 说明
genType length (genType x) 计算向量的长度, \(\sqrt{x1^2+x2^2+...}\)
genType distance (genType p0, genType p1) p0和p1之间的距离,即length(p0-p1)
genType dot (genType x, genType y) 向量x与向量y的点积
genType cross (vec3 x, vec3 y) 向量x与向量y的叉积
genType normalize (genType x) 返回向量x对应的单位向量,即方向相同,长度为1
genType faceforward(genType N, genType I, genType Nref) 如果dot(Nref, I) < 0,则返回N,否则返回-N
genType reflect (genType I, genType N) I是入射光的方向,N是反射平面的法线,返回值是反射光的方向。I – 2 * dot(N, I) * N。N必须是单位向量。
genType refract(genType I, genType N, float eta) I是入射光的方向,N是反射平面的法线,折射率是eta,返回值是折射后的光线的向量。I和N必须是单位向量。

矩阵函数

语法 说明
mat matrixCompMult (mat x, mat y) 返回矩阵x乘以矩阵y的结果。例如result[i][j] 等于 x[i][j] * y[i][j]。注意:如果想进行线性代数里的乘法,请使用符号“*”。

向量关系函数

大小比较的运算符主要有:<, <=, >, >=, ==, !=,返回一些标量的布尔值。对于向量来说,主要使用下面的函数进行大小判断。

关于这些函数的一些约定:
bvec指代bvec2、bvec3、bvec4其中的一种;
ivec指代ivec2、ivec3、ivec4其中的一种;
vec指代vec2、vec3、vec4其中的一种。

所有场景下,输入的向量的维度要和输出向量的维度保持一致。

语法 说明
bvec lessThan(vec x, vec y)
bvec lessThan(ivec x, ivec y)
判断x<y
bvec lessThanEqual(vec x, vec y)
bvec lessThanEqual(ivec x, ivec y)
判断x<=y
bvec greaterThan(vec x, vec y)
bvec greaterThan(ivec x, ivec y)
判断x>y
bvec greaterThanEqual(vec x, vec y)
bvec greaterThanEqual(ivec x, ivec y)
判断x>=y
bvec equal(vec x, vec y)
bvec equal(ivec x, ivec y)
bvec equal(bvec x, bvec y)
判断x==y
bvec notEqual(vec x, vec y)
bvec notEqual(ivec x, ivec y)
bvec notEqual(bvec x, bvec y)
判断x!=y
bool any(bvec x) 判断x的元素是否有true
bool all(bvec x) 判断x的元素是否全部为true
bool not(bvec x)

Texture查找函数

Vertex Shader和Fragment Shader都可以使用纹理查找函数。但是,对于Vertex Shader来说,详细程度(level of detail)尚未经过计算,所以在Vertex Shader和Fragment Shader查找纹理时还是存在一定的差别。下面表格中的函数提供了通过采样器来获取textures的方法,这些方法被写入OpenGL ES API。Texture的属性,例如大小、像素格式、尺寸、滤镜方法、mip-map等级数量、深度比较等等信息也可以通过OpenGL ES API获取。通过下面的内置函数访问texture的时候,这些信息都会被考虑到。

包含bias参数的函数只能在Fragment Shader中使用。如果设置了bias参数,则在操作texture之前会先计算详细程度。如果没设置bias参数,则会自动选择详细程度:

对于一个没有mip-mapped的texture,则直接使用这个texture,对于已经mip-mapped的texture并且是在Fragment Shader中调用,则LOD用来进行texture的查找,对于已经mip-mapped的texture并且是在Vertex Shader中调用,直接返回基础的texture。

内置的函数以Lod结尾的只能用于Vertex Shader,并且Lod直接当成详细程度使用。

语法 说明
vec4 texture2D (sampler2D sampler, vec2 coord)
vec4 texture2D (sampler2D sampler, vec2 coord, float bias)
vec4 texture2DProj (sampler2D sampler, vec3 coord)
vec4 texture2DProj (sampler2D sampler, vec3 coord, float bias)
vec4 texture2DProj (sampler2D sampler, vec4 coord)
vec4 texture2DProj (sampler2D sampler, vec4 coord, float bias)
vec4 texture2DLod (sampler2D sampler, vec2 coord, float lod)
vec4 texture2DProjLod (sampler2D sampler, vec3 coord, float lod)
vec4 texture2DProjLod (sampler2D sampler, vec4 coord, float lod)
使用texture坐标coord来查找当前绑定到采样器的texture。对于函数名中含有Proj的函数来说,texture的坐标(coord.s,coord.t)会先除以coord的最后一个坐标。对于vec4这种变种来说,坐标的第三个元素直接被忽略。
vec4 textureCube (samplerCube sampler, vec3 coord)
vec4 textureCube (samplerCube sampler, vec3 coord, float bias)
vec4 textureCubeLod (samplerCube sampler, vec3 coord, float lod)
使用coord这个坐标去查找当前绑定到采样器的cube mapcoord的方向用来表示去查找cube map的哪一个二维平面。OpenGL说明书的2.0版本的3.8.6小节详细描述了这一点。