如何在float和vec4,vec3,vec2之间进行转换?

kya*_*bal 4 opengl-es webgl glsles

这个问题与这里的问题非常相关(如何将vec4 rgba值转换为浮点数?).

已经有一些与此问题相关的文章或问题,但我想知道大多数文章都没有确定哪种类型的浮动值.只要我能想到,下面有一些浮动值包装/拆包公式.

  • 无符号规范化浮点数
  • 签署标准化浮点数
  • 签名远程浮点数(浮点值我可以找到范围限制)
  • 无符号远程浮点数
  • 无符号浮点数
  • 签名浮动

然而,实际上这只是两个案例.其他包装/拆包可以通过这两种方法处理.

  • unsigned ranged float(我可以通过简单的位移来打包/解压缩)
  • 签名浮动

我想将已签名的浮动值打包并解压缩到vec3或vec2中.

对于我的情况,浮动值不能确保标准化,所以我不能使用简单的位移方式.

gma*_*man 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);
}
Run Code Online (Sandbox Code Playgroud)

要把它放回去,你会做相反的事情.组装零件,除以返回零到一个值,然后按范围扩展.

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;
}
Run Code Online (Sandbox Code Playgroud)

对于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;
}
Run Code Online (Sandbox Code Playgroud)

  • 在 packFloatInto... 函数中有两个拼写错误: 在 return 语句中应该使用 `zeroTo16Bit` 和 `zeroTo24Bit`。 (2认同)

Ent*_*ack 5

几天前我用 shadertoy 写了一个小例子:https ://www.shadertoy.com/view/XdK3Dh

它将浮点数存储为 RGB 或从像素加载浮点数。还有一个测试函数是精确的逆函数(我见过的许多其他函数由于精度差而在某些范围内存在错误)。

整个示例假设您想将值保存在缓冲区中并在下一次绘制时将其读回。只有 256 种颜色,它限制您获得 16777216 个不同的值。大多数时候我不需要更大的规模。我还将它转移到在区间 <-8388608;8388608> 中插入的签名浮点数。

float color2float(in vec3 c) {
    c *= 255.;
    c = floor(c); // without this value could be shifted for some intervals
    return c.r*256.*256. + c.g*256. + c.b - 8388608.;
}

// values out of <-8388608;8388608> are stored as min/max values
vec3 float2color(in float val) {
    val += 8388608.; // this makes values signed
    if(val < 0.) {
        return vec3(0.);
    }
    if(val > 16777216.) {
        return vec3(1.);
    }
    vec3 c = vec3(0.);
    c.b = mod(val, 256.);
    val = floor(val/256.);
    c.g = mod(val, 256.);
    val = floor(val/256.);
    c.r = mod(val, 256.);
    return c/255.;
}
Run Code Online (Sandbox Code Playgroud)

还有一件事,溢出的值将四舍五入为最小值/最大值。