我有一个从一组 uint 生成的纹理图集。在我的像素着色器中对其进行采样,颜色正确显示。这是相关的HLSL:
Texture2D textureAtlas : register(t8);
SamplerState smoothSampler : register(s9)
{
Filter = MIN_MAG_MIP_LINEAR;
AddressU = Clamp;
AddressV = Clamp;
}
struct PS_OUTPUT
{
float4 Color : SV_TARGET0;
float Depth : SV_DEPTH0;
}
PS_OUTPUT PixelShader
{
// among other things, u and v are calculated here
output.Color = textureAtlas.Sample(smoothSampler, float2(u,v));
}
这很好用。通过颜色处理,我扩展了纹理图集以包含深度信息。我想要的只有几千个深度值,远低于 24 位(我的深度缓冲区是 24 位宽 + 8 位模板)。输入深度值是 uint,就像颜色一样,当然在深度情况下,这些值将分布在四个颜色通道上,并且在着色器中我想要一个介于 0 和 1 之间的浮点数,因此需要从样本计算。这是附加的像素着色器代码:
// u and v are recalculated for the depth portion of the texture atlas
float4 depthSample = textureAtlas.Sample(smoothSampler, float2(u,v));
float depthValue =
(depthSample.b * 65536.0 +
depthSample.g * 256.0 +
depthSample.r)
/ 65793.003921568627450980392156863;
output.Depth = depthValue;
这里的长常量是 16777216/255,它应该将整个 uint 范围映射到一个 unorm。
现在,当我生成纹理时,如果我将深度值限制在 0..2048 的范围内,则输出深度是正确的。但是,如果我允许范围的上限增加(即使它只是通过获取输入值并执行左移 16),那么输出深度将略微偏离。不是很多,只是+/- 0.002,但足以让输出看起来很糟糕。
有人可以在这里发现我的错误吗?或者,更一般地说,有没有更好的方法将 uint 打包和解包到纹理中?
我正在使用着色器模型 4 级别 9_3 和 C++ 11。