【问题标题】:Sampling values in fragment shader from a R16_UINT-3D texture in Vulkan从 Vulkan 中的 R16_UINT-3D 纹理对片段着色器中的值进行采样
【发布时间】:2026-01-12 01:55:02
【问题描述】:

我正在使用 Sascha Willems 的纹理教程,它可以正常工作。然后我将纹理从 2D 纹理更改为 3D 纹理无符号 16 位。

我设置了正确的深度,然后更改了这些值:

VK_FORMAT_BC3_UNORM_BLOCK -> VK_FORMAT_R16_UINT
VK_IMAGE_TYPE_2D -> VK_IMAGE_TYPE_3D
and just one component ->   view.components = { VK_COMPONENT_SWIZZLE_R };

在着色器中:

sampler2D -> sampler3D

但是我从 texture(volumeTexture, textPos).r 得到的所有值现在都为零。 我想要做的是上传一个 UINT16 图像,但从片段着色器将其采样为浮点数。

如果我打开 RenderDoc,纹理看起来不错。

pastie.org/private/i7dqw7pm0snkbf40eyywg

这是我在opengl中所做的:

  const auto& glType           = GL_SHORT;
  const auto& glFormat         = GL_LUMINANCE;
  const auto& glInternalFormat = GL_LUMINANCE16F_ARB;
  const auto& glClampMode      = GL_CLAMP_TO_EDGE;

【问题讨论】:

  • “将其采样为浮点数”是什么意思?作为什么种类的浮动? 16 位 IEEE-754 浮点数? 16 位无符号归一化定点?

标签: c++ glsl textures vulkan


【解决方案1】:

这是我在opengl中所做的:

OpenGL 的pixel transfer functionality 需要接受不愉快或缓慢的事情。 Vulkan 没有。

您在 OpenGL 中所做的是强制驱动程序将每个像素从 16 位无符号 normalized fixed-point value 转换为 16-bit IEEE-754 floating-point value。几乎可以肯定,这种转换是在 CPU 上完成的。

Vulkan 没有辅助轮,Vulkan 驱动程序不会为您工作。 Vulkan 有格式,规范准确地说明了它们的含义。如果您的数据与您最终要使用的格式不匹配,则由您进行转换。

【讨论】:

  • 这就解释了一切,现在它可以工作了。谢谢
【解决方案2】:

您能补充更多信息吗? “从纹理读取”是指在片段着色器中采样吗?您是否从验证层收到任何错误?您的实现是否支持从 R16_UINT 采样?

如果 RenderDoc 显示您的纹理,但它在您的应用程序中不“可见”,您也可能会错过正确的图像布局过渡,至少在需要它们的硬件上是这样。这也包括正确的子资源范围。

请查看https://www.khronos.org/registry/vulkan/specs/1.0/xhtml/vkspec.html#resources-image-views提供的表格

并确保您的图像和视图参数适合 3D 纹理。

【讨论】:

  • 是的,在片段着色器中采样。我在opengl中所做的是内部格式是USHORT,但纹理的格式是float。因此,当您从纹理中采样时,您会得到浮点值。而且我想我在这里应该做的是,将图像加载为 ushort,然后在 VkImageViewCreateInfo 中将格式设置为 VK_FORMAT_R16_SFLOAT
  • @hidayat: "我在 opengl 中所做的是内部格式是 USHORT 但纹理的格式是浮点数。" ...如果你谈到使用GL_R16 作为OpenGL internal format,等效的Vulkan 格式将是R16_UNORM,而不是R16_UINT