将四个字节打包成一个浮点数

Posted

技术标签:

【中文标题】将四个字节打包成一个浮点数【英文标题】:Pack four bytes in a float 【发布时间】:2011-06-16 05:20:25 【问题描述】:

我正在编写一个着色器 (HLSL),我需要将一个颜色值打包成 R32 格式。我发现了各种将浮点数打包成 R8G8B8A8 格式的代码,但它们似乎都没有反向工作。我的目标是 SM3.0,所以(afaik)位操作不是一个选项。

总而言之,我需要能够做到这一点:

float4 color = ...; // Where color ranges from 0 -> 1
float packedValue = pack(color);

有人知道怎么做吗?

更新 我已经取得了一些的进展...也许这将有助于澄清问题。 我的临时解决方案是这样的:

const int PRECISION = 64;

float4 unpack(float value)
   
    float4 color;

    color.a = value % PRECISION;
    value = floor(value / PRECISION);

    color.b = value % PRECISION;
    value = floor(value / PRECISION);

    color.g = value % PRECISION;
    value = floor(value / PRECISION);

    color.r = value;

    return color / (PRECISION - 1);


float pack(float4 color)
   
    int4 iVal = floor(color * (PRECISION - 1));

    float output = 0;

    output += iVal.r * PRECISION * PRECISION * PRECISION;
    output += iVal.g * PRECISION * PRECISION;
    output += iVal.b * PRECISION;
    output += iVal.a;

    return output;

我基本上......假装我正在使用整数类型:s 通过猜测和检查,64 是我可以使用的最高数字,同时仍保持 [0...1] 范围。不幸的是,这也意味着我失去了一些精度 - 6 位而不是 8 位。

【问题讨论】:

最终会被问到的,所以你不妨把它搞定:) 为什么你必须使用 R32 而不是整数格式? 嘿...我知道它会来,但仍然...实际上,我使用的是R32G32B32A32,我只说R32是为了简化。我只是想弄清楚如何将尽可能多的信息推送到单个渲染目标中。当然,我仍然需要进行一些测量,但我想将我的所有数据推送到单个渲染目标中比通过 MRT 使用四个要便宜一些。 我期待看到人们可以为这个问题提供什么答案。 我知道我没有帮助回答你的问题,但我怀疑通过将所有这些工作打包到一个大的渲染目标中而不是仅仅使用 MRT 是否会有所收获。更不用说一些旧硬件(如 Xbox 360)甚至不支持 R32G32B32A32。 这只是一个实验。此外,我讨厌 Xbox :D 【参考方案1】:

看看: http://diaryofagraphicsprogrammer.blogspot.com/2009/10/bitmasks-packing-data-into-fp-render.html

简短的回答是不可能将 4 个浮点数无损打包成 1 个浮点数。

即使您确实找到了打包 4 个浮点数、存储它们的指数和有效数字的方法,打包和解包过程也可能过于昂贵。

【讨论】:

好吧,实际上(正如标题所说)我试图打包四个字节,而不是四个浮点数。虽然我以前看过那个帖子。不幸的是,代码使用位运算符 - 使用 SM3.0 不会发生... :( 您可以用乘法替换位移。例如。 x << 16x *= 2^16 是一回事 哦,虽然他确实使用了位掩码。并且在 SM3.0 中不能使用。 @YellPika,情况与4字节相同。打包时会损失精度。 我不能只做 x * 2^n 因为我正在处理浮点类型,而且我认为它们的工作方式与整数类型不同。另外,浮点数的大小不是和四个字节一样大吗?【参考方案2】:

喜欢您的 3 个组件的示例代码,将它们打包到 s=significand 中,然后执行 exp2(color.g)(1+s) 将其他组件打包到指数中。您仍然会丢失精度,但不会像您尝试将所有内容都打包到有效数字中那样糟糕。

不幸的是,没有办法避免丢失精度,因为有一堆 NaN 和 Inf 浮点值彼此无法区分且难以使用(甚至可能不受 GPU 支持,具体取决于它的使用年限)是)。

【讨论】:

以上是关于将四个字节打包成一个浮点数的主要内容,如果未能解决你的问题,请参考以下文章

组合四个字节并转换为浮点数

怎么将4字节16进制转化成浮点数

SSE1 使用 divps 内在 xmmintrin.h 来划分四个 32 位浮点数并使用 printf?

将字节转换为浮点数?

FLOAT 和 DOUBLE区别

Abplc浮点数怎么传给4个字节