如何在GLSL中量化浮点到无符号字节

时间:2016-05-03 07:25:13

标签: c++ opengl floating-point glsl

我在GLSL中使用浮点纹理作为数据缓冲区,需要将数据保存在普通纹理上(每个像素的颜色有1个字节)。在我的情况下,浮点是[-2048.0,2048.0],因此我必须将[-2048.0,2048.0]量化为[0,255]。我认为这个问题的C ++代码就像:

//*quantization*
float fvalue = ... ;  // floating point data
fvalue /= 16.0f;  // [-128.0, 128.0]
fvalue = roundf(fvalue);  // [-128, 128]
if(fvalue > 127.0f) fvalue = 127.0f;
else if(fvalue < -128.0f) fvalue = -128.0f;
u_char byte = (int)fvalue + 128;  // [0, 255]

//*inverse quantization*
u_char byte = ...;  // [0, 255]
float fvalue = byte - 128;  // [-128, 127]
fvalue *= 16.0f;  // [-2048, 2032] (it can't be helped?)

我不确定这段代码是否合适,但我还不确定GLSL中有什么好处(GLSL将字节值[0,255]作为浮点[0.0,1.0]处理)。我的代码是:

//*quantization*
vec3 F = ...;  //F is floating vector [-2048.0, 2048.0]
F /= 16;  // [-128.0, 128.0]
F /= 256;  // [-0.5, 0.5]
F += vec3(0.50f);  // [0.0, 1.0]
gl_FragData[0] = vec4(F, 1.0);

//*inverse quantization*
vec3 F = texture2D(...); //byte data [0.0, 1.0]
F -= vec3(0.50f); //byte data [-0.5, 0.5]
F *= 256; //[-128, 128]
F *= 16; //[-2048, 2048]

这并没有奏效。但是,如果我将代码F += vec3(0.50f);重写为F += vec3(0.51f);,又将F -= vec3(0.50f);重写为F -= vec3(0.51f);,那么它似乎运作良好。但我不认为价值0.51f是合理的。实际上,这在一个硬件中运行良好,而这在另一个硬件中不能很好地工作。  我想知道量化(也是量子化)浮点值的好方法。

2 个答案:

答案 0 :(得分:1)

我可以找到适用的方式&#34;以及#34;。我不敢说我​​无法合理解释为什么它有效,所以我不知道这是否是多功能方法。

dialog.setCancelable(false);

答案 1 :(得分:1)

首先,每个具有1个字节的像素不能充分传达您想要描述的内容。这种所谓的“正常纹理”更准确地称为“无符号标准化”(通常缩写为unorm)。

你想要一个8位的unorm纹理(理想情况下有多个组件);这些是存储定点数据的纹理,当通过将数据标准化为其固有范围进行采样时,将其视为浮点(在[ 0.0 1.0 ]范围内) (例如升级到浮点并除以 255.0 )。

鉴于刚刚描述的内容,您只需将原始数据[ -2048.0 2048.0 ]转换为[ 0.0 1.0 ]然后乘以 255

但这是不太理想的,因为您将无法在没有严重混叠的情况下表示原始范围。相反,乘以 4294967295 256 4 - 1 )并将8位打包成R,8位到G,8位到B和8位到A。你没有尝试在显示的着色器中打包组件。