将四个字节打包成一个浮点数 [英] Pack four bytes in a float

查看:477
本文介绍了将四个字节打包成一个浮点数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在编写一个着色器(HLSL),并且需要将颜色值打包为R32格式.我发现了用于将浮点数打包为R8G8B8A8格式的各种代码,但它们似乎都没有相反的作用.我的目标是SM3.0,因此(afaik)位操作不是一种选择.

I'm writing a shader (HLSL), and I need to pack a color value into the R32 format. I've found various pieces of code for packing a float into the R8G8B8A8 format, but none of them seem to work in reverse. I'm targeting SM3.0, so (afaik) bit operations are not an option.

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

To sum it up, I need to be able to do this:

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

有人知道该怎么做吗?

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

UPDATE
I've gotten some headway... perhaps this will help to clarify the question.
My temporary solution is as such:

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位.

I'm basically... pretending I'm using integer types :s
Through guess and check, 64 was the highest number I could use while still maintaining a [0...1] range. Unfortunately, that also means I'm losing some precision - 6 bits instead of 8.

推荐答案

对3个组件的示例代码进行处理,以将它们打包到s = significand中,然后对exp2(color.g)(1 + s)进行打包另一部分变成指数.您仍然会失去精度,但不会像尝试将所有东西打包到重要位置那样糟糕.

Do like your sample code for 3 components to pack them into into the s=significand, and do exp2(color.g)(1+s) to pack the other component into the exponent. You'll still lose precision, but it won't be as bad as if you try to pack everything into the significand like you seem to be doing.

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

Unfortunately there's no way to avoid losing precision, as there are a bunch of NaN and Inf float values that are both indistinguishable from each other and hard to work with (and possibly not even supported by your GPU, depending on how old it is).

这篇关于将四个字节打包成一个浮点数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