这章介绍在片元shader中计算导数近似值的技术。这个技术把特别的值载入纹理mipmap的每个级别,以特殊的方式使用纹理映射硬件,计算出导数的结果,给出在屏幕上的像素间某个量的变化率。
Cg标准程序库提供ddx和ddy函数,计算任意关于x和y像素的导数,但是有些硬件不支持这些导数的计算(至少在写这本书的时候),本文提供了一个解决方案,可以基于纹理映射功能解决这个问题。
在程序纹理中需要特别注意shader的反走样,大致来说,不应该在单个点上计算程序函数的值,而是在面积上计算函数的平均值,更准确的说,就是要计算函数在当前像素和邻近像素之间的平均值。
用导数函数计算过滤宽度:
float filterwidth(float2 v) {float2 fw = max(abs(ddx(v)), abs(ddy(v)));return max(fw.x, fw.y); }
用纹理计算过滤宽度:用函数tex2D()所做的纹理贴图查询,可以自动地对纹理查询进行反走样,即使真实纹理坐标的像素异常地变化,适当过滤的纹理值还是能在每个像素的地方返回。基于在相邻像素上所计算的纹理坐标,硬件可以为每个查询决定过滤的纹理面积。我们以这样一种方式进行纹理查询:(1)为特定的纹理坐标租选择mipmap级别(2)利用这一点决定过滤宽度
先将宽度信息写入纹理中
再从根据输入的uv信息读出宽度信息
uniform sampler2D filterMap;float filterwidth(float2 uv) {float log2width = (255./16.) * tex2D(filterMap, uv).x;return exp2(-log2width); }