知方号

知方号

技术美术图形部分2.3 HLSL常用函数<十二个函数图像对应值>

——介绍HLSL常用函数,API的使用。

想要成为合格的技术美术,一定要具备Shader开发能力,满足性能的需求,无论是技术美术的哪一个方向,HLSL都是需要点满的技能点。

参考

微软官方HLSL库:HLSL 参考 - Win32 apps | Microsoft Docs

 《DirectX 3D HLSL高级实例精讲》我看的是实体书:GitHub - ljb1672/DirectX-3D-HLSL-Senior-instance-succinctly: code for DirectX 3D HLSL Senior instance succinctly

HLSL 语言

在渲染管线和介绍主流API的博客中,都提到了“可编程渲染管线”,其核心就是HLSL语言,正是因为HLSL才能对渲染管线可编程(针对微软的DX而言,当然还有Cg和OpenGL)。

HLSL语言和C++很相似,但是除了bool、int、float、double等标准型变量外,还有texture纹理变量、float、vec等向量类型等等。

本篇博客就根据技术美术百人计划的进度,主要介绍介绍HLSL的常用函数,秉持着不单纯copy老师PPT的原则,惯例会加入自己的理解。

HLSL的函数

HLSL的核心函数是由显卡驱动程序提供的函数库,用于向量及图形的计算,有了此函数库,程序的重点是将物理现象和光照模型转化成数学算法,算法则是由核心函数表达的代码,HLSL常用的函数大概有以下几种。

图形计算器

推荐了一个很方便的、图形相关数学函数实施验证的网站:Graphtoy

当然,其他的例如dmsmos也可以: Desmos | 图形计算器

把HLSL函数输进去,可以实时看到函数的数学表达形式,无需写Shader才能可视化。

1 基本数学运算

10个常用的数学运算

max(a,b)返回较大的一个min(a,b)返回较小的一个mul(a,b)两变量相乘,常用于矩阵运算abs(value a)返回a的绝对值round(x)返回与x最近的整数sqrt(x)返回x的平方根rsqrt(x)返回x的平方根的倒数degrees(x)弧度转换成角度redians(x)角度转换成弧度noise(x)噪声函数,传入二维坐标返回[0,1]随机值 2 幂指对函数

常用的幂指对函数

pow(x,y)x的y次幂exp(x)返回以e为底的指数函数exp2(value x)返回以2为底,x为指数的幂ldexp(x,exp)返回x与2的exp次方乘积log(x)返回以e为底的对数ln xlog2(x)返回以2为底的对数log10(x)返回以10为底的对数frexp(x,out exp)把浮点数x分解成尾数和指数,返回值是尾数ret,exp参数返回的是指数,如果x为0,则exp和ret均0 in/out/inout关键字

frexp(x,out exp)中出现了out,是个关键字,一起的还有in、inout:

in——默认的,可不加,表必须传递参数值out——表该参数是函数的一个返回值,仅用作输出,不能用作输入inout——可输入也可输出

关于out具体点的解释:指定实参应该在函数返回时被拷贝给型参,这样可以通过参数返回值。out关键字是必须的,因为HLSL不允许传递一个引用或一个指针。如果实参标记为out,在函数开始前,型参就不拷贝给实参了。换句话说,out实参仅可以被用于输出数据——它不能用于输入。

3  三角函数和双曲函数

三角函数

sin(x)求正弦,下划线前x均为弧度cons(x)求余弦tan(x)求正切sincos(x,out s,out c)返回x的正弦值s和余弦值ctan(y,x)返回y/x的正切值asin(x)返回输入值的反正弦值acos(x)返回输入值的反余弦值atan(x)返回输入值的反正切值atan2(y,x)返回y/x的反正切值

双曲函数

sinh(x)返回x的双曲正弦值cosh(x)返回x的双曲余弦值tanh(x)返回x的双曲正切值 双曲函数——悬链线

这部分参考了:可能是最好的讲解双曲函数的文章 - 知乎 (zhihu.com)

双曲函数的起源是悬链线。双曲函数是一条有点像二次抛物线又不完全是的曲线,这条曲线与两端固定的绳子(铁链)在均匀引力作用下下垂的弧度相似,因此这条曲线也直接被叫做悬链线。具体的直接看上面的参考文章把,讲得非常不错!

