将2个单浮子存储在一个中

时间:2013-12-23 22:49:59

标签: c# c++ encoding floating-point glsl

我已经阅读了几个链接,讨论在一个浮点数中存储2个或3个浮点数。这是一个例子:

Storing two float values in a single float variable

和另一个:

http://uncommoncode.wordpress.com/2012/11/07/float-packing-in-shaders-encoding-multiple-components-in-one-float/

还有另一个:

decode rgb value to single float without bit-shift in glsl

我见过其他人,但他们都使用相同的原则。如果要对x和y进行编码,则将y乘以某个因子,然后将x添加到其中。这就是从纸上开始,但我不明白它在存储到浮动值时如何工作。浮动值只有7位有效数字。如果添加一个大数字和一个小数字,则小数字会被截断并丢失。精度仅显示大数字的值。

由于每个人似乎都开出相同的方法,我自己尝试了它,它完全按照我的想法行事。当我解码数字时,未乘数的数字变为0.0。它在编码的浮点数中完全丢失了。

以下是我尝试测试的一些MaxScript示例:

cp = 256.0 * 256.0
scaleFac = 16777215

for i = 1 to 20 do (
    for j = 1 to 20 do (
            x = (i as float / 20.01f) as float;
            y = (j as float / 20.01f) as float;
            xScaled = x * scaleFac;
            yScaled = y * scaleFac;

            f = (xScaled + yScaled * cp) as float
            print ("x[" + xScaled as string + "] y[" + yScaled as string + "]" + " e[" + f as string + "]")

            dy = floor(f / cp)
            dx = (f - dy * cp)

            print ("x[" + dx as string + "] y[" + dy as string + "]" + " e[" + f as string + "]")
    )
)

dx每次都是0.0。任何人都可以对此有所了解吗?注意:无论我是否制作cp = 128,256,512或其他什么都没关系。它仍然给我相同类型的结果。

4 个答案:

答案 0 :(得分:3)

此方法适用于存储两个整数。您通过乘以scaleFac有效地将浮点数转换为大整数,这很好,但最好使用int()将其显式化。然后,您需要确定两件事:cp大于您正在使用的最大数字(scaleFac),cp的平方小到足以适合没有截断的浮点数(单精度浮点数约为7位)。

答案 1 :(得分:1)

以下是 C 中的工作代码,用于将两个float打包到一个float中并解压缩。

您应根据可能的值范围(scaleFactor)更改cpyourBiggestNumber * scaleFactor < cp参数。这是一场精准的战斗。尝试打印一些结果,为您的案例找到合适的价值。以下示例允许[0 to 1)范围内的浮点数。

#include <math.h>

/* yourBiggestNumber * scaleFactor < cp */
double scaleFactor = 65530.0;
double cp = 256.0 * 256.0;

/* packs given two floats into one float */
float pack_float(float x, float y) {
    int x1 = (int) (x * scaleFactor);
    int y1 = (int) (y * scaleFactor);
    float f = (y1 * cp) + x1;
    return f;
}

/* unpacks given float to two floats */
int unpack_float(float f, float* x, float* y){
  double dy = floor(f / cp);
  double dx = f - (dy * cp);
  *y = (float) (dy / scaleFactor);
  *x = (float) (dx / scaleFactor);
  return 0;
}

答案 2 :(得分:0)

只有当你的个人花车足够小以便装入一个漂浮位置时,它才会起作用。

所以你可以把2个数字“分”成两个来存储2个数字,这些数字可以用一半的空间来表示。

答案 3 :(得分:0)

这是我用于打包和解包浮动的代码。它的工作原理是将第一个浮点数(0..1)打包到8位(0..256)数字的前四个字节中,然后将下一个浮点数打包到剩余的4个位中。得到的数字各有16种可能的组合(2 ^ 4)。在某些情况下,这已经足够了:

private float PackFloatsInto8Bits( float v1, float v2 )
{
    var a = Mathf.Round( v1 * 15f );
    var b = Mathf.Round( v2 * 15f );

    var bitShiftVector = new Vector2( 1f/( 255f/16f ), 1f/255f );

    return Vector2.Dot( new Vector2( a, b ), bitShiftVector );
}

private Vector2 UnpackFloatsFrom8Bits( float input )
{
    float temp = input * 15.9375f;

    float a = Mathf.Floor(temp) / 15.0f;
    float b = Frac( temp ) * 1.0667f;

    return new Vector2(a, b);
}