Unity Shader常用函数

Unity Shader常用函数

CG标准函数库

Unity坐标转换

  • transform.localToWorldMatrix 本地坐标转世界坐标的矩阵
  • transform.worldToLocalMatrix 世界坐标转本地坐标的矩阵
  • Unity Shader中 左乘 _World2Object 矩阵来实现世界坐标转本地坐标变换
  • Unity Shader中 左乘 _Object2World 矩阵来实现本地坐标转世界坐标变换
  • UNITY_MATRIX_MV 基本变换矩阵 × 摄像机变换矩阵
  • UNITY_MATRIX_MVP 基本变换矩阵 × 摄像机变换矩阵 × 投影变换矩阵
  • UNITY_MATRIX_V 摄像机变换矩阵
  • UNITY_MATRIX_P 投影变换矩阵
  • UNITY_MATRIX_VP 摄像机变换矩阵 × 投影变换矩阵
  • UNITY_MATRIX_T_MV (基本变换矩阵 × 摄像机变换矩阵)的转置矩阵
  • UNITY_MATRIX_IT_MV (基本变换矩阵 × 摄像机变换矩阵)的逆转置矩阵
  • UNITY_MATRIX_TEXTURE0 纹理变换矩阵

数学函数

数学函数用于执行数学上常用计算,包括三角函数、幂函数、圆函数、向量和矩阵操作函数,这些函数都被重载,以支持标量数据和不同长度的向量作为输入参数

