将 2 个单浮点数存储在一个浮点数中

Jam*_*oux 4 c# c++ floating-point encoding glsl

我读过几个讨论在一个浮点数中存储 2 或 3 个浮点数的链接。这是一个例子:

将两个浮点值存储在单个浮点变量中

另一个:

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

还有另一个:

在 glsl 中将 RGB 值解码为单个浮点数,无需进行位移位

我见过其他人,但他们都使用相同的原理。如果要对 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 + "]")
    )
)
Run Code Online (Sandbox Code Playgroud)

dx 每次都是 0.0。有人能解释一下吗?注意:无论我设置 cp = 128、256、512 还是其他都没关系。它仍然给我相同类型的结果。

Mar*_*som 6

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


bek*_*kce 5

下面是C 语言的工作代码,用于将两个floats 打包为一个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;
}
Run Code Online (Sandbox Code Playgroud)