微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

像素值在 DirectX 11 HLSL 着色器中的表现如何?

如何解决像素值在 DirectX 11 HLSL 着色器中的表现如何?

在像素着色器中采样纹素值时,采样器总是返回一个 float4。但是,纹理本身可能包含基于 dxgi_FORMAT 的多种格式中的任何一种。任何 _UnorM 格式都可以确保 float4 中的所有值都在 0 和 1 之间,这似乎相当简单。回到 DirectX9 时代,人们几乎假设,无论像素格式如何,所有值采样将始终介于 0 和 1 之间。

DirectX 11 似乎不是这种情况。例如,使用 dxgi_FORMAT_R32_FLOAT 格式的纹理似乎能够存储任何有效的 32 位浮点数,从一般的角度来看这确实有意义,因为您可能没有使用用于渲染的纹理(或缓冲区)。

那么,如果 R32_FLOAT 之类的东西有这样一个任意范围,如果它不使用 0 到 1 范围,那么渲染管道如何确定输出的像素值呢?它似乎不是 -FLT_MAX 到 +FLT_MAX,因为我可以使用 0.0-65.0 之间的值渲染这种类型的纹理,并且我在最终结果中看到红色。但是调试像素着色器并查看源纹理,只有真正接近 65.0 的值才实际显示为红色。但是,后台缓冲区的最终渲染结果中有很多红色。

这是一个示例源纹理,如 VS 图形调试器中所示:

Source R32_Float Texture

如果我仅使用像素着色器的基本采样器输出将其渲染到屏幕,我会得到:

Resulting Image

后台缓冲区格式为 R10G10B10A10_UnorM。

那么它如何决定浮点纹理的“最大强度”是多少?同样,如果您使用其中一种 _SINT 格式,它会如何处理?

解决方法

  • 如果您对纹理进行采样,则返回值不会限制在任何特定范围内。如果纹理格式可以包含 0..1 范围之外的值,Sample/Load 方法将返回这些值不变
  • 当您的像素着色器返回一个值时,该返回值将被限制在您的渲染目标支持的任何范围内。如果您在 R32_FLOAT 上渲染,您的渲染值将不会被限制,并且“有效范围”确实是 -FLT_MAX 到 +FLT_MAX。然后,VS 图形调试器仅根据实际存储在纹理中的最低和最高值在一个范围内显示纹理,因此您可以在调试器中以有意义的方式查看纹理。另一方面,您的后台缓冲区格式使用 UNORM 格式,因此它只能包含 0..1 范围内的值,这意味着每个大于 1 的值都将被限制为 1,这就是为什么这么多你的屏幕是红色的。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。