内置函数
glsl提供了非常丰富的函数库,供我们使用,这些功能都是非常有用且会经常用到的. 这些函数按功能区分大改可以分成7类:
通用函数
下文中的 类型 T可以是 float, vec2, vec3, vec4,且可以逐分量操作.
方法 | 说明 |
---|---|
T abs(T x) | 返回x的绝对值 |
T sign(T x) | 比较x与0的值,大于,等于,小于 分别返回 1.0 ,0.0,-1.0 |
T floor(T x) | 返回一个值,该值等于小于或等于 x 的最接近整数。 |
T ceil(T x) | 返回一个值,该值等于大于或等于 x 的最接近整数。 |
T fract(T x) | 获取x的小数部分 |
T mod(T x, T y) | x - y * floor(x/y) |
T min(T x, T y) | 取x,y的最小值 |
T max(T x, T y) | 取x,y的最大值 |
T clamp(T x, T minVal, T maxVal) | min(max(x, minVal), maxVal),返回值被限定在 minVal,maxVal之间 |
T mix(T x, T y, T a) T mix(T x, T y, float a) | 取x,y的线性混合,x*(1−a)+y*a |
T step(T edge, T x) | 如果 x<edge 返回 0.0 否则返回1.0 |
T smoothstep(T edge0, T edge1, T x) T smoothstep(float edge0,float edge1, T x) | 如果x<edge0 返回 0.0 如果x>edge1返回1.0, 否则返回Hermite插值 |
角度&三角函数
下文中的 类型 T可以是 float, vec2, vec3, vec4,且可以逐分量操作.
方法 | 说明 |
---|---|
T radians(T degrees) | 角度转弧度 |
T degrees(T radians) | 弧度转角度 |
T sin(T angle) | 正弦函数,角度是弧度 |
T cos(T angle) | 余弦函数,角度是弧度 |
T tan(T angle) | 正切函数,角度是弧度 |
T asin(T x) | 反正弦函数,返回值是弧度 |
T acos(T x) | 反余弦函数,返回值是弧度 |
T atan(T y, T x) T atan(T y_over_x) | 反正切函数,返回值是弧度 |
指数函数
下文中的 类型 T可以是 float, vec2, vec3, vec4,且可以逐分量操作.
方法 | 说明 |
---|---|
T pow(T x, T y) | 返回x的y次幂 xy |
T exp(T x) | 返回x的自然指数幂 ex |
T log(T x) | 返回x的自然对数 ln |
T exp2(T x) | 返回2的x次幂 2x |
T log2(T x) | 返回2为底的对数 log2 |
T sqrt(T x) | 开根号 √x |
T inversesqrt(T x) | 先开根号,在取倒数,就是 1/√x |
几何函数
下文中的 类型 T可以是 float, vec2, vec3, vec4,且可以逐分量操作.
方法 | 说明 |
---|---|
float length(T x) | 返回矢量x的长度 |
float distance(T p0, T p1) | 返回p0 p1两点的距离 |
float dot(T x, T y) | 返回x y的点积 |
vec3 cross(vec3 x, vec3 y) | 返回x y的叉积 |
T normalize(T x) | 对x进行归一化,保持向量方向不变但长度变为1 |
T faceforward(T N, T I, T Nref) | 根据 矢量 N 与Nref 调整法向量 |
T reflect(T I, T N) | 返回 I - 2 * dot(N,I) * N, 结果是入射矢量 I 关于法向量N的 镜面反射矢量 |
T refract(T I, T N, float eta) | 返回入射矢量I关于法向量N的折射矢量,折射率为eta |
矩阵函数
mat可以为任意类型矩阵.
方法 | 说明 |
---|---|
mat matrixCompMult(mat x, mat y) | 将矩阵 x 和 y的元素逐分量相乘 |
向量函数
下文中的 类型 T可以是 vec2, vec3, vec4, 且可以逐分量操作.
bvec指的是由bool类型组成的一个向量:
GLSL
vec3 v3= vec3(0.,0.,0.);
vec3 v3_1= vec3(1.,1.,1.);
bvec3 aa= lessThan(v3,v3_1); //bvec3(true,true,true)
vec3 v3= vec3(0.,0.,0.);
vec3 v3_1= vec3(1.,1.,1.);
bvec3 aa= lessThan(v3,v3_1); //bvec3(true,true,true)
方法 | 说明 |
---|---|
bvec lessThan(T x, T y) | 逐分量比较x < y,将结果写入bvec对应位置 |
bvec lessThanEqual(T x, T y) | 逐分量比较 x <= y,将结果写入bvec对应位置 |
bvec greaterThan(T x, T y) | 逐分量比较 x > y,将结果写入bvec对应位置 |
bvec greaterThanEqual(T x, T y) | 逐分量比较 x >= y,将结果写入bvec对应位置 |
bvec equal(T x, T y) bvec equal(bvec x, bvec y) | 逐分量比较 x == y,将结果写入bvec对应位置 |
bvec notEqual(T x, T y) bvec notEqual(bvec x, bvec y) | 逐分量比较 x!= y,将结果写入bvec对应位置 |
bool any(bvec x) | 如果x的任意一个分量是true,则结果为true |
bool all(bvec x) | 如果x的所有分量是true,则结果为true |
bvec not(bvec x) | bool矢量的逐分量取反 |
纹理查询函数
图像纹理有两种 一种是平面2d纹理,另一种是盒纹理,针对不同的纹理类型有不同访问方法.
纹理查询的最终目的是从sampler中提取指定坐标的颜色信息. 函数中带有Cube字样的是指 需要传入盒状纹理. 带有Proj字样的是指带投影的版本.
以下函数只在vertex shader中可用:
GLSL
vec4 texture2DLod(sampler2D sampler, vec2 coord, float lod);
vec4 texture2DProjLod(sampler2D sampler, vec3 coord, float lod);
vec4 texture2DProjLod(sampler2D sampler, vec4 coord, float lod);
vec4 textureCubeLod(samplerCube sampler, vec3 coord, float lod);
vec4 texture2DLod(sampler2D sampler, vec2 coord, float lod);
vec4 texture2DProjLod(sampler2D sampler, vec3 coord, float lod);
vec4 texture2DProjLod(sampler2D sampler, vec4 coord, float lod);
vec4 textureCubeLod(samplerCube sampler, vec3 coord, float lod);
以下函数只在fragment shader中可用:
GLSL
vec4 texture2D(sampler2D sampler, vec2 coord, float bias);
vec4 texture2DProj(sampler2D sampler, vec3 coord, float bias);
vec4 texture2DProj(sampler2D sampler, vec4 coord, float bias);
vec4 textureCube(samplerCube sampler, vec3 coord, float bias);
vec4 texture2D(sampler2D sampler, vec2 coord, float bias);
vec4 texture2DProj(sampler2D sampler, vec3 coord, float bias);
vec4 texture2DProj(sampler2D sampler, vec4 coord, float bias);
vec4 textureCube(samplerCube sampler, vec3 coord, float bias);
在 vertex shader 与 fragment shader 中都可用:
GLSL
vec4 texture2D(sampler2D sampler, vec2 coord);
vec4 texture2DProj(sampler2D sampler, vec3 coord);
vec4 texture2DProj(sampler2D sampler, vec4 coord);
vec4 textureCube(samplerCube sampler, vec3 coord);
vec4 texture2D(sampler2D sampler, vec2 coord);
vec4 texture2DProj(sampler2D sampler, vec3 coord);
vec4 texture2DProj(sampler2D sampler, vec4 coord);
vec4 textureCube(samplerCube sampler, vec3 coord);
官方shader示例
Vertex Shader:
cpp
uniform mat4 mvp_matrix; //透视矩阵 * 视图矩阵 * 模型变换矩阵
uniform mat3 normal_matrix; //法线变换矩阵(用于物体变换后法线跟着变换)
uniform vec3 ec_light_dir; //光照方向
attribute vec4 a_vertex; // 顶点坐标
attribute vec3 a_normal; //顶点法线
attribute vec2 a_texcoord; //纹理坐标
varying float v_diffuse; //法线与入射光的夹角
varying vec2 v_texcoord; //2d纹理坐标
void main(void)
{
//归一化法线
vec3 ec_normal = normalize(normal_matrix * a_normal);
//v_diffuse 是法线与光照的夹角.根据向量点乘法则,当两向量长度为1是 乘积即cosθ值
v_diffuse = max(dot(ec_light_dir, ec_normal), 0.0);
v_texcoord = a_texcoord;
gl_Position = mvp_matrix * a_vertex;
}
uniform mat4 mvp_matrix; //透视矩阵 * 视图矩阵 * 模型变换矩阵
uniform mat3 normal_matrix; //法线变换矩阵(用于物体变换后法线跟着变换)
uniform vec3 ec_light_dir; //光照方向
attribute vec4 a_vertex; // 顶点坐标
attribute vec3 a_normal; //顶点法线
attribute vec2 a_texcoord; //纹理坐标
varying float v_diffuse; //法线与入射光的夹角
varying vec2 v_texcoord; //2d纹理坐标
void main(void)
{
//归一化法线
vec3 ec_normal = normalize(normal_matrix * a_normal);
//v_diffuse 是法线与光照的夹角.根据向量点乘法则,当两向量长度为1是 乘积即cosθ值
v_diffuse = max(dot(ec_light_dir, ec_normal), 0.0);
v_texcoord = a_texcoord;
gl_Position = mvp_matrix * a_vertex;
}
Fragment Shader:
cpp
precision mediump float;
uniform sampler2D t_reflectance;
uniform vec4 i_ambient;
varying float v_diffuse;
varying vec2 v_texcoord;
void main (void)
{
vec4 color = texture2D(t_reflectance, v_texcoord);
//这里分解开来是 color*vec3(1,1,1)*v_diffuse + color*i_ambient
//色*光*夹角cos + 色*环境光
gl_FragColor = color*(vec4(v_diffuse) + i_ambient);
}
precision mediump float;
uniform sampler2D t_reflectance;
uniform vec4 i_ambient;
varying float v_diffuse;
varying vec2 v_texcoord;
void main (void)
{
vec4 color = texture2D(t_reflectance, v_texcoord);
//这里分解开来是 color*vec3(1,1,1)*v_diffuse + color*i_ambient
//色*光*夹角cos + 色*环境光
gl_FragColor = color*(vec4(v_diffuse) + i_ambient);
}