百人计划学习 图形 2.3 常用函数介绍(重点:HLSL + ddx/ddy)

这是个人学习笔记,有错欢迎指出
学习链接:

HLSL

CG语言逐渐被淘汰
HLSL API参考链接
微软定义的高阶着色器语言(High Level Shader Language)

函数

一、基本数学运算

函数可视化网站:https://graphtoy.com/

函数作用
max(a,b)返回较大的那个
min(a,b)返回较小的那个
mul(a,b)两数相乘,常用于矩阵运算
abs(a)返回输入值的绝对值
round(x)返回与x最近的整数
sqrt(x)返回指定值的平方根
rsqrt(x)返回指定值的平方根的倒数
degrees(x)转换成弧度
radians(x)将角度转为弧度制
noise(x)噪声函数:返回一个The Perlin noise value within a range between -1 and 1.

二、幂指对函数

函数作用
pow(x,y)x的y次幂(x和y均可为自变量或具体的数)
ldexp(x,exp): x * 2exp
exp(x)返回以e为底的指数函数
exp2(value x)返回以2为底,x为幂的指数
log(x)返回指定值的以e为底的对数(lnx)
log10(x)求以10为底的对数
log2(x)求以2为底的对数
frexp(x,out exp)把浮点数 x 分解成尾数和指数,返回值是尾数,exp参数返回的值是指数 (如果x参数为0,则此函数的尾数和指数均返回0)

out关键字:传值引用,不要求在传递之前初始化变量

三、三角函数与双曲线函数

函数作用
asin(x)返回输入值的反正弦值
acos(x)返回输入值反余弦值
atan(x)返回输入值的反正切值
atan2(y,x)返回y/x的反正切值
sincos(x,out s ,out c)返回x的正弦值和余弦值
tan(y,x)返回y/x的正切值
sinh(x)返回x的双曲正弦值 即0.5*(ex-e-x)
cosh(x)返回x的双曲余弦值 即0.5*(ex-e-x)
tanh(x)返回x双曲正切值,值域从1开始

sin(x) cos(x) tan(x) x均为弧度

在这里插入图片描述

四、数据范围类

函数作用
ceil(x)返回>=x的最小整数
step(x,y)x<=y为1,否则为0
floor(x)返回小于或等于x的最大整数
saturate(x)返回将x钳制到0和1之间的值
clamp(x,min,max)把x限制在[min, max]范围内,小于返回min,大于返回max
frac(x)返回x部分的小数f
modf(x, out ip)将值x分为小数和整数部分(各部分符号与x相同) ip返回整数部分,整体返回小数部分
smoothstep(min,max,x)如果x在[ min,max ]范围内,则返回介于0和1之间的平滑Hermite插值;使用smoothstep HLSL内在函数在两个值之间创建平滑过渡。例如,使用此功能平滑地混合两种颜色

lerp(x,y,s) = x*(1-s) + y*s

五、类型判断类

  • all(x): 确定指定量的所有分量是否均为非零,均非零则返回true,否则返回false (处理由浮点型、整型、布尔型数据定义的标量、向量或者矩阵)
  • clip(x) 如果输入值小于零,则丢弃当前像素 常用于判定范围(不仅仅针对0,返回值为void)常用于测试alpha,如果每个分量代表到平面的距离,还可以用来模拟剪切平面
  • sign(x) 返回x的正负性 如果x小于零返回-1,如果x等于零返回0,如果x大于零返回1 isinf(x) 如果x参数为+ INF或-INF(无穷+无穷仍无穷,0x3f3f3f3f),返回true,否则返回False
  • isfinite(x) 判断x参数是有限,即有界的,与isinf(x)
  • isnan(x) 如果x参数为NAN(非数字),返回true,否则返回false

六、向量与矩阵类

  • length(v) 返回向量的长度normalize(v) 向量归一化,x/length(x) 方向向量归一化
  • distance(a,b) 返回两个向量之间的距离,按理说应该为0,此处表示为根号下各分量之差的平方和
  • dot(a,b) 返回a和b这两个向量的标积/内积/数量积/点积 (a在b上的投影长,a·b=|a||b|·cosθ)
  • cross(a,b) 返回a和b这两个向量的矢积/外积/向量积/叉积 (返回值是个向量,而且与a、b都垂直,大小上| a x b | = |a| * |b| * sinθ )平行四边形面积,返回的是矢量求物体的表面法线
  • determinant(m) 返回指定浮点矩阵的按行列式方式计算的值
  • transpose(m) 返回矩阵m的转置矩阵

