You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用usampler2D采样R16_UINT图像时是否支持插值?

采样R16_UINT纹理无插值的问题分析与解决

你用usampler2D采样R16_UINT格式图像时遇到了无插值的问题,代码如下:

uvec4 upix_color = texture(usampler2D(utextures[nonuniformEXT(idx_of_height_map)], samplers[0]), result.uvs);

问题原因

GLSL中的无符号整数采样器(usampler2D)不支持硬件原生的纹理过滤插值。多数GPU的硬件设计中,整数格式纹理的采样仅默认支持最近邻模式,线性插值等过滤操作对整数纹理无效——硬件不会对整数像素值进行插值计算,只会返回距离采样点最近的整数像素。

解决办法

1. 改用R16_UNORM格式(推荐)

将纹理格式改为R16_UNORM,使用普通sampler2D采样,硬件会原生支持线性插值。采样得到的归一化浮点数可再转换回0-65535的整数:

vec4 pix_color = texture(sampler2D(textures[idx_of_height_map], samplers[0]), result.uvs);
uint height_value = uint(pix_color.r * 65535.0);

这种方式性能最优,是最常用的方案。

2. 手动实现整数插值(仅当必须保留R16_UINT时)

如果必须使用R16_UINT格式,只能在着色器中手动计算插值逻辑。以双线性插值为例,步骤为:获取采样点周围4个像素的整数取值,再根据UV的小数部分完成插值:

vec2 uv = result.uvs;
// 获取纹理尺寸
vec2 tex_size = textureSize(utextures[idx_of_height_map], 0);
// 计算纹理坐标的整数部分和小数偏移
vec2 tex_coord = uv * tex_size;
vec2 int_coord = floor(tex_coord);
vec2 frac_coord = fract(tex_coord);

// 采样周围4个像素(需加0.5取像素中心)
uvec4 tl = texture(usampler2D(utextures[idx_of_height_map], samplers[0]), (int_coord + vec2(0.5)) / tex_size);
uvec4 tr = texture(usampler2D(utextures[idx_of_height_map], samplers[0]), (int_coord + vec2(1.5, 0.5)) / tex_size);
uvec4 bl = texture(usampler2D(utextures[idx_of_height_map], samplers[0]), (int_coord + vec2(0.5, 1.5)) / tex_size);
uvec4 br = texture(usampler2D(utextures[idx_of_height_map], samplers[0]), (int_coord + vec2(1.5, 1.5)) / tex_size);

// 双线性插值计算最终值
uint interpolated_r = uint(mix(mix(float(tl.r), float(tr.r), frac_coord.x), mix(float(bl.r), float(br.r), frac_coord.x), frac_coord.y));
// 其他通道同理处理
uvec4 final_color = uvec4(interpolated_r, tl.g, tl.b, tl.a);

注意手动插值会增加着色器计算开销,性能不如原生浮点插值。

内容的提问来源于stack exchange,提问作者Zebrafish

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 00:17:06