函数 功能
abs(x) 返回输入参数的绝对值
acos(x) 反余切函数,输入参数范围为[-1, 1], 返回[0, π]区间的角度值
all(x) 如果输入参数均不为0,则返回true,否则返回false。与运算
any(x) 输入参数只要有其中一个不为0,则返回true。 或运算
asin(x) 反正弦函数,输入参数范围为[-1, 1],返回[-π/2, π/2]区间的角度值
atan(x) 反正切函数,返回角度值范围为[-π/2, π/2]
atan2(y, x) 计算 y/x 的反正切值。实际上和 atan(x) 函数功能完全一样,只是输入参数不同。atan(x) = atan2(x, float(1))
ceil(x) 对输入参数向上取整。例如:ceil(float(1.3)),其返回值为2.0
clamp(x, a, b) 如果 x 值小于 a ,返回 a ; 如果 x 值大于 b ,返回 b ;否则返回 x
cos(x) 返回弧度 x 的余弦值。返回值范围为 [-1, 1]
cosh(x) 双曲余弦函数,计算 x 的双曲余弦值
cross(A, B) 返回两个三元向量的叉积。注意,输入参数必须是三元向量
degrees(x) 输入参数为弧度值(radians), 函数将其转换为角度值(degrees)
determinant(m) 计算矩阵的行列式因子
dot(A, B) 计算 A 和 B 的点积。参数 A 和 B 可以是标量,也可以是向量(输入参数方面,点积和叉积函数有很大的不同)
exp(x) 计算 e^x 的值,e = 2.71828182845904523536
exp2(x) 计算 2^x 的值
floor(x) 对输入参数向下取整。例如:floor(float(1.3)) 返回的值为1.0;但是 floor(float(-1.3)) 返回的值为-2.0
fmod(x, y) 返回 x/y 的余数。如果 y 为0,结果不可预料
frexp(x, out exp) 将浮点数 x 分解为尾数和指数,即 x = m * 2^exp, 返回m,并将指数存入exp中;如果 x 为 0,则尾数和指数都返回0
frac(x) 向下取整
isfinite(x) 判断标量或者向量中的每个数据是否是有限数,如果是返回true;否则返回false;无限的或者非数据(not-a-number NaN)
isinf(x) 判断标量或者向量中的每个数据是否是无限数,如果是返回true;否则返回false
isnan(x) 判断标量或者向量中的每个数据是否是非数据(not-a-number NaN),如果是返回true;否则返回false
ldexp(x, n) 计算 x*2^n 的值
lerp(a, b, f) 计算(1 - f) * a + b * f 或者 a + f * (b - a) 的值。即在下限 a 和上限 b 之间进行插值,f 表示权值。注意:如果 a 和 b 是向量,则权值 f 必须是标量或者等长的向量
lit(NdotL, NdotH, m) N 表示法向量;L 表示入射光向量;H 表示半角向量;m 表示高光系数。 函数计算环境光、散射光、镜面光的贡献,返回的 4 元向量:X 位表示环境光的贡献,总是 1.0。 Y 位代表散射光的贡献,如果 N • L < 0 ,则为 0;否则为 N • L。Z 位代表镜面光的贡献,如果 N • L < 0 或者 N • H < 0,则为 0;否则为 (N • H) ^ m。 W 位始终为 1.0
log(x) 计算 ln(x) 的值,x 必须大于0
log2(x) 计算 log2(x) 的值,x 必须大于0 (函数返回一个数字以2为底的对数)
log10(x) 计算 log10(x) 的值,x 必须大于 0 (函数返回一个数字以10为底的对数)
max(a, b) 比较两个标量或等长向量元素,返回大值
min(a, b) 比较两个标量或等长向量元素,返回小值
pow(x, y) x 的 y 次方
round(x) 离 x 最近的整数
modf(x, out lp) 将值 x 分成小数部分和整数部分
mul(M, N) 计算两个矩阵相乘,如果 M 为 AxB 阶矩阵, N 为 BxC 阶矩阵,则返回 AxC 阶矩阵。下面两个函数为其重载函数。
mul(M, v) 计算矩阵和向量相乘
mul(v, M) 计算向量和矩阵相乘
noise(x) 噪声函数,返回值始终在[0, 1]之间;对于同样的输入,始终返回相同的值(也就是说,并不是真正意义上的随机噪声)。
radians(x) 函数将角度值转换为弧度值
rsqrt(x) x 的反平方根,x 必须大于0
saturate(x) 如果 x 小于0,返回0;如果 x 大于1,返回1;否则返回 x
sign(x) 如果 x 大于0,返回1;如果 x 小于0,返回 0;否则返回 0
sin(x) 输入参数为弧度,计算正弦值,返回值范围为[-1, 1]
sincos(float x, out s, out c) 该函数是同时计算 x 的 sin 值和 cos 值,其中 s=sin(x),c=cos(x)。该函数用于“同时需要计算 sin 值和 cos 值的情况”,比分别运算要快很多!
sinh(x) 计算双曲正弦值
smoothstep(min, max, x) 值 x 位于 min、max 区间中。如果 x = min,返回0;如果 x = max,返回1;如果 x 在两者之间,按照下列公式返回数据:float smoothstep(float min, float max, float x) { x = clamp((x - min)/(max - min), 0.0, 1.0); }
step(a, x) 如果 x < a,返回0;否则返回1
sqrt(x) 求 x 的平方根,x 必须大于0
tan(x) 输入参数为弧度,计算正切值
tanh(x) 计算双曲正切值
transpose(M) M 为矩阵,计算其转置矩阵

几何函数

CG语言标准函数库中有3个几何函数会经常被使用到,分别是:

  • normalize,对向量进行归一化
  • reflect,计算反射关方向向量
  • refract,计算折射光方向向量

注意:

  • 着色程序中的向量最好进行归一化之后再使用,否则会出现难以预料的错误
  • reflect 函数和 refract 函数都存在以“入射光方向向量”作为参数,注意这两个函数中使用的入射光方向向量是从外指向几何顶点的;平时我们在着色程序中或者在课本上都是将入射光方向向量作为从顶点发出