一图展示三角函数和双曲函数的关系: 

4  数据范围类

接下来是10个求数据范围的常用函数。

数据范围相关常用函数

ceil(x)返回≥x的最小整数floor(x)返回≤x的最大整数step(x,y)x≤y为1,否则为0saturate(x)钳制x在0到1之间,返回clamp(x,min,max)把x限制在[min,max]内,小于返回min大于返回max,是saturate()的升级版fmod(x,y)返回x/y的浮点部分(取余的余数部分)frac(x)返回输入x的小数部分modf(x,out ip)将x分为小数和整数部分,ip返回整数,整体返回小数lerp(x,y,s)按照s在x到y之间插值,可以看成按照s分段,即x*(1-s)+y*ssmoothstep(min,max,x)如果x在[min,max]范围内,则返回介于0和1之间的平滑Hermite插值,使用smoothstep在两个值之间创建平滑过渡,例如平滑的混合两种颜色值

smoothstep函数应用之-产生距离场

这部分参考了:GLSL函数smoothstep讲解 - 简书 (jianshu.com)

Shader实验室: smoothstep函数 - 知乎 (zhihu.com)

min --> edge0下界,max --> edge1上界,x插值输入,三者不仅可以是float,还可以是vec2/vec3/vec4变量,其用法:

float smoothstep(float edge0, float edge1, float x)  vec2 smoothstep(vec2 edge0, vec2 edge1, vec2 x)  vec3 smoothstep(vec3 edge0, vec3 edge1, vec3 x)  vec4 smoothstep(vec4 edge0, vec4 edge1, vec4 x)vec2 smoothstep(float edge0, float edge1, vec2 x)  vec3 smoothstep(float edge0, float edge1, vec3 x)  vec4 smoothstep(float edge0, float edge1, vec4 x)

如果想要创建一个能够输出平滑过渡的函数,就可以用smoothstep,它其实又等同于:

genType t;t = clamp((x - edge0) / (edge1 - edge0), 0.0, 1.0);return (3.0 - 2.0 * t) * t * t;

 可以用来干什么?——产生距离场(Distance Field)效果,下图是参考文章Shader实验室: smoothstep函数 - 知乎 (zhihu.com)中实现的效果:

5 类型判断类

给出了6个与数据类型判断相关的函数:

类型判断函数

all(x)可以传入矢量,所有分量均为非0返回true,否则falseany(x)只要传入的x有任何一个分量非0返回true,否则falseclip(x)

如果输入值小于0,丢弃该像素值,不进行渲染

(像素值为负->没有颜色)

sign(x)返回x的正负,x0返回1isinf(x)

如果x参数为+INF或-INF,返回true,否则false

isinite(x)判断x参数是否有限(有界),与isinf(x) 相反isnan(x)

x为NAN(非数字),返回true

x为数字,则返回false

clip函数应用之-透明度测试

这部分参考自《入门精要》

在片元着色器中使用clip函数进行透明度测试,如果给定参数的任何一个分量是负数,就会舍弃当前像素的输出颜色,它相当于:

