283*_*283 6 shader hlsl data-conversion unity-game-engine
我一直在尝试将 4 个 uint(8 位)编码为一个浮点数,以便我可以轻松地将它们与深度值一起存储在纹理中。我的代码无法正常工作,最终我发现问题归结为:
asuint(asfloat(uint(x))) 在大多数情况下返回 0,而实际上它应该返回 x。
理论上,此代码应该返回 x(其中 x 是整数),因为 x 中的位将被转换为 float,然后返回 uint,因此相同的位最终会再次被解释为 uint。但是,我发现该函数似乎返回 x 的唯一情况是 x 的位被解释为非常大的浮点数。我考虑到这可能是图形驱动程序问题,因此我在两台不同的计算机上进行了尝试,并且在两台计算机上都遇到了相同的问题。
我测试了此代码的其他几个变体,所有这些变体似乎都能正常工作。
asfloat(asuint(float(x))) = x
asuint(asint(uint(x))) = x
asuint(uint(x)) = x
唯一无法按预期工作的情况是本文中提到的第一个情况。这是一个错误,还是我做错了什么?此外,此代码正在 Unity 内部的片段着色器中运行。
经过很长时间的搜索,我找到了某种答案,所以我想我会将其发布在这里,以防其他人偶然发现这个问题。这段代码不起作用的原因与浮点数非规范化有关。(我不完全理解。)无论如何,非规范化浮点数被 asuint 解释为 0,因此非规范化浮点数的 asuint 始终为 0。
一个稍微可接受的解决方案可能是(asuint(asfloat(x | 1073741824)) & 3221225471) 这确保了浮点数标准化,但它也会擦除存储在第二位中的任何数据。如果有人有任何其他解决方案可以保留这一点,请告诉我!