我想在一个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也会很好,因为重新映射到着色器内的任何范围都很便宜.重要的是保持尽可能高的精度.负值并不重要.
根据 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 偷工减料,结果可能会更糟糕。
无论如何,我不知道这是否是最好的算法,但它似乎适合我的情况。
| 归档时间: |
|
| 查看次数: |
3873 次 |
| 最近记录: |