Floating point 像素值在DirectX 11 HLSL着色器中的行为如何?
在像素着色器中采样texel值时,采样器始终返回float4。但是,纹理本身可能包含基于DXGI_格式的多种格式中的任何一种。任何_UNORM格式都将确保float4中的所有值都在0和1之间,这似乎是相当直截了当的。回到DirectX9时代,人们几乎假设,不管像素格式如何,所有采样值都始终在0到1之间 DirectX 11似乎并非如此。例如,使用DXGI_格式_R32_浮点格式的纹理似乎能够存储任何有效的32位浮点,这从一般角度来看是有意义的,因为您可能根本不使用该纹理(或缓冲区)进行渲染 那么,如果渲染管道没有使用0到1的范围,那么在R32_FLOAT这样的任意范围内,渲染管道如何计算出输出的像素值呢?它似乎不是-FLT_MAX到+FLT_MAX,因为我可以使用0.0-65.0之间的值渲染这种类型的纹理,并且在最终结果中看到红色。但调试像素着色器并查看源纹理时,只有真正接近65.0的值才会显示为红色。不过,在后缓冲区上的最终渲染结果中有很多红色 以下是一个示例源纹理,如VS graphics debugger中所示: 如果我仅使用像素着色器的基本采样器输出将其渲染到屏幕上,我会得到以下结果: 后台缓冲区格式为R10G10B10A10_UNORM 那么它是如何决定浮点纹理的“最大强度”的呢?同样,如果您使用了一种_SINT格式,它是如何处理的?Floating point 像素值在DirectX 11 HLSL着色器中的行为如何?,floating-point,directx-11,hlsl,pixel-shader,Floating Point,Directx 11,Hlsl,Pixel Shader,在像素着色器中采样texel值时,采样器始终返回float4。但是,纹理本身可能包含基于DXGI_格式的多种格式中的任何一种。任何_UNORM格式都将确保float4中的所有值都在0和1之间,这似乎是相当直截了当的。回到DirectX9时代,人们几乎假设,不管像素格式如何,所有采样值都始终在0到1之间 DirectX 11似乎并非如此。例如,使用DXGI_格式_R32_浮点格式的纹理似乎能够存储任何有效的32位浮点,这从一般角度来看是有意义的,因为您可能根本不使用该纹理(或缓冲区)进行渲染 那么
- 如果对纹理进行采样,则返回的值不会限制在任何特定范围内。如果纹理格式可以包含0..1范围之外的值,则采样/加载方法将不更改地返回这些值
- 当像素着色器返回值时,该返回值将被钳制到渲染目标支持的任何范围。如果在R32_浮点上渲染,渲染值将不会被钳制,“有效范围”实际上是-FLT_MAX到+FLT_MAX。VS图形调试器然后仅根据纹理中实际存储的最低值和最高值在某个范围内显示纹理,因此您可以在调试器中以有意义的方式查看纹理。另一方面,您的后缓冲区格式使用UNORM格式,因此它只能包含0..1范围内的值,这意味着每个大于1的值都将被钳制为1,这就是为什么屏幕上有这么多是红色的