函数 功能
tex1D(sampler1D tex, float s) 一维纹理查询
tex1D(sampler1D tex, float s, float dsdx, float dsdy) 使用导数值(derivatives)查询一维纹理
tex1D(sampler1D tex, float2 sz) 一维纹理查询,并进行深度值比较
tex1D(sampler1D tex, float2 sz, float dsdx, float dsdy) 使用导数值(derivatives)查询一维纹理,并进行深度值比较
tex1Dproj(sampler1D tex,float2 sq) 一维投影纹理查询
tex1Dproj(sampler1D tex,float3 szq) 一维投影纹理查询,并比较深度值
tex2D(sampler2D tex, float2 sq) 二维纹理查询
tex2D(sampler2D tex, float2 s, float2 dsdx, float2 dsdy) 使用导数值(derivatives)查询二维纹理
tex2D(sampler2D tex, float3 sz) 二维纹理查询,并进行深度值比较
tex2D(sampler2D tex, float3 sz, float2 dsdx, float2 dsdy) 使用导数值(derivatives)查询二维纹理,并进行深度值比较
tex2Dproj(sampler2D tex, float3 sq) 二维投影纹理查询
tex2Dproj(sampler2D tex,float4 szq) 二维投影纹理查询,并比较深度值
texRECT(samplerRECT tex, float2 s)
texRECT(samplerRECT tex, float2 s, float2 dsdx, float2 dsdy)
texRECT(samplerRECT tex, float3 sz)
texRECT(samplerRECT tex, float3 sz, float2 dsdx, float2 dsdy)
texRECTproj(samplerRECT tex,float3 sq)
texRECTproj(samplerRECT tex,float4 szq)
tex3D(sampler3D tex, float3 s) 三维纹理查询
tex3D(sampler3D tex, float3 s, float3 dsdx, float3 dsdy) 结合导数值(derivatives)查询三维纹理
tex3Dproj(sampler3D tex,float4 szq) 三维投影纹理查询,并比较深度值
texCUBE(samplerCUBE tex,float3 s) 查询立方体纹理
texCUBE(samplerCUBE tex, float3 s, float3 dsdx, float3 dsdy) 结合导数值(derivatives)查询立方体纹理
texCUBE(samplerCUBE tex,float4 sq) 立方体投影纹理查询

s 象征一元、二元和三元纹理坐标

z 代表使用深度比较的值

q 表示一个透视值(其实就是透视投影后所得到的的齐次坐标的后一位),这个值被用来除以纹理坐标(S),得到新的纹理坐标(已归一化到0和1之间)然后用于纹理查询

纹理函数非常多,总的来说,按照纹理数进行分类,即1D纹理函数、2D纹理函数、3D纹理函数以及立方体纹理函数。需要注意,texRECT 函数查询的纹理实际上也是二维纹理。3D纹理,另一个比较学术化的名称是“体纹理”,体纹理通常用于体绘制,体纹理用于记录空间中的体细节数据。

还有一类比较特殊的纹理查询函数以 proj 结尾,主要针对投影纹理进行查询。所谓投影纹理是指:将纹理当做一张幻灯片投影到场景中,使用投影纹理技术需要计算投影纹理坐标,然后使用投影纹理坐标进行查询,使用投影纹理坐标进行查询的函数就是投影纹理查询函数。本质来说,投影纹理查询函数和普通的纹理查询函数没什么不同,唯一区别在于“投影纹理查询函数使用计算得到的投影纹理坐标,并在使用之前会将该投影纹理坐标除以透视值”。

🌰:计算得到的投影纹理坐标为float4 uvproj, 使用二维投影纹理查询函数:tex2Dproj(texture, uvproj);

等价于按如下方式使用普通二维纹理查询函数:

1
2
float4 uvproj = uvproj/uvproj.q;
tex2D(texture, uvproj);

偏导函数

函数 功能
ddx(a) 参数a对应一个像素位置,返回该像素值在X轴上的偏导数
ddy(a) 参数a对应一个像素位置,返回该像素值在Y轴上的偏导数
  • 函数 ddxddy 用于求取相邻像素间某属性的差值;
  • 函数 ddxddy 的输入参数通常是纹理坐标;
  • 函数 ddxddy 返回相邻像素间的属性差值;

其他

旋转公式

  • 顺时针旋转:x = x * cos(α) - y*cos(α), y = x * sin(α) + y * cos(α)

  • 逆时针旋转:x = x * cos(α) + y*cos(α), y = x * sin(α) - y * cos(α)

坐标转换

UnityObjectToClipPos(v.vertex) == mul(UNITY_MATRIX_MVP, v.vertex)

top