转自:https://unity.cn/projects/unity-hdrp-custom-pass-post-processing-hou-chu-li-te-xiao-xue-xi-er-zong-jie
ddx/ddy
ddx
返回指定值相对于屏幕空间x坐标的偏导数。
ddy
返回指定值相对于屏幕空间y座标的偏导数。
计算方法
在三角形光栅化过程中,GPU一次运行许多片段着色器的实例,将它们组织成2×2像素的块。dFdx是将块中像素值的差值减去块左侧的像素值和右侧的像素值,dFdy是将底部像素的值减去顶部像素的值。请看下面的图片,其中网格表示渲染的屏幕像素,dFdx、dFdy表达式是为由片段着色器实例在(x、y)屏幕坐标处计算的通用值p提供的,属于2×2块的红色高亮显示的2×2块。导数可以对片段着色器中的每个变量进行计算。
对于向量和矩阵类型,导数是按元素计算的。
值得注意的是图上是以glsl中的dFdx和dFdy进行讲解,实际上Unity中使用的是hlsl中的ddx和ddy,并且是以左下角为坐标原点。其次,既然ddx和ddy是像图中一样,ddx(p(x,y))=p(x+1,y)-p(x,y),ddy(p(x,y))=p(x,y+1)-p(x,y)。对于显卡内部计算这个2x2块,并不知道旁边的2x2块的数据,那么他是怎么计算ddx(p(x+1,y))、ddx(p(x,y+1))、ddx(p(x+1,y+1))、ddy(p(x+1,y))、ddy(p(x,y+1))、ddy(p(x+1,y+1))的呢?
怀着这个疑问,进行了测试与探讨,最终得出结论,2x2块中,4个像素的ddx共享一个值,4个像素的ddy共享一个值。ddx只与p(x,y)、p(x+1,y)有关,ddy只与p(x,y)、p(x,y+1)有关。无论ddx与ddy都与p(x+1,y+1)无关。
例子:
float3 dpdx = ddx(i.worldPos); // 得到自身片元与x方向上的相邻片元之间世界坐标的差值
float3 dpdy = ddy(i.worldPos); // 得到自身片元与y方向上的相邻片元之间世界坐标的差值