地址:【技术美术百人计划】图形 2.3 常用函数介绍

笔记

HLSL内部函数文档:英文文档,不要看中文,机翻还把函数名给翻译了
函数可视化预览:graphtoy

基本数学运算

// 返回较大的值
max(a,b);
// 返回较小的值
min(a,b);
// 变量相乘,常用于矩阵运算
mul(a,b);
// 取绝对值
abs(a);
// 四舍五入取整
round(x);
// 求平方根
sqrt(x);
// 求平方根的倒数
// 雷神之锤著名的魔法数字就是求这东西?
rsqrt(x);
// 将弧度转成角度
degrees(x);
// 将角度转成弧度
radians(x);
// 使用柏林噪声(Perlin-noise)生成随机值
noise(x);

幂、指数、对数函数

// 求x的y次幂
pow(x,y);
// e的x次幂
exp(x);
// 2的x次幂
exp2(x);
// x*exp2(y)
ldexp(x,y);
// e为底x的对数
log(x);
// 10为底x的对数
log10(x);
// 2为底x的对数
log2(x);
// 返回浮点数表示为x=ret*2^y形式(二进制的科学计数法)
// 的尾数ret和指数y,y为输出变量
frexp(x,y);

三角函数、双曲函数

// 三角函数,x为弧度制的角度(返回值也是)
sin(x);
cos(x);
tan(x);
// 同时返回sin和cos值,s和c为输出函数
sincos(x,out s,out c);
// 反 正弦/余弦/...
asin(x);
acos(x);
atan(x);
atan2(y,x);
// 双曲 正弦/余弦/...
sinh(x);
cosh(x);
tanh(x);

数据范围

// 向上取整
ceil(x);
// 向下取整
floor(x);
// x<=y?1:0
step(x,y);
// 钳制x到0-1范围
saturate(x);
// 截取限制在min-max范围内的值,小于min取min,大于max取max
clamp(x,min,max);
// x对y取余
fmod(x,y);
// 取小数部分
frac(x);
// 同时返回小数部分和整数部分
// 返回值为小数部分,ip为整数部分
modf(x, out ip);
// 插值 返回x*(1-s)+y*s
lerp(x,y,s);
// 平滑Hermite插值
smoothstep(min,max,x);

类型判断

// 是否所有值都非零
all(x);
// 输入值小于0丢弃当前像素
// 会影响到early-z?
clip(x);
// x<0返回-1,x==0返回0,x>0返回1
sign(x);
// x是否INF(无穷)
isinf(x);
// !isinf(x)
isfinite(x)
// 是否NAN(非数字)
isnan(x);

向量与矩阵

// 向量长度
length(v);
// 归一化 x/length(x)
normallize(v);
// 两点(向量)间距离 各分量之差平方和开根号
distance(a,b);
// 向量点积 |a||b|cosΘ
dot(a,b);
// 向量×积 |a|*|b|*sinΘ
cross(a,b);
// 矩阵行列式计算
determinant(m);
// 矩阵转置
transpose(m);

光线运算

// 反射光 i为入射光向量,n为法线方向
reflect(i,n);
// 折射光。ri为折射率
refract(i,n,ri);
// 返回光照向量 (环境光,漫反射,高光,1)
// 参数为(dot(法向量,光向量),dot(法向量,半角向量),高光指数)
lit(n_dot_l, n_dot_h, m);
// 获得表面朝向镜头一面的法向量。 n为法向量,i为观察方向
// 算法-n sign(dot(i, ng)).

纹理查找

GPU在片元着色器阶段在屏幕空间下对每一个像素对应的纹理中查找对应纹素来确定像素颜色。
ddy、ddy: 用于求取屏幕空间坐标上相邻像素间某属性的差值。ddx、ddy通常输入纹理坐标

// 一维查找 纹理采样器s在t位置的值
tex1D(s,t);
// 使用微分查询。以ddx,ddy幅度进行采样
tex1D(s,t,ddx,ddy);
// 根据LOD查询纹理。mipmap的LOD为t.w
tex1Dlod(s,t);
// mip等级偏执t.w后进行纹理采样
tex1Dbias(s,t);
// 根据梯度选择mip等级进行采样
tex1Dgrad(s,t,ddx,ddy);
// 使用投影,在查找纹理前坐标会除以t.w
tex1Dproj(s,t);
// 2D、3D纹理查找类似
// tex2D、tex3D
//
// 立体纹理查找
// CubeMap。常用于环境光照。  
// 和上面列出的类似。texCUBE前缀

作业

觉得最常用的5个函数

  1. normalize:向量归一化
  2. dot:向量点积,算光照常用
  3. lerp:各种插值
  4. tex2D:纹理采样
  5. mul:矩阵运算,坐标变换计算常用

ddx、ddy实际使用测试

考虑既然ddx、ddy是像素间属性的差值,那么是否可以取深度的差值来获得一个描边效果。
描边
后处理中ddy、ddx取深度差值、超过阈值画上红色,效果就是这样
整体
加上原来的颜色,效果就是这样
效果看起来有明显的锯齿感不知道是不是深度值的精度较低导致的

#if defined(POSTPROCESSING)
    vec3 scene = texture2D(u_scene, st).rgb;
    float depth = texture2D(u_sceneDepth, st).r;
    depth = linearizeDepth(depth) * u_cameraFarClip;

    float dx = abs(dFdx(depth));
    float dy = abs(dFdy(depth));
    float dz = step(0.15,(dx+dy)/2.0);
    if(dz>0.0){
        color = vec3(1.0,0.0,0.0);
    } else {
        color = scene;
    }
#endif