在单个float变量中存储两个float值

Zol*_*anE 7 c# hlsl

我想在一个32位浮点变量中存储两个浮点值.编码将在C#中进行,而解码将在HLSL着色器中完成.

到目前为止,我发现的最佳解决方案是将编码值中的小数偏移硬连接,并将它们存储为"载波"浮点的整数和小数:

123.456 -> 12.3 and 45.6
Run Code Online (Sandbox Code Playgroud)

它无法处理负值,但没关系.

但是我想知道是否有更好的方法来做到这一点.

编辑:有关该任务的更多细节:

我正在使用Unity中的固定数据结构,其中顶点数据存储为浮点数.(Float2表示UV,float3正常,依此类推.)显然没有办法正确添加额外的数据,所以我必须在这些限制范围内工作,这就是为什么我认为这完全是一个更普遍的编码数据问题.例如,我可以牺牲二级UV数据来传输2x2额外数据通道.

目标是着色器模型3.0但我不介意解码是否在SM2.0上合理地工作.

只要它"合理",数据丢失就可以了.预期的值范围是0..64,但是当我想到它时,0..1也会很好,因为重新映射到着色器内的任何范围都很便宜.重要的是保持尽可能高的精度.负值并不重要.

Zol*_*anE 4

根据 Gnietschow 的建议,我改编了YellPika的算法。(这是 Unity 3d 的 C#。)

float Pack(Vector2 input, int precision)
{
    Vector2 output = input;
    output.x = Mathf.Floor(output.x * (precision - 1));
    output.y = Mathf.Floor(output.y * (precision - 1));

    return (output.x * precision) + output.y;
}

Vector2 Unpack(float input, int precision)
{
    Vector2 output = Vector2.zero;

    output.y = input % precision;
    output.x = Mathf.Floor(input / precision);

    return output / (precision - 1);
}
Run Code Online (Sandbox Code Playgroud)

快速而肮脏的测试产生了以下统计数据(0..1 范围内的 100 万个随机值对):

Precision: 2048 | Avg error: 0.00024424 | Max error: 0.00048852
Precision: 4096 | Avg error: 0.00012208 | Max error: 0.00024417
Precision: 8192 | Avg error: 0.00011035 | Max error: 0.99999940
Run Code Online (Sandbox Code Playgroud)

4096 的精度似乎是最佳选择。请注意,这些测试中的打包和解包都在 CPU 上运行,因此如果 GPU 偷工减料,结果可能会更糟糕。

无论如何,我不知道这是否是最好的算法,但它似乎适合我的情况。