GLES Encode/Decode 32 bits float to 2 16 bits
GLES Encode/Decode 32bits float to 2x16bits
我正在尝试优化纹理内存,所有阻止我将 GL_RGBA32F LUT 转换为 GL_RGBA16F 的因素是(可能)超过限制的一个索引。无论如何,我可以在 C 中获取一个浮点数并将其拆分为 2 个值,然后在 GLSL 中从存储在 LUT 中的 2 个值重建该浮点数吗?
我的意思是这样的:
[C]
float v0,v1, *pixel_array;
magic_function_in_c( my_big_value, &v0, &v1 );
pixel_array[ index++ ] = pos.x; // R
pixel_array[ index++ ] = pos.y; // G
pixel_array[ index++ ] = v0; // B
pixel_array[ index++ ] = v1; // A
[GLSL]
vec4 lookup = texture2D( sampler0, texcoord );
float v = magic_function_in_glsl( lookup.b, lookup.a );
ps:我正在使用 GLES 2.0(也与 WebGL 兼容)
如果您只需要比 float16 提供的范围更大,并且只在一个方向(更大或更小),您可以乘以一个固定的比例因子。
例如,如果您需要某个数字 N,大于 65503,您可以 'encode' 将 N 除以 2,'decode' 乘以 2。这会向上移动有效范围,牺牲 1/N 的范围,但扩大 +/-N 的范围最大值。如果您需要 1/N 比 +/-N 更大的范围,您可以交换乘法和除法。如果您需要它根据数据进行更改,您可以使用第二个值来存储比例因子。
您还可以尝试使用 exp2 和 log2,例如:
void
magic_function_in_c(float fVal, uint16_t* hExponent, uint16_t* hMult)
{
float fExponent = log2f(f);
*hExponent = f32_to_f16(fExponent);
// Compensate for f32->f16 precision loss
float fActualExponent = f16_to_f32(*hExponent);
float fValFromExponent = exp2f(fActualExponent);
float fMult;
if (fValFromExponent != 0.0f) {
fMult = fVal / fValFromExponent;
} else if (fVal < 0.0f) {
fMult = -1.0f;
} else {
fMult = 1.0f
}
*hMult = f32_to_f16(fMult);
}
highp float
magic_function_in_glsl(highp float hExponent, highp float hMult)
{
return exp2(hExponent) * hMult;
}
请注意,如果您的 GLSL 着色器中没有 highp 浮点数,其中的 none 将起作用。
我正在尝试优化纹理内存,所有阻止我将 GL_RGBA32F LUT 转换为 GL_RGBA16F 的因素是(可能)超过限制的一个索引。无论如何,我可以在 C 中获取一个浮点数并将其拆分为 2 个值,然后在 GLSL 中从存储在 LUT 中的 2 个值重建该浮点数吗?
我的意思是这样的:
[C]
float v0,v1, *pixel_array;
magic_function_in_c( my_big_value, &v0, &v1 );
pixel_array[ index++ ] = pos.x; // R
pixel_array[ index++ ] = pos.y; // G
pixel_array[ index++ ] = v0; // B
pixel_array[ index++ ] = v1; // A
[GLSL]
vec4 lookup = texture2D( sampler0, texcoord );
float v = magic_function_in_glsl( lookup.b, lookup.a );
ps:我正在使用 GLES 2.0(也与 WebGL 兼容)
如果您只需要比 float16 提供的范围更大,并且只在一个方向(更大或更小),您可以乘以一个固定的比例因子。
例如,如果您需要某个数字 N,大于 65503,您可以 'encode' 将 N 除以 2,'decode' 乘以 2。这会向上移动有效范围,牺牲 1/N 的范围,但扩大 +/-N 的范围最大值。如果您需要 1/N 比 +/-N 更大的范围,您可以交换乘法和除法。如果您需要它根据数据进行更改,您可以使用第二个值来存储比例因子。
您还可以尝试使用 exp2 和 log2,例如:
void
magic_function_in_c(float fVal, uint16_t* hExponent, uint16_t* hMult)
{
float fExponent = log2f(f);
*hExponent = f32_to_f16(fExponent);
// Compensate for f32->f16 precision loss
float fActualExponent = f16_to_f32(*hExponent);
float fValFromExponent = exp2f(fActualExponent);
float fMult;
if (fValFromExponent != 0.0f) {
fMult = fVal / fValFromExponent;
} else if (fVal < 0.0f) {
fMult = -1.0f;
} else {
fMult = 1.0f
}
*hMult = f32_to_f16(fMult);
}
highp float
magic_function_in_glsl(highp float hExponent, highp float hMult)
{
return exp2(hExponent) * hMult;
}
请注意,如果您的 GLSL 着色器中没有 highp 浮点数,其中的 none 将起作用。