GLSL中纹理位的精确控制



我正在尝试使用OpenGL和GLSL实现八叉树遍历方案,并希望将数据保存在纹理中。虽然纹理数据有很多格式可供选择(不同大小的浮点和整数),但我很难弄清楚是否有办法对比特进行更精确的控制,从而实现更高的效率和紧凑的存储。这可能是一个普遍的问题,不仅适用于OpenGL和GLSL。

作为一个简单的玩具示例,假设我有一个包含16位整数的texel。我想把两个布尔值分别编码为1位,一个10位整数值,然后一个4位整数值到这个texel中。是否有一种技术可以在创建纹理时对此进行编码,然后在使用GLSL着色器采样纹理时对这些组件进行解码?

编辑:看起来我实际上是在寻找比特操作技术。既然他们似乎得到了支持,经过更多的研究,我应该会没事的。

自OpenGL 3以来,GLSL着色器内部支持整数和位操作(因此存在于DX10类硬件上,如果这告诉您更多)。所以你可以在着色器中自己做这个维护。

但是处理整数是一回事,将它们从纹理中取出是另一回事。标准OpenGL纹理格式(您可能已经习惯了)要么直接存储浮点值(如GL_R16F),要么存储归一化的固定点值(如GL_R16,实际上是未初始化的整数;),但从中读取(使用texturetexelFetch或其他)将使着色器中的浮点值净额,您无法从中轻松或可靠地推导出内部存储整数的原始位模式。

因此,您真正需要使用的是一个整数纹理,它也需要OpenGL 3(或者可能是GL_EXT_texture_integer扩展,但支持它的硬件可能无论如何都有GL3)。因此,对于您的纹理,您需要使用实际的整数内部格式,例如GL_R16UI(用于单分量16位无符号整数),而不是通常的定点格式(例如GL_R16,用于16位精度的归一化[0,1]-颜色)。

然后在着色器中,您需要使用整数采样器类型,例如usampler2D用于无符号整数2D纹理(同样isampler...用于有符号变体),以便从texturetexelFetch调用中实际获得无符号整数:

CPU:

glTexImage2D(GL_TEXTURE_2D, 0, GL_R16UI, ..., GL_R, GL_UNSIGNED_SHORT, data);

GPU:

uniform usampler2D tex;
...
uint value = texture(tex, ...).r;
bool b1 = (value&0x8000) == 0x8000, 
     b2 = (value&0x4000) == 0x4000;
uint i1 = (value>>4) & 0x3FF, 
     i2 = value & 0xF;

最新更新