精确控制GLSL中的纹理位

时间:2013-02-19 15:26:38

标签: opengl glsl shader bit-manipulation textures

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

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

编辑:看起来我实际上正在寻找位操作技术。由于它们似乎得到了支持,经过一些研究后我会没事的。

1 个答案:

答案 0 :(得分:3)

自OpenGL 3以来,支持GLSL着色器内部的整数和位操作(因此,如果能够提供更多信息,则会出现在DX10类硬件上)。所以你可以在着色器内部自己做这个位维护。

但是使用整数是一回事,让它们脱离纹理是另一回事。标准的OpenGL纹理格式(您可能习惯)要么直接存储浮点数(如GL_R16F),要么标准化的固定点值(如GL_R16,有效整数为未启动的;)),但是读取从它们(使用texturetexelFetch或其他)将在着色器中净化浮点值,从中您无法轻易或可靠地推导出内部存储的整数的原始位模式。

所以你真正需要使用的是一个整数纹理,它也需要OpenGL 3(或者可能是GL_EXT_texture_integer扩展,但支持的硬件可能还有GL3)。因此,对于纹理,您需要使用实际的整数内部格式,例如GL_R16UI(对于1分量16位无符号整数)与通常的固定点格式相比(例如GL_R16用于标准化[0,1] - 颜色,精度为16位)。 / p>

然后在着色器中,您需要使用整数采样器类型,例如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;