七、光线运算类

此部分会在复习完101之后再更新

  • reflect(i,n) 以i为入射向量,n为法线方向的反射光

  • refract(i,n,ri) 以i为入射向量n为法线方向,ri为折射率的折射光

  • lit(n_dot_l,n_dot_h,m) 输入标量(normal,light,半角向量h,镜面反射系数m)**返回光照向量(环境光,漫反射光,镜面高光反射,1)**Bling Phong模型
    在这里插入图片描述

  • faceforward(n,i,ng) 得到面向视图方向的曲面法向量输入输出为同元向量,返回-n*sign(dot(i,ng))(normal,light,normal)

八、1D纹理查找(几乎不用)

GPU在PS阶段是在屏幕空间XY坐标系中对每一个像素去对应的纹理中查找对应的纹素来确定像素的颜色

  • tex1D(s, t) 普通一维纹理查找 返回纹理采样器s在标量t位置的color4 //tex1D(s,t,ddx,ddy) 使用微分查询一维纹理 t和ddxy均为vector
  • tex1Dlod(s, t) 使用LOD查找纹理s在t.w位置的color4
  • tex1Dbias(s, t) 将t.w决定的某个MIP层偏置后的一维纹理查找
  • tex1Dgrad(s,t,ddx,ddy) 使用微分并指定MIP层的一维纹理查找
  • tex1Dproj(s, t) 把纹理当做一张幻灯片投影到场景中,先使用投影纹理技术需要计算出投影纹理坐标t(坐标t.w除以透视值),然后使用投影纹理坐标进行查询

九、2D纹理查找

  • tex2D(s, t) 普通二维纹理查找 返回纹理采样器s在vector t位置的颜色
  • tex2D(s,t,ddx,ddy) 使用微分查询二维纹理 t和ddxy均为vectortex2Dlod(s, t) 使用LOD查找纹理s在t.w位置的color4
  • tex2Dbias(s, t) 将t.w决定的某个MIP层偏置后的二维纹理查找
  • tex2Dgrad(s,t,ddx,ddy) 使用微分并指定MIP层的二维纹理查找
  • tex2Dproj(s, t) 把纹理当做一张幻灯片投影到场景中,先使用投影纹理技术需要计算出投影纹理坐标t(坐标t.w除以透视值),然后使用投影纹理坐标进行查询

十、3D纹理查找

二维图片的叠加

  • tex3D(s, t) 普通三维纹理查找 返回纹理采样器s在vector t位置的颜色
  • tex3D(s,t,ddx,ddy) 使用微分查询三维纹理 t和ddxy均为vector
  • tex3Dlod(s, t) 使用LOD查找纹理s在t.w位置的color4
  • tex3Dbias(s, t) 将t.w决定的某个MIP层偏置后的三维纹理查找
  • tex3Dgrad(s,t,ddx,ddy) 使用微分并指定MIP层的三维纹理查找
  • tex3Dproj(s, t) 把纹理当做一张幻灯片投影到场景中,先使用投影纹理技术需要计算出投影纹理坐标t(坐标t.w除以透视值),然后使用投影纹理坐标进行查询
在纹理采样时使用mipmap
  • lod:查找时使用mipmap图
  • bias:查找mipmap图后在使用偏置
  • grad:使用微分并指定mipmap层的查找

11.立体

  • texCUBE(s,t) 返回纹理采样器s在vector t位置的颜色
  • texCUBE(s,t,ddx,ddy)使用微分查询立方体维纹理 t和ddxy均为vector
  • texCUBEDload(s,t) 使用LOD查找纹理s在t.w位置的color4
  • texCUBEbias(s,t) 将t.w决定的某个MIP层偏置后的立方体纹理查找
  • texCUBEgrad(s,t,ddx,ddy) 使用微分并指定MIP层的立方体纹理查找
  • texCUBEproj(s,t) 使用投影方式的立方体纹理查找

ddx与ddy的学习

偏导函数( Derivative Functions )
参考:

1.简介
  1.    函数 ddx 和 ddy 用于求取相邻像素间某属性的差值;
    
  2.    函数 ddx 和 ddy 的输入参数通常是纹理坐标;
    
  3.    函数 ddx 和 ddy 返回相邻像素键的属性差值;
    

