9

我正在编写一个着色器(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位。

4

2 回答 2

1

喜欢您的 3 个组件的示例代码,将它们打包到 s=significand 中,然后执行 exp2(color.g)(1+s) 将其他组件打包到指数中。你仍然会失去精度,但它不会像你试图将所有东西都打包到有效数字中那样糟糕,就像你似乎正在做的那样。

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

于 2011-02-05T10:50:31.823 回答
1

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

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

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

于 2011-01-29T19:03:20.567 回答