此问题与此处的问题(How do I convert a vec4 rgba value to a float?)非常相关。
已经有一些与此问题相关的文章或问题,但我想知道大多数文章都没有确定哪种类型的浮动值。 只要我能想到,下面有一些浮动值包装/拆包公式。
然而,实际上这只是2个案例。其他包装/拆包可以通过这两种方法进行处理。
我想将已签名的浮动值打包并解压缩到vec3或vec2中。
对于我的情况,浮动值不能保证标准化,所以我不能使用简单的位移方式。
答案 0 :(得分:7)
如果您知道要存储的最大值范围,比如说+5到-5,那么最简单的方法就是选择一些转换范围为0到1的值。将其扩展为位数你有,然后把它分成几部分。
vec2 packFloatInto8BitVec2(float v, float min, float max) {
float zeroToOne = (v - min) / (max - min);
float zeroTo16Bit = zeroToOne * 256.0 * 255.0;
return vec2(mod(zeroToOne, 256.0), zeroToOne / 256.0);
}
要把它放回去你做相反的事情。组装零件,除以返回零点值,然后按范围扩展。
float unpack8BitVec2IntoFloat(vec2 v, float min, float max) {
float zeroTo16Bit = v.x + v.y * 256.0;
float zeroToOne = zeroTo16Bit / 256.0 / 255.0;
return zeroToOne * (max - min) + min;
}
对于vec3,只需展开它
vec3 packFloatInto8BitVec3(float v, float min, float max) {
float zeroToOne = (v - min) / (max - min);
float zeroTo24Bit = zeroToOne * 256.0 * 256.0 * 255.0;
return vec3(mod(zeroToOne, 256.0), mod(zeroToOne / 256.0, 256.0), zeroToOne / 256.0 / 256.0);
}
float unpack8BitVec3IntoFloat(vec3 v, float min, float max) {
float zeroTo24Bit = v.x + v.y * 256.0 + v.z * 256.0 * 256.0;
float zeroToOne = zeroTo24Bit / 256.0 / 256.0 / 256.0;
return zeroToOne * (max - min) + min;
}
答案 1 :(得分:3)
我几天前用shadertoy写了一个小例子: https://www.shadertoy.com/view/XdK3Dh
它将float存储为RGB或从像素加载浮点数。还有测试函数是精确的反转(由于精度差,我见过的很多其他函数在某些范围内都有bug)。
整个示例假设您要在缓冲区中保存值并在下一次绘制中将其读回。只有256种颜色,它限制您获得16777216个不同的值。大多数时候我不需要更大的规模。我也把它移到了间隔< -8388608; 8388608>中的签名浮点数。
(function (el) {
var ship = $("<div class='ship' id='saleShip'></div>");
el.append(ship);
setTimeout(function () {
ship.remove();
}, 5000);
}($('#saleShipHolder')));
还有一件事,溢出的值将四舍五入为最小值/最大值。
答案 2 :(得分:2)
为了在vec3
,vec4
或minVal
中打包浮点值,必须限制并明确指定源值的范围,或者指数必须以某种方式存储。
一般来说,如果浮点数的有效数字应以字节为单位,则必须从有效数字中提取连续的8位数据包,并且必须将其存储在一个字节中。
必须定义值范围[maxVal
,minVal
],其中包括要编码的所有值,并且值范围必须映射到[0.0,1.0]的范围。
将[maxVal
,vec2
]范围内的浮点数编码为vec3
,vec4
和vec2 EncodeRangeV2( in float value, in float minVal, in float maxVal )
{
value = clamp( (value-minVal) / (maxVal-minVal), 0.0, 1.0 );
value *= (256.0*256.0 - 1.0) / (256.0*256.0);
vec3 encode = fract( value * vec3(1.0, 256.0, 256.0*256.0) );
return encode.xy - encode.yz / 256.0 + 1.0/512.0;
}
vec3 EncodeRangeV3( in float value, in float minVal, in float maxVal )
{
value = clamp( (value-minVal) / (maxVal-minVal), 0.0, 1.0 );
value *= (256.0*256.0*256.0 - 1.0) / (256.0*256.0*256.0);
vec4 encode = fract( value * vec4(1.0, 256.0, 256.0*256.0, 256.0*256.0*256.0) );
return encode.xyz - encode.yzw / 256.0 + 1.0/512.0;
}
vec4 EncodeRangeV4( in float value, in float minVal, in float maxVal )
{
value = clamp( (value-minVal) / (maxVal-minVal), 0.0, 1.0 );
value *= (256.0*256.0*256.0 - 1.0) / (256.0*256.0*256.0);
vec4 encode = fract( value * vec4(1.0, 256.0, 256.0*256.0, 256.0*256.0*256.0) );
return vec4( encode.xyz - encode.yzw / 256.0, encode.w ) + 1.0/512.0;
}
:
vec2
将vec3
,vec4
和minVal
解码为[maxVal
,float DecodeRangeV2( in vec2 pack, in float minVal, in float maxVal )
{
float value = dot( pack, 1.0 / vec2(1.0, 256.0) );
value *= (256.0*256.0) / (256.0*256.0 - 1.0);
return mix( minVal, maxVal, value );
}
float DecodeRangeV3( in vec3 pack, in float minVal, in float maxVal )
{
float value = dot( pack, 1.0 / vec3(1.0, 256.0, 256.0*256.0) );
value *= (256.0*256.0*256.0) / (256.0*256.0*256.0 - 1.0);
return mix( minVal, maxVal, value );
}
float DecodeRangeV4( in vec4 pack, in float minVal, in float maxVal )
{
float value = dot( pack, 1.0 / vec4(1.0, 256.0, 256.0*256.0, 256.0*256.0*256.0) );
value *= (256.0*256.0*256.0) / (256.0*256.0*256.0 - 1.0);
return mix( minVal, maxVal, value );
}
]范围内的浮点数:
vec2
注意,由于标准的32位IEEE 754号码只有24位有效数字,因此将数字编码为3个字节就足够了。
将浮点数及其指数的有效数字编码为vec3
,vec4
和vec2 EncodeExpV2( in float value )
{
int exponent = int( log2( abs( value ) ) + 1.0 );
value /= exp2( float( exponent ) );
value = (value + 1.0) * 255.0 / (2.0*256.0);
vec2 encode = fract( value * vec2(1.0, 256.0) );
return vec2( encode.x - encode.y / 256.0 + 1.0/512.0, (float(exponent) + 127.5) / 256.0 );
}
vec3 EncodeExpV3( in float value )
{
int exponent = int( log2( abs( value ) ) + 1.0 );
value /= exp2( float( exponent ) );
value = (value + 1.0) * (256.0*256.0 - 1.0) / (2.0*256.0*256.0);
vec3 encode = fract( value * vec3(1.0, 256.0, 256.0*256.0) );
return vec3( encode.xy - encode.yz / 256.0 + 1.0/512.0, (float(exponent) + 127.5) / 256.0 );
}
vec4 EncodeExpV4( in float value )
{
int exponent = int( log2( abs( value ) ) + 1.0 );
value /= exp2( float( exponent ) );
value = (value + 1.0) * (256.0*256.0*256.0 - 1.0) / (2.0*256.0*256.0*256.0);
vec4 encode = fract( value * vec4(1.0, 256.0, 256.0*256.0, 256.0*256.0*256.0) );
return vec4( encode.xyz - encode.yzw / 256.0 + 1.0/512.0, (float(exponent) + 127.5) / 256.0 );
}
:
vec2
将vec3
,vec4
和float DecodeExpV2( in vec2 pack )
{
int exponent = int( pack.z * 256.0 - 127.0 );
float value = pack.x * (2.0*256.0) / 255.0 - 1.0;
return value * exp2( float(exponent) );
}
float DecodeExpV3( in vec3 pack )
{
int exponent = int( pack.z * 256.0 - 127.0 );
float value = dot( pack.xy, 1.0 / vec2(1.0, 256.0) );
value = value * (2.0*256.0*256.0) / (256.0*256.0 - 1.0) - 1.0;
return value * exp2( float(exponent) );
}
float DecodeExpV4( in vec4 pack )
{
int exponent = int( pack.w * 256.0 - 127.0 );
float value = dot( pack.xyz, 1.0 / vec3(1.0, 256.0, 256.0*256.0) );
value = value * (2.0*256.0*256.0*256.0) / (256.0*256.0*256.0 - 1.0) - 1.0;
return value * exp2( float(exponent) );
}
解码为浮点数及其指数的有效数字:
{{1}}
另见以下问题的答案:
答案 3 :(得分:1)
我测试了gman的解决方案,发现比例因子不正确,并且会产生舍入误差,如果要将结果存储在RGB纹理中,则需要除以255.0。这是我修改后的解决方案:
#define SCALE_FACTOR (256.0 * 256.0 * 256.0 - 1.0)
vec3 packFloatInto8BitVec3(float v, float min, float max) {
float zeroToOne = (v - min) / (max - min);
float zeroTo24Bit = zeroToOne * SCALE_FACTOR;
return floor(
vec3(
mod(zeroTo24Bit, 256.0),
mod(zeroTo24Bit / 256.0, 256.0),
zeroTo24Bit / 256.0 / 256.0
)
) / 255.0;
}
float unpack8BitVec3IntoFloat(vec3 v, float min, float max) {
vec3 scaleVector = vec3(1.0, 256.0, 256.0 * 256.0) / SCALE_FACTOR * 255.0;
float zeroToOne = dot(v, scaleVector);
return zeroToOne * (max - min) + min;
}
示例: