glsl将两个签名的浮动包装在一起

时间:2014-04-23 14:03:21

标签: opengl-es opengl-es-2.0 glsl

在GLSL ES 2.0中 我想将2个带符号的浮点值打包到alpha通道中。
频道可以是低音或中音。
我怎么能这样做?

P.S。我需要这个用于后处理/解析传递,所以我认为打包/解包开销值得。

2 个答案:

答案 0 :(得分:0)

不幸的是,我不知道在ES 2.0中如何做到这一点(我不相信这是可行的)。

但是,如果您能够使用ES 3.0,那么ES 3.0中有一些新的内置函数可供使用:

highp uint packSnorm2x16(vec2 v)
highp vec2 unpackSnorm2x16(highp uint p)
highp uint packUnorm2x16(vec2 v)
highp vec2 unpackUnorm2x16(highp uint p)

这些将一对浮动包打包并解压缩为有符号或无符号的规范化整数格式,这种格式对于存储而言较小。

还有内置函数可以在mediump(half-float)上运行:

highp uint   packHalf2x16(mediump vec2 v)
mediump vec2 unpackHalf2x16(highp uint v)

您还可以使用ARB_shader_bit_encoding(ES 3.0的一部分)中的函数,结合前面提到的那些或单独实现自己的打包:

genIType floatBitsToInt(genType value)
genUType floatBitsToUint(genType value)

genType intBitsToFloat(genIType value)
genType uintBitsToFloat(genUType value)

它们执行从浮点到整数类型的位转换。

ES 3.0与ES 2.0向后兼容(以某些极端情况为模)。障碍是您所定位的硬件是否可以执行ES 3.0。祝你好运!

答案 1 :(得分:0)

来自Unity's UnityCG.cginc

// Encoding/decoding [0..1) floats into 8 bit/channel RGBA. Note that 1.0 will not be encoded properly.
inline float4 EncodeFloatRGBA( float v )
{
    float4 kEncodeMul = float4(1.0, 255.0, 65025.0, 160581375.0);
    float kEncodeBit = 1.0/255.0;
    float4 enc = kEncodeMul * v;
    enc = frac (enc);
    enc -= enc.yzww * kEncodeBit;
    return enc;
}
inline float DecodeFloatRGBA( float4 enc )
{
    float4 kDecodeDot = float4(1.0, 1/255.0, 1/65025.0, 1/160581375.0);
    return dot( enc, kDecodeDot );
}

但是必须注意存储的打包/解包值,因为它们必须是编码基数的一部分(这里是255)。例如0.1在这里不起作用,但25/255 = 0.098是可以的。 这让我很困惑。

P.S。正如Andon M. Coleman所说 - 我们宁愿存储整数值(除以编码基数)而不是实际浮点数 P.P.S.最好总是在打包前修剪到最接近的离散值(如果从某些计算中得到它)