正是由于 ddx 和 ddy 指令是作用于像素级的,所以 ddx 和 ddy 函数只被片段程序所支持。
注意:偏导数ddx/ddy可以计算我们FragmentShader中任意的变量。向量,矩阵等等。

2.计算方式

在三角栅格化过程中,GPU一次运行许多片段着色器,它不是一个像素一个像素去计算的,而是将它们组织成2 × 2像素的块
ddx计算如下图:
(ddx and ddy in HLSL[a], dFdx and dFdy in GLSL[b])

3.应用
3.1 mipmap的使用

Mipmaps[d] are pre-computed sequences of images obtained by filtering down a texture into smaller sizes (each mipmap level is two times smaller than the previous). They are used to avoid aliasing artifacts when minifying a texture.
Mipmap是通过将纹理过滤到更小的尺寸(每个 mipmap 级别比前一个级别小两倍)而获得的预先计算的图像序列。它们被用来避免在缩小纹理时产生混淆(avoid aliasing artifacts).
我之前的笔记: 百人学习 1.3 纹理的秘密

  • ddx = p(x +1,y) - p(x,y)
  • ddy = p(x,y+1) - p(x,y)
    在这里插入图片描述

所谓图像过滤,一个比较简单的定义是:对于给定的输入图像 A ,要创建新的图像 B ,把源图像 A 变换到目标图像 B 的操作就是图像滤波。最一般的变换是调整图像大小、锐化、变化颜色,以及模糊图像等。复杂的过滤有赖于知道究竟需要过滤多少纹理

1.相邻像素差值越大,采样的纹理在屏幕上占比越小,对应需要使用的mip map level越大,
2.离相机越远的表面,在进行纹理采样的时候使用更低的mipmap等级
3.tex2Dlod可以根据参数lod采样特定的mip map level
4.比如原本0-1的UV可以铺满1000x1000的屏幕,相邻像素点UV差值为0.001=1/1000,当只能铺满1/4屏幕,也就是500x500的屏幕时,相邻像素点UV差值为0.002=1/500,因此500*500需要更大的level

在这里插入图片描述
在这里插入图片描述

3.2 Flat Shader(对顶点做偏导的应用)

原理:
1.VertexShader,将顶点的Pos传入到FragmentShader中;
2.在FragShader中,我们调用ddx(Pos),和ddy(Pos)这个代表求出相邻的2个像素块之间坐标的差值,即下面图中的红色和绿色2个矢量,而这2个矢量都在这个三角形的平面上,那么执行normalize( cross(ddx(pos),ddy(pos)) ) 就求出的面的法线,但是这里要注意,在HlSL上面,或者Unity上面要写成normalize( cross(ddy(pos),ddx(pos)) ,不然法线是反向的。这个是由于左右手坐标系引起的。

在这里插入图片描述

3.3 贴图勾边锐化(对贴图颜色求偏导的例子)

在这里插入图片描述

作业

1.五个最常用的函数

  1. mul(a,b) -> 两数相乘,常用于矩阵运算

o.worldNormal = mul(v.normal,(float3x3)unity_WorldToObject);
//把世界空间下的法线传递给片元着色器

  1. normalize(x) ->returns the normalized x parameter. If the length of the x parameter is 0, the result is indefinite.

fixed3 worldNormal = normalize(i.worldNormal);

  1. dot(a,b) 点积

fixed halfLambert = dot(worldNormal,worldLightDir)*0.5 + 0.5;//半兰伯特模型

  1. tex2D(s, t) 普通二维纹理查找 返回纹理采样器s在vector t位置的颜色

fixed3 albedo = tex2D(_MainTex, i.uv).rgb * _Color.rgb;
第一个参数是需要被采样的纹理,第二个是一个float2的纹理坐标,返回得到纹素值,与_Color乘积得到反射率

  1. clamp(x,min,max) 把x限制在[min, max]范围内,小于返回min,大于返回max

2.ddx ddy的实际使用测试

2.1 flat shading

主要的做法就是:
将顶点着色器将顶点信息传到片段着色器中,片段着色器利用ddx、ddy计算面法线
在这里插入图片描述

在这里插入图片描述

2.2 边缘锐化

在这里插入图片描述

在这里插入图片描述

  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值