图形 2.3 常用函数介绍
常用函数介绍
基本数学运算
max(a,b) | 返回最大的数 |
min(a,b) | 返回最小的数 |
mul(a,b) | 两变量相乘,常用于矩阵计算 |
abs(a,b) | 返回x的绝对值 |
round(x) | 返回与x最近的整数(四舍五入) |
sqrt(x) | 返回x的平方根 |
rsqrt(x) | 返回x的平方根的倒数 |
degrees(x) | 将弧度转换成角度 |
redians(x) | 将角度转换成弧度 |
noise(x) | 噪声函数 |
幂指对函数
pow(x,y) | 返回x的y次幂 |
exp(x) | 返回以e为底的指数函数 |
exp2(x) | 返回以2为底的指数函数 |
ldexp(x,y) | 返回x与2的y次方的乘积 |
log(x) | 返回x以e为底的对数 |
log10(x) | 返回x以10为底的对数 |
log2(x) | 返回x以2为底的对数 |
frexp(x,out exp) |
把浮点数x分解为尾数和指数x = ret * 2 ^exp的形式,返回尾数,并把指数传到exp中,如果x是0,两个返回值都是0 |
三角函数与双曲函数
sin(x),cos(x),tan(x) | 返回正弦值、余弦值、正切值 |
sincos(x,out s,out c) | 返回x的正弦值和余弦值 |
tan(y,x) | 返回y/x的正切值 |
asin(x) | 返回x的反正弦值 |
acos(x) | 返回x的反余弦值 |
atan(x) | 返回x的反正切值 |
atan2(y,x) | 返回y/x的反正切值 |
sinh(x) | 返回x的双曲正弦值
(e^x - e^-x)/ 2
|
cosh(x) | 返回x的双曲余弦值
(e^x + e^-x)/ 2
|
tanh(x) | 返回x的双曲正弦值
(e^x - e^-x)/ (e^x + e^-x) |
以上传进去的x值均为弧度值,即rad。1rad = 180°/PI |
关于双曲函数:知乎链接-可能是最好的讲解双曲函数的文章
数据范围类
ceil(x) | 返回大于x的最小整数,向上取整 |
floor(x) | 返回小于x的最小整数,向下取整 |
step(x,y) | 若y大于x返回1,否则返回0 |
saturate(x) | 返回将x钳制到0-1之间的值 |
clamp(x,min,max) | 把x限制在[min,max]范围内,小于返回min,大于返回max |
fmod(x,y) | 返回x对y取余的余数 |
frac(x) | 返回x的小数部分 |
modf(x,out ip) |
将值x分为小数和整数部分,整数部分传到ip,函数返回小数部分。 |
lerp(x,y,s) | 常用插值函数,按照s在x到y之间插值,s在0-1之间 |
smoothstep(min,max,x) | 如果x在[min,max]范围内,则返回介于0 - 1之间的平滑Hermite插值。这个差值不是线性的。 |
类型判断类
all(x) | x的所有分量均为非零则返回true,反之则返回false(浮点型,整型,布尔型数据定义的标量,向量或者是矩阵)。 |
clip(x) | 如果输入值小于零,则丢弃当前像素,可以代替AlphaTest |
sign(x) | x小于0返回-1,等于0返回0,大于0返回1 |
isinf(x) | x为INF值返回true,否则返回false(无论正负) |
isfinite(x) | x为INF值返回false,否则返回true(无论正负) |
isnan(x) | x为非数字返回true,否则返回false |
向量与矩阵类
关于这个Vector类型,我不知道从哪看到的说法,说是没有必要再用额外的一个类型去区分点,因为点和向量的计算大部分都是相通的,只是所代表的意义不一样。Vector这个类型既可以是点,也可以是向量,隐约好像记得是庄懂的课。
length(v) | 返回向量的模 |
normalize(v) | 向量归一化 |
distance(a,b) | 返回两个点的距离 |
dot(a,b) | 返回两个向量的点积 |
cross(a,b) | 返回两个向量的叉积 |
determinant(m) | 返回矩阵m用行列式方式计算的值 |
transpose(m) | 返回矩阵m的转置矩阵 |
光线运算类
reflect(i,n) | 返回以i为入射向量n为法线方向的反射光 |
refract(i,n,ri) | 返回以i为入射向量n为法线向量,ri为折射率的折射光 |
lit(n_dot_l,n_dot_h,m) | 输入标量normal与light的点积,normal与半角向量h的点积,镜面反射系数m,返回一个光照向量float4(环境光,漫反射光,镜面高光反射,1) |
faceforward(n,i,ng) | 得到面向视图方向的曲面法向量输入输出为同元向量,返回-n*sign(dot(i,ng))(normal,light,normal) |
1D纹理查找
罕见。
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均为vector
|
tex2Dlod(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) |
使用微分并指定MIP层的三维纹理查找
|
tex3Dproj(s,t) |
把纹理当做一张幻灯片投影到场景中,先使用投影纹理技术需要计算出投影纹理坐标t(坐标t.w除以透视值),然后使用投影纹理坐标进行查询
|
立方纹理查找
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)
|
使用投影方式的立方体纹理查找
|
扩展作业
——写出你觉得最常用的5个函数
三件套,mul,dot,normalize
tex2D肯定少不了
剩下的我觉得都差不多,max可能稍微高点。
——ddx ddy的实际使用测试
模糊
预先绘制一张模糊位置的遮罩图 RGB分别代表不同的模糊遮罩
然后调整出不同的模糊效果。最开始只有远处的楼房是模糊化的,之后两侧的楼房也变得模糊,最后只剩下神社鸟居和地面反光等部分没有被模糊化,可以用这种方法来强调画面主体。值得注意的并不一定要按远近关系进行模糊,事实上距离画面近的一些部分也被模糊化了,模糊遮罩根据自己的想法来绘制,不一定非要去模拟远近效果。
shader的面板很简单,两张贴图,模糊系数的乘算因子,以及模糊插值。
这里粗略的把[0, 0.5]这段区间来对遮罩图中红色部分进行模糊,[0.5, 0.75]则开始对蓝色部分进行模糊,[0.75,1]则对绿色部分进行模糊,这三段区间均被映射到[0,1]这个区间上,这意味着蓝色和绿色部分对模糊插值会更加敏感。
重要代码部分
Properties { _MainTex ("Texture", 2D) = "white" {} _MaskTex("模糊遮罩", 2D) = "white" {} //这个范围不宜设置过大 否则得不到比较好的效果 _ddxPower("ddx(横向模糊)", Range(-0.02,0.02)) = 0 _ddyPower("ddy(纵向模糊)", Range(-0.02,0.02)) = 0 _MaskPower("模糊插值", Range(0,1)) = 0 } fixed4 frag (v2f i) : SV_Target { //模糊部分 fixed4 mask = tex2D(_MaskTex, i.uv); float maskPower1 = mask.r *_MaskPower; float maskPower2 = mask.g * max(0, (_MaskPower - 0.5)) / 0.5; float maskPower3 = mask.b * max(0, (_MaskPower - 0.75)) / 0.25; float ddx_R = maskPower1 * _ddxPower; float ddx_G = maskPower2 * _ddxPower; float ddx_B = maskPower3 * _ddxPower; float ddx = ddx_R + ddx_G + ddx_B; float ddy_R = maskPower1 * _ddyPower; float ddy_G = maskPower2 * _ddyPower; float ddy_B = maskPower3 * _ddyPower; float ddy = ddy_R + ddy_G + ddy_B; fixed4 col = tex2D(_MainTex, i.uv, ddx, ddy); return col; }
锐化
随便找了个Cube套上了贴图,然后对其进行锐化,锐化后的Cube看起来“战痕累累”
面板没有太多的变换,也去掉了Mask贴图,只做了简单的锐化,没有什么特别的想法。
代码部分
fixed4 frag (v2f i) : SV_Target { fixed4 col = tex2D(_MainTex, i.uv); col += ddx(col) * _ddxPower + ddy(col) * _ddyPower; return col; }
参考