I'm sampling a R16_UINT image in the shader with a usampler2D. I do:
uvec4 upix_color = texture(usampler2D(utextures[nonuniformEXT(idx_of_height_map)], samplers[0]), result.uvs);
But it seems the values do not come back filtered/interpolated, as this image shows:
I know that an R16 grayscale image can also be R16_UNORM, in which case it's read as a normalised float, and I know that integers may be harder to interpolate, but integers in the range 0 to 65,535 should be able to be interpolated.
In OpenGL, interpolation (linear filtering) is not supported for integer textures. In fact, trying to configure this would result in an incomplete texture. From the OpenGL 4.5 specification, Section 8.17:
Using the preceding definitions, a texture is complete unless any of the following conditions hold true:
- ...
- The internal format of the texture is integer (see table 8.12) [...] and either the magnification filter is not
NEAREST
, or the minification filter is neitherNEAREST
norNEAREST_MIPMAP_NEAREST
.- ...
(Text reordered for clarity.)
In other words, for integer textures, the filtering parameters must be set to nearest neighbor filtering.
This is also expressed on the Khronos website in less techincal terms:
Integer color formats [...] do not support linear filtering. As such, the
GL_TEXTURE_MAG_FILTER
sampling parameter must beGL_NEAREST
, andGL_TEXTURE_MIN_FILTER
must be eitherGL_NEAREST
orGL_NEAREST_MIPMAP_NEAREST
.
In Vulkan, an implementation may support interpolation (linear filtering) for integer textures, but it is not required to. From the Vulkan 1.4.310 specification, Section 48.3:
Implementations must support at least the following set of features on the listed formats. For images, these features must be supported for every
VkImageType
[...].
...
The following tables show which feature bits must be supported for each format.
In the table that follows, it shows that VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT
(i.e. support for linear filtering) is not supported for integer image formats, including VK_FORMAT_R16_UINT
.
In theory, you could use GetPhysicalDeviceFormatProperties
to query whether interpolation is available on the implementation. However, I would expect this to (almost) never be the case, as floating point interpolation for textures is typically implemented in hardware, but integer interpolation isn't.