笔记08 图形 2.3 HLSL常用函数介绍

笔记08 图形 2.3 HLSL常用函数介绍

铁名_IronName Lv4

图形 2.3 HLSL常用函数介绍

MSDN中HLSL的常用API: https://docs.microsoft.com/en-us/windows/win32/direct3dhlsl/dx-graphics-hlsl-intrinsic-functions

基本数学运算

图形相关数学函数实时验证:https://graphtoy.com

函数作用
max(a,b)返回较大的那个
min(a,b)返回较小的那个
mul(a,b)两变量相乘,常用于矩阵运算
abs(a)返回a的绝对值
round(x)返回与x最近的整数
sqrt(x)返回x的平方根
rsqrt(x)返回x的平方根的倒数
degrees(x)将弧度转换成角度
radians(x)将角度转换成弧度
noise(x)噪声函数

幂指对函数

函数作用
pow(x,y)xyx^y
exp(x)exe^x
exp2(x)2x2^x
ldexp(x,exp)x2expx*2^{exp}
log(x)lnx\ln x
log10(x)log10x\log_{10}x
log2(x)log2x\log_{2}x
frexp(x, out exp)把浮点数 x 分解成尾数和指数x=ret2expx=ret*2^{exp},返回值是尾数,exp参数返回的值是指数

三角函数与双曲线函数

函数作用
sin(x), cos(x), tan(x)
sincos(x, out s, out c)返回x的正弦值和余弦值
tan(y,x)返回y/x的正切值
asin(x)返回输入值的反正弦值
acos(x)返回输入值反余弦值
atan(x)返回输入值的反正切值
atan2(y,x)返回y/x的反正切值
以上单位为弧度;
sinh(x)返回x的双曲正弦值 (exex)/2(e^x-e^{-x})/2
cosh(x)返回x的双曲余弦值 (ex+ex)/2(e^x+e^{-x})/2
tanh(x)返回x的双曲正切值 (exex)/(ex+ex)(e^x-e^{-x})/(e^x+e^{-x})

数据范围类

函数作用
ceil(x)返回>=x的最小整数
floor(x)返回<=x的最大整数
step(x, y)xyx\leq y 为 1, 否则为 0
smoothstep(min, max, x)若 x 在[min, max]范围内,返回介于 0 和 1 之间的平滑Hermite插值
saturate(x)返回将 x 钳制到 0 和 1 之间的值
clamp(x, min, max)把 x 限制在[min, max]范围内
fmod(x,y)返回x对y取余的余数
frac(x)返回x的小数部分
modf(x, out ip)将值x分为小数和整数部分(各部分符号与x相同);ip返回整数部分,整体返回小数部分
lerp(x,y,s)按照 s 在 x 到 y 之间插值,即返回 x(1s)+ysx*(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这两个向量的点积(又叫标积/内积/数量积)ab=abcosθa\cdot b=\|a\| \|b\|\cdot\cos\theta
cross(a,b)返回a和b这两个向量的叉积(又叫矢积/外积/向量积),返回值是个向量,而且与a、b都垂直,大小上a×b=absinθ\|a\times b\|=\|a\|*\|b\|*\sin\theta
determinant(m)返回矩阵m按行列式方式计算的值
transpose(m)返回矩阵m的转置矩阵

光线运算类

函数作用
reflect(i,n)以i为入射向量,n为法线方向的反射光
refract(i,n,ri)以i为入射向量,n为法线方向,ri为折射率的折射光
lit(n_dot_I,n_dot_h, m)输入标量(normal, light, 半角向量h,镜面反射系数m),返回光照向量 vec4(环境光,漫反射光,镜面高光反射, 1)(Blinn模型)
faceforward(n,i,ng)得到面向视图方向的曲面法向量。输入输出为同元向量,返回-n*sign(dot(i,ng)) (normal,light,normal)

纹理查找

函数分类

关于ddx、ddy的介绍:《GPU编程与CG语言之阳春白雪下里巴人》 第 91 页

微分类

  • 函数 ddx 和 ddy 返回相邻像素的属性差值;
  • 如果函数 ddx 和 ddy 的输入参数为常数,则函数返回值永远为 0。
  • 在选择mipmap的level时,会用到偏导数

避免在条件分支中使用ddx 和 ddy 的计算依赖于2x2像素块内的所有像素执行相同的代码。如果它们被放在 if 分支中,导数结果将是未定义的,可能导致画面出现奇怪的条纹或错误。

投影类

将纹理当做一张幻灯片投影到场景中,使用投影纹理技术需要计算投影纹理坐标,然后使用投影纹理坐标进行查询。使用投影纹理坐标进行查询的函数就是投影纹理查询函数。

投影纹理: 《GPU编程与CG语言之阳春白雪下里巴人》 第 137 页

Mipmap类

  • lod采样一张mipmap
  • bias偏置后再采样 (由t,w决定)
  • grad使用微分来选择mip的层,进行采样

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,ddx,ddy)使用微分并指定MIP层的三维纹理查找
tex3Dproj(s, t)把纹理当做一张幻灯片投影到场景中,先使用投影纹理技术需要计算出投影纹理坐标t(坐标t.w除以透视值),然后使用投影纹理坐标进行查询

立体纹理查找

立方体贴图。 https://docs.microsoft.com/en-us/windows/win32/direct3d9/cubic-environment-mapping

函数作用
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)使用投影方式的立方体纹理查找

-作业-

1.写出你觉得最常用的5个函数。

step, smoothstep, clamp, saturate, normalize

2.ddx, ddy的实际使用测试。

屏幕后处理,使用 ddx,ddy 输出法线变化大的像素。

为什么会有断裂?

ddx 和 ddy 是通过比较当前像素与相邻像素(2×2 块内)的值来计算的。当边缘恰好位于两个物体之间时:

  • 如果边缘正好穿过 2×2 像素块,那么块内既有前景也有背景像素,导数会非常大(前景法线与背景法线差异大),因此边缘会高亮。
  • 但如果边缘比较锐利且恰好与像素边界对齐,导致整个 2×2 块都落在同一物体上,那么导数就不会检测到突变。这会产生“断断续续”的高亮,看起来不连续。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
fixed4 frag(v2f i) : SV_Target{
fixed3 normal = DecodeViewNormalStereo(tex2D(_CameraDepthNormalsTexture,i.uv));
float3 normalView = normal * 0.5 + 0.5;

float3 dx = ddx(normal);
float3 dy = ddy(normal);

// 计算变化率的长度(大小)
float diffX = length(dx);
float diffY = length(dy);
float diff = max(diffX, diffY); // 取两个方向中最大的变化量

// 将变化量映射到颜色(钳制到0-1范围)
// 为了更容易观察,可以适当缩放,比如乘以一个系数让边缘更亮
float intensity = saturate(diff * 5.0); // 系数5可以调整
intensity = diff;

return fixed4(intensity, intensity, intensity, 1.0);
// return n_col;
}
  • 标题: 笔记08 图形 2.3 HLSL常用函数介绍
  • 作者: 铁名_IronName
  • 创建于 : 2026-02-15 16:52:00
  • 更新于 : 2026-02-24 10:13:14
  • 链接: https://blog.ironname.top/2026/02/15/笔记08-技术美术百人计划/
  • 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。
评论