在顶点着色器中将超过4个组件打包到RGBA_32纹理中

时间:2015-01-17 11:28:48

标签: c opengl glsl vertex-shader

问题

  • 顶点着色器只能从非mipmapped RGBA_32图像(128位浮点)获取纹素
  • 我需要每顶点超过4个值
  • 使用多个RGBA_32图像是过度的(我猜),至少我不需要为每个单个组件提供那么多精度)

所以我需要一种方法来在4个RGBA值中包含4个以上的组件,当然还有一种方法可以在Vertex着色器中解压缩这些组件。

我需要的一些组件:

  • RGBA颜色(32位)
  • 位置(每个组件16位,总共48位)
  • 正常(??位)

性能不是问题(我认为任何解包功能都比两次采样RGBA_32纹理更好,因为这些纹理很大,而且每个额外的纹理都会吃十几个MB!)

必须可以在片段着色器内部(假设使用渲染目标)和可移植的C代码(在需要时从CPU更新纹理的部分)进行打包。

1 个答案:

答案 0 :(得分:0)

如何使用每个通道精度低于8位的多个图像?例如,两个类型为GL_UNSIGNED_SHORT_4_4_4_4的RGBA图像和内部格式RGBA4(即每个通道4位)。

另一种可能性是打包位。例如,两个半字节可以打包成八位字节。因此,使用R8_G8_B8_A8(即GL_RGBA8)纹理,您可以编码16个元素。

包装组件

uint8_t pack_nibbles(unsigned a, unsigned b) {
    return (a & 0x0f) | ((b & 0x0f) << 4);
}

打开包装

ivec2 unpack_nibbles2(int c) {
    return ivec2(c & 0x0f, (c >> 4) & 0x0f);
}

ivec4 unpack_nibbles4(ivec2 c) {
    return ivec4(c.x & 0x0f, (c.x >> 4) & 0x0f,
                 c.y & 0x0f, (c.y >> 4) & 0x0f);
}

后者可以像

一样使用
uniform usampler2D tex;

/* ... */

ivec4 t = texture(tex, ...);
ivec4 a = unpack_nibbles4(t.xy);
ivec4 b = unpack_nibbles4(t.wz);