试图在JavaScript
中将标准化浮点数编码为rgba数组(四个0-255整数值)。具体而言,我正在尝试移植此GLSL
代码:
vec4 packFloatToVec4i(const float value) {
const vec4 bitSh = vec4(256.0*256.0*256.0, 256.0*256.0, 256.0, 1.0);
const vec4 bitMsk = vec4(0.0, 1.0/256.0, 1.0/256.0, 1.0/256.0);
vec4 res = fract(value * bitSh);
res -= res.xxyz * bitMsk;
return res;
}
应该相当简单,但我仍然很难使用按位操作
据我所知,将vec4 bitSh
应用于值相当于在[value << 24, value << 16, value << 8, value]
中执行JS
而且我认为我理解比特移位和掩蔽作为一个概念应该做什么,但它对我来说仍然看起来像黑魔法。
预期结果:
packFloatToVec4i(0.4242) = [0,95,151,108]
packFloatToVec4i(0.108108) = [64,246,171,27]
更新 - 我尝试以粗略的形式重现没有位移操作符会产生奇怪的结果:
value = 0.4242
bitSh = [256.0*256.0*256.0, 256.0*256.0, 256.0, 1.0]
bitMsk = [0.0, 1.0/256.0, 1.0/256.0, 1.0/256.0]
res = bitSh.map(function(sh){return (sh*value)%1})
masked = [res[0]*bitMsk[0],res[0]*bitMsk[1],res[1]*bitMsk[2],res[2]*bitMsk[3]]
resres = res.map(function(r,i){return r - masked[i]});
console.log(resres) => [0.0272000003606081, 0.37109375, 0.59375, 0.421875]
顺便说一句,如果我将所有这些乘以255 - gba
部分(rgba
)似乎匹配预期结果(如果舍入)r
- 不是。 :\
你能帮我理解这里发生了什么,并在JS中复制这个吗?
答案 0 :(得分:0)
我已经建立了一个工作端口:
function packFloatToVec4i(value) {
value = new Float32Array([value])[0];
var msk = 1/256;
var bitSh = [16777216, 65536, 256.0, 1.0];
var bitMsk = [0.0, msk, msk, msk];
var shifted = [value*bitSh[0]%1,value*bitSh[1]%1,value*bitSh[2]%1,value*bitSh[3]%1];
var masked = [shifted[0]*bitMsk[0],shifted[0]*bitMsk[1],shifted[1]*bitMsk[2],shifted[2]*bitMsk[3]];
var res = [Math.round((shifted[0]-masked[0])*255),Math.round((shifted[1]-masked[1])*255),Math.round((shifted[2]-masked[2])*255),Math.round((shifted[3]-masked[3])*255)];
return res;
};
与我发布的问题的差异是输入值的双重转换。如果没有它,由于GLSL中的浮点值的函数这一事实导致结果失效 此外,为了提高性能,我还展开了我的.map循环。
关于bitshift操作,似乎在内部,在JS中,它们应用的任何值 - 转换为32位整数,这有效地删除了任何小数信息。因此,在这种情况下,位移操作似乎不可能。
纠正我,如果我错了,可以在这里使用位移/屏蔽,但就目前而言,这将有所帮助。