void clip(float4 x){ if(any(x(环境光,漫反射光,镜面高光反射,1)

faceforward函数

仍旧放上官方:faceforward - Win32 apps | Microsoft Docs

注意,返回的n的方向肯定会朝着入射向量i的相反方向。

8 纹理映射函数(纹理查找)

须知,纹理从一维、二维到三维都可进行查询。低维(一维或二维)的纹理例如法线纹理、渐变纹理、遮罩纹理等等,一维类比一维数组,二维的类比二维数组,很好理解。三维的相当于二维的叠加,还有立方体纹理查找。

所有的纹理查找函数都可以分为普通的、微分的和投影的三类方式。关于每一个查找函数细节一点的解释,我都放在了2D纹理查找函数介绍中进行说明。

8.1 1D纹理查找(几乎不用) tex1D(s,t)普通1D纹理查找,s是纹理采样器,t是位置,返回颜色值tex1D(s,t,ddx,ddy)带微分的1D纹理查找值,即使用导数查找纹理tex1Dbias(s,t)使用t.w决定某个MIP层的1D纹理查找tex1Dgrad(s,t,ddx,ddy)使用微分(梯度)并指定MIP层的1D纹理查找tex1Dlod(s,t)

使用LOD方式的1D纹理查找

tex1Dproj(s,t)使用投影方式的1D纹理查找,把纹理当作一张图片投影到场景中,先使用投影纹理技术计算出投影纹理坐标t(做了透视除法的t.w),然后使用投影纹理坐标进行查询 8.2 2D纹理查找 tex2D(s,t)普通2D纹理查找,s是纹理采样器,t是vector,返回颜色tex2D(s,t,ddx,ddy)带微分的2D纹理查找值,t和ddxy都是vector,ddx和ddy的作用是取屏幕上相邻采样点的差值(本身偏导的作用就是表示方向上变化的快慢),ddxddy越大差值越大,采样像素越少,结果越模糊tex2Dbias(s,t)

使用t.w决定某个MIP层的偏移量,把计算出来的纹理层全部偏移某个指定的值

例如tex2Dbias(_Texture, float4(uv,0,1));则是将MIPMAP的level提高一个等级,可用于对图像采样结果进行模糊or锐化

tex2Dgrad(s,t,ddx,ddy)使用微分(梯度)并指定MIP层的2D纹理查找tex2Dlod(s,t)

使用LOD方式的2D纹理查找,查找t.w纹理、t.uv位置处的color4

tex2Dproj(s,t)使用投影方式的2D纹理查找,把纹理当作一张图片投影到场景中,先使用投影纹理技术计算出投影纹理坐标t(做了透视除法的t.w),然后使用投影纹理坐标进行查询 8.3 3D纹理查找

3D纹理可以理解成多个2D纹理叠加的结果,因此在查找时除了指定uv还需要指定3D纹理的层数。

但我其实不是很分得开三维纹理和MIPMAP的区别?或许三维纹理对每一层的纹理可控性更高吗?因为MIPMAP层次是有规律的,而3D纹理我可以按照喜好存放每一层纹理的大小。

tex3D(s,t)普通3D纹理查找tex3D(s,t,ddx,ddy)带微分的3D纹理查找值tex3Dbias(s,t)使用t.w决定某个MIP层的3D纹理查找tex3Dgrad(s,t,ddx,ddy)使用微分(梯度)并指定MIP层的3D纹理查找tex3Dlod(s,t)

使用LOD方式的3D纹理查找

tex3Dproj(s,t)使用投影方式的3D纹理查找,把纹理当作一张图片投影到场景中,先使用投影纹理技术计算出投影纹理坐标t(做了透视除法的t.w),然后使用投影纹理坐标进行查询 8.4 立方体纹理查找

除了低维的纹理查找,和3维的纹理(2维纹理的叠加)查找,还有更复杂一点的立方体纹理(Cubemap),立方体纹理一般用以实现环境映射来模拟物体周围的环境。

立方体纹理一共包含了6张图像,每张图像对应立方体的六个面,那么如何进行查询(采样)呢?三维纹理坐标——从立方体中心出发,向外部延伸并和六个面之一相交,采样得到的结果就是由这个交点计算而来的。

texCUBE(s,t)立方体环境贴图texCUBE(s,t,ddx,ddy)带微分的立方体纹理查找值texCUBEbias(s,t)使用t.w决定某个MIP层的立方体纹理查找texCUBEgrad(s,t,ddx,ddy)使用微分(梯度)并指定MIP层的立方体纹理查找texCUBElod(s,t)

使用LOD方式的立方体纹理查找

texCUBEproj(s,t)使用投影方式的立方体纹理查找,把纹理当作一张图片投影到场景中,先使用投影纹理技术计算出投影纹理坐标t(做了透视除法的t.w),然后使用投影纹理坐标进行查询 作业 1.写出你觉得最常用的5个函数

常用的话,感觉是涉及到向量计算的一些函数还有随机取值的一些:

mul(a,b)——变量相乘dot(a,b)——向量点乘,光照计算里再普遍不过了cross(a,b)——叉积,求垂直向量的时候经常用到,比如TBN矩阵那里normalize(v)——向量归一化clamp(x,min,max)——限制数的范围 2.ddx和ddy的实际使用测试

后续再填坑。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至lizi9903@foxmail.com举报,一经查实,本站将立刻删除。