在GPU硬件提供的纹理线性插值中,与具体硬件相关地,插值系数的精度可能相当有限。譬如,CUDA文档明确指出其插值系数以9bits定点数存储(文档链接),其中8bits是分数位。

本文代码

来做个小实验。在Rtrc中构造一个简单的一维纹理,宽度为2,纹素值为[0.0, 1.0]——

const float texData[2] = { 0, 1 };
texture_ = GetDevice()->CreateAndUploadTexture(RHI::TextureDesc
{
    .dim    = RHI::TextureDimension::Tex1D,
    .format = RHI::Format::R32_Float,
    .width  = 2,
    .usage  = RHI::TextureUsage::ShaderResource
}, texData, RHI::TextureLayout::ShaderTexture);

它在PIX中长这样:

center

接下来,我们在屏幕上画一条被细分为1024个小段的水平线段,在shader中用坐标采样这个纹理的中间部分,sampler使用硬件提供的线性插值,把采样结果转换为顶点的坐标。不出所料,画出的结果不是一条从左往右斜向上的直线,而是阶梯状的:

遇到相关问题时,读多个纹素值,然后手工插